diff options
Diffstat (limited to 'generic/tclStrToD.c')
| -rw-r--r-- | generic/tclStrToD.c | 544 |
1 files changed, 355 insertions, 189 deletions
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index e0c9f15..7ef1c8c 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -303,7 +303,7 @@ static double MakeNaN(int signum, Tcl_WideUInt tag); #endif static double RefineApproximation(double approx, mp_int *exactSignificand, int exponent); -static void MulPow5(mp_int *, unsigned, mp_int *); +static mp_err MulPow5(mp_int *, unsigned, mp_int *) MP_WUR; static int NormalizeRightward(Tcl_WideUInt *); static int RequiredPrecision(Tcl_WideUInt); static void DoubleToExpAndSig(double, Tcl_WideUInt *, int *, @@ -533,6 +533,7 @@ TclParseNumber( char d = 0; /* Last hexadecimal digit scanned; initialized * to avoid a compiler warning. */ int shift = 0; /* Amount to shift when accumulating binary */ + mp_err err = MP_OKAY; #define ALL_BITS ((Tcl_WideUInt)-1) #define MOST_BITS (ALL_BITS >> 1) @@ -711,7 +712,7 @@ TclParseNumber( || (octalSignificandWide > ((Tcl_WideUInt)-1 >> shift)))) { octalSignificandOverflow = 1; - mp_init_u64(&octalSignificandBig, + err = mp_init_u64(&octalSignificandBig, octalSignificandWide); } } @@ -719,10 +720,17 @@ TclParseNumber( octalSignificandWide = (octalSignificandWide << shift) + (c - '0'); } else { - mp_mul_2d(&octalSignificandBig, shift, - &octalSignificandBig); - mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'), - &octalSignificandBig); + if (err == MP_OKAY) { + err = mp_mul_2d(&octalSignificandBig, shift, + &octalSignificandBig); + } + if (err == MP_OKAY) { + err = mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'), + &octalSignificandBig); + } + } + if (err != MP_OKAY) { + return TCL_ERROR; } } if (numSigDigs != 0) { @@ -776,17 +784,22 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - mp_init_u64(&significandBig, + err = mp_init_u64(&significandBig, significandWide); } } if (!significandOverflow) { significandWide = (significandWide << shift) + d; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); - mp_add_d(&significandBig, (mp_digit) d, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); + if (err == MP_OKAY) { + err = mp_add_d(&significandBig, (mp_digit) d, &significandBig); + } } } + if (err != MP_OKAY) { + return TCL_ERROR; + } numTrailZeros = 0; state = HEXADECIMAL; break; @@ -818,17 +831,22 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - mp_init_u64(&significandBig, + err = mp_init_u64(&significandBig, significandWide); } } if (!significandOverflow) { significandWide = (significandWide << shift) + 1; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); - mp_add_d(&significandBig, (mp_digit) 1, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); + if (err == MP_OKAY) { + err = mp_add_d(&significandBig, (mp_digit) 1, &significandBig); + } } } + if (err != MP_OKAY) { + return TCL_ERROR; + } numTrailZeros = 0; state = BINARY; break; @@ -1160,15 +1178,18 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - mp_init_u64(&significandBig, significandWide); + err = mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { significandWide <<= shift; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); } } + if (err != MP_OKAY) { + return TCL_ERROR; + } goto returnInteger; case HEXADECIMAL: @@ -1181,15 +1202,18 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - mp_init_u64(&significandBig, significandWide); + err = mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { significandWide <<= shift; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); } } + if (err != MP_OKAY) { + return TCL_ERROR; + } goto returnInteger; case OCTAL: @@ -1202,20 +1226,20 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || octalSignificandWide > (MOST_BITS + signum) >> shift)) { octalSignificandOverflow = 1; - mp_init_u64(&octalSignificandBig, + err = mp_init_u64(&octalSignificandBig, octalSignificandWide); } if (shift) { if (!octalSignificandOverflow) { octalSignificandWide <<= shift; - } else { - mp_mul_2d(&octalSignificandBig, shift, + } else if (err == MP_OKAY) { + err = mp_mul_2d(&octalSignificandBig, shift, &octalSignificandBig); } } if (!octalSignificandOverflow) { - if (octalSignificandWide > (MOST_BITS + signum)) { - mp_init_u64(&octalSignificandBig, + if ((err == MP_OKAY) && (octalSignificandWide > (MOST_BITS + signum))) { + err = mp_init_u64(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; } else { @@ -1229,26 +1253,29 @@ TclParseNumber( } } } - if (octalSignificandOverflow) { + if ((err == MP_OKAY) && octalSignificandOverflow) { if (signum) { - (void)mp_neg(&octalSignificandBig, &octalSignificandBig); + err = mp_neg(&octalSignificandBig, &octalSignificandBig); } TclSetBignumIntRep(objPtr, &octalSignificandBig); } + if (err != MP_OKAY) { + return TCL_ERROR; + } break; case ZERO: case DECIMAL: significandOverflow = AccumulateDecimalDigit(0, numTrailZeros-1, &significandWide, &significandBig, significandOverflow); - if (!significandOverflow && (significandWide > MOST_BITS+signum)) { + if ((err == MP_OKAY) && !significandOverflow && (significandWide > MOST_BITS+signum)) { significandOverflow = 1; - mp_init_u64(&significandBig, significandWide); + err = mp_init_u64(&significandBig, significandWide); } returnInteger: if (!significandOverflow) { - if (significandWide > MOST_BITS+signum) { - mp_init_u64(&significandBig, + if ((err == MP_OKAY) && (significandWide > MOST_BITS+signum)) { + err = mp_init_u64(&significandBig, significandWide); significandOverflow = 1; } else { @@ -1262,12 +1289,15 @@ TclParseNumber( } } } - if (significandOverflow) { + if ((err == MP_OKAY) && significandOverflow) { if (signum) { - (void)mp_neg(&significandBig, &significandBig); + err = mp_neg(&significandBig, &significandBig); } TclSetBignumIntRep(objPtr, &significandBig); } + if (err != MP_OKAY) { + return TCL_ERROR; + } break; case FRACTION: @@ -1429,7 +1459,9 @@ AccumulateDecimalDigit( * bignum and fall through into the bignum case. */ - mp_init_u64(bignumRepPtr, w); + if (mp_init_u64(bignumRepPtr, w) != MP_OKAY) { + return 0; + } } else { /* * Wide multiplication. @@ -1449,10 +1481,12 @@ AccumulateDecimalDigit( * Up to about 8 zeros - single digit multiplication. */ - mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1], - bignumRepPtr); - mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr); + if ((mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1], + bignumRepPtr) != MP_OKAY) + || (mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr) != MP_OKAY)) + return 0; } else { + mp_err err; /* * More than single digit multiplication. Multiply by the appropriate * small powers of 5, and then shift. Large strings of zeroes are @@ -1463,18 +1497,21 @@ AccumulateDecimalDigit( */ n = numZeros + 1; - mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr); - for (i=3; i<=7; ++i) { + err = mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr); + for (i = 3; (err == MP_OKAY) && (i <= 7); ++i) { if (n & (1 << i)) { - mp_mul(bignumRepPtr, pow5+i, bignumRepPtr); + err = mp_mul(bignumRepPtr, pow5+i, bignumRepPtr); } } - while (n >= 256) { - mp_mul(bignumRepPtr, pow5+8, bignumRepPtr); + while ((err == MP_OKAY) && (n >= 256)) { + err = mp_mul(bignumRepPtr, pow5+8, bignumRepPtr); n -= 256; } - mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr); - mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr); + if ((err != MP_OKAY) + || (mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr) != MP_OKAY) + || (mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr) != MP_OKAY)) { + return 0; + } } return 1; @@ -1575,7 +1612,9 @@ MakeLowPrecisionDouble( * call MakeHighPrecisionDouble to do it the hard way. */ - mp_init_u64(&significandBig, significand); + if (mp_init_u64(&significandBig, significand) != MP_OKAY) { + return 0.0; + } retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs, exponent); mp_clear(&significandBig); @@ -1624,7 +1663,7 @@ MakeHighPrecisionDouble( long exponent) /* Power of 10 by which to multiply */ { double retval; - int machexp; /* Machine exponent of a power of 10. */ + int machexp = 0; /* Machine exponent of a power of 10. */ /* * With gcc on x86, the floating point rounding mode is double-extended. @@ -1789,6 +1828,7 @@ RefineApproximation( Tcl_WideInt rteSigWide; /* Wide integer version of the significand * for testing evenness */ int i; + mp_err err = MP_OKAY; /* * The first approximation is always low. If we find that it's HUGE_VAL, @@ -1837,7 +1877,9 @@ RefineApproximation( msb = binExponent + M2; /* 1008 */ nDigits = msb / MP_DIGIT_BIT + 1; - mp_init_size(&twoMv, nDigits); + if (mp_init_size(&twoMv, nDigits) != MP_OKAY) { + return approxResult; + } i = (msb % MP_DIGIT_BIT + 1); twoMv.used = nDigits; significand *= SafeLdExp(1.0, i); @@ -1847,8 +1889,9 @@ RefineApproximation( significand = SafeLdExp(significand, MP_DIGIT_BIT); } for (i = 0; i <= 8; ++i) { - if (M5 & (1 << i)) { - mp_mul(&twoMv, pow5+i, &twoMv); + if (M5 & (1 << i) && (mp_mul(&twoMv, pow5+i, &twoMv) != MP_OKAY)) { + mp_clear(&twoMv); + return approxResult; } } @@ -1858,20 +1901,27 @@ RefineApproximation( * by 2**(M5+exponent+1), which is, of couse, a left shift. */ - mp_init_copy(&twoMd, exactSignificand); - for (i=0; i<=8; ++i) { + if (mp_init_copy(&twoMd, exactSignificand) != MP_OKAY) { + mp_clear(&twoMv); + return approxResult; + } + for (i = 0; (i <= 8); ++i) { if ((M5 + exponent) & (1 << i)) { - mp_mul(&twoMd, pow5+i, &twoMd); + err = mp_mul(&twoMd, pow5+i, &twoMd); } } - mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); + if (err == MP_OKAY) { + err = mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); + } /* * Now let twoMd = twoMd - twoMv, the difference between the exact and * approximate values. */ - mp_sub(&twoMd, &twoMv, &twoMd); + if (err == MP_OKAY) { + err = mp_sub(&twoMd, &twoMv, &twoMd); + } /* * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction @@ -1882,16 +1932,25 @@ RefineApproximation( scale = binExponent - mantBits - 1; mp_set_u64(&twoMv, 1); - for (i=0; i<=8; ++i) { + for (i = 0; (i <= 8) && (err == MP_OKAY); ++i) { if (M5 & (1 << i)) { - mp_mul(&twoMv, pow5+i, &twoMv); + err = mp_mul(&twoMv, pow5+i, &twoMv); } } multiplier = M2 + scale + 1; - if (multiplier > 0) { - mp_mul_2d(&twoMv, multiplier, &twoMv); + if (err != MP_OKAY) { + mp_clear(&twoMd); + mp_clear(&twoMv); + return approxResult; + } else if (multiplier > 0) { + err = mp_mul_2d(&twoMv, multiplier, &twoMv); } else if (multiplier < 0) { - mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); + err = mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); + } + if (err != MP_OKAY) { + mp_clear(&twoMd); + mp_clear(&twoMv); + return approxResult; } /* @@ -1940,8 +1999,15 @@ RefineApproximation( */ shift = mp_count_bits(&twoMv) - FP_PRECISION - 1; if (shift > 0) { - mp_div_2d(&twoMv, shift, &twoMv, NULL); - mp_div_2d(&twoMd, shift, &twoMd, NULL); + err = mp_div_2d(&twoMv, shift, &twoMv, NULL); + if (err == MP_OKAY) { + err = mp_div_2d(&twoMd, shift, &twoMd, NULL); + } + } + if (err != MP_OKAY) { + mp_clear(&twoMd); + mp_clear(&twoMv); + return approxResult; } /* @@ -1980,7 +2046,7 @@ RefineApproximation( *---------------------------------------------------------------------- */ -static inline void +static inline mp_err MulPow5( mp_int *base, /* Number to multiply. */ unsigned n, /* Power of 5 to multiply by. */ @@ -1989,23 +2055,25 @@ MulPow5( mp_int *p = base; int n13 = n / 13; int r = n % 13; + mp_err err = MP_OKAY; if (r != 0) { - mp_mul_d(p, dpow5[r], result); + err = mp_mul_d(p, dpow5[r], result); p = result; } r = 0; - while (n13 != 0) { + while ((err == MP_OKAY) && (n13 != 0)) { if (n13 & 1) { - mp_mul(p, pow5_13+r, result); + err = mp_mul(p, pow5_13+r, result); p = result; } n13 >>= 1; ++r; } - if (p != result) { - mp_copy(p, result); + if ((err == MP_OKAY) && (p != result)) { + err = mp_copy(p, result); } + return err; } /* @@ -3205,8 +3273,7 @@ ShouldBankerRoundUpToNextPowD( * 2**(MP_DIGIT_BIT*sd) */ - mp_add(b, m, temp); - if (temp->used <= sd) { /* Too few digits to be > s */ + if ((mp_add(b, m, temp) != MP_OKAY) || (temp->used <= sd)) { /* Too few digits to be > s */ return 0; } if (temp->used > sd+1 || temp->dp[sd] > 1) { @@ -3274,23 +3341,31 @@ ShorteningBignumConversionPowD( int i; /* Index in the output buffer. */ mp_int temp; int r1; + mp_err err = MP_OKAY; /* * b = bw * 2**b2 * 5**b5 * mminus = 5**m5 */ - mp_init_u64(&b, bw); - mp_init_set(&mminus, 1); - MulPow5(&b, b5, &b); - mp_mul_2d(&b, b2, &b); + if ((retval == NULL) || (mp_init_u64(&b, bw) != MP_OKAY)) { + return NULL; + } + if (mp_init_set(&mminus, 1) != MP_OKAY) { + mp_clear(&b); + return NULL; + } + err = MulPow5(&b, b5, &b); + if (err == MP_OKAY) { + err = mp_mul_2d(&b, b2, &b); + } /* * Adjust if the logarithm was guessed wrong. */ - if (b.used <= sd) { - mp_mul_d(&b, 10, &b); + if ((err == MP_OKAY) && (b.used <= sd)) { + err = mp_mul_d(&b, 10, &b); ++m2plus; ++m2minus; ++m5; ilim = ilim1; --k; @@ -3301,13 +3376,21 @@ ShorteningBignumConversionPowD( * mplus = 5**m5 * 2**m2plus */ - mp_mul_2d(&mminus, m2minus, &mminus); - MulPow5(&mminus, m5, &mminus); - if (m2plus > m2minus) { - mp_init_copy(&mplus, &mminus); - mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + if (err == MP_OKAY) { + err = mp_mul_2d(&mminus, m2minus, &mminus); + } + if (err == MP_OKAY) { + err = MulPow5(&mminus, m5, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_init_copy(&mplus, &mminus); + if (err == MP_OKAY) { + err = mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + } + } + if (err == MP_OKAY) { + err = mp_init(&temp); } - mp_init(&temp); /* * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT) @@ -3389,10 +3472,14 @@ ShorteningBignumConversionPowD( * Advance to the next digit. */ - mp_mul_d(&b, 10, &b); - mp_mul_d(&mminus, 10, &mminus); - if (m2plus > m2minus) { - mp_mul_2d(&mminus, m2plus-m2minus, &mplus); + if (err == MP_OKAY) { + err = mp_mul_d(&b, 10, &b); + } + if (err == MP_OKAY) { + err = mp_mul_d(&mminus, 10, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_mul_2d(&mminus, m2plus-m2minus, &mplus); } ++i; } @@ -3411,7 +3498,7 @@ ShorteningBignumConversionPowD( if (endPtr) { *endPtr = s; } - return retval; + return (err == MP_OKAY) ? retval : NULL; } /* @@ -3459,21 +3546,26 @@ StrictBignumConversionPowD( mp_digit digit; /* Current output digit. */ char *s = retval; /* Cursor in the output buffer. */ int i; /* Index in the output buffer. */ + mp_err err; /* * b = bw * 2**b2 * 5**b5 */ - mp_init_u64(&b, bw); - MulPow5(&b, b5, &b); - mp_mul_2d(&b, b2, &b); + if (mp_init_u64(&b, bw) != MP_OKAY) { + return NULL; + } + err = MulPow5(&b, b5, &b); + if (err == MP_OKAY) { + err = mp_mul_2d(&b, b2, &b); + } /* * Adjust if the logarithm was guessed wrong. */ - if (b.used <= sd) { - mp_mul_d(&b, 10, &b); + if ((err == MP_OKAY) && (b.used <= sd)) { + err = mp_mul_d(&b, 10, &b); ilim = ilim1; --k; } @@ -3484,7 +3576,7 @@ StrictBignumConversionPowD( */ i = 1; - for (;;) { + while (err == MP_OKAY) { if (b.used <= sd) { digit = 0; } else { @@ -3516,7 +3608,7 @@ StrictBignumConversionPowD( * Advance to the next digit. */ - mp_mul_d(&b, 10, &b); + err = mp_mul_d(&b, 10, &b); ++i; } @@ -3598,8 +3690,9 @@ ShouldBankerRoundUpToNext( * Compare b and S-m: this is the same as comparing B+m and S. */ - mp_init(&temp); - mp_add(b, m, &temp); + if ((mp_init(&temp) != MP_OKAY) || (mp_add(b, m, &temp) != MP_OKAY)) { + return 0; + } r = mp_cmp_mag(&temp, S); mp_clear(&temp); switch(r) { @@ -3658,23 +3751,33 @@ ShorteningBignumConversion( int minit = 1; /* Fudge factor for when we misguess k. */ int i; int r1; + mp_err err; /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ - mp_init_u64(&b, bw); - mp_mul_2d(&b, b2, &b); - mp_init_set(&S, 1); - MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); + if ((retval == NULL) || (mp_init_u64(&b, bw) != MP_OKAY)) { + return NULL; + } + err = mp_mul_2d(&b, b2, &b); + if (err == MP_OKAY) { + err = mp_init_set(&S, 1); + } + if (err == MP_OKAY) { + err = MulPow5(&S, s5, &S); + } + if (err == MP_OKAY) { + err = mp_mul_2d(&S, s2, &S); + } /* * Handle the case where we guess the position of the decimal point wrong. */ - if (mp_cmp_mag(&b, &S) == MP_LT) { - mp_mul_d(&b, 10, &b); + if ((err == MP_OKAY) && (mp_cmp_mag(&b, &S) == MP_LT)) { + err = mp_mul_d(&b, 10, &b); minit = 10; ilim =ilim1; --k; @@ -3684,21 +3787,29 @@ ShorteningBignumConversion( * mminus = 2**m2minus * 5**m5 */ - mp_init_set(&mminus, minit); - mp_mul_2d(&mminus, m2minus, &mminus); - if (m2plus > m2minus) { - mp_init_copy(&mplus, &mminus); - mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + if (err == MP_OKAY) { + err = mp_init_set(&mminus, minit); + } + if (err == MP_OKAY) { + err = mp_mul_2d(&mminus, m2minus, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_init_copy(&mplus, &mminus); + if (err == MP_OKAY) { + err = mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + } } /* * Loop through the digits. */ - mp_init(&dig); + if (err == MP_OKAY) { + err = mp_init(&dig); + } i = 1; - for (;;) { - mp_div(&b, &S, &dig, &b); + while (err == MP_OKAY) { + err = mp_div(&b, &S, &dig, &b); if (dig.used > 1 || dig.dp[0] >= 10) { Tcl_Panic("wrong digit!"); } @@ -3711,7 +3822,7 @@ ShorteningBignumConversion( r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus); if (r1 == MP_LT || (r1 == MP_EQ && (dPtr->w.word1 & 1) == 0)) { - mp_mul_2d(&b, 1, &b); + err = mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { ++digit; if (digit == 10) { @@ -3746,8 +3857,8 @@ ShorteningBignumConversion( */ *s++ = '0' + digit; - if (i == ilim) { - mp_mul_2d(&b, 1, &b); + if ((err == MP_OKAY) && (i == ilim)) { + err = mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } @@ -3758,17 +3869,21 @@ ShorteningBignumConversion( * Advance to the next digit. */ - if (s5 > 0) { + if ((err == MP_OKAY) && (s5 > 0)) { /* * Can possibly shorten the denominator. */ - mp_mul_2d(&b, 1, &b); - mp_mul_2d(&mminus, 1, &mminus); - if (m2plus > m2minus) { - mp_mul_2d(&mplus, 1, &mplus); + err = mp_mul_2d(&b, 1, &b); + if (err == MP_OKAY) { + err = mp_mul_2d(&mminus, 1, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_mul_2d(&mplus, 1, &mplus); + } + if (err == MP_OKAY) { + err = mp_div_d(&S, 5, &S, NULL); } - mp_div_d(&S, 5, &S, NULL); --s5; /* @@ -3798,11 +3913,13 @@ ShorteningBignumConversion( * 10**42 16 trips * thereafter no gain. */ - } else { - mp_mul_d(&b, 10, &b); - mp_mul_d(&mminus, 10, &mminus); - if (m2plus > m2minus) { - mp_mul_2d(&mplus, 10, &mplus); + } else if (err == MP_OKAY) { + err = mp_mul_d(&b, 10, &b); + if (err == MP_OKAY) { + err = mp_mul_d(&mminus, 10, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_mul_2d(&mplus, 10, &mplus); } } @@ -3866,24 +3983,36 @@ StrictBignumConversion( int digit; /* Current digit of the result. */ int g; /* Size of the current digit ground. */ int i, j; + mp_err err; /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ - mp_init_multi(&dig, NULL); - mp_init_u64(&b, bw); - mp_mul_2d(&b, b2, &b); - mp_init_set(&S, 1); - MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); + if (mp_init(&dig) != MP_OKAY) { + return NULL; + } + if (mp_init_u64(&b, bw) != MP_OKAY) { + mp_clear(&dig); + return NULL; + } + err = mp_mul_2d(&b, b2, &b); + if (err == MP_OKAY) { + err = mp_init_set(&S, 1); + } + if (err == MP_OKAY) { + err = MulPow5(&S, s5, &S); + if (err == MP_OKAY) { + err = mp_mul_2d(&S, s2, &S); + } + } /* * Handle the case where we guess the position of the decimal point wrong. */ - if (mp_cmp_mag(&b, &S) == MP_LT) { - mp_mul_d(&b, 10, &b); + if ((mp_cmp_mag(&b, &S) == MP_LT) && (mp_mul_d(&b, 10, &b) == MP_OKAY)) { ilim =ilim1; --k; } @@ -3893,7 +4022,7 @@ StrictBignumConversion( */ i = 0; - mp_div(&b, &S, &dig, &b); + err = mp_div(&b, &S, &dig, &b); if (dig.used > 1 || dig.dp[0] >= 10) { Tcl_Panic("wrong digit!"); } @@ -3905,12 +4034,11 @@ StrictBignumConversion( *s++ = '0' + digit; if (++i >= ilim) { - mp_mul_2d(&b, 1, &b); - if (ShouldBankerRoundUp(&b, &S, digit&1)) { + if ((mp_mul_2d(&b, 1, &b) == MP_OKAY) && ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } } else { - for (;;) { + while (err == MP_OKAY) { /* * Shift by a group of digits. */ @@ -3920,16 +4048,20 @@ StrictBignumConversion( g = DIGIT_GROUP; } if (s5 >= g) { - mp_div_d(&S, dpow5[g], &S, NULL); + err = mp_div_d(&S, dpow5[g], &S, NULL); s5 -= g; } else if (s5 > 0) { - mp_div_d(&S, dpow5[s5], &S, NULL); - mp_mul_d(&b, dpow5[g - s5], &b); + err = mp_div_d(&S, dpow5[s5], &S, NULL); + if (err == MP_OKAY) { + err = mp_mul_d(&b, dpow5[g - s5], &b); + } s5 = 0; } else { - mp_mul_d(&b, dpow5[g], &b); + err = mp_mul_d(&b, dpow5[g], &b); + } + if (err == MP_OKAY) { + err = mp_mul_2d(&b, g, &b); } - mp_mul_2d(&b, g, &b); /* * As with the shortening bignum conversion, it's possible at this @@ -3943,8 +4075,8 @@ StrictBignumConversion( * Extract the next group of digits. */ - mp_div(&b, &S, &dig, &b); - if (dig.used > 1) { + + if ((err != MP_OKAY) || (mp_div(&b, &S, &dig, &b) != MP_OKAY) || (dig.used > 1)) { Tcl_Panic("wrong digit!"); } digit = dig.dp[0]; @@ -3961,8 +4093,7 @@ StrictBignumConversion( */ if (i == ilim) { - mp_mul_2d(&b, 1, &b); - if (ShouldBankerRoundUp(&b, &S, digit&1)) { + if ((mp_mul_2d(&b, 1, &b) == MP_OKAY) && ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } break; @@ -4336,6 +4467,7 @@ TclInitDoubleConversion(void) Tcl_WideUInt iv; } bitwhack; #endif + mp_err err = MP_OKAY; #if defined(__sgi) && defined(_COMPILER_VERSION) union fpc_csr mipsCR; @@ -4392,16 +4524,19 @@ TclInitDoubleConversion(void) */ for (i=0; i<9; ++i) { - mp_init(pow5 + i); + err = err || mp_init(pow5 + i); } mp_set_u64(pow5, 5); for (i=0; i<8; ++i) { - mp_sqr(pow5+i, pow5+i+1); + err = err || mp_sqr(pow5+i, pow5+i+1); } - mp_init_u64(pow5_13, 1220703125); + err = err || mp_init_u64(pow5_13, 1220703125); for (i = 1; i < 5; ++i) { - mp_init(pow5_13 + i); - mp_sqr(pow5_13 + i - 1, pow5_13 + i); + err = err || mp_init(pow5_13 + i); + err = err || mp_sqr(pow5_13 + i - 1, pow5_13 + i); + } + if (err != MP_OKAY) { + Tcl_Panic("out of memory"); } /* @@ -4493,6 +4628,7 @@ Tcl_InitBignumFromDouble( { double fract; int expt; + mp_err err; /* * Infinite values can't convert to bignum. @@ -4510,19 +4646,24 @@ Tcl_InitBignumFromDouble( fract = frexp(d, &expt); if (expt <= 0) { - mp_init(b); + err = mp_init(b); mp_zero(b); } else { Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits); int shift = expt - mantBits; - mp_init_i64(b, w); - if (shift < 0) { - mp_div_2d(b, -shift, b, NULL); + err = mp_init_i64(b, w); + if (err != MP_OKAY) { + /* just skip */ + } else if (shift < 0) { + err = mp_div_2d(b, -shift, b, NULL); } else if (shift > 0) { - mp_mul_2d(b, shift, b); + err = mp_mul_2d(b, shift, b); } } + if (err != MP_OKAY) { + return TCL_ERROR; + } return TCL_OK; } @@ -4548,6 +4689,7 @@ TclBignumToDouble( mp_int b; int bits, shift, i, lsb; double r; + mp_err err; /* @@ -4576,11 +4718,13 @@ TclBignumToDouble( * 'rounded to even'. */ - mp_init(&b); - if (shift == 0) { - mp_copy(a, &b); + err = mp_init(&b); + if (err != MP_OKAY) { + /* just skip */ + } else if (shift == 0) { + err = mp_copy(a, &b); } else if (shift > 0) { - mp_mul_2d(a, shift, &b); + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { lsb = mp_cnt_lsb(a); if (lsb == -1-shift) { @@ -4589,12 +4733,12 @@ TclBignumToDouble( * Round to even */ - mp_div_2d(a, -shift, &b, NULL); - if (mp_isodd(&b)) { + err = mp_div_2d(a, -shift, &b, NULL); + if ((err == MP_OKAY) && mp_isodd(&b)) { if (mp_isneg(&b)) { - mp_sub_d(&b, 1, &b); + err = mp_sub_d(&b, 1, &b); } else { - mp_add_d(&b, 1, &b); + err = mp_add_d(&b, 1, &b); } } } else { @@ -4603,13 +4747,15 @@ TclBignumToDouble( * Ordinary rounding */ - mp_div_2d(a, -1-shift, &b, NULL); - if (mp_isneg(&b)) { - mp_sub_d(&b, 1, &b); + err = mp_div_2d(a, -1-shift, &b, NULL); + if (err != MP_OKAY) { + /* just skip */ + } else if (mp_isneg(&b)) { + err = mp_sub_d(&b, 1, &b); } else { - mp_add_d(&b, 1, &b); + err = mp_add_d(&b, 1, &b); } - mp_div_2d(&b, 1, &b, NULL); + err = mp_div_2d(&b, 1, &b, NULL); } } @@ -4617,8 +4763,11 @@ TclBignumToDouble( * Accumulate the result, one mp_digit at a time. */ + if (err != MP_OKAY) { + return 0.0; + } r = 0.0; - for (i=b.used-1 ; i>=0 ; --i) { + for (i = b.used-1; i>=0; --i) { r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; } mp_clear(&b); @@ -4660,10 +4809,11 @@ TclCeil( { double r = 0.0; mp_int b; + mp_err err; - mp_init(&b); - if (mp_isneg(a)) { - mp_neg(a, &b); + err = mp_init(&b); + if ((err == MP_OKAY) && mp_isneg(a)) { + err = mp_neg(a, &b); r = -TclFloor(&b); } else { int bits = mp_count_bits(a); @@ -4673,19 +4823,26 @@ TclCeil( } else { int i, exact = 1, shift = mantBits - bits; - if (shift > 0) { - mp_mul_2d(a, shift, &b); + if (err != MP_OKAY) { + /* just skip */ + } else if (shift > 0) { + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { mp_int d; - mp_init(&d); - mp_div_2d(a, -shift, &b, &d); + err = mp_init(&d); + if (err == MP_OKAY) { + err = mp_div_2d(a, -shift, &b, &d); + } exact = mp_iszero(&d); mp_clear(&d); } else { - mp_copy(a, &b); + err = mp_copy(a, &b); } - if (!exact) { - mp_add_d(&b, 1, &b); + if ((err == MP_OKAY) && !exact) { + err = mp_add_d(&b, 1, &b); + } + if (err != MP_OKAY) { + return 0.0; } for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; @@ -4717,10 +4874,11 @@ TclFloor( { double r = 0.0; mp_int b; + mp_err err; - mp_init(&b); - if (mp_isneg(a)) { - mp_neg(a, &b); + err = mp_init(&b); + if ((err == MP_OKAY) && mp_isneg(a)) { + err = mp_neg(a, &b); r = -TclCeil(&b); } else { int bits = mp_count_bits(a); @@ -4731,11 +4889,14 @@ TclFloor( int i, shift = mantBits - bits; if (shift > 0) { - mp_mul_2d(a, shift, &b); + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { - mp_div_2d(a, -shift, &b, NULL); + err = mp_div_2d(a, -shift, &b, NULL); } else { - mp_copy(a, &b); + err = mp_copy(a, &b); + } + if (err != MP_OKAY) { + return 0.0; } for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; @@ -4777,6 +4938,7 @@ BignumToBiasedFrExp( int shift; int i; double r; + mp_err err = MP_OKAY; /* * Determine how many bits we need, and extract that many from the input. @@ -4785,13 +4947,15 @@ BignumToBiasedFrExp( bits = mp_count_bits(a); shift = mantBits - 2 - bits; - mp_init(&b); + if (mp_init(&b)) { + return 0.0; + } if (shift > 0) { - mp_mul_2d(a, shift, &b); + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { - mp_div_2d(a, -shift, &b, NULL); + err = mp_div_2d(a, -shift, &b, NULL); } else { - mp_copy(a, &b); + err = mp_copy(a, &b); } /* @@ -4799,8 +4963,10 @@ BignumToBiasedFrExp( */ r = 0.0; - for (i=b.used-1; i>=0; --i) { - r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; + if (err == MP_OKAY) { + for (i=b.used-1; i>=0; --i) { + r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; + } } mp_clear(&b); |
