Commit b29acfb9 authored by miloyip's avatar miloyip

Limit significand to 17 digits for fast path

Should fix gcc debug error in tranvis. May need further refactoring.
parent bea4fa7f
...@@ -447,12 +447,11 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adj ...@@ -447,12 +447,11 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adj
return cmp; return cmp;
} }
inline double FullPrecision(double d, int dExp, const char* decimals, size_t length) { inline double FullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
RAPIDJSON_ASSERT(d >= 0.0); RAPIDJSON_ASSERT(d >= 0.0);
// Use fast path for string-to-double conversion if possible // Use fast path for string-to-double conversion if possible
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
int p = dExp;
if (p > 22) { if (p > 22) {
if (p < 22 + 16) { if (p < 22 + 16) {
// Fast Path Cases In Disguise // Fast Path Cases In Disguise
...@@ -468,6 +467,7 @@ inline double FullPrecision(double d, int dExp, const char* decimals, size_t len ...@@ -468,6 +467,7 @@ inline double FullPrecision(double d, int dExp, const char* decimals, size_t len
return 0.0; return 0.0;
const BigInteger dInt(decimals, length); const BigInteger dInt(decimals, length);
const int dExp = (int)decimalPosition - (int)length + exp;
Double approx = NormalPrecision(d, p); Double approx = NormalPrecision(d, p);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
bool adjustToNegative; bool adjustToNegative;
......
...@@ -779,6 +779,7 @@ private: ...@@ -779,6 +779,7 @@ private:
unsigned i = 0; unsigned i = 0;
uint64_t i64 = 0; uint64_t i64 = 0;
bool use64bit = false; bool use64bit = false;
int significandDigit = 0;
if (s.Peek() == '0') { if (s.Peek() == '0') {
i = 0; i = 0;
s.TakePush(); s.TakePush();
...@@ -796,6 +797,7 @@ private: ...@@ -796,6 +797,7 @@ private:
} }
} }
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
} }
else else
while (s.Peek() >= '0' && s.Peek() <= '9') { while (s.Peek() >= '0' && s.Peek() <= '9') {
...@@ -807,6 +809,7 @@ private: ...@@ -807,6 +809,7 @@ private:
} }
} }
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
} }
} }
else else
...@@ -825,6 +828,7 @@ private: ...@@ -825,6 +828,7 @@ private:
break; break;
} }
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
} }
else else
while (s.Peek() >= '0' && s.Peek() <= '9') { while (s.Peek() >= '0' && s.Peek() <= '9') {
...@@ -835,6 +839,7 @@ private: ...@@ -835,6 +839,7 @@ private:
break; break;
} }
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
} }
} }
...@@ -849,8 +854,13 @@ private: ...@@ -849,8 +854,13 @@ private:
// Parse frac = decimal-point 1*DIGIT // Parse frac = decimal-point 1*DIGIT
int expFrac = 0; int expFrac = 0;
size_t decimalPosition;
if (s.Peek() == '.') { if (s.Peek() == '.') {
s.Take(); s.Take();
decimalPosition = s.Length();
if (!(s.Peek() >= '0' && s.Peek() <= '9'))
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
if (!useDouble) { if (!useDouble) {
#if RAPIDJSON_64BIT #if RAPIDJSON_64BIT
...@@ -864,6 +874,8 @@ private: ...@@ -864,6 +874,8 @@ private:
else { else {
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
--expFrac; --expFrac;
if (i64 != 0)
significandDigit++;
} }
} }
...@@ -876,13 +888,18 @@ private: ...@@ -876,13 +888,18 @@ private:
} }
while (s.Peek() >= '0' && s.Peek() <= '9') { while (s.Peek() >= '0' && s.Peek() <= '9') {
if (significandDigit < 17) {
d = d * 10.0 + (s.TakePush() - '0'); d = d * 10.0 + (s.TakePush() - '0');
--expFrac; --expFrac;
if (d != 0.0)
significandDigit++;
} }
else
if (expFrac == 0) s.TakePush();
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
} }
}
else
decimalPosition = s.Length(); // decimal position at the end of integer.
// Parse exp = e [ minus / plus ] 1*DIGIT // Parse exp = e [ minus / plus ] 1*DIGIT
int exp = 0; int exp = 0;
...@@ -924,7 +941,7 @@ private: ...@@ -924,7 +941,7 @@ private:
if (useDouble) { if (useDouble) {
int p = exp + expFrac; int p = exp + expFrac;
if (parseFlags & kParseFullPrecisionFlag) if (parseFlags & kParseFullPrecisionFlag)
d = internal::FullPrecision(d, p, decimal, length); d = internal::FullPrecision(d, p, decimal, length, decimalPosition, exp);
else else
d = internal::NormalPrecision(d, p); d = internal::NormalPrecision(d, p);
......
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