div.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Josef Cejka
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include<sftypes.h>
00036 #include<add.h>
00037 #include<div.h>
00038 #include<comparison.h>
00039 #include<mul.h>
00040 #include<common.h>
00041 
00042 
00043 float32 divFloat32(float32 a, float32 b) 
00044 {
00045         float32 result;
00046         int32_t aexp, bexp, cexp;
00047         uint64_t afrac, bfrac, cfrac;
00048         
00049         result.parts.sign = a.parts.sign ^ b.parts.sign;
00050         
00051         if (isFloat32NaN(a)) {
00052                 if (isFloat32SigNaN(a)) {
00053                         /*FIXME: SigNaN*/
00054                 }
00055                 /*NaN*/
00056                 return a;
00057         }
00058         
00059         if (isFloat32NaN(b)) {
00060                 if (isFloat32SigNaN(b)) {
00061                         /*FIXME: SigNaN*/
00062                 }
00063                 /*NaN*/
00064                 return b;
00065         }
00066         
00067         if (isFloat32Infinity(a)) {
00068                 if (isFloat32Infinity(b)) {
00069                         /*FIXME: inf / inf */
00070                         result.binary = FLOAT32_NAN;
00071                         return result;
00072                 }
00073                 /* inf / num */
00074                 result.parts.exp = a.parts.exp;
00075                 result.parts.fraction = a.parts.fraction;
00076                 return result;
00077         }
00078 
00079         if (isFloat32Infinity(b)) {
00080                 if (isFloat32Zero(a)) {
00081                         /* FIXME 0 / inf */
00082                         result.parts.exp = 0;
00083                         result.parts.fraction = 0;
00084                         return result;
00085                 }
00086                 /* FIXME: num / inf*/
00087                 result.parts.exp = 0;
00088                 result.parts.fraction = 0;
00089                 return result;
00090         }
00091         
00092         if (isFloat32Zero(b)) {
00093                 if (isFloat32Zero(a)) {
00094                         /*FIXME: 0 / 0*/
00095                         result.binary = FLOAT32_NAN;
00096                         return result;
00097                 }
00098                 /* FIXME: division by zero */
00099                 result.parts.exp = 0;
00100                 result.parts.fraction = 0;
00101                 return result;
00102         }
00103 
00104         
00105         afrac = a.parts.fraction;
00106         aexp = a.parts.exp;
00107         bfrac = b.parts.fraction;
00108         bexp = b.parts.exp;
00109         
00110         /* denormalized numbers */
00111         if (aexp == 0) {
00112                 if (afrac == 0) {
00113                 result.parts.exp = 0;
00114                 result.parts.fraction = 0;
00115                 return result;
00116                 }
00117                 /* normalize it*/
00118                 
00119                 afrac <<= 1;
00120                         /* afrac is nonzero => it must stop */  
00121                 while (! (afrac & FLOAT32_HIDDEN_BIT_MASK) ) {
00122                         afrac <<= 1;
00123                         aexp--;
00124                 }
00125         }
00126 
00127         if (bexp == 0) {
00128                 bfrac <<= 1;
00129                         /* bfrac is nonzero => it must stop */  
00130                 while (! (bfrac & FLOAT32_HIDDEN_BIT_MASK) ) {
00131                         bfrac <<= 1;
00132                         bexp--;
00133                 }
00134         }
00135 
00136         afrac = (afrac | FLOAT32_HIDDEN_BIT_MASK ) << (32 - FLOAT32_FRACTION_SIZE - 1 );
00137         bfrac = (bfrac | FLOAT32_HIDDEN_BIT_MASK ) << (32 - FLOAT32_FRACTION_SIZE );
00138 
00139         if ( bfrac <= (afrac << 1) ) {
00140                 afrac >>= 1;
00141                 aexp++;
00142         }
00143         
00144         cexp = aexp - bexp + FLOAT32_BIAS - 2;
00145         
00146         cfrac = (afrac << 32) / bfrac;
00147         if ((  cfrac & 0x3F ) == 0) { 
00148                 cfrac |= ( bfrac * cfrac != afrac << 32 );
00149         }
00150         
00151         /* pack and round */
00152         
00153         /* find first nonzero digit and shift result and detect possibly underflow */
00154         while ((cexp > 0) && (cfrac) && (!(cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7 )))) {
00155                 cexp--;
00156                 cfrac <<= 1;
00157                         /* TODO: fix underflow */
00158         };
00159         
00160         cfrac += (0x1 << 6); /* FIXME: 7 is not sure*/
00161         
00162         if (cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
00163                 ++cexp;
00164                 cfrac >>= 1;
00165                 }       
00166 
00167         /* check overflow */
00168         if (cexp >= FLOAT32_MAX_EXPONENT ) {
00169                 /* FIXME: overflow, return infinity */
00170                 result.parts.exp = FLOAT32_MAX_EXPONENT;
00171                 result.parts.fraction = 0;
00172                 return result;
00173         }
00174 
00175         if (cexp < 0) {
00176                 /* FIXME: underflow */
00177                 result.parts.exp = 0;
00178                 if ((cexp + FLOAT32_FRACTION_SIZE) < 0) {
00179                         result.parts.fraction = 0;
00180                         return result;
00181                 }
00182                 cfrac >>= 1;
00183                 while (cexp < 0) {
00184                         cexp ++;
00185                         cfrac >>= 1;
00186                 }
00187                 
00188         } else {
00189                 result.parts.exp = (uint32_t)cexp;
00190         }
00191         
00192         result.parts.fraction = ((cfrac >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)); 
00193         
00194         return result;  
00195 }
00196 
00197 float64 divFloat64(float64 a, float64 b) 
00198 {
00199         float64 result;
00200         int64_t aexp, bexp, cexp;
00201         uint64_t afrac, bfrac, cfrac; 
00202         uint64_t remlo, remhi;
00203         
00204         result.parts.sign = a.parts.sign ^ b.parts.sign;
00205         
00206         if (isFloat64NaN(a)) {
00207                 
00208                 if (isFloat64SigNaN(b)) {
00209                         /*FIXME: SigNaN*/
00210                         return b;
00211                 }
00212                 
00213                 if (isFloat64SigNaN(a)) {
00214                         /*FIXME: SigNaN*/
00215                 }
00216                 /*NaN*/
00217                 return a;
00218         }
00219         
00220         if (isFloat64NaN(b)) {
00221                 if (isFloat64SigNaN(b)) {
00222                         /*FIXME: SigNaN*/
00223                 }
00224                 /*NaN*/
00225                 return b;
00226         }
00227         
00228         if (isFloat64Infinity(a)) {
00229                 if (isFloat64Infinity(b) || isFloat64Zero(b)) {
00230                         /*FIXME: inf / inf */
00231                         result.binary = FLOAT64_NAN;
00232                         return result;
00233                 }
00234                 /* inf / num */
00235                 result.parts.exp = a.parts.exp;
00236                 result.parts.fraction = a.parts.fraction;
00237                 return result;
00238         }
00239 
00240         if (isFloat64Infinity(b)) {
00241                 if (isFloat64Zero(a)) {
00242                         /* FIXME 0 / inf */
00243                         result.parts.exp = 0;
00244                         result.parts.fraction = 0;
00245                         return result;
00246                 }
00247                 /* FIXME: num / inf*/
00248                 result.parts.exp = 0;
00249                 result.parts.fraction = 0;
00250                 return result;
00251         }
00252         
00253         if (isFloat64Zero(b)) {
00254                 if (isFloat64Zero(a)) {
00255                         /*FIXME: 0 / 0*/
00256                         result.binary = FLOAT64_NAN;
00257                         return result;
00258                 }
00259                 /* FIXME: division by zero */
00260                 result.parts.exp = 0;
00261                 result.parts.fraction = 0;
00262                 return result;
00263         }
00264 
00265         
00266         afrac = a.parts.fraction;
00267         aexp = a.parts.exp;
00268         bfrac = b.parts.fraction;
00269         bexp = b.parts.exp;
00270         
00271         /* denormalized numbers */
00272         if (aexp == 0) {
00273                 if (afrac == 0) {
00274                         result.parts.exp = 0;
00275                         result.parts.fraction = 0;
00276                         return result;
00277                 }
00278                 /* normalize it*/
00279                 
00280                 aexp++;
00281                         /* afrac is nonzero => it must stop */  
00282                 while (! (afrac & FLOAT64_HIDDEN_BIT_MASK) ) {
00283                         afrac <<= 1;
00284                         aexp--;
00285                 }
00286         }
00287 
00288         if (bexp == 0) {
00289                 bexp++;
00290                         /* bfrac is nonzero => it must stop */  
00291                 while (! (bfrac & FLOAT64_HIDDEN_BIT_MASK) ) {
00292                         bfrac <<= 1;
00293                         bexp--;
00294                 }
00295         }
00296 
00297         afrac = (afrac | FLOAT64_HIDDEN_BIT_MASK ) << (64 - FLOAT64_FRACTION_SIZE - 2 );
00298         bfrac = (bfrac | FLOAT64_HIDDEN_BIT_MASK ) << (64 - FLOAT64_FRACTION_SIZE - 1);
00299 
00300         if ( bfrac <= (afrac << 1) ) {
00301                 afrac >>= 1;
00302                 aexp++;
00303         }
00304         
00305         cexp = aexp - bexp + FLOAT64_BIAS - 2; 
00306         
00307         cfrac = divFloat64estim(afrac, bfrac);
00308         
00309         if ((  cfrac & 0x1FF ) <= 2) { /*FIXME:?? */
00310                 mul64integers( bfrac, cfrac, &remlo, &remhi);
00311                 /* (__u128)afrac << 64 - ( ((__u128)remhi<<64) + (__u128)remlo )*/      
00312                 remhi = afrac - remhi - ( remlo > 0);
00313                 remlo = - remlo;
00314                 
00315                 while ((int64_t) remhi < 0) {
00316                         cfrac--;
00317                         remlo += bfrac;
00318                         remhi += ( remlo < bfrac );
00319                 }
00320                 cfrac |= ( remlo != 0 );
00321         }
00322         
00323         /* round and shift */
00324         result = finishFloat64(cexp, cfrac, result.parts.sign);
00325         return result;
00326 
00327 }
00328 
00329 uint64_t divFloat64estim(uint64_t a, uint64_t b)
00330 {
00331         uint64_t bhi;
00332         uint64_t remhi, remlo;
00333         uint64_t result;
00334         
00335         if ( b <= a ) {
00336                 return 0xFFFFFFFFFFFFFFFFull;
00337         }
00338         
00339         bhi = b >> 32;
00340         result = ((bhi << 32) <= a) ?( 0xFFFFFFFFull << 32) : ( a / bhi) << 32;
00341         mul64integers(b, result, &remlo, &remhi);
00342         
00343         remhi = a - remhi - (remlo > 0);
00344         remlo = - remlo;
00345 
00346         b <<= 32;
00347         while ( (int64_t) remhi < 0 ) {
00348                         result -= 0x1ll << 32;  
00349                         remlo += b;
00350                         remhi += bhi + ( remlo < b );
00351                 }
00352         remhi = (remhi << 32) | (remlo >> 32);
00353         if (( bhi << 32) <= remhi) {
00354                 result |= 0xFFFFFFFF;
00355         } else {
00356                 result |= remhi / bhi;
00357         }
00358         
00359         
00360         return result;
00361 }
00362 

Generated on Sun Jun 18 18:00:18 2006 for HelenOS Userspace (ia64) by  doxygen 1.4.6