Annotation of previous_trunk/src/softfloat/softfloat_decimal.c, revision 1.1.1.1

1.1       root        1: 
                      2: /*============================================================================
                      3: 
                      4: This C source file is an extension to the SoftFloat IEC/IEEE Floating-point 
                      5: Arithmetic Package, Release 2a.
                      6: 
                      7: =============================================================================*/
                      8: 
                      9: #include "softfloat.h"
                     10: 
                     11: /*----------------------------------------------------------------------------
                     12: | Methods for converting decimal floats to binary extended precision floats.
                     13: *----------------------------------------------------------------------------*/
                     14: 
                     15: INLINE void round128to64(flag aSign, int32 *aExp, bits64 *aSig0, bits64 *aSig1, float_ctrl* c)
                     16: {
                     17:     int8 roundingMode;
                     18:     flag increment;
                     19:     int32 zExp;
                     20:     bits64 zSig0, zSig1;
                     21:     
                     22:     zExp = *aExp;
                     23:     zSig0 = *aSig0;
                     24:     zSig1 = *aSig1;
                     25:     
                     26:     roundingMode = get_float_rounding_mode(c);
                     27:     increment = ( (sbits64) zSig1 < 0 );
                     28:     if (roundingMode != float_round_nearest_even) {
                     29:         if (roundingMode == float_round_to_zero) {
                     30:             increment = 0;
                     31:         } else {
                     32:             if (aSign) {
                     33:                 increment = (roundingMode == float_round_down) && zSig1;
                     34:             } else {
                     35:                 increment = (roundingMode == float_round_up) && zSig1;
                     36:             }
                     37:         }
                     38:     }
                     39:     
                     40:     if (increment) {
                     41:         ++zSig0;
                     42:         if (zSig0 == 0) {
                     43:             ++zExp;
                     44:             zSig0 = LIT64(0x8000000000000000);
                     45:         } else {
                     46:             zSig0 &= ~ (((bits64) (zSig1<<1) == 0) & (roundingMode == float_round_nearest_even));
                     47:         }
                     48:     } else {
                     49:         if ( zSig0 == 0 ) zExp = 0;
                     50:     }
                     51:     
                     52:     *aExp = zExp;
                     53:     *aSig0 = zSig0;
                     54:     *aSig1 = 0;
                     55: }
                     56: 
                     57: INLINE void mul128by128round(int32 *aExp, bits64 *aSig0, bits64 *aSig1, int32 bExp, bits64 bSig0, bits64 bSig1, float_ctrl* c)
                     58: {
                     59:     int32 zExp;
                     60:     bits64 zSig0, zSig1, zSig2, zSig3;
                     61:     
                     62:     zExp = *aExp;
                     63:     zSig0 = *aSig0;
                     64:     zSig1 = *aSig1;
                     65:     
                     66:     round128to64(0, &bExp, &bSig0, &bSig1, c);
                     67:     
                     68:     zExp += bExp - 0x3FFE;
                     69:     mul128To256(zSig0, zSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3);
                     70:     zSig1 |= (zSig2 | zSig3) != 0;
                     71:     if ( 0 < (sbits64) zSig0 ) {
                     72:         shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
                     73:         --zExp;
                     74:     }
                     75:     *aExp = zExp;
                     76:     *aSig0 = zSig0;
                     77:     *aSig1 = zSig1;
                     78:     
                     79:     round128to64(0, aExp, aSig0, aSig1, c);
                     80: }
                     81: 
                     82: INLINE void mul128by128(int32 *aExp, bits64 *aSig0, bits64 *aSig1, int32 bExp, bits64 bSig0, bits64 bSig1)
                     83: {
                     84:     int32 zExp;
                     85:     bits64 zSig0, zSig1, zSig2, zSig3;
                     86:     
                     87:     zExp = *aExp;
                     88:     zSig0 = *aSig0;
                     89:     zSig1 = *aSig1;
                     90: 
                     91:     zExp += bExp - 0x3FFE;
                     92:     mul128To256(zSig0, zSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3);
                     93:     zSig1 |= (zSig2 | zSig3) != 0;
                     94:     if ( 0 < (sbits64) zSig0 ) {
                     95:         shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
                     96:         --zExp;
                     97:     }
                     98:     *aExp = zExp;
                     99:     *aSig0 = zSig0;
                    100:     *aSig1 = zSig1;
                    101: }
                    102: 
                    103: INLINE void div128by128(int32 *paExp, bits64 *paSig0, bits64 *paSig1, int32 bExp, bits64 bSig0, bits64 bSig1)
                    104: {
                    105:     int32 zExp, aExp;
                    106:     bits64 zSig0, zSig1, aSig0, aSig1;
                    107:     bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
                    108:     
                    109:     aExp = *paExp;
                    110:     aSig0 = *paSig0;
                    111:     aSig1 = *paSig1;
                    112:     
                    113:     zExp = aExp - bExp + 0x3FFE;
                    114:     if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
                    115:         shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
                    116:         ++zExp;
                    117:     }
                    118:     zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
                    119:     mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
                    120:     sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
                    121:     while ( (sbits64) rem0 < 0 ) {
                    122:         --zSig0;
                    123:         add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
                    124:     }
                    125:     zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
                    126:     if ( ( zSig1 & 0x3FFF ) <= 4 ) {
                    127:         mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
                    128:         sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
                    129:         while ( (sbits64) rem1 < 0 ) {
                    130:             --zSig1;
                    131:             add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
                    132:         }
                    133:         zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
                    134:     }
                    135: 
                    136:     *paExp = zExp;
                    137:     *paSig0 = zSig0;
                    138:     *paSig1 = zSig1;
                    139: }
                    140: 
                    141: INLINE void tentoint128(flag mSign, flag eSign, int32 *aExp, bits64 *aSig0, bits64 *aSig1, int32 scale, float_ctrl* c)
                    142: {
                    143:     int8 roundingMode;
                    144:     int8 save_rounding_mode;
                    145:     int32 mExp;
                    146:     bits64 mSig0, mSig1;
                    147:     
                    148:     roundingMode = get_float_rounding_mode(c);
                    149:     save_rounding_mode = get_float_rounding_mode(c);
                    150:     switch (roundingMode) {
                    151:         case float_round_nearest_even:
                    152:             break;
                    153:         case float_round_down:
                    154:             if (mSign != eSign) {
                    155:                 set_float_rounding_mode(float_round_up, c);
                    156:             }
                    157:             break;
                    158:         case float_round_up:
                    159:             if (mSign != eSign) {
                    160:                 set_float_rounding_mode(float_round_down, c);
                    161:             }
                    162:             break;
                    163:         case float_round_to_zero:
                    164:             if (eSign == 0) {
                    165:                 set_float_rounding_mode(float_round_down, c);
                    166:             } else {
                    167:                 set_float_rounding_mode(float_round_up, c);
                    168:             }
                    169:             break;
                    170:         default:
                    171:             break;
                    172:     }
                    173:     
                    174:     *aExp = 0x3FFF;
                    175:     *aSig0 = LIT64(0x8000000000000000);
                    176:     *aSig1 = 0;
                    177: 
                    178:     mExp = 0x4002;
                    179:     mSig0 = LIT64(0xA000000000000000);
                    180:     mSig1 = 0;
                    181:     
                    182:     while (scale) {
                    183:         if (scale & 1) {
                    184:             mul128by128round(aExp, aSig0, aSig1, mExp, mSig0, mSig1, c);
                    185:         }
                    186:         mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1);
                    187:         scale >>= 1;
                    188:     }
                    189:     
                    190:     set_float_rounding_mode(save_rounding_mode, c);
                    191: }
                    192: 
                    193: INLINE int64 tentointdec(int32 scale)
                    194: {
                    195:     bits64 decM, decX;
                    196:     
                    197:     decX = 1;
                    198:     decM = 10;
                    199:     
                    200:     while (scale) {
                    201:         if (scale & 1) {
                    202:             decX *= decM;
                    203:         }
                    204:         decM *= decM;
                    205:         scale >>= 1;
                    206:     }
                    207:     
                    208:     return decX;
                    209: }
                    210: 
                    211: INLINE int64 float128toint64(flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, float_ctrl* c)
                    212: {
                    213:     int8 roundingMode;
                    214:     flag roundNearestEven, increment;
                    215:     int64 z;
                    216:     
                    217:     shift128RightJamming(zSig0, zSig1, 0x403E - zExp, &zSig0, &zSig1);
                    218: 
                    219:     roundingMode = get_float_rounding_mode(c);
                    220:     roundNearestEven = (roundingMode == float_round_nearest_even);
                    221:     increment = ((sbits64)zSig1 < 0);
                    222:     if (!roundNearestEven) {
                    223:         if (roundingMode == float_round_to_zero) {
                    224:             increment = 0;
                    225:         } else {
                    226:             if (zSign) {
                    227:                 increment = (roundingMode == float_round_down ) && zSig1;
                    228:             } else {
                    229:                 increment = (roundingMode == float_round_up ) && zSig1;
                    230:             }
                    231:         }
                    232:     }
                    233:     if (increment) {
                    234:         ++zSig0;
                    235:         zSig0 &= ~ (((bits64)(zSig1<<1) == 0) & roundNearestEven);
                    236:     }
                    237:     z = zSig0;
                    238:     if (zSig1) float_raise(float_flag_inexact, c);
                    239:     return z;
                    240: }
                    241: 
                    242: INLINE int32 getDecimalExponent(int32 aExp, bits64 aSig)
                    243: {
                    244:     flag zSign;
                    245:     int32 zExp, shiftCount;
                    246:     bits64 zSig0, zSig1;
                    247:     
                    248:     if (aSig == 0 || aExp == 0x3FFF) {
                    249:         return 0;
                    250:     }
                    251:     if (aExp < 0) {
                    252:         return -4932;
                    253:     }
                    254: 
                    255:     aSig ^= LIT64(0x8000000000000000);
                    256:     aExp -= 0x3FFF;
                    257:     zSign = (aExp < 0);
                    258:     aExp = zSign ? -aExp : aExp;
                    259:     shiftCount = 31 - countLeadingZeros32(aExp);
                    260:     zExp = 0x3FFF + shiftCount;
                    261:     
                    262:     if (shiftCount < 0) {
                    263:         shortShift128Left(aSig, 0, -shiftCount, &zSig0, &zSig1);
                    264:     } else {
                    265:         shift128Right(aSig, 0, shiftCount, &zSig0, &zSig1);
                    266:         aSig = (bits64)aExp << (63 - shiftCount);
                    267:         if (zSign) {
                    268:             sub128(aSig, 0, zSig0, zSig1, &zSig0, &zSig1);
                    269:         } else {
                    270:             add128(aSig, 0, zSig0, zSig1, &zSig0, &zSig1);
                    271:         }
                    272:     }
                    273:     
                    274:     shiftCount = countLeadingZeros64(zSig0);
                    275:     shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
                    276:     zExp -= shiftCount;
                    277:     mul128by128(&zExp, &zSig0, &zSig1, 0x3FFD, LIT64(0x9A209A84FBCFF798), LIT64(0x8F8959AC0B7C9178));
                    278:     
                    279:     shiftCount = 0x403E - zExp;
                    280:     shift128RightJamming(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
                    281: 
                    282:     if ((sbits64)zSig1 < 0) {
                    283:         ++zSig0;
                    284:         zSig0 &= ~((bits64)(zSig1<<1) == 0);
                    285:     }
                    286:     
                    287:     zExp = zSign ? -zSig0 : zSig0;
                    288: 
                    289:     return zExp;
                    290: }
                    291: 
                    292: /*----------------------------------------------------------------------------
                    293: | Decimal to binary
                    294: *----------------------------------------------------------------------------*/
                    295: 
                    296: floatx80 floatdecimal_to_floatx80(floatx80 a, float_ctrl* c)
                    297: {
                    298:     flag decSign, zSign, decExpSign;
                    299:     int32 decExp, zExp, xExp, shiftCount;
                    300:     bits64 decSig, zSig0, zSig1, xSig0, xSig1;
                    301:     
                    302:     decSign = extractFloatx80Sign(a);
                    303:     decExp = extractFloatx80Exp(a);
                    304:     decSig = extractFloatx80Frac(a);
                    305:     
                    306:     if (decExp == 0x7FFF) return a;
                    307:     
                    308:     if (decExp == 0 && decSig == 0) return a;
                    309:     
                    310:     decExpSign = (decExp >> 14) & 1;
                    311:     decExp &= 0x3FFF;
                    312:     
                    313:     shiftCount = countLeadingZeros64( decSig );
                    314:     zExp = 0x403E - shiftCount;
                    315:     zSig0 = decSig << shiftCount;
                    316:     zSig1 = 0;
                    317:     zSign = decSign;
                    318:     
                    319:     tentoint128(decSign, decExpSign, &xExp, &xSig0, &xSig1, decExp, c);
                    320:     
                    321:     if (decExpSign) {
                    322:         div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    323:     } else {
                    324:         mul128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    325:     }
                    326:     
                    327:     if (zSig1) float_raise(float_flag_decimal, c);
                    328:     round128to64(zSign, &zExp, &zSig0, &zSig1, c);
                    329:     
                    330:     return packFloatx80( zSign, zExp, zSig0 );
                    331: }
                    332: 
                    333: 
                    334: /*----------------------------------------------------------------------------
                    335:  | Binary to decimal
                    336:  *----------------------------------------------------------------------------*/
                    337: 
                    338: floatx80 floatx80_to_floatdecimal(floatx80 a, int32 *k, float_ctrl* c)
                    339: {
                    340:     flag aSign, decSign;
                    341:     int32 aExp, decExp, zExp, xExp;
                    342:     bits64 aSig, decSig, decX, zSig0, zSig1, xSig0, xSig1;
                    343:     flag ictr, lambda;
                    344:     int32 kfactor, ilog, iscale, len;
                    345:     
                    346:     aSign = extractFloatx80Sign(a);
                    347:     aExp = extractFloatx80Exp(a);
                    348:     aSig = extractFloatx80Frac(a);
                    349:     
                    350:     if (aExp == 0x7FFF) {
                    351:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a, c);
                    352:         return a;
                    353:     }
                    354:     
                    355:     if (aExp == 0) {
                    356:         if (aSig == 0) return packFloatx80(aSign, 0, 0);
                    357:         normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
                    358:     }
                    359: 
                    360:     kfactor = *k;
                    361:     
                    362:     ilog = getDecimalExponent(aExp, aSig);
                    363:     
                    364:     ictr = 0;
                    365:     
                    366: try_again:
                    367: 
                    368:     if (kfactor > 0) {
                    369:         if (kfactor > 17) {
                    370:             kfactor = 17;
                    371:             float_raise(float_flag_invalid, c);
                    372:         }
                    373:         len = kfactor;
                    374:     } else {
                    375:         len = ilog + 1 - kfactor;
                    376:         if (len > 17) {
                    377:             len = 17;
                    378:         }
                    379:         if (len < 1) {
                    380:             len = 1;
                    381:         }
                    382:         if (kfactor > ilog) {
                    383:             ilog = kfactor;
                    384:         }
                    385:     }
                    386: #ifdef SOFTFLOAT_DECIMAL_DEBUG
                    387:     printf("ILOG = %i, LEN = %i\n", ilog, len);
                    388: #endif
                    389: 
                    390:     lambda = 0;
                    391:     iscale = ilog + 1 - len;
                    392:     
                    393:     if (iscale < 0) {
                    394:         lambda = 1;
                    395:         iscale = -iscale;
                    396:     }
                    397: #ifdef SOFTFLOAT_DECIMAL_DEBUG
                    398:     printf("ISCALE = %i, LAMBDA = %i\n",iscale,lambda);
                    399: #endif
                    400:     
                    401:     tentoint128(lambda, 0, &xExp, &xSig0, &xSig1, iscale, c);
                    402:     
                    403:     zExp = aExp;
                    404:     zSig0 = aSig;
                    405:     zSig1 = 0;
                    406:     
                    407:     if (lambda) {
                    408:         mul128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    409:     } else {
                    410:         div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    411:     }
                    412: #ifdef SOFTFLOAT_DECIMAL_DEBUG
                    413:     printf("BEFORE: zExp = %04x, zSig0 = %16llx, zSig1 = %16llx\n",zExp,zSig0,zSig1);
                    414: #endif
                    415:     
                    416:     decSig = float128toint64(aSign, zExp, zSig0, zSig1, c);
                    417: 
                    418: #ifdef SOFTFLOAT_DECIMAL_DEBUG
                    419:     printf("AFTER: decSig = %llu\n",decSig);
                    420: #endif
                    421:     
                    422:     if (ictr == 0) {
                    423: 
                    424:         decX = tentointdec(len - 1);
                    425:         
                    426:         if (decSig < decX) { // z < x
                    427:             ilog -= 1;
                    428:             ictr = 1;
                    429:             goto try_again;
                    430:         }
                    431:         
                    432:         decX *= 10;
                    433:         
                    434:         if (decSig > decX) { // z > x
                    435:             ilog += 1;
                    436:             ictr = 1;
                    437:             goto try_again;
                    438:         }
                    439:     }
                    440:     
                    441:     decSign = aSign;
                    442:     decExp = (ilog < 0) ? -ilog : ilog;
                    443:     if (decExp > 999) {
                    444:         float_raise(float_flag_invalid, c);
                    445:     }
                    446:     if (ilog < 0) decExp |= 0x4000;
                    447:     
                    448:     *k = len;
                    449:     
                    450:     return packFloatx80(decSign, decExp, decSig);
                    451: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.