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);
132inline bool StrtodDiyFp(
const char* decimals,
int dLen,
int dExp,
double* result) {
135 for (; i < dLen; i++) {
139 significand = significand * 10u +
static_cast<unsigned>(decimals[i] -
'0');
142 if (i < dLen && decimals[i] >=
'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);
157 DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
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;
183 const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + 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)) {
198 if (rounded.f & (DiyFp::kDpHiddenBit << 1)) {
204 *result = rounded.ToDouble();
206 return halfWay -
static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay +
static_cast<unsigned>(error);
209inline double StrtodBigInteger(
double approx,
const char* decimals,
int dLen,
int dExp) {
211 const BigInteger dInt(decimals,
static_cast<unsigned>(dLen));
213 int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
218 if (a.Significand() & 1)
219 return a.NextPositiveDouble();
224 return a.NextPositiveDouble();
227inline double StrtodFullPrecision(
double d,
int p,
const char* decimals,
size_t length,
size_t decimalPosition,
int exp) {
232 if (StrtodFast(d, p, &result))
236 int dLen =
static_cast<int>(length);
240 int dExpAdjust =
static_cast<int>(length - decimalPosition);
243 int dExp =
exp - dExpAdjust;
249 while (dLen > 0 && *decimals ==
'0') {
255 while (dLen > 0 && decimals[dLen - 1] ==
'0') {
265 const int kMaxDecimalDigit = 767 + 1;
266 if (dLen > kMaxDecimalDigit) {
267 dExp += dLen - kMaxDecimalDigit;
268 dLen = kMaxDecimalDigit;
273 if (dLen + dExp <= -324)
278 if (dLen + dExp > 309)
279 return std::numeric_limits<double>::infinity();
281 if (StrtodDiyFp(decimals, dLen, dExp, &result))
285 return StrtodBigInteger(result, decimals, dLen, dExp);
Lecteur des fichiers de maillage via la bibliothèque LIMA.
#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)
ARCCORE_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.