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

unix.superglobalmegacorp.com

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