MCPcopy Create free account
hub / github.com/OpenFodder/openfodder / grisu2_digit_gen

Function grisu2_digit_gen

Source/Utils/json.hpp:14920–15153  ·  view source on GitHub ↗

! 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. */

Source from the content-addressed store, hash-verified

14918 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
14919 */
14920 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
14921 diyfp M_minus, diyfp w, diyfp M_plus)
14922 {
14923 static_assert(kAlpha >= -60, "internal error");
14924 static_assert(kGamma <= -32, "internal error");
14925
14926 // Generates the digits (and the exponent) of a decimal floating-point
14927 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
14928 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
14929 //
14930 // <--------------------------- delta ---->
14931 // <---- dist --------->
14932 // --------------[------------------+-------------------]--------------
14933 // M- w M+
14934 //
14935 // Grisu2 generates the digits of M+ from left to right and stops as soon as
14936 // V is in [M-,M+].
14937
14938 JSON_ASSERT(M_plus.e >= kAlpha);
14939 JSON_ASSERT(M_plus.e <= kGamma);
14940
14941 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
14942 std::uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
14943
14944 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
14945 //
14946 // M+ = f * 2^e
14947 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
14948 // = ((p1 ) * 2^-e + (p2 )) * 2^e
14949 // = p1 + p2 * 2^e
14950
14951 const diyfp one(std::uint64_t{ 1 } << -M_plus.e, M_plus.e);
14952
14953 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.)
14954 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
14955
14956 // 1)
14957 //
14958 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
14959
14960 JSON_ASSERT(p1 > 0);
14961
14962 std::uint32_t pow10;
14963 const int k = find_largest_pow10(p1, pow10);
14964
14965 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
14966 //
14967 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
14968 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
14969 //
14970 // M+ = p1 + p2 * 2^e
14971 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
14972 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
14973 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
14974 //
14975 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
14976 //
14977 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]

Callers 1

grisu2Function · 0.85

Calls 2

find_largest_pow10Function · 0.85
grisu2_roundFunction · 0.85

Tested by

no test coverage detected