add.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 <comparison.h>
00038 
00041 float32 addFloat32(float32 a, float32 b)
00042 {
00043         int expdiff;
00044         uint32_t exp1, exp2,frac1, frac2;
00045         
00046         expdiff = a.parts.exp - b.parts.exp;
00047         if (expdiff < 0) {
00048                 if (isFloat32NaN(b)) {
00049                         /* TODO: fix SigNaN */
00050                         if (isFloat32SigNaN(b)) {
00051                         };
00052 
00053                         return b;
00054                 };
00055                 
00056                 if (b.parts.exp == FLOAT32_MAX_EXPONENT) { 
00057                         return b;
00058                 }
00059                 
00060                 frac1 = b.parts.fraction;
00061                 exp1 = b.parts.exp;
00062                 frac2 = a.parts.fraction;
00063                 exp2 = a.parts.exp;
00064                 expdiff *= -1;
00065         } else {
00066                 if ((isFloat32NaN(a)) || (isFloat32NaN(b))) {
00067                         /* TODO: fix SigNaN */
00068                         if (isFloat32SigNaN(a) || isFloat32SigNaN(b)) {
00069                         };
00070                         return (isFloat32NaN(a)?a:b);
00071                 };
00072                 
00073                 if (a.parts.exp == FLOAT32_MAX_EXPONENT) { 
00074                         return a;
00075                 }
00076                 
00077                 frac1 = a.parts.fraction;
00078                 exp1 = a.parts.exp;
00079                 frac2 = b.parts.fraction;
00080                 exp2 = b.parts.exp;
00081         };
00082         
00083         if (exp1 == 0) {
00084                 /* both are denormalized */
00085                 frac1 += frac2;
00086                 if (frac1 & FLOAT32_HIDDEN_BIT_MASK ) {
00087                         /* result is not denormalized */
00088                         a.parts.exp = 1;
00089                 };
00090                 a.parts.fraction = frac1;
00091                 return a;
00092         };
00093         
00094         frac1 |= FLOAT32_HIDDEN_BIT_MASK; /* add hidden bit */
00095 
00096         if (exp2 == 0) {
00097                 /* second operand is denormalized */
00098                 --expdiff;
00099         } else {
00100                 /* add hidden bit to second operand */
00101                 frac2 |= FLOAT32_HIDDEN_BIT_MASK; 
00102         };
00103         
00104         /* create some space for rounding */
00105         frac1 <<= 6;
00106         frac2 <<= 6;
00107         
00108         if (expdiff < (FLOAT32_FRACTION_SIZE + 2) ) {
00109                 frac2 >>= expdiff;
00110                 frac1 += frac2;
00111         } else {
00112                 a.parts.exp = exp1;
00113                 a.parts.fraction = (frac1 >> 6) & (~(FLOAT32_HIDDEN_BIT_MASK));
00114                 return a;
00115         }
00116         
00117         if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7) ) {
00118                 ++exp1;
00119                 frac1 >>= 1;
00120         };
00121         
00122         /* rounding - if first bit after fraction is set then round up */
00123         frac1 += (0x1 << 5);
00124         
00125         if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) { 
00126                 /* rounding overflow */
00127                 ++exp1;
00128                 frac1 >>= 1;
00129         };
00130         
00131         
00132         if ((exp1 == FLOAT32_MAX_EXPONENT ) || (exp2 > exp1)) {
00133                         /* overflow - set infinity as result */
00134                         a.parts.exp = FLOAT32_MAX_EXPONENT;
00135                         a.parts.fraction = 0;
00136                         return a;
00137                         }
00138         
00139         a.parts.exp = exp1;
00140         
00141         /* Clear hidden bit and shift */
00142         a.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)) ; 
00143         return a;
00144 }
00145 
00148 float64 addFloat64(float64 a, float64 b)
00149 {
00150         int expdiff;
00151         uint32_t exp1, exp2;
00152         uint64_t frac1, frac2;
00153         
00154         expdiff = ((int )a.parts.exp) - b.parts.exp;
00155         if (expdiff < 0) {
00156                 if (isFloat64NaN(b)) {
00157                         /* TODO: fix SigNaN */
00158                         if (isFloat64SigNaN(b)) {
00159                         };
00160 
00161                         return b;
00162                 };
00163                 
00164                 /* b is infinity and a not */   
00165                 if (b.parts.exp == FLOAT64_MAX_EXPONENT ) { 
00166                         return b;
00167                 }
00168                 
00169                 frac1 = b.parts.fraction;
00170                 exp1 = b.parts.exp;
00171                 frac2 = a.parts.fraction;
00172                 exp2 = a.parts.exp;
00173                 expdiff *= -1;
00174         } else {
00175                 if (isFloat64NaN(a)) {
00176                         /* TODO: fix SigNaN */
00177                         if (isFloat64SigNaN(a) || isFloat64SigNaN(b)) {
00178                         };
00179                         return a;
00180                 };
00181                 
00182                 /* a is infinity and b not */
00183                 if (a.parts.exp == FLOAT64_MAX_EXPONENT ) { 
00184                         return a;
00185                 }
00186                 
00187                 frac1 = a.parts.fraction;
00188                 exp1 = a.parts.exp;
00189                 frac2 = b.parts.fraction;
00190                 exp2 = b.parts.exp;
00191         };
00192         
00193         if (exp1 == 0) {
00194                 /* both are denormalized */
00195                 frac1 += frac2;
00196                 if (frac1 & FLOAT64_HIDDEN_BIT_MASK) { 
00197                         /* result is not denormalized */
00198                         a.parts.exp = 1;
00199                 };
00200                 a.parts.fraction = frac1;
00201                 return a;
00202         };
00203         
00204         /* add hidden bit - frac1 is sure not denormalized */
00205         frac1 |= FLOAT64_HIDDEN_BIT_MASK;
00206 
00207         /* second operand ... */
00208         if (exp2 == 0) {
00209                 /* ... is denormalized */
00210                 --expdiff;      
00211         } else {
00212                 /* is not denormalized */
00213                 frac2 |= FLOAT64_HIDDEN_BIT_MASK;
00214         };
00215         
00216         /* create some space for rounding */
00217         frac1 <<= 6;
00218         frac2 <<= 6;
00219         
00220         if (expdiff < (FLOAT64_FRACTION_SIZE + 2) ) {
00221                 frac2 >>= expdiff;
00222                 frac1 += frac2;
00223         } else {
00224                 a.parts.exp = exp1;
00225                 a.parts.fraction = (frac1 >> 6) & (~(FLOAT64_HIDDEN_BIT_MASK));
00226                 return a;
00227         }
00228         
00229         if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7) ) {
00230                 ++exp1;
00231                 frac1 >>= 1;
00232         };
00233         
00234         /* rounding - if first bit after fraction is set then round up */
00235         frac1 += (0x1 << 5); 
00236         
00237         if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) { 
00238                 /* rounding overflow */
00239                 ++exp1;
00240                 frac1 >>= 1;
00241         };
00242         
00243         if ((exp1 == FLOAT64_MAX_EXPONENT ) || (exp2 > exp1)) {
00244                         /* overflow - set infinity as result */
00245                         a.parts.exp = FLOAT64_MAX_EXPONENT;
00246                         a.parts.fraction = 0;
00247                         return a;
00248                         }
00249         
00250         a.parts.exp = exp1;
00251         /* Clear hidden bit and shift */
00252         a.parts.fraction = ( (frac1 >> 6 ) & (~FLOAT64_HIDDEN_BIT_MASK));
00253         
00254         return a;
00255 }
00256 

Generated on Thu Jun 2 07:45:48 2011 for HelenOS/USB by  doxygen 1.4.7