Commit 37d820a1 authored by miloyip's avatar miloyip

Remove unused code paths in double conversions

parent 5b89f331
...@@ -135,25 +135,9 @@ struct DiyFp { ...@@ -135,25 +135,9 @@ struct DiyFp {
double d; double d;
uint64_t u64; uint64_t u64;
}u; }u;
uint64_t significand = f; const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
int exponent = e; static_cast<uint64_t>(e + kDpExponentBias);
while (significand > kDpHiddenBit + kDpSignificandMask) { u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
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<uint64_t>(exponent + kDpExponentBias);
u.u64 = (significand & kDpSignificandMask) | (be << kDpSignificandSize);
return u.d; return u.d;
} }
......
...@@ -50,8 +50,10 @@ inline unsigned CountDecimalDigit32(uint32_t n) { ...@@ -50,8 +50,10 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
if (n < 1000000) return 6; if (n < 1000000) return 6;
if (n < 10000000) return 7; if (n < 10000000) return 7;
if (n < 100000000) return 8; if (n < 100000000) return 8;
if (n < 1000000000) return 9; // Will not reach 10 digits in DigitGen()
return 10; //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) { 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 ...@@ -60,13 +62,12 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
const DiyFp wp_w = Mp - W; const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1); uint64_t p2 = Mp.f & (one.f - 1);
int kappa = CountDecimalDigit32(p1); int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0; *len = 0;
while (kappa > 0) { while (kappa > 0) {
uint32_t d; uint32_t d = 0;
switch (kappa) { switch (kappa) {
case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
case 9: d = p1 / 100000000; p1 %= 100000000; break; case 9: d = p1 / 100000000; p1 %= 100000000; break;
case 8: d = p1 / 10000000; p1 %= 10000000; break; case 8: d = p1 / 10000000; p1 %= 10000000; break;
case 7: d = p1 / 1000000; p1 %= 1000000; 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 ...@@ -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 3: d = p1 / 100; p1 %= 100; break;
case 2: d = p1 / 10; p1 %= 10; break; case 2: d = p1 / 10; p1 %= 10; break;
case 1: d = p1; p1 = 0; 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) if (d || *len)
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d)); buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
......
...@@ -34,14 +34,6 @@ public: ...@@ -34,14 +34,6 @@ public:
return Double(u + 1).Value(); 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; } bool Sign() const { return (u & kSignMask) != 0; }
uint64_t Significand() const { return u & kSignificandMask; } uint64_t Significand() const { return u & kSignificandMask; }
int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; } int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
......
...@@ -52,7 +52,7 @@ inline T Min3(T a, T b, T c) { ...@@ -52,7 +52,7 @@ inline T Min3(T a, T b, T c) {
return m; 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 Double db(b);
const uint64_t bInt = db.IntegerSignificand(); const uint64_t bInt = db.IntegerSignificand();
const int bExp = db.IntegerExponent(); const int bExp = db.IntegerExponent();
...@@ -104,12 +104,12 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adj ...@@ -104,12 +104,12 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adj
hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
BigInteger delta(0); BigInteger delta(0);
*adjustToNegative = dS.Difference(bS, &delta); bool adjustToNegative = dS.Difference(bS, &delta);
int cmp = delta.Compare(hS); int cmp = delta.Compare(hS);
// If delta is within 1/2 ULP, check for special case when significand is power of two. // 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. // 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.IsNormal() && (bInt & (bInt - 1)) == 0 && // Power of 2
db.Uint64Value() != RAPIDJSON_UINT64_C2(0x00100000, 0x00000000)) // minimum normal number must not do this 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 ...@@ -213,24 +213,18 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt
const BigInteger dInt(decimals, length); const BigInteger dInt(decimals, length);
const int dExp = (int)decimalPosition - (int)length + exp; const int dExp = (int)decimalPosition - (int)length + exp;
Double a(approx); Double a(approx);
for (int i = 0; i < 10; i++) { int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
bool adjustToNegative; if (cmp < 0)
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative); return a.Value(); // within half ULP
if (cmp < 0) else if (cmp == 0) {
return a.Value(); // within half ULP // Round towards even
else if (cmp == 0) { if (a.Significand() & 1)
// Round towards even return a.NextPositiveDouble();
if (a.Significand() & 1) else
return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble(); return a.Value();
else
return a.Value();
}
else // adjustment
a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
} }
else // adjustment
// This should not happen, but in case there is really a bug, break the infinite-loop return a.NextPositiveDouble();
return a.Value();
} }
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment