diff options
Diffstat (limited to 'Source/JavaScriptCore/wtf/dtoa.cpp')
-rw-r--r-- | Source/JavaScriptCore/wtf/dtoa.cpp | 534 |
1 files changed, 15 insertions, 519 deletions
diff --git a/Source/JavaScriptCore/wtf/dtoa.cpp b/Source/JavaScriptCore/wtf/dtoa.cpp index 3732fe614..4c4041e1c 100644 --- a/Source/JavaScriptCore/wtf/dtoa.cpp +++ b/Source/JavaScriptCore/wtf/dtoa.cpp @@ -228,25 +228,6 @@ static void multadd(BigInt& b, int m, int a) /* multiply by m and add a */ b.append((uint32_t)carry); } -static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9) -{ - b.sign = 0; - b.resize(1); - b.words()[0] = y9; - - int i = 9; - if (9 < nd0) { - s += 9; - do { - multadd(b, 10, *s++ - '0'); - } while (++i < nd0); - s++; - } else - s += 10; - for (; i < nd; i++) - multadd(b, 10, *s++ - '0'); -} - static int hi0bits(uint32_t x) { int k = 0; @@ -603,57 +584,6 @@ static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef c.resize(wa); } -static double ulp(U *x) -{ - register int32_t L; - U u; - - L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1; - word0(&u) = L; - word1(&u) = 0; - return dval(&u); -} - -static double b2d(const BigInt& a, int* e) -{ - const uint32_t* xa; - const uint32_t* xa0; - uint32_t w; - uint32_t y; - uint32_t z; - int k; - U d; - -#define d0 word0(&d) -#define d1 word1(&d) - - xa0 = a.words(); - xa = xa0 + a.size(); - y = *--xa; - ASSERT(y); - k = hi0bits(y); - *e = 32 - k; - if (k < Ebits) { - d0 = Exp_1 | (y >> (Ebits - k)); - w = xa > xa0 ? *--xa : 0; - d1 = (y << (32 - Ebits + k)) | (w >> (Ebits - k)); - goto returnD; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - d0 = Exp_1 | (y << k) | (z >> (32 - k)); - y = xa > xa0 ? *--xa : 0; - d1 = (z << k) | (y >> (32 - k)); - } else { - d0 = Exp_1 | y; - d1 = z; - } -returnD: -#undef d0 -#undef d1 - return dval(&d); -} - static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) { int de, k; @@ -701,23 +631,6 @@ static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) #undef d0 #undef d1 -static double ratio(const BigInt& a, const BigInt& b) -{ - U da, db; - int k, ka, kb; - - dval(&da) = b2d(a, &ka); - dval(&db) = b2d(b, &kb); - k = ka - kb + 32 * (a.size() - b.size()); - if (k > 0) - word0(&da) += k * Exp_msk1; - else { - k = -k; - word0(&db) += k * Exp_msk1; - } - return dval(&da) / dval(&db); -} - static const double tens[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, @@ -735,443 +648,26 @@ static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, #define Scale_Bit 0x10 #define n_bigtens 5 +template<AllowTrailingJunkTag allowTrailingJunk> double strtod(const char* s00, char** se) { - int scale; - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, - e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - const char *s, *s0, *s1; - double aadj, aadj1; - U aadj2, adj, rv, rv0; - int32_t L; - uint32_t y, z; - BigInt bb, bb1, bd, bd0, bs, delta; - - sign = nz0 = nz = 0; - dval(&rv) = 0; - for (s = s00; ; s++) { - switch (*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } - } -break2: - if (*s == '0') { - nz0 = 1; - while (*++s == '0') { } - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = (10 * y) + c - '0'; - else if (nd < 16) - z = (10 * z) + c - '0'; - nd0 = nd; - if (c == '.') { - c = *++s; - if (!nd) { - for (; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto haveDig; - } - goto digDone; - } - for (; c >= '0' && c <= '9'; c = *++s) { -haveDig: - nz++; - if (c -= '0') { - nf += nz; - for (i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = (10 * y) + c; - else if (nd <= DBL_DIG + 1) - z = (10 * z) + c; - nz = 0; - } - } - } -digDone: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) - goto ret0; - s00 = s; - esign = 0; - switch (c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while (c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while ((c = *++s) >= '0' && c <= '9') - L = (10 * L) + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } else - e = 0; - } else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -ret0: - s = s00; - sign = 0; - } - goto ret; - } - e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(&rv) = y; - if (k > 9) - dval(&rv) = tens[k - 9] * dval(&rv) + z; - if (nd <= DBL_DIG) { - if (!e) - goto ret; - if (e > 0) { - if (e <= Ten_pmax) { - /* rv = */ rounded_product(dval(&rv), tens[e]); - goto ret; - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ - e -= i; - dval(&rv) *= tens[i]; - /* rv = */ rounded_product(dval(&rv), tens[e]); - goto ret; - } - } else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(&rv), tens[-e]); - goto ret; - } - } - e1 += nd - k; - - scale = 0; - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - if ((i = e1 & 15)) - dval(&rv) *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { -ovfl: -#if HAVE(ERRNO_H) - errno = ERANGE; -#endif - /* Can't trust HUGE_VAL */ - word0(&rv) = Exp_mask; - word1(&rv) = 0; - goto ret; - } - e1 >>= 4; - for (j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= bigtens[j]; - /* The last multiplication could overflow. */ - word0(&rv) -= P * Exp_msk1; - dval(&rv) *= bigtens[j]; - if ((z = word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) - goto ovfl; - if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - word0(&rv) = Big0; - word1(&rv) = Big1; - } else - word0(&rv) += P * Exp_msk1; - } - } else if (e1 < 0) { - e1 = -e1; - if ((i = e1 & 15)) - dval(&rv) /= tens[i]; - if (e1 >>= 4) { - if (e1 >= 1 << n_bigtens) - goto undfl; - if (e1 & Scale_Bit) - scale = 2 * P; - for (j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - if (scale && (j = (2 * P) + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { - /* scaled rv is denormal; clear j low bits */ - if (j >= 32) { - word1(&rv) = 0; - if (j >= 53) - word0(&rv) = (P + 2) * Exp_msk1; - else - word0(&rv) &= 0xffffffff << (j - 32); - } else - word1(&rv) &= 0xffffffff << j; - } - if (!dval(&rv)) { -undfl: - dval(&rv) = 0.; -#if HAVE(ERRNO_H) - errno = ERANGE; -#endif - goto ret; - } - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - s2b(bd0, s0, nd0, nd, y); - - for (;;) { - bd = bd0; - d2b(bb, &rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ - i2b(bs, 1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; - j = bbe - scale; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; - bb2 += j; - bd2 += j; - bd2 += scale; - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - pow5mult(bs, bb5); - mult(bb, bs); - } - if (bb2 > 0) - lshift(bb, bb2); - if (bd5 > 0) - pow5mult(bd, bd5); - if (bd2 > 0) - lshift(bd, bd2); - if (bs2 > 0) - lshift(bs, bs2); - diff(delta, bb, bd); - dsign = delta.sign; - delta.sign = 0; - i = cmp(delta, bs); - - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask - || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1 - ) { - break; - } - if (!delta.words()[0] && delta.size() <= 1) { - /* exact result */ - break; - } - lshift(delta, Log2P); - if (cmp(delta, bs) > 0) - goto dropDown; - break; - } - if (!i) { - /* exactly half-way between */ - if (dsign) { - if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 - && word1(&rv) == ( - (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) - ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) : - 0xffffffff)) { - /*boundary case -- increment exponent*/ - word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1; - word1(&rv) = 0; - dsign = 0; - break; - } - } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { -dropDown: - /* boundary case -- decrement exponent */ - if (scale) { - L = word0(&rv) & Exp_mask; - if (L <= (2 * P + 1) * Exp_msk1) { - if (L > (P + 2) * Exp_msk1) - /* round even ==> */ - /* accept rv */ - break; - /* rv = smallest denormal */ - goto undfl; - } - } - L = (word0(&rv) & Exp_mask) - Exp_msk1; - word0(&rv) = L | Bndry_mask1; - word1(&rv) = 0xffffffff; - break; - } - if (!(word1(&rv) & LSB)) - break; - if (dsign) - dval(&rv) += ulp(&rv); - else { - dval(&rv) -= ulp(&rv); - if (!dval(&rv)) - goto undfl; - } - dsign = 1 - dsign; - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (dsign) - aadj = aadj1 = 1.; - else if (word1(&rv) || word0(&rv) & Bndry_mask) { - if (word1(&rv) == Tiny1 && !word0(&rv)) - goto undfl; - aadj = 1.; - aadj1 = -1.; - } else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2. / FLT_RADIX) - aadj = 1. / FLT_RADIX; - else - aadj *= 0.5; - aadj1 = -aadj; - } - } else { - aadj *= 0.5; - aadj1 = dsign ? aadj : -aadj; - } - y = word0(&rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) { - dval(&rv0) = dval(&rv); - word0(&rv) -= P * Exp_msk1; - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; - if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { - if (word0(&rv0) == Big0 && word1(&rv0) == Big1) - goto ovfl; - word0(&rv) = Big0; - word1(&rv) = Big1; - goto cont; - } - word0(&rv) += P * Exp_msk1; - } else { - if (scale && y <= 2 * P * Exp_msk1) { - if (aadj <= 0x7fffffff) { - if ((z = (uint32_t)aadj) <= 0) - z = 1; - aadj = z; - aadj1 = dsign ? aadj : -aadj; - } - dval(&aadj2) = aadj1; - word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y; - aadj1 = dval(&aadj2); - } - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; - } - z = word0(&rv) & Exp_mask; - if (!scale && y == z) { - /* Can we stop now? */ - L = (int32_t)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } else if (aadj < .4999999 / FLT_RADIX) - break; - } -cont: - {} - } - if (scale) { - word0(&rv0) = Exp_1 - 2 * P * Exp_msk1; - word1(&rv0) = 0; - dval(&rv) *= dval(&rv0); -#if HAVE(ERRNO_H) - /* try to avoid the bug of testing an 8087 register value */ - if (!word0(&rv) && !word1(&rv)) - errno = ERANGE; -#endif - } -ret: + int length = strlen(s00); + double_conversion::StringToDoubleConverter converter( + (allowTrailingJunk ? double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK : 0) | + double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES, + 0.0, + (allowTrailingJunk ? std::numeric_limits<double>::quiet_NaN() : 0.0), + "Infinity", "NaN"); + int processedCharacterCount = 0; + double result = converter.StringToDouble(s00, length, &processedCharacterCount); if (se) - *se = const_cast<char*>(s); - return sign ? -dval(&rv) : dval(&rv); + *se = const_cast<char*>(s00 + processedCharacterCount); + return result; } +template double strtod<AllowTrailingJunk>(const char*, char**); +template double strtod<DisallowTrailingJunk>(const char*, char**); + static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S) { size_t n; |