15 #ifndef RAPIDJSON_STRTOD_
16 #define RAPIDJSON_STRTOD_
28 inline double FastPath(
double significand,
int exp) {
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);
116 if (p > 22 && p < 22 + 16) {
122 if (p >= -22 && p <= 22 && d <= 9007199254740991.0) {
131 template<
typename Ch>
132 inline bool StrtodDiyFp(
const Ch* decimals,
int dLen,
int dExp,
double* result) {
135 for (; i < dLen; i++) {
139 significand = significand * 10u +
static_cast<unsigned>(decimals[i] - Ch(
'0'));
142 if (i < dLen && decimals[i] >= Ch(
'5'))
145 int remaining = dLen - i;
146 const int kUlpShift = 3;
147 const int kUlp = 1 << kUlpShift;
148 int64_t error = (remaining == 0) ? 0 : kUlp / 2;
150 DiyFp v(significand, 0);
158 if (actualExp != dExp) {
159 static const DiyFp kPow10[] = {
168 int adjustment = dExp - actualExp;
170 v = v * kPow10[adjustment - 1];
171 if (dLen + adjustment > 19)
177 error += kUlp + (error == 0 ? 0 : 1);
179 const int oldExp = v.
e;
181 error <<= oldExp - v.
e;
184 int precisionSize = 64 - effectiveSignificandSize;
185 if (precisionSize + kUlpShift >= 64) {
186 int scaleExp = (precisionSize + kUlpShift) - 63;
189 error = (error >> scaleExp) + 1 + kUlp;
190 precisionSize -= scaleExp;
193 DiyFp rounded(v.
f >> precisionSize, v.
e + precisionSize);
194 const uint64_t precisionBits = (v.
f & ((
uint64_t(1) << precisionSize) - 1)) * kUlp;
196 if (precisionBits >= halfWay +
static_cast<unsigned>(error)) {
206 return halfWay -
static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay +
static_cast<unsigned>(error);
209 template<
typename Ch>
212 const BigInteger dInt(decimals,
static_cast<unsigned>(dLen));
219 if (
a.Significand() & 1)
220 return a.NextPositiveDouble();
225 return a.NextPositiveDouble();
228 template<
typename Ch>
229 inline double StrtodFullPrecision(
double d,
int p,
const Ch* decimals,
size_t length,
size_t decimalPosition,
int exp) {
238 int dLen =
static_cast<int>(length);
242 int dExpAdjust =
static_cast<int>(length - decimalPosition);
245 int dExp = exp - dExpAdjust;
251 while (dLen > 0 && *decimals ==
'0') {
257 while (dLen > 0 && decimals[dLen - 1] ==
'0') {
267 const int kMaxDecimalDigit = 767 + 1;
268 if (dLen > kMaxDecimalDigit) {
269 dExp += dLen - kMaxDecimalDigit;
270 dLen = kMaxDecimalDigit;
275 if (dLen + dExp <= -324)
280 if (dLen + dExp > 309)
281 return std::numeric_limits<double>::infinity();
293 #endif // RAPIDJSON_STRTOD_