15 #ifndef RAPIDJSON_STRTOD_
16 #define RAPIDJSON_STRTOD_
19 #include "biginteger.h"
25 RAPIDJSON_NAMESPACE_BEGIN
28 inline double FastPath(
double significand,
int exp) {
32 return significand * internal::Pow10(exp);
34 return significand / internal::Pow10(-exp);
37 inline double StrtodNormalPrecision(
double d,
int p) {
40 d = FastPath(d, -308);
41 d = FastPath(d, p + 308);
49 inline T Min3(T a, T b, T c) {
56 inline int CheckWithinHalfULP(
double b,
const BigInteger& d,
int dExp) {
58 const uint64_t bInt = db.IntegerSignificand();
59 const int bExp = db.IntegerExponent();
60 const int hExp = bExp - 1;
62 int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
93 int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
94 dS_Exp2 -= common_Exp2;
95 bS_Exp2 -= common_Exp2;
96 hS_Exp2 -= common_Exp2;
99 dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
102 bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
105 hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
108 dS.Difference(bS, &delta);
110 return delta.Compare(hS);
113 inline bool StrtodFast(
double d,
int p,
double* result) {
116 if (p > 22 && p < 22 + 16) {
118 d *= internal::Pow10(p - 22);
122 if (p >= -22 && p <= 22 && d <= 9007199254740991.0) {
123 *result = FastPath(d, p);
131 inline bool StrtodDiyFp(
const char* decimals,
int dLen,
int dExp,
double* result) {
132 uint64_t significand = 0;
134 for (; i < dLen; i++) {
138 significand = significand * 10u + static_cast<unsigned>(decimals[i] -
'0');
141 if (i < dLen && decimals[i] >=
'5')
144 int remaining = dLen - i;
145 const int kUlpShift = 3;
146 const int kUlp = 1 << kUlpShift;
147 int64_t error = (remaining == 0) ? 0 : kUlp / 2;
149 DiyFp v(significand, 0);
156 DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
157 if (actualExp != dExp) {
158 static const DiyFp kPow10[] = {
167 int adjustment = dExp - actualExp;
169 v = v * kPow10[adjustment - 1];
170 if (dLen + adjustment > 19)
176 error += kUlp + (error == 0 ? 0 : 1);
178 const int oldExp = v.e;
180 error <<= oldExp - v.e;
182 const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
183 int precisionSize = 64 - effectiveSignificandSize;
184 if (precisionSize + kUlpShift >= 64) {
185 int scaleExp = (precisionSize + kUlpShift) - 63;
188 error = (error >> scaleExp) + 1 + kUlp;
189 precisionSize -= scaleExp;
192 DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
193 const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
194 const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
195 if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
197 if (rounded.f & (DiyFp::kDpHiddenBit << 1)) {
203 *result = rounded.ToDouble();
205 return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
208 inline double StrtodBigInteger(
double approx,
const char* decimals,
int dLen,
int dExp) {
210 const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
212 int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
217 if (a.Significand() & 1)
218 return a.NextPositiveDouble();
223 return a.NextPositiveDouble();
226 inline double StrtodFullPrecision(
double d,
int p,
const char* decimals,
size_t length,
size_t decimalPosition,
int exp) {
231 if (StrtodFast(d, p, &result))
235 int dLen = static_cast<int>(length);
239 int dExpAdjust = static_cast<int>(length - decimalPosition);
242 int dExp = exp - dExpAdjust;
248 while (dLen > 0 && *decimals ==
'0') {
254 while (dLen > 0 && decimals[dLen - 1] ==
'0') {
264 const int kMaxDecimalDigit = 767 + 1;
265 if (dLen > kMaxDecimalDigit) {
266 dExp += dLen - kMaxDecimalDigit;
267 dLen = kMaxDecimalDigit;
272 if (dLen + dExp <= -324)
277 if (dLen + dExp > 309)
278 return std::numeric_limits<double>::infinity();
280 if (StrtodDiyFp(decimals, dLen, dExp, &result))
284 return StrtodBigInteger(result, decimals, dLen, dExp);
288 RAPIDJSON_NAMESPACE_END
290 #endif // RAPIDJSON_STRTOD_