Limit significand to 17 digits for fast path
Should fix gcc debug error in tranvis. May need further refactoring.
This commit is contained in:
parent
bea4fa7f6a
commit
b29acfb90d
@ -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
|
|||||||
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:
|
|||||||
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:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
|
|
||||||
// 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:
|
|||||||
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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
d = d * 10.0 + (s.TakePush() - '0');
|
if (significandDigit < 17) {
|
||||||
--expFrac;
|
d = d * 10.0 + (s.TakePush() - '0');
|
||||||
|
--expFrac;
|
||||||
|
if (d != 0.0)
|
||||||
|
significandDigit++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s.TakePush();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expFrac == 0)
|
|
||||||
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:
|
|||||||
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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user