TerraForge3D  2.3.1
3D Terrain And Landscape Generator

◆ grisu2_digit_gen()

void nlohmann::detail::dtoa_impl::grisu2_digit_gen ( char *  buffer,
int &  length,
int &  decimal_exponent,
diyfp  M_minus,
diyfp  w,
diyfp  M_plus 
)
inline

Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. M- and M+ must be normalized and share the same exponent -60 <= e <= -32.

Definition at line 16097 of file json.hpp.

16099{
16100 static_assert(kAlpha >= -60, "internal error");
16101 static_assert(kGamma <= -32, "internal error");
16102 // Generates the digits (and the exponent) of a decimal floating-point
16103 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
16104 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
16105 //
16106 // <--------------------------- delta ---->
16107 // <---- dist --------->
16108 // --------------[------------------+-------------------]--------------
16109 // M- w M+
16110 //
16111 // Grisu2 generates the digits of M+ from left to right and stops as soon as
16112 // V is in [M-,M+].
16113 JSON_ASSERT(M_plus.e >= kAlpha);
16114 JSON_ASSERT(M_plus.e <= kGamma);
16115 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
16116 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
16117 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
16118 //
16119 // M+ = f * 2^e
16120 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
16121 // = ((p1 ) * 2^-e + (p2 )) * 2^e
16122 // = p1 + p2 * 2^e
16123 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
16124 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
16125 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
16126 // 1)
16127 //
16128 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
16129 JSON_ASSERT(p1 > 0);
16130 std::uint32_t pow10{};
16131 const int k = find_largest_pow10(p1, pow10);
16132 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
16133 //
16134 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
16135 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
16136 //
16137 // M+ = p1 + p2 * 2^e
16138 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
16139 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
16140 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
16141 //
16142 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
16143 //
16144 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
16145 //
16146 // but stop as soon as
16147 //
16148 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
16149 int n = k;
16150
16151 while (n > 0)
16152 {
16153 // Invariants:
16154 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
16155 // pow10 = 10^(n-1) <= p1 < 10^n
16156 //
16157 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
16158 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
16159 //
16160 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
16161 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
16162 //
16163 JSON_ASSERT(d <= 9);
16164 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16165 //
16166 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
16167 //
16168 p1 = r;
16169 n--;
16170 //
16171 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
16172 // pow10 = 10^n
16173 //
16174 // Now check if enough digits have been generated.
16175 // Compute
16176 //
16177 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
16178 //
16179 // Note:
16180 // Since rest and delta share the same exponent e, it suffices to
16181 // compare the significands.
16182 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
16183
16184 if (rest <= delta)
16185 {
16186 // V = buffer * 10^n, with M- <= V <= M+.
16187 decimal_exponent += n;
16188 // We may now just stop. But instead look if the buffer could be
16189 // decremented to bring V closer to w.
16190 //
16191 // pow10 = 10^n is now 1 ulp in the decimal representation V.
16192 // The rounding procedure works with diyfp's with an implicit
16193 // exponent of e.
16194 //
16195 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
16196 //
16197 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
16198 grisu2_round(buffer, length, dist, delta, rest, ten_n);
16199 return;
16200 }
16201
16202 pow10 /= 10;
16203 //
16204 // pow10 = 10^(n-1) <= p1 < 10^n
16205 // Invariants restored.
16206 }
16207
16208 // 2)
16209 //
16210 // The digits of the integral part have been generated:
16211 //
16212 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
16213 // = buffer + p2 * 2^e
16214 //
16215 // Now generate the digits of the fractional part p2 * 2^e.
16216 //
16217 // Note:
16218 // No decimal point is generated: the exponent is adjusted instead.
16219 //
16220 // p2 actually represents the fraction
16221 //
16222 // p2 * 2^e
16223 // = p2 / 2^-e
16224 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
16225 //
16226 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
16227 //
16228 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
16229 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
16230 //
16231 // using
16232 //
16233 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
16234 // = ( d) * 2^-e + ( r)
16235 //
16236 // or
16237 // 10^m * p2 * 2^e = d + r * 2^e
16238 //
16239 // i.e.
16240 //
16241 // M+ = buffer + p2 * 2^e
16242 // = buffer + 10^-m * (d + r * 2^e)
16243 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
16244 //
16245 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
16246 JSON_ASSERT(p2 > delta);
16247 int m = 0;
16248
16249 for (;;)
16250 {
16251 // Invariant:
16252 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
16253 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
16254 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
16255 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
16256 //
16257 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
16258 p2 *= 10;
16259 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
16260 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
16261 //
16262 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
16263 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
16264 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
16265 //
16266 JSON_ASSERT(d <= 9);
16267 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16268 //
16269 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
16270 //
16271 p2 = r;
16272 m++;
16273 //
16274 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
16275 // Invariant restored.
16276 // Check if enough digits have been generated.
16277 //
16278 // 10^-m * p2 * 2^e <= delta * 2^e
16279 // p2 * 2^e <= 10^m * delta * 2^e
16280 // p2 <= 10^m * delta
16281 delta *= 10;
16282 dist *= 10;
16283
16284 if (p2 <= delta)
16285 {
16286 break;
16287 }
16288 }
16289
16290 // V = buffer * 10^-m, with M- <= V <= M+.
16291 decimal_exponent -= m;
16292 // 1 ulp in the decimal representation is now 10^-m.
16293 // Since delta and dist are now scaled by 10^m, we need to do the
16294 // same with ulp in order to keep the units in sync.
16295 //
16296 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
16297 //
16298 const std::uint64_t ten_m = one.f;
16299 grisu2_round(buffer, length, dist, delta, p2, ten_m);
16300 // By construction this algorithm generates the shortest possible decimal
16301 // number (Loitsch, Theorem 6.2) which rounds back to w.
16302 // For an input number of precision p, at least
16303 //
16304 // N = 1 + ceil(p * log_10(2))
16305 //
16306 // decimal digits are sufficient to identify all binary floating-point
16307 // numbers (Matula, "In-and-Out conversions").
16308 // This implies that the algorithm does not produce more than N decimal
16309 // digits.
16310 //
16311 // N = 17 for p = 53 (IEEE double precision)
16312 // N = 9 for p = 24 (IEEE single precision)
16313}