From 37d820a13e66e57a6ebb9444593485614ed5e982 Mon Sep 17 00:00:00 2001 From: miloyip Date: Wed, 15 Apr 2015 10:58:49 +0800 Subject: [PATCH] Remove unused code paths in double conversions --- include/rapidjson/internal/diyfp.h | 22 +++--------------- include/rapidjson/internal/dtoa.h | 19 +++++----------- include/rapidjson/internal/ieee754.h | 8 ------- include/rapidjson/internal/strtod.h | 34 ++++++++++++---------------- 4 files changed, 23 insertions(+), 60 deletions(-) diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index 0b098af..de3d1f0 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -135,25 +135,9 @@ struct DiyFp { double d; uint64_t u64; }u; - uint64_t significand = f; - int exponent = e; - while (significand > kDpHiddenBit + kDpSignificandMask) { - significand >>= 1; - exponent++; - } - while (exponent > kDpDenormalExponent && (significand & kDpHiddenBit) == 0) { - significand <<= 1; - exponent--; - } - if (exponent >= kDpMaxExponent) { - u.u64 = kDpExponentMask; // Infinity - return u.d; - } - else if (exponent < kDpDenormalExponent) - return 0.0; - const uint64_t be = (exponent == kDpDenormalExponent && (significand & kDpHiddenBit) == 0) ? 0 : - static_cast(exponent + kDpExponentBias); - u.u64 = (significand & kDpSignificandMask) | (be << kDpSignificandSize); + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); return u.d; } diff --git a/include/rapidjson/internal/dtoa.h b/include/rapidjson/internal/dtoa.h index aec6bcd..55dae8a 100644 --- a/include/rapidjson/internal/dtoa.h +++ b/include/rapidjson/internal/dtoa.h @@ -50,8 +50,10 @@ inline unsigned CountDecimalDigit32(uint32_t n) { if (n < 1000000) return 6; if (n < 10000000) return 7; if (n < 100000000) return 8; - if (n < 1000000000) return 9; - return 10; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; } inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { @@ -60,13 +62,12 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff const DiyFp wp_w = Mp - W; uint32_t p1 = static_cast(Mp.f >> -one.e); uint64_t p2 = Mp.f & (one.f - 1); - int kappa = CountDecimalDigit32(p1); + int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] *len = 0; while (kappa > 0) { - uint32_t d; + uint32_t d = 0; switch (kappa) { - case 10: d = p1 / 1000000000; p1 %= 1000000000; break; case 9: d = p1 / 100000000; p1 %= 100000000; break; case 8: d = p1 / 10000000; p1 %= 10000000; break; case 7: d = p1 / 1000000; p1 %= 1000000; break; @@ -76,14 +77,6 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff case 3: d = p1 / 100; p1 %= 100; break; case 2: d = p1 / 10; p1 %= 10; break; case 1: d = p1; p1 = 0; break; - default: -#if defined(_MSC_VER) - __assume(0); -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) - __builtin_unreachable(); -#else - d = 0; -#endif } if (d || *len) buffer[(*len)++] = static_cast('0' + static_cast(d)); diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index 152be8f..9a82880 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -34,14 +34,6 @@ public: return Double(u + 1).Value(); } - double PreviousPositiveDouble() const { - RAPIDJSON_ASSERT(!Sign()); - if (IsZero()) - return 0.0; - else - return Double(u - 1).Value(); - } - bool Sign() const { return (u & kSignMask) != 0; } uint64_t Significand() const { return u & kSignificandMask; } int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; } diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h index 980b2c5..6644f37 100644 --- a/include/rapidjson/internal/strtod.h +++ b/include/rapidjson/internal/strtod.h @@ -52,7 +52,7 @@ inline T Min3(T a, T b, T c) { return m; } -inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adjustToNegative) { +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { const Double db(b); const uint64_t bInt = db.IntegerSignificand(); const int bExp = db.IntegerExponent(); @@ -104,12 +104,12 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adj hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; BigInteger delta(0); - *adjustToNegative = dS.Difference(bS, &delta); + bool adjustToNegative = dS.Difference(bS, &delta); int cmp = delta.Compare(hS); // If delta is within 1/2 ULP, check for special case when significand is power of two. // In this case, need to compare with 1/2h in the lower bound. - if (cmp < 0 && *adjustToNegative && // within and dS < bS + if (cmp < 0 && adjustToNegative && // within and dS < bS db.IsNormal() && (bInt & (bInt - 1)) == 0 && // Power of 2 db.Uint64Value() != RAPIDJSON_UINT64_C2(0x00100000, 0x00000000)) // minimum normal number must not do this { @@ -213,24 +213,18 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt const BigInteger dInt(decimals, length); const int dExp = (int)decimalPosition - (int)length + exp; Double a(approx); - for (int i = 0; i < 10; i++) { - bool adjustToNegative; - int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative); - if (cmp < 0) - return a.Value(); // within half ULP - else if (cmp == 0) { - // Round towards even - if (a.Significand() & 1) - return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble(); - else - return a.Value(); - } - else // adjustment - a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble(); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); } - - // This should not happen, but in case there is really a bug, break the infinite-loop - return a.Value(); + else // adjustment + return a.NextPositiveDouble(); } inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {