mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-03-09 11:09:32 +01:00
Extract conversion code to strtod.h [ci skip]
This commit is contained in:
parent
30ea2a32d1
commit
359ebc78c0
75
include/rapidjson/internal/strtod.h
Normal file
75
include/rapidjson/internal/strtod.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2011 Milo Yip
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef RAPIDJSON_STRTOD_
|
||||
#define RAPIDJSON_STRTOD_
|
||||
|
||||
#include "pow10.h"
|
||||
|
||||
namespace rapidjson {
|
||||
namespace internal {
|
||||
|
||||
inline double StrtodFastPath(double significand, int exp) {
|
||||
if (exp < -308)
|
||||
return 0.0;
|
||||
else if (exp >= 0)
|
||||
return significand * internal::Pow10(exp);
|
||||
else
|
||||
return significand / internal::Pow10(-exp);
|
||||
}
|
||||
|
||||
inline double NormalPrecision(double d, int p) {
|
||||
if (p < -308) {
|
||||
// Prevent expSum < -308, making Pow10(p) = 0
|
||||
d = StrtodFastPath(d, -308);
|
||||
d = StrtodFastPath(d, p + 308);
|
||||
}
|
||||
else
|
||||
d = StrtodFastPath(d, p);
|
||||
return d;
|
||||
}
|
||||
|
||||
inline double FullPrecision(bool useStrtod, double d, int p, const char* str) {
|
||||
// Use fast path for string-to-double conversion if possible
|
||||
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||
if (!useStrtod && p > 22) {
|
||||
if (p < 22 + 16) {
|
||||
// Fast Path Cases In Disguise
|
||||
d *= internal::Pow10(p - 22);
|
||||
p = 22;
|
||||
}
|
||||
else
|
||||
useStrtod = true;
|
||||
}
|
||||
|
||||
if (!useStrtod && p >= -22 && d <= 9007199254740991.0) // 2^53 - 1
|
||||
d = StrtodFastPath(d, p);
|
||||
else {
|
||||
printf("s=%s p=%d\n", str, p);
|
||||
double guess = NormalPrecision(d, p);
|
||||
d = guess;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_STRTOD_
|
@ -26,11 +26,8 @@
|
||||
#include "rapidjson.h"
|
||||
#include "encodings.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/pow10.h"
|
||||
#include "internal/stack.h"
|
||||
|
||||
#include <cstdlib> // strtod()
|
||||
#include <cmath> // HUGE_VAL
|
||||
#include "internal/strtod.h"
|
||||
|
||||
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
@ -763,26 +760,6 @@ private:
|
||||
StackStream<char> stackStream;
|
||||
};
|
||||
|
||||
static double StrtodFastPath(double significand, int exp) {
|
||||
if (exp < -308)
|
||||
return 0.0;
|
||||
else if (exp >= 0)
|
||||
return significand * internal::Pow10(exp);
|
||||
else
|
||||
return significand / internal::Pow10(-exp);
|
||||
}
|
||||
|
||||
static double NormalPrecision(double d, int p, int exp, int expFrac) {
|
||||
if (p < -308) {
|
||||
// Prevent expSum < -308, making Pow10(p) = 0
|
||||
d = StrtodFastPath(d, exp);
|
||||
d = StrtodFastPath(d, expFrac);
|
||||
}
|
||||
else
|
||||
d = StrtodFastPath(d, p);
|
||||
return d;
|
||||
}
|
||||
|
||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||
void ParseNumber(InputStream& is, Handler& handler) {
|
||||
internal::StreamLocalCopy<InputStream> copy(is);
|
||||
@ -886,7 +863,7 @@ private:
|
||||
if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) { // 2^53 - 1 for fast path
|
||||
if (parseFlags & kParseFullPrecisionFlag) {
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
s.TakeAndPush();
|
||||
s.TakePush();
|
||||
--expFrac;
|
||||
}
|
||||
useStrtod = true;
|
||||
@ -894,7 +871,7 @@ private:
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i64 = i64 * 10 + static_cast<unsigned>(s.TakeAndPush() - '0');
|
||||
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
|
||||
--expFrac;
|
||||
}
|
||||
}
|
||||
@ -963,30 +940,11 @@ private:
|
||||
|
||||
if (useDouble) {
|
||||
int p = exp + expFrac;
|
||||
if (parseFlags & kParseFullPrecisionFlag) {
|
||||
// Use fast path for string-to-double conversion if possible
|
||||
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||
if (!useStrtod && p > 22) {
|
||||
if (p < 22 + 16) {
|
||||
// Fast Path Cases In Disguise
|
||||
d *= internal::Pow10(p - 22);
|
||||
p = 22;
|
||||
}
|
||||
else
|
||||
useStrtod = true;
|
||||
}
|
||||
if (parseFlags & kParseFullPrecisionFlag)
|
||||
d = internal::FullPrecision(useStrtod, d, p, str);
|
||||
else
|
||||
d = internal::NormalPrecision(d, p);
|
||||
|
||||
if (!useStrtod && p >= -22 && d <= 9007199254740991.0) // 2^53 - 1
|
||||
d = StrtodFastPath(d, p);
|
||||
else {
|
||||
printf("s=%s p=%d\n", str, p);
|
||||
double guess = NormalPrecision(d, p, exp, expFrac);
|
||||
d = guess;
|
||||
}
|
||||
}
|
||||
else {
|
||||
d = NormalPrecision(d, p, exp, expFrac);
|
||||
}
|
||||
cont = handler.Double(minus ? -d : d);
|
||||
}
|
||||
else {
|
||||
|
@ -262,7 +262,7 @@ static void TestParseDouble() {
|
||||
TEST_DOUBLE(fullPrecision, n1e308, 1E308);
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
// Random test for double
|
||||
{
|
||||
union {
|
||||
|
Loading…
x
Reference in New Issue
Block a user