16#ifndef RAPIDJSON_STRTOD_
17#define RAPIDJSON_STRTOD_
20#include "biginteger.h"
29inline double FastPath(
double significand,
int exp) {
33 return significand * internal::Pow10(exp);
35 return significand / internal::Pow10(-exp);
38inline double StrtodNormalPrecision(
double d,
int p) {
41 d = FastPath(d, -308);
42 d = FastPath(d, p + 308);
50inline T Min3(T a, T b, T c) {
57inline int CheckWithinHalfULP(
double b,
const BigInteger& d,
int dExp) {
59 const uint64_t bInt = db.IntegerSignificand();
60 const int bExp = db.IntegerExponent();
61 const int hExp = bExp - 1;
63 int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
94 int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
95 dS_Exp2 -= common_Exp2;
96 bS_Exp2 -= common_Exp2;
97 hS_Exp2 -= common_Exp2;
100 dS.MultiplyPow5(
static_cast<unsigned>(dS_Exp5)) <<=
static_cast<unsigned>(dS_Exp2);
103 bS.MultiplyPow5(
static_cast<unsigned>(bS_Exp5)) <<=
static_cast<unsigned>(bS_Exp2);
106 hS.MultiplyPow5(
static_cast<unsigned>(hS_Exp5)) <<=
static_cast<unsigned>(hS_Exp2);
109 dS.Difference(bS, &delta);
111 return delta.Compare(hS);
114inline bool StrtodFast(
double d,
int p,
double* result) {
117 if (p > 22 && p < 22 + 16) {
119 d *= internal::Pow10(p - 22);
123 if (p >= -22 && p <= 22 && d <= 9007199254740991.0) {
124 *result = FastPath(d, p);
133inline bool StrtodDiyFp(
const Ch* decimals,
int dLen,
int dExp,
double* result) {
134 uint64_t significand = 0;
136 for (; i < dLen; i++) {
140 significand = significand * 10u +
static_cast<unsigned>(decimals[i] - Ch(
'0'));
143 if (i < dLen && decimals[i] >= Ch(
'5'))
146 int remaining = dLen - i;
147 const int kUlpShift = 3;
148 const int kUlp = 1 << kUlpShift;
149 int64_t error = (remaining == 0) ? 0 : kUlp / 2;
151 DiyFp v(significand, 0);
158 DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
159 if (actualExp != dExp) {
160 static const DiyFp kPow10[] = {
169 int adjustment = dExp - actualExp;
171 v = v * kPow10[adjustment - 1];
172 if (dLen + adjustment > 19)
178 error += kUlp + (error == 0 ? 0 : 1);
180 const int oldExp = v.e;
182 error <<= oldExp - v.e;
184 const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
185 int precisionSize = 64 - effectiveSignificandSize;
186 if (precisionSize + kUlpShift >= 64) {
187 int scaleExp = (precisionSize + kUlpShift) - 63;
190 error = (error >> scaleExp) + 1 + kUlp;
191 precisionSize -= scaleExp;
194 DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
195 const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
196 const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
197 if (precisionBits >= halfWay +
static_cast<unsigned>(error)) {
199 if (rounded.f & (DiyFp::kDpHiddenBit << 1)) {
205 *result = rounded.ToDouble();
207 return halfWay -
static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay +
static_cast<unsigned>(error);
211inline double StrtodBigInteger(
double approx,
const Ch* decimals,
int dLen,
int dExp) {
213 const BigInteger dInt(decimals,
static_cast<unsigned>(dLen));
215 int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
220 if (a.Significand() & 1)
221 return a.NextPositiveDouble();
226 return a.NextPositiveDouble();
230inline double StrtodFullPrecision(
double d,
int p,
const Ch* decimals,
size_t length,
size_t decimalPosition,
int exp) {
235 if (StrtodFast(d, p, &result))
239 int dLen =
static_cast<int>(length);
243 int dExpAdjust =
static_cast<int>(length - decimalPosition);
246 int dExp =
exp - dExpAdjust;
252 while (dLen > 0 && *decimals ==
'0') {
258 while (dLen > 0 && decimals[dLen - 1] ==
'0') {
268 const int kMaxDecimalDigit = 767 + 1;
269 if (dLen > kMaxDecimalDigit) {
270 dExp += dLen - kMaxDecimalDigit;
271 dLen = kMaxDecimalDigit;
276 if (dLen + dExp <= -324)
281 if (dLen + dExp > 309)
282 return std::numeric_limits<double>::infinity();
284 if (StrtodDiyFp(decimals, dLen, dExp, &result))
288 return StrtodBigInteger(result, decimals, dLen, dExp);
#define RAPIDJSON_ASSERT(x)
Assertion.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
__host__ __device__ double exp(double v)
Exponentielle de v.
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.