Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/softfloat/generic/mul.c

    rc67aff2 r750636a  
    11/*
    22 * Copyright (c) 2005 Josef Cejka
    3  * Copyright (c) 2011 Petr Koupy
    43 * All rights reserved.
    54 *
     
    3130 * @{
    3231 */
    33 /** @file Multiplication functions.
     32/** @file
    3433 */
    3534
     
    3938#include <common.h>
    4039
    41 /**
    42  * Multiply two single-precision floats.
    43  *
    44  * @param a First input operand.
    45  * @param b Second input operand.
    46  * @return Result of multiplication.
     40/** Multiply two 32 bit float numbers
     41 *
    4742 */
    4843float32 mulFloat32(float32 a, float32 b)
     
    5449        result.parts.sign = a.parts.sign ^ b.parts.sign;
    5550       
    56         if (isFloat32NaN(a) || isFloat32NaN(b)) {
     51        if (isFloat32NaN(a) || isFloat32NaN(b) ) {
    5752                /* TODO: fix SigNaNs */
    5853                if (isFloat32SigNaN(a)) {
     
    6055                        result.parts.exp = a.parts.exp;
    6156                        return result;
    62                 }
     57                };
    6358                if (isFloat32SigNaN(b)) { /* TODO: fix SigNaN */
    6459                        result.parts.fraction = b.parts.fraction;
    6560                        result.parts.exp = b.parts.exp;
    6661                        return result;
    67                 }
     62                };
    6863                /* set NaN as result */
    6964                result.binary = FLOAT32_NAN;
    7065                return result;
    71         }
     66        };
    7267               
    7368        if (isFloat32Infinity(a)) {
     
    10398                result.parts.sign = a.parts.sign ^ b.parts.sign;
    10499                return result;
    105         }
     100        };
    106101       
    107102        if (exp < 0) {
     
    111106                result.parts.exp = 0x0;
    112107                return result;
    113         }
     108        };
    114109       
    115110        frac1 = a.parts.fraction;
     
    118113        } else {
    119114                ++exp;
    120         }
     115        };
    121116       
    122117        frac2 = b.parts.fraction;
     
    126121        } else {
    127122                ++exp;
    128         }
     123        };
    129124
    130125        frac1 <<= 1; /* one bit space for rounding */
    131126
    132127        frac1 = frac1 * frac2;
    133 
    134         /* round and return */
    135         while ((exp < FLOAT32_MAX_EXPONENT) && (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 2)))) {
    136                 /* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left) */
     128/* round and return */
     129       
     130        while ((exp < FLOAT32_MAX_EXPONENT) && (frac1 >= ( 1 << (FLOAT32_FRACTION_SIZE + 2)))) {
     131                /* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left)*/
    137132                ++exp;
    138133                frac1 >>= 1;
    139         }
     134        };
    140135
    141136        /* rounding */
     
    146141                ++exp;
    147142                frac1 >>= 1;
    148         }
    149 
    150         if (exp >= FLOAT32_MAX_EXPONENT) {     
     143        };
     144
     145        if (exp >= FLOAT32_MAX_EXPONENT ) {     
    151146                /* TODO: fix overflow */
    152147                /* return infinity*/
     
    164159                        frac1 >>= 1;
    165160                        ++exp;
    166                 }
     161                };
    167162                if (frac1 == 0) {
    168163                        /* FIXME : underflow */
    169                         result.parts.exp = 0;
    170                         result.parts.fraction = 0;
    171                         return result;
    172                 }
    173         }
     164                result.parts.exp = 0;
     165                result.parts.fraction = 0;
     166                return result;
     167                };
     168        };
    174169        result.parts.exp = exp;
    175         result.parts.fraction = frac1 & ((1 << FLOAT32_FRACTION_SIZE) - 1);
     170        result.parts.fraction = frac1 & ( (1 << FLOAT32_FRACTION_SIZE) - 1);
    176171       
    177172        return result; 
     173       
    178174}
    179175
    180 /**
    181  * Multiply two double-precision floats.
    182  *
    183  * @param a First input operand.
    184  * @param b Second input operand.
    185  * @return Result of multiplication.
     176/** Multiply two 64 bit float numbers
     177 *
    186178 */
    187179float64 mulFloat64(float64 a, float64 b)
     
    193185        result.parts.sign = a.parts.sign ^ b.parts.sign;
    194186       
    195         if (isFloat64NaN(a) || isFloat64NaN(b)) {
     187        if (isFloat64NaN(a) || isFloat64NaN(b) ) {
    196188                /* TODO: fix SigNaNs */
    197189                if (isFloat64SigNaN(a)) {
     
    199191                        result.parts.exp = a.parts.exp;
    200192                        return result;
    201                 }
     193                };
    202194                if (isFloat64SigNaN(b)) { /* TODO: fix SigNaN */
    203195                        result.parts.fraction = b.parts.fraction;
    204196                        result.parts.exp = b.parts.exp;
    205197                        return result;
    206                 }
     198                };
    207199                /* set NaN as result */
    208200                result.binary = FLOAT64_NAN;
    209201                return result;
    210         }
     202        };
    211203               
    212204        if (isFloat64Infinity(a)) {
     
    241233        } else {
    242234                ++exp;
    243         }
     235        };
    244236       
    245237        frac2 = b.parts.fraction;
     
    249241        } else {
    250242                ++exp;
    251         }
     243        };
    252244
    253245        frac1 <<= (64 - FLOAT64_FRACTION_SIZE - 1);
    254246        frac2 <<= (64 - FLOAT64_FRACTION_SIZE - 2);
    255247
    256         mul64(frac1, frac2, &frac1, &frac2);
    257 
    258         frac1 |= (frac2 != 0);
    259         if (frac1 & (0x1ll << 62)) {
    260                 frac1 <<= 1;
     248        mul64integers(frac1, frac2, &frac1, &frac2);
     249
     250        frac2 |= (frac1 != 0);
     251        if (frac2 & (0x1ll << 62)) {
     252                frac2 <<= 1;
    261253                exp--;
    262254        }
    263255
    264         result = finishFloat64(exp, frac1, result.parts.sign);
     256        result = finishFloat64(exp, frac2, result.parts.sign);
    265257        return result;
    266258}
    267259
    268 /**
    269  * Multiply two quadruple-precision floats.
    270  *
    271  * @param a First input operand.
    272  * @param b Second input operand.
    273  * @return Result of multiplication.
    274  */
    275 float128 mulFloat128(float128 a, float128 b)
     260/** Multiply two 64 bit numbers and return result in two parts
     261 * @param a first operand
     262 * @param b second operand
     263 * @param lo lower part from result
     264 * @param hi higher part of result
     265 */
     266void mul64integers(uint64_t a,uint64_t b, uint64_t *lo, uint64_t *hi)
    276267{
    277         float128 result;
    278         uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
    279         int32_t exp;
    280 
    281         result.parts.sign = a.parts.sign ^ b.parts.sign;
    282 
    283         if (isFloat128NaN(a) || isFloat128NaN(b)) {
    284                 /* TODO: fix SigNaNs */
    285                 if (isFloat128SigNaN(a)) {
    286                         result.parts.frac_hi = a.parts.frac_hi;
    287                         result.parts.frac_lo = a.parts.frac_lo;
    288                         result.parts.exp = a.parts.exp;
    289                         return result;
    290                 }
    291                 if (isFloat128SigNaN(b)) { /* TODO: fix SigNaN */
    292                         result.parts.frac_hi = b.parts.frac_hi;
    293                         result.parts.frac_lo = b.parts.frac_lo;
    294                         result.parts.exp = b.parts.exp;
    295                         return result;
    296                 }
    297                 /* set NaN as result */
    298                 result.binary.hi = FLOAT128_NAN_HI;
    299                 result.binary.lo = FLOAT128_NAN_LO;
    300                 return result;
    301         }
    302 
    303         if (isFloat128Infinity(a)) {
    304                 if (isFloat128Zero(b)) {
    305                         /* FIXME: zero * infinity */
    306                         result.binary.hi = FLOAT128_NAN_HI;
    307                         result.binary.lo = FLOAT128_NAN_LO;
    308                         return result;
    309                 }
    310                 result.parts.frac_hi = a.parts.frac_hi;
    311                 result.parts.frac_lo = a.parts.frac_lo;
    312                 result.parts.exp = a.parts.exp;
    313                 return result;
    314         }
    315 
    316         if (isFloat128Infinity(b)) {
    317                 if (isFloat128Zero(a)) {
    318                         /* FIXME: zero * infinity */
    319                         result.binary.hi = FLOAT128_NAN_HI;
    320                         result.binary.lo = FLOAT128_NAN_LO;
    321                         return result;
    322                 }
    323                 result.parts.frac_hi = b.parts.frac_hi;
    324                 result.parts.frac_lo = b.parts.frac_lo;
    325                 result.parts.exp = b.parts.exp;
    326                 return result;
    327         }
    328 
    329         /* exp is signed so we can easy detect underflow */
    330         exp = a.parts.exp + b.parts.exp - FLOAT128_BIAS - 1;
    331 
    332         frac1_hi = a.parts.frac_hi;
    333         frac1_lo = a.parts.frac_lo;
    334 
    335         if (a.parts.exp > 0) {
    336                 or128(frac1_hi, frac1_lo,
    337                 FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
    338                 &frac1_hi, &frac1_lo);
    339         } else {
    340                 ++exp;
    341         }
    342 
    343         frac2_hi = b.parts.frac_hi;
    344         frac2_lo = b.parts.frac_lo;
    345 
    346         if (b.parts.exp > 0) {
    347                 or128(frac2_hi, frac2_lo,
    348                     FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
    349                     &frac2_hi, &frac2_lo);
    350         } else {
    351                 ++exp;
    352         }
    353 
    354         lshift128(frac2_hi, frac2_lo,
    355             128 - FLOAT128_FRACTION_SIZE, &frac2_hi, &frac2_lo);
    356 
    357         tmp_hi = frac1_hi;
    358         tmp_lo = frac1_lo;
    359         mul128(frac1_hi, frac1_lo, frac2_hi, frac2_lo,
    360             &frac1_hi, &frac1_lo, &frac2_hi, &frac2_lo);
    361         add128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &frac1_hi, &frac1_lo);
    362         frac2_hi |= (frac2_lo != 0x0ll);
    363 
    364         if ((FLOAT128_HIDDEN_BIT_MASK_HI << 1) <= frac1_hi) {
    365                 frac2_hi >>= 1;
    366                 if (frac1_lo & 0x1ll) {
    367                         frac2_hi |= (0x1ull < 64);
    368                 }
    369                 rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
    370                 ++exp;
    371         }
    372 
    373         result = finishFloat128(exp, frac1_hi, frac1_lo, result.parts.sign, frac2_hi);
    374         return result;
     268        uint64_t low, high, middle1, middle2;
     269        uint32_t alow, blow;
     270
     271        alow = a & 0xFFFFFFFF;
     272        blow = b & 0xFFFFFFFF;
     273       
     274        a >>= 32;
     275        b >>= 32;
     276       
     277        low = ((uint64_t)alow) * blow;
     278        middle1 = a * blow;
     279        middle2 = alow * b;
     280        high = a * b;
     281
     282        middle1 += middle2;
     283        high += (((uint64_t)(middle1 < middle2)) << 32) + (middle1 >> 32);
     284        middle1 <<= 32;
     285        low += middle1;
     286        high += (low < middle1);
     287        *lo = low;
     288        *hi = high;
     289       
     290        return;
    375291}
    376292
Note: See TracChangeset for help on using the changeset viewer.