1c5f01b2fSopenharmony_ci// __ _____ _____ _____ 2c5f01b2fSopenharmony_ci// __| | __| | | | JSON for Modern C++ 3c5f01b2fSopenharmony_ci// | | |__ | | | | | | version 3.11.2 4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5c5f01b2fSopenharmony_ci// 6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> 7c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 8c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT 9c5f01b2fSopenharmony_ci 10c5f01b2fSopenharmony_ci#pragma once 11c5f01b2fSopenharmony_ci 12c5f01b2fSopenharmony_ci#include <array> // array 13c5f01b2fSopenharmony_ci#include <cmath> // signbit, isfinite 14c5f01b2fSopenharmony_ci#include <cstdint> // intN_t, uintN_t 15c5f01b2fSopenharmony_ci#include <cstring> // memcpy, memmove 16c5f01b2fSopenharmony_ci#include <limits> // numeric_limits 17c5f01b2fSopenharmony_ci#include <type_traits> // conditional 18c5f01b2fSopenharmony_ci 19c5f01b2fSopenharmony_ci#include <nlohmann/detail/macro_scope.hpp> 20c5f01b2fSopenharmony_ci 21c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_BEGIN 22c5f01b2fSopenharmony_cinamespace detail 23c5f01b2fSopenharmony_ci{ 24c5f01b2fSopenharmony_ci 25c5f01b2fSopenharmony_ci/*! 26c5f01b2fSopenharmony_ci@brief implements the Grisu2 algorithm for binary to decimal floating-point 27c5f01b2fSopenharmony_ciconversion. 28c5f01b2fSopenharmony_ci 29c5f01b2fSopenharmony_ciThis implementation is a slightly modified version of the reference 30c5f01b2fSopenharmony_ciimplementation which may be obtained from 31c5f01b2fSopenharmony_cihttp://florian.loitsch.com/publications (bench.tar.gz). 32c5f01b2fSopenharmony_ci 33c5f01b2fSopenharmony_ciThe code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. 34c5f01b2fSopenharmony_ci 35c5f01b2fSopenharmony_ciFor a detailed description of the algorithm see: 36c5f01b2fSopenharmony_ci 37c5f01b2fSopenharmony_ci[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with 38c5f01b2fSopenharmony_ci Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming 39c5f01b2fSopenharmony_ci Language Design and Implementation, PLDI 2010 40c5f01b2fSopenharmony_ci[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 41c5f01b2fSopenharmony_ci Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 42c5f01b2fSopenharmony_ci Design and Implementation, PLDI 1996 43c5f01b2fSopenharmony_ci*/ 44c5f01b2fSopenharmony_cinamespace dtoa_impl 45c5f01b2fSopenharmony_ci{ 46c5f01b2fSopenharmony_ci 47c5f01b2fSopenharmony_citemplate<typename Target, typename Source> 48c5f01b2fSopenharmony_ciTarget reinterpret_bits(const Source source) 49c5f01b2fSopenharmony_ci{ 50c5f01b2fSopenharmony_ci static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); 51c5f01b2fSopenharmony_ci 52c5f01b2fSopenharmony_ci Target target; 53c5f01b2fSopenharmony_ci std::memcpy(&target, &source, sizeof(Source)); 54c5f01b2fSopenharmony_ci return target; 55c5f01b2fSopenharmony_ci} 56c5f01b2fSopenharmony_ci 57c5f01b2fSopenharmony_cistruct diyfp // f * 2^e 58c5f01b2fSopenharmony_ci{ 59c5f01b2fSopenharmony_ci static constexpr int kPrecision = 64; // = q 60c5f01b2fSopenharmony_ci 61c5f01b2fSopenharmony_ci std::uint64_t f = 0; 62c5f01b2fSopenharmony_ci int e = 0; 63c5f01b2fSopenharmony_ci 64c5f01b2fSopenharmony_ci constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} 65c5f01b2fSopenharmony_ci 66c5f01b2fSopenharmony_ci /*! 67c5f01b2fSopenharmony_ci @brief returns x - y 68c5f01b2fSopenharmony_ci @pre x.e == y.e and x.f >= y.f 69c5f01b2fSopenharmony_ci */ 70c5f01b2fSopenharmony_ci static diyfp sub(const diyfp& x, const diyfp& y) noexcept 71c5f01b2fSopenharmony_ci { 72c5f01b2fSopenharmony_ci JSON_ASSERT(x.e == y.e); 73c5f01b2fSopenharmony_ci JSON_ASSERT(x.f >= y.f); 74c5f01b2fSopenharmony_ci 75c5f01b2fSopenharmony_ci return {x.f - y.f, x.e}; 76c5f01b2fSopenharmony_ci } 77c5f01b2fSopenharmony_ci 78c5f01b2fSopenharmony_ci /*! 79c5f01b2fSopenharmony_ci @brief returns x * y 80c5f01b2fSopenharmony_ci @note The result is rounded. (Only the upper q bits are returned.) 81c5f01b2fSopenharmony_ci */ 82c5f01b2fSopenharmony_ci static diyfp mul(const diyfp& x, const diyfp& y) noexcept 83c5f01b2fSopenharmony_ci { 84c5f01b2fSopenharmony_ci static_assert(kPrecision == 64, "internal error"); 85c5f01b2fSopenharmony_ci 86c5f01b2fSopenharmony_ci // Computes: 87c5f01b2fSopenharmony_ci // f = round((x.f * y.f) / 2^q) 88c5f01b2fSopenharmony_ci // e = x.e + y.e + q 89c5f01b2fSopenharmony_ci 90c5f01b2fSopenharmony_ci // Emulate the 64-bit * 64-bit multiplication: 91c5f01b2fSopenharmony_ci // 92c5f01b2fSopenharmony_ci // p = u * v 93c5f01b2fSopenharmony_ci // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) 94c5f01b2fSopenharmony_ci // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) 95c5f01b2fSopenharmony_ci // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) 96c5f01b2fSopenharmony_ci // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) 97c5f01b2fSopenharmony_ci // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) 98c5f01b2fSopenharmony_ci // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) 99c5f01b2fSopenharmony_ci // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) 100c5f01b2fSopenharmony_ci // 101c5f01b2fSopenharmony_ci // (Since Q might be larger than 2^32 - 1) 102c5f01b2fSopenharmony_ci // 103c5f01b2fSopenharmony_ci // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) 104c5f01b2fSopenharmony_ci // 105c5f01b2fSopenharmony_ci // (Q_hi + H does not overflow a 64-bit int) 106c5f01b2fSopenharmony_ci // 107c5f01b2fSopenharmony_ci // = p_lo + 2^64 p_hi 108c5f01b2fSopenharmony_ci 109c5f01b2fSopenharmony_ci const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; 110c5f01b2fSopenharmony_ci const std::uint64_t u_hi = x.f >> 32u; 111c5f01b2fSopenharmony_ci const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; 112c5f01b2fSopenharmony_ci const std::uint64_t v_hi = y.f >> 32u; 113c5f01b2fSopenharmony_ci 114c5f01b2fSopenharmony_ci const std::uint64_t p0 = u_lo * v_lo; 115c5f01b2fSopenharmony_ci const std::uint64_t p1 = u_lo * v_hi; 116c5f01b2fSopenharmony_ci const std::uint64_t p2 = u_hi * v_lo; 117c5f01b2fSopenharmony_ci const std::uint64_t p3 = u_hi * v_hi; 118c5f01b2fSopenharmony_ci 119c5f01b2fSopenharmony_ci const std::uint64_t p0_hi = p0 >> 32u; 120c5f01b2fSopenharmony_ci const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; 121c5f01b2fSopenharmony_ci const std::uint64_t p1_hi = p1 >> 32u; 122c5f01b2fSopenharmony_ci const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; 123c5f01b2fSopenharmony_ci const std::uint64_t p2_hi = p2 >> 32u; 124c5f01b2fSopenharmony_ci 125c5f01b2fSopenharmony_ci std::uint64_t Q = p0_hi + p1_lo + p2_lo; 126c5f01b2fSopenharmony_ci 127c5f01b2fSopenharmony_ci // The full product might now be computed as 128c5f01b2fSopenharmony_ci // 129c5f01b2fSopenharmony_ci // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) 130c5f01b2fSopenharmony_ci // p_lo = p0_lo + (Q << 32) 131c5f01b2fSopenharmony_ci // 132c5f01b2fSopenharmony_ci // But in this particular case here, the full p_lo is not required. 133c5f01b2fSopenharmony_ci // Effectively we only need to add the highest bit in p_lo to p_hi (and 134c5f01b2fSopenharmony_ci // Q_hi + 1 does not overflow). 135c5f01b2fSopenharmony_ci 136c5f01b2fSopenharmony_ci Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up 137c5f01b2fSopenharmony_ci 138c5f01b2fSopenharmony_ci const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); 139c5f01b2fSopenharmony_ci 140c5f01b2fSopenharmony_ci return {h, x.e + y.e + 64}; 141c5f01b2fSopenharmony_ci } 142c5f01b2fSopenharmony_ci 143c5f01b2fSopenharmony_ci /*! 144c5f01b2fSopenharmony_ci @brief normalize x such that the significand is >= 2^(q-1) 145c5f01b2fSopenharmony_ci @pre x.f != 0 146c5f01b2fSopenharmony_ci */ 147c5f01b2fSopenharmony_ci static diyfp normalize(diyfp x) noexcept 148c5f01b2fSopenharmony_ci { 149c5f01b2fSopenharmony_ci JSON_ASSERT(x.f != 0); 150c5f01b2fSopenharmony_ci 151c5f01b2fSopenharmony_ci while ((x.f >> 63u) == 0) 152c5f01b2fSopenharmony_ci { 153c5f01b2fSopenharmony_ci x.f <<= 1u; 154c5f01b2fSopenharmony_ci x.e--; 155c5f01b2fSopenharmony_ci } 156c5f01b2fSopenharmony_ci 157c5f01b2fSopenharmony_ci return x; 158c5f01b2fSopenharmony_ci } 159c5f01b2fSopenharmony_ci 160c5f01b2fSopenharmony_ci /*! 161c5f01b2fSopenharmony_ci @brief normalize x such that the result has the exponent E 162c5f01b2fSopenharmony_ci @pre e >= x.e and the upper e - x.e bits of x.f must be zero. 163c5f01b2fSopenharmony_ci */ 164c5f01b2fSopenharmony_ci static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept 165c5f01b2fSopenharmony_ci { 166c5f01b2fSopenharmony_ci const int delta = x.e - target_exponent; 167c5f01b2fSopenharmony_ci 168c5f01b2fSopenharmony_ci JSON_ASSERT(delta >= 0); 169c5f01b2fSopenharmony_ci JSON_ASSERT(((x.f << delta) >> delta) == x.f); 170c5f01b2fSopenharmony_ci 171c5f01b2fSopenharmony_ci return {x.f << delta, target_exponent}; 172c5f01b2fSopenharmony_ci } 173c5f01b2fSopenharmony_ci}; 174c5f01b2fSopenharmony_ci 175c5f01b2fSopenharmony_cistruct boundaries 176c5f01b2fSopenharmony_ci{ 177c5f01b2fSopenharmony_ci diyfp w; 178c5f01b2fSopenharmony_ci diyfp minus; 179c5f01b2fSopenharmony_ci diyfp plus; 180c5f01b2fSopenharmony_ci}; 181c5f01b2fSopenharmony_ci 182c5f01b2fSopenharmony_ci/*! 183c5f01b2fSopenharmony_ciCompute the (normalized) diyfp representing the input number 'value' and its 184c5f01b2fSopenharmony_ciboundaries. 185c5f01b2fSopenharmony_ci 186c5f01b2fSopenharmony_ci@pre value must be finite and positive 187c5f01b2fSopenharmony_ci*/ 188c5f01b2fSopenharmony_citemplate<typename FloatType> 189c5f01b2fSopenharmony_ciboundaries compute_boundaries(FloatType value) 190c5f01b2fSopenharmony_ci{ 191c5f01b2fSopenharmony_ci JSON_ASSERT(std::isfinite(value)); 192c5f01b2fSopenharmony_ci JSON_ASSERT(value > 0); 193c5f01b2fSopenharmony_ci 194c5f01b2fSopenharmony_ci // Convert the IEEE representation into a diyfp. 195c5f01b2fSopenharmony_ci // 196c5f01b2fSopenharmony_ci // If v is denormal: 197c5f01b2fSopenharmony_ci // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) 198c5f01b2fSopenharmony_ci // If v is normalized: 199c5f01b2fSopenharmony_ci // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) 200c5f01b2fSopenharmony_ci 201c5f01b2fSopenharmony_ci static_assert(std::numeric_limits<FloatType>::is_iec559, 202c5f01b2fSopenharmony_ci "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); 203c5f01b2fSopenharmony_ci 204c5f01b2fSopenharmony_ci constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit) 205c5f01b2fSopenharmony_ci constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1); 206c5f01b2fSopenharmony_ci constexpr int kMinExp = 1 - kBias; 207c5f01b2fSopenharmony_ci constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) 208c5f01b2fSopenharmony_ci 209c5f01b2fSopenharmony_ci using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type; 210c5f01b2fSopenharmony_ci 211c5f01b2fSopenharmony_ci const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value)); 212c5f01b2fSopenharmony_ci const std::uint64_t E = bits >> (kPrecision - 1); 213c5f01b2fSopenharmony_ci const std::uint64_t F = bits & (kHiddenBit - 1); 214c5f01b2fSopenharmony_ci 215c5f01b2fSopenharmony_ci const bool is_denormal = E == 0; 216c5f01b2fSopenharmony_ci const diyfp v = is_denormal 217c5f01b2fSopenharmony_ci ? diyfp(F, kMinExp) 218c5f01b2fSopenharmony_ci : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias); 219c5f01b2fSopenharmony_ci 220c5f01b2fSopenharmony_ci // Compute the boundaries m- and m+ of the floating-point value 221c5f01b2fSopenharmony_ci // v = f * 2^e. 222c5f01b2fSopenharmony_ci // 223c5f01b2fSopenharmony_ci // Determine v- and v+, the floating-point predecessor and successor if v, 224c5f01b2fSopenharmony_ci // respectively. 225c5f01b2fSopenharmony_ci // 226c5f01b2fSopenharmony_ci // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) 227c5f01b2fSopenharmony_ci // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) 228c5f01b2fSopenharmony_ci // 229c5f01b2fSopenharmony_ci // v+ = v + 2^e 230c5f01b2fSopenharmony_ci // 231c5f01b2fSopenharmony_ci // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ 232c5f01b2fSopenharmony_ci // between m- and m+ round to v, regardless of how the input rounding 233c5f01b2fSopenharmony_ci // algorithm breaks ties. 234c5f01b2fSopenharmony_ci // 235c5f01b2fSopenharmony_ci // ---+-------------+-------------+-------------+-------------+--- (A) 236c5f01b2fSopenharmony_ci // v- m- v m+ v+ 237c5f01b2fSopenharmony_ci // 238c5f01b2fSopenharmony_ci // -----------------+------+------+-------------+-------------+--- (B) 239c5f01b2fSopenharmony_ci // v- m- v m+ v+ 240c5f01b2fSopenharmony_ci 241c5f01b2fSopenharmony_ci const bool lower_boundary_is_closer = F == 0 && E > 1; 242c5f01b2fSopenharmony_ci const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); 243c5f01b2fSopenharmony_ci const diyfp m_minus = lower_boundary_is_closer 244c5f01b2fSopenharmony_ci ? diyfp(4 * v.f - 1, v.e - 2) // (B) 245c5f01b2fSopenharmony_ci : diyfp(2 * v.f - 1, v.e - 1); // (A) 246c5f01b2fSopenharmony_ci 247c5f01b2fSopenharmony_ci // Determine the normalized w+ = m+. 248c5f01b2fSopenharmony_ci const diyfp w_plus = diyfp::normalize(m_plus); 249c5f01b2fSopenharmony_ci 250c5f01b2fSopenharmony_ci // Determine w- = m- such that e_(w-) = e_(w+). 251c5f01b2fSopenharmony_ci const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); 252c5f01b2fSopenharmony_ci 253c5f01b2fSopenharmony_ci return {diyfp::normalize(v), w_minus, w_plus}; 254c5f01b2fSopenharmony_ci} 255c5f01b2fSopenharmony_ci 256c5f01b2fSopenharmony_ci// Given normalized diyfp w, Grisu needs to find a (normalized) cached 257c5f01b2fSopenharmony_ci// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies 258c5f01b2fSopenharmony_ci// within a certain range [alpha, gamma] (Definition 3.2 from [1]) 259c5f01b2fSopenharmony_ci// 260c5f01b2fSopenharmony_ci// alpha <= e = e_c + e_w + q <= gamma 261c5f01b2fSopenharmony_ci// 262c5f01b2fSopenharmony_ci// or 263c5f01b2fSopenharmony_ci// 264c5f01b2fSopenharmony_ci// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q 265c5f01b2fSopenharmony_ci// <= f_c * f_w * 2^gamma 266c5f01b2fSopenharmony_ci// 267c5f01b2fSopenharmony_ci// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies 268c5f01b2fSopenharmony_ci// 269c5f01b2fSopenharmony_ci// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma 270c5f01b2fSopenharmony_ci// 271c5f01b2fSopenharmony_ci// or 272c5f01b2fSopenharmony_ci// 273c5f01b2fSopenharmony_ci// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) 274c5f01b2fSopenharmony_ci// 275c5f01b2fSopenharmony_ci// The choice of (alpha,gamma) determines the size of the table and the form of 276c5f01b2fSopenharmony_ci// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well 277c5f01b2fSopenharmony_ci// in practice: 278c5f01b2fSopenharmony_ci// 279c5f01b2fSopenharmony_ci// The idea is to cut the number c * w = f * 2^e into two parts, which can be 280c5f01b2fSopenharmony_ci// processed independently: An integral part p1, and a fractional part p2: 281c5f01b2fSopenharmony_ci// 282c5f01b2fSopenharmony_ci// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e 283c5f01b2fSopenharmony_ci// = (f div 2^-e) + (f mod 2^-e) * 2^e 284c5f01b2fSopenharmony_ci// = p1 + p2 * 2^e 285c5f01b2fSopenharmony_ci// 286c5f01b2fSopenharmony_ci// The conversion of p1 into decimal form requires a series of divisions and 287c5f01b2fSopenharmony_ci// modulos by (a power of) 10. These operations are faster for 32-bit than for 288c5f01b2fSopenharmony_ci// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be 289c5f01b2fSopenharmony_ci// achieved by choosing 290c5f01b2fSopenharmony_ci// 291c5f01b2fSopenharmony_ci// -e >= 32 or e <= -32 := gamma 292c5f01b2fSopenharmony_ci// 293c5f01b2fSopenharmony_ci// In order to convert the fractional part 294c5f01b2fSopenharmony_ci// 295c5f01b2fSopenharmony_ci// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... 296c5f01b2fSopenharmony_ci// 297c5f01b2fSopenharmony_ci// into decimal form, the fraction is repeatedly multiplied by 10 and the digits 298c5f01b2fSopenharmony_ci// d[-i] are extracted in order: 299c5f01b2fSopenharmony_ci// 300c5f01b2fSopenharmony_ci// (10 * p2) div 2^-e = d[-1] 301c5f01b2fSopenharmony_ci// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... 302c5f01b2fSopenharmony_ci// 303c5f01b2fSopenharmony_ci// The multiplication by 10 must not overflow. It is sufficient to choose 304c5f01b2fSopenharmony_ci// 305c5f01b2fSopenharmony_ci// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. 306c5f01b2fSopenharmony_ci// 307c5f01b2fSopenharmony_ci// Since p2 = f mod 2^-e < 2^-e, 308c5f01b2fSopenharmony_ci// 309c5f01b2fSopenharmony_ci// -e <= 60 or e >= -60 := alpha 310c5f01b2fSopenharmony_ci 311c5f01b2fSopenharmony_ciconstexpr int kAlpha = -60; 312c5f01b2fSopenharmony_ciconstexpr int kGamma = -32; 313c5f01b2fSopenharmony_ci 314c5f01b2fSopenharmony_cistruct cached_power // c = f * 2^e ~= 10^k 315c5f01b2fSopenharmony_ci{ 316c5f01b2fSopenharmony_ci std::uint64_t f; 317c5f01b2fSopenharmony_ci int e; 318c5f01b2fSopenharmony_ci int k; 319c5f01b2fSopenharmony_ci}; 320c5f01b2fSopenharmony_ci 321c5f01b2fSopenharmony_ci/*! 322c5f01b2fSopenharmony_ciFor a normalized diyfp w = f * 2^e, this function returns a (normalized) cached 323c5f01b2fSopenharmony_cipower-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c 324c5f01b2fSopenharmony_cisatisfies (Definition 3.2 from [1]) 325c5f01b2fSopenharmony_ci 326c5f01b2fSopenharmony_ci alpha <= e_c + e + q <= gamma. 327c5f01b2fSopenharmony_ci*/ 328c5f01b2fSopenharmony_ciinline cached_power get_cached_power_for_binary_exponent(int e) 329c5f01b2fSopenharmony_ci{ 330c5f01b2fSopenharmony_ci // Now 331c5f01b2fSopenharmony_ci // 332c5f01b2fSopenharmony_ci // alpha <= e_c + e + q <= gamma (1) 333c5f01b2fSopenharmony_ci // ==> f_c * 2^alpha <= c * 2^e * 2^q 334c5f01b2fSopenharmony_ci // 335c5f01b2fSopenharmony_ci // and since the c's are normalized, 2^(q-1) <= f_c, 336c5f01b2fSopenharmony_ci // 337c5f01b2fSopenharmony_ci // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) 338c5f01b2fSopenharmony_ci // ==> 2^(alpha - e - 1) <= c 339c5f01b2fSopenharmony_ci // 340c5f01b2fSopenharmony_ci // If c were an exact power of ten, i.e. c = 10^k, one may determine k as 341c5f01b2fSopenharmony_ci // 342c5f01b2fSopenharmony_ci // k = ceil( log_10( 2^(alpha - e - 1) ) ) 343c5f01b2fSopenharmony_ci // = ceil( (alpha - e - 1) * log_10(2) ) 344c5f01b2fSopenharmony_ci // 345c5f01b2fSopenharmony_ci // From the paper: 346c5f01b2fSopenharmony_ci // "In theory the result of the procedure could be wrong since c is rounded, 347c5f01b2fSopenharmony_ci // and the computation itself is approximated [...]. In practice, however, 348c5f01b2fSopenharmony_ci // this simple function is sufficient." 349c5f01b2fSopenharmony_ci // 350c5f01b2fSopenharmony_ci // For IEEE double precision floating-point numbers converted into 351c5f01b2fSopenharmony_ci // normalized diyfp's w = f * 2^e, with q = 64, 352c5f01b2fSopenharmony_ci // 353c5f01b2fSopenharmony_ci // e >= -1022 (min IEEE exponent) 354c5f01b2fSopenharmony_ci // -52 (p - 1) 355c5f01b2fSopenharmony_ci // -52 (p - 1, possibly normalize denormal IEEE numbers) 356c5f01b2fSopenharmony_ci // -11 (normalize the diyfp) 357c5f01b2fSopenharmony_ci // = -1137 358c5f01b2fSopenharmony_ci // 359c5f01b2fSopenharmony_ci // and 360c5f01b2fSopenharmony_ci // 361c5f01b2fSopenharmony_ci // e <= +1023 (max IEEE exponent) 362c5f01b2fSopenharmony_ci // -52 (p - 1) 363c5f01b2fSopenharmony_ci // -11 (normalize the diyfp) 364c5f01b2fSopenharmony_ci // = 960 365c5f01b2fSopenharmony_ci // 366c5f01b2fSopenharmony_ci // This binary exponent range [-1137,960] results in a decimal exponent 367c5f01b2fSopenharmony_ci // range [-307,324]. One does not need to store a cached power for each 368c5f01b2fSopenharmony_ci // k in this range. For each such k it suffices to find a cached power 369c5f01b2fSopenharmony_ci // such that the exponent of the product lies in [alpha,gamma]. 370c5f01b2fSopenharmony_ci // This implies that the difference of the decimal exponents of adjacent 371c5f01b2fSopenharmony_ci // table entries must be less than or equal to 372c5f01b2fSopenharmony_ci // 373c5f01b2fSopenharmony_ci // floor( (gamma - alpha) * log_10(2) ) = 8. 374c5f01b2fSopenharmony_ci // 375c5f01b2fSopenharmony_ci // (A smaller distance gamma-alpha would require a larger table.) 376c5f01b2fSopenharmony_ci 377c5f01b2fSopenharmony_ci // NB: 378c5f01b2fSopenharmony_ci // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. 379c5f01b2fSopenharmony_ci 380c5f01b2fSopenharmony_ci constexpr int kCachedPowersMinDecExp = -300; 381c5f01b2fSopenharmony_ci constexpr int kCachedPowersDecStep = 8; 382c5f01b2fSopenharmony_ci 383c5f01b2fSopenharmony_ci static constexpr std::array<cached_power, 79> kCachedPowers = 384c5f01b2fSopenharmony_ci { 385c5f01b2fSopenharmony_ci { 386c5f01b2fSopenharmony_ci { 0xAB70FE17C79AC6CA, -1060, -300 }, 387c5f01b2fSopenharmony_ci { 0xFF77B1FCBEBCDC4F, -1034, -292 }, 388c5f01b2fSopenharmony_ci { 0xBE5691EF416BD60C, -1007, -284 }, 389c5f01b2fSopenharmony_ci { 0x8DD01FAD907FFC3C, -980, -276 }, 390c5f01b2fSopenharmony_ci { 0xD3515C2831559A83, -954, -268 }, 391c5f01b2fSopenharmony_ci { 0x9D71AC8FADA6C9B5, -927, -260 }, 392c5f01b2fSopenharmony_ci { 0xEA9C227723EE8BCB, -901, -252 }, 393c5f01b2fSopenharmony_ci { 0xAECC49914078536D, -874, -244 }, 394c5f01b2fSopenharmony_ci { 0x823C12795DB6CE57, -847, -236 }, 395c5f01b2fSopenharmony_ci { 0xC21094364DFB5637, -821, -228 }, 396c5f01b2fSopenharmony_ci { 0x9096EA6F3848984F, -794, -220 }, 397c5f01b2fSopenharmony_ci { 0xD77485CB25823AC7, -768, -212 }, 398c5f01b2fSopenharmony_ci { 0xA086CFCD97BF97F4, -741, -204 }, 399c5f01b2fSopenharmony_ci { 0xEF340A98172AACE5, -715, -196 }, 400c5f01b2fSopenharmony_ci { 0xB23867FB2A35B28E, -688, -188 }, 401c5f01b2fSopenharmony_ci { 0x84C8D4DFD2C63F3B, -661, -180 }, 402c5f01b2fSopenharmony_ci { 0xC5DD44271AD3CDBA, -635, -172 }, 403c5f01b2fSopenharmony_ci { 0x936B9FCEBB25C996, -608, -164 }, 404c5f01b2fSopenharmony_ci { 0xDBAC6C247D62A584, -582, -156 }, 405c5f01b2fSopenharmony_ci { 0xA3AB66580D5FDAF6, -555, -148 }, 406c5f01b2fSopenharmony_ci { 0xF3E2F893DEC3F126, -529, -140 }, 407c5f01b2fSopenharmony_ci { 0xB5B5ADA8AAFF80B8, -502, -132 }, 408c5f01b2fSopenharmony_ci { 0x87625F056C7C4A8B, -475, -124 }, 409c5f01b2fSopenharmony_ci { 0xC9BCFF6034C13053, -449, -116 }, 410c5f01b2fSopenharmony_ci { 0x964E858C91BA2655, -422, -108 }, 411c5f01b2fSopenharmony_ci { 0xDFF9772470297EBD, -396, -100 }, 412c5f01b2fSopenharmony_ci { 0xA6DFBD9FB8E5B88F, -369, -92 }, 413c5f01b2fSopenharmony_ci { 0xF8A95FCF88747D94, -343, -84 }, 414c5f01b2fSopenharmony_ci { 0xB94470938FA89BCF, -316, -76 }, 415c5f01b2fSopenharmony_ci { 0x8A08F0F8BF0F156B, -289, -68 }, 416c5f01b2fSopenharmony_ci { 0xCDB02555653131B6, -263, -60 }, 417c5f01b2fSopenharmony_ci { 0x993FE2C6D07B7FAC, -236, -52 }, 418c5f01b2fSopenharmony_ci { 0xE45C10C42A2B3B06, -210, -44 }, 419c5f01b2fSopenharmony_ci { 0xAA242499697392D3, -183, -36 }, 420c5f01b2fSopenharmony_ci { 0xFD87B5F28300CA0E, -157, -28 }, 421c5f01b2fSopenharmony_ci { 0xBCE5086492111AEB, -130, -20 }, 422c5f01b2fSopenharmony_ci { 0x8CBCCC096F5088CC, -103, -12 }, 423c5f01b2fSopenharmony_ci { 0xD1B71758E219652C, -77, -4 }, 424c5f01b2fSopenharmony_ci { 0x9C40000000000000, -50, 4 }, 425c5f01b2fSopenharmony_ci { 0xE8D4A51000000000, -24, 12 }, 426c5f01b2fSopenharmony_ci { 0xAD78EBC5AC620000, 3, 20 }, 427c5f01b2fSopenharmony_ci { 0x813F3978F8940984, 30, 28 }, 428c5f01b2fSopenharmony_ci { 0xC097CE7BC90715B3, 56, 36 }, 429c5f01b2fSopenharmony_ci { 0x8F7E32CE7BEA5C70, 83, 44 }, 430c5f01b2fSopenharmony_ci { 0xD5D238A4ABE98068, 109, 52 }, 431c5f01b2fSopenharmony_ci { 0x9F4F2726179A2245, 136, 60 }, 432c5f01b2fSopenharmony_ci { 0xED63A231D4C4FB27, 162, 68 }, 433c5f01b2fSopenharmony_ci { 0xB0DE65388CC8ADA8, 189, 76 }, 434c5f01b2fSopenharmony_ci { 0x83C7088E1AAB65DB, 216, 84 }, 435c5f01b2fSopenharmony_ci { 0xC45D1DF942711D9A, 242, 92 }, 436c5f01b2fSopenharmony_ci { 0x924D692CA61BE758, 269, 100 }, 437c5f01b2fSopenharmony_ci { 0xDA01EE641A708DEA, 295, 108 }, 438c5f01b2fSopenharmony_ci { 0xA26DA3999AEF774A, 322, 116 }, 439c5f01b2fSopenharmony_ci { 0xF209787BB47D6B85, 348, 124 }, 440c5f01b2fSopenharmony_ci { 0xB454E4A179DD1877, 375, 132 }, 441c5f01b2fSopenharmony_ci { 0x865B86925B9BC5C2, 402, 140 }, 442c5f01b2fSopenharmony_ci { 0xC83553C5C8965D3D, 428, 148 }, 443c5f01b2fSopenharmony_ci { 0x952AB45CFA97A0B3, 455, 156 }, 444c5f01b2fSopenharmony_ci { 0xDE469FBD99A05FE3, 481, 164 }, 445c5f01b2fSopenharmony_ci { 0xA59BC234DB398C25, 508, 172 }, 446c5f01b2fSopenharmony_ci { 0xF6C69A72A3989F5C, 534, 180 }, 447c5f01b2fSopenharmony_ci { 0xB7DCBF5354E9BECE, 561, 188 }, 448c5f01b2fSopenharmony_ci { 0x88FCF317F22241E2, 588, 196 }, 449c5f01b2fSopenharmony_ci { 0xCC20CE9BD35C78A5, 614, 204 }, 450c5f01b2fSopenharmony_ci { 0x98165AF37B2153DF, 641, 212 }, 451c5f01b2fSopenharmony_ci { 0xE2A0B5DC971F303A, 667, 220 }, 452c5f01b2fSopenharmony_ci { 0xA8D9D1535CE3B396, 694, 228 }, 453c5f01b2fSopenharmony_ci { 0xFB9B7CD9A4A7443C, 720, 236 }, 454c5f01b2fSopenharmony_ci { 0xBB764C4CA7A44410, 747, 244 }, 455c5f01b2fSopenharmony_ci { 0x8BAB8EEFB6409C1A, 774, 252 }, 456c5f01b2fSopenharmony_ci { 0xD01FEF10A657842C, 800, 260 }, 457c5f01b2fSopenharmony_ci { 0x9B10A4E5E9913129, 827, 268 }, 458c5f01b2fSopenharmony_ci { 0xE7109BFBA19C0C9D, 853, 276 }, 459c5f01b2fSopenharmony_ci { 0xAC2820D9623BF429, 880, 284 }, 460c5f01b2fSopenharmony_ci { 0x80444B5E7AA7CF85, 907, 292 }, 461c5f01b2fSopenharmony_ci { 0xBF21E44003ACDD2D, 933, 300 }, 462c5f01b2fSopenharmony_ci { 0x8E679C2F5E44FF8F, 960, 308 }, 463c5f01b2fSopenharmony_ci { 0xD433179D9C8CB841, 986, 316 }, 464c5f01b2fSopenharmony_ci { 0x9E19DB92B4E31BA9, 1013, 324 }, 465c5f01b2fSopenharmony_ci } 466c5f01b2fSopenharmony_ci }; 467c5f01b2fSopenharmony_ci 468c5f01b2fSopenharmony_ci // This computation gives exactly the same results for k as 469c5f01b2fSopenharmony_ci // k = ceil((kAlpha - e - 1) * 0.30102999566398114) 470c5f01b2fSopenharmony_ci // for |e| <= 1500, but doesn't require floating-point operations. 471c5f01b2fSopenharmony_ci // NB: log_10(2) ~= 78913 / 2^18 472c5f01b2fSopenharmony_ci JSON_ASSERT(e >= -1500); 473c5f01b2fSopenharmony_ci JSON_ASSERT(e <= 1500); 474c5f01b2fSopenharmony_ci const int f = kAlpha - e - 1; 475c5f01b2fSopenharmony_ci const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0); 476c5f01b2fSopenharmony_ci 477c5f01b2fSopenharmony_ci const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; 478c5f01b2fSopenharmony_ci JSON_ASSERT(index >= 0); 479c5f01b2fSopenharmony_ci JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size()); 480c5f01b2fSopenharmony_ci 481c5f01b2fSopenharmony_ci const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)]; 482c5f01b2fSopenharmony_ci JSON_ASSERT(kAlpha <= cached.e + e + 64); 483c5f01b2fSopenharmony_ci JSON_ASSERT(kGamma >= cached.e + e + 64); 484c5f01b2fSopenharmony_ci 485c5f01b2fSopenharmony_ci return cached; 486c5f01b2fSopenharmony_ci} 487c5f01b2fSopenharmony_ci 488c5f01b2fSopenharmony_ci/*! 489c5f01b2fSopenharmony_ciFor n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. 490c5f01b2fSopenharmony_ciFor n == 0, returns 1 and sets pow10 := 1. 491c5f01b2fSopenharmony_ci*/ 492c5f01b2fSopenharmony_ciinline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) 493c5f01b2fSopenharmony_ci{ 494c5f01b2fSopenharmony_ci // LCOV_EXCL_START 495c5f01b2fSopenharmony_ci if (n >= 1000000000) 496c5f01b2fSopenharmony_ci { 497c5f01b2fSopenharmony_ci pow10 = 1000000000; 498c5f01b2fSopenharmony_ci return 10; 499c5f01b2fSopenharmony_ci } 500c5f01b2fSopenharmony_ci // LCOV_EXCL_STOP 501c5f01b2fSopenharmony_ci if (n >= 100000000) 502c5f01b2fSopenharmony_ci { 503c5f01b2fSopenharmony_ci pow10 = 100000000; 504c5f01b2fSopenharmony_ci return 9; 505c5f01b2fSopenharmony_ci } 506c5f01b2fSopenharmony_ci if (n >= 10000000) 507c5f01b2fSopenharmony_ci { 508c5f01b2fSopenharmony_ci pow10 = 10000000; 509c5f01b2fSopenharmony_ci return 8; 510c5f01b2fSopenharmony_ci } 511c5f01b2fSopenharmony_ci if (n >= 1000000) 512c5f01b2fSopenharmony_ci { 513c5f01b2fSopenharmony_ci pow10 = 1000000; 514c5f01b2fSopenharmony_ci return 7; 515c5f01b2fSopenharmony_ci } 516c5f01b2fSopenharmony_ci if (n >= 100000) 517c5f01b2fSopenharmony_ci { 518c5f01b2fSopenharmony_ci pow10 = 100000; 519c5f01b2fSopenharmony_ci return 6; 520c5f01b2fSopenharmony_ci } 521c5f01b2fSopenharmony_ci if (n >= 10000) 522c5f01b2fSopenharmony_ci { 523c5f01b2fSopenharmony_ci pow10 = 10000; 524c5f01b2fSopenharmony_ci return 5; 525c5f01b2fSopenharmony_ci } 526c5f01b2fSopenharmony_ci if (n >= 1000) 527c5f01b2fSopenharmony_ci { 528c5f01b2fSopenharmony_ci pow10 = 1000; 529c5f01b2fSopenharmony_ci return 4; 530c5f01b2fSopenharmony_ci } 531c5f01b2fSopenharmony_ci if (n >= 100) 532c5f01b2fSopenharmony_ci { 533c5f01b2fSopenharmony_ci pow10 = 100; 534c5f01b2fSopenharmony_ci return 3; 535c5f01b2fSopenharmony_ci } 536c5f01b2fSopenharmony_ci if (n >= 10) 537c5f01b2fSopenharmony_ci { 538c5f01b2fSopenharmony_ci pow10 = 10; 539c5f01b2fSopenharmony_ci return 2; 540c5f01b2fSopenharmony_ci } 541c5f01b2fSopenharmony_ci 542c5f01b2fSopenharmony_ci pow10 = 1; 543c5f01b2fSopenharmony_ci return 1; 544c5f01b2fSopenharmony_ci} 545c5f01b2fSopenharmony_ci 546c5f01b2fSopenharmony_ciinline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, 547c5f01b2fSopenharmony_ci std::uint64_t rest, std::uint64_t ten_k) 548c5f01b2fSopenharmony_ci{ 549c5f01b2fSopenharmony_ci JSON_ASSERT(len >= 1); 550c5f01b2fSopenharmony_ci JSON_ASSERT(dist <= delta); 551c5f01b2fSopenharmony_ci JSON_ASSERT(rest <= delta); 552c5f01b2fSopenharmony_ci JSON_ASSERT(ten_k > 0); 553c5f01b2fSopenharmony_ci 554c5f01b2fSopenharmony_ci // <--------------------------- delta ----> 555c5f01b2fSopenharmony_ci // <---- dist ---------> 556c5f01b2fSopenharmony_ci // --------------[------------------+-------------------]-------------- 557c5f01b2fSopenharmony_ci // M- w M+ 558c5f01b2fSopenharmony_ci // 559c5f01b2fSopenharmony_ci // ten_k 560c5f01b2fSopenharmony_ci // <------> 561c5f01b2fSopenharmony_ci // <---- rest ----> 562c5f01b2fSopenharmony_ci // --------------[------------------+----+--------------]-------------- 563c5f01b2fSopenharmony_ci // w V 564c5f01b2fSopenharmony_ci // = buf * 10^k 565c5f01b2fSopenharmony_ci // 566c5f01b2fSopenharmony_ci // ten_k represents a unit-in-the-last-place in the decimal representation 567c5f01b2fSopenharmony_ci // stored in buf. 568c5f01b2fSopenharmony_ci // Decrement buf by ten_k while this takes buf closer to w. 569c5f01b2fSopenharmony_ci 570c5f01b2fSopenharmony_ci // The tests are written in this order to avoid overflow in unsigned 571c5f01b2fSopenharmony_ci // integer arithmetic. 572c5f01b2fSopenharmony_ci 573c5f01b2fSopenharmony_ci while (rest < dist 574c5f01b2fSopenharmony_ci && delta - rest >= ten_k 575c5f01b2fSopenharmony_ci && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) 576c5f01b2fSopenharmony_ci { 577c5f01b2fSopenharmony_ci JSON_ASSERT(buf[len - 1] != '0'); 578c5f01b2fSopenharmony_ci buf[len - 1]--; 579c5f01b2fSopenharmony_ci rest += ten_k; 580c5f01b2fSopenharmony_ci } 581c5f01b2fSopenharmony_ci} 582c5f01b2fSopenharmony_ci 583c5f01b2fSopenharmony_ci/*! 584c5f01b2fSopenharmony_ciGenerates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. 585c5f01b2fSopenharmony_ciM- and M+ must be normalized and share the same exponent -60 <= e <= -32. 586c5f01b2fSopenharmony_ci*/ 587c5f01b2fSopenharmony_ciinline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, 588c5f01b2fSopenharmony_ci diyfp M_minus, diyfp w, diyfp M_plus) 589c5f01b2fSopenharmony_ci{ 590c5f01b2fSopenharmony_ci static_assert(kAlpha >= -60, "internal error"); 591c5f01b2fSopenharmony_ci static_assert(kGamma <= -32, "internal error"); 592c5f01b2fSopenharmony_ci 593c5f01b2fSopenharmony_ci // Generates the digits (and the exponent) of a decimal floating-point 594c5f01b2fSopenharmony_ci // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's 595c5f01b2fSopenharmony_ci // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. 596c5f01b2fSopenharmony_ci // 597c5f01b2fSopenharmony_ci // <--------------------------- delta ----> 598c5f01b2fSopenharmony_ci // <---- dist ---------> 599c5f01b2fSopenharmony_ci // --------------[------------------+-------------------]-------------- 600c5f01b2fSopenharmony_ci // M- w M+ 601c5f01b2fSopenharmony_ci // 602c5f01b2fSopenharmony_ci // Grisu2 generates the digits of M+ from left to right and stops as soon as 603c5f01b2fSopenharmony_ci // V is in [M-,M+]. 604c5f01b2fSopenharmony_ci 605c5f01b2fSopenharmony_ci JSON_ASSERT(M_plus.e >= kAlpha); 606c5f01b2fSopenharmony_ci JSON_ASSERT(M_plus.e <= kGamma); 607c5f01b2fSopenharmony_ci 608c5f01b2fSopenharmony_ci std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) 609c5f01b2fSopenharmony_ci std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) 610c5f01b2fSopenharmony_ci 611c5f01b2fSopenharmony_ci // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): 612c5f01b2fSopenharmony_ci // 613c5f01b2fSopenharmony_ci // M+ = f * 2^e 614c5f01b2fSopenharmony_ci // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e 615c5f01b2fSopenharmony_ci // = ((p1 ) * 2^-e + (p2 )) * 2^e 616c5f01b2fSopenharmony_ci // = p1 + p2 * 2^e 617c5f01b2fSopenharmony_ci 618c5f01b2fSopenharmony_ci const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); 619c5f01b2fSopenharmony_ci 620c5f01b2fSopenharmony_ci 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.) 621c5f01b2fSopenharmony_ci std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e 622c5f01b2fSopenharmony_ci 623c5f01b2fSopenharmony_ci // 1) 624c5f01b2fSopenharmony_ci // 625c5f01b2fSopenharmony_ci // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] 626c5f01b2fSopenharmony_ci 627c5f01b2fSopenharmony_ci JSON_ASSERT(p1 > 0); 628c5f01b2fSopenharmony_ci 629c5f01b2fSopenharmony_ci std::uint32_t pow10{}; 630c5f01b2fSopenharmony_ci const int k = find_largest_pow10(p1, pow10); 631c5f01b2fSopenharmony_ci 632c5f01b2fSopenharmony_ci // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) 633c5f01b2fSopenharmony_ci // 634c5f01b2fSopenharmony_ci // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) 635c5f01b2fSopenharmony_ci // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) 636c5f01b2fSopenharmony_ci // 637c5f01b2fSopenharmony_ci // M+ = p1 + p2 * 2^e 638c5f01b2fSopenharmony_ci // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e 639c5f01b2fSopenharmony_ci // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e 640c5f01b2fSopenharmony_ci // = d[k-1] * 10^(k-1) + ( rest) * 2^e 641c5f01b2fSopenharmony_ci // 642c5f01b2fSopenharmony_ci // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) 643c5f01b2fSopenharmony_ci // 644c5f01b2fSopenharmony_ci // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] 645c5f01b2fSopenharmony_ci // 646c5f01b2fSopenharmony_ci // but stop as soon as 647c5f01b2fSopenharmony_ci // 648c5f01b2fSopenharmony_ci // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e 649c5f01b2fSopenharmony_ci 650c5f01b2fSopenharmony_ci int n = k; 651c5f01b2fSopenharmony_ci while (n > 0) 652c5f01b2fSopenharmony_ci { 653c5f01b2fSopenharmony_ci // Invariants: 654c5f01b2fSopenharmony_ci // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) 655c5f01b2fSopenharmony_ci // pow10 = 10^(n-1) <= p1 < 10^n 656c5f01b2fSopenharmony_ci // 657c5f01b2fSopenharmony_ci const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) 658c5f01b2fSopenharmony_ci const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) 659c5f01b2fSopenharmony_ci // 660c5f01b2fSopenharmony_ci // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e 661c5f01b2fSopenharmony_ci // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) 662c5f01b2fSopenharmony_ci // 663c5f01b2fSopenharmony_ci JSON_ASSERT(d <= 9); 664c5f01b2fSopenharmony_ci buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 665c5f01b2fSopenharmony_ci // 666c5f01b2fSopenharmony_ci // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) 667c5f01b2fSopenharmony_ci // 668c5f01b2fSopenharmony_ci p1 = r; 669c5f01b2fSopenharmony_ci n--; 670c5f01b2fSopenharmony_ci // 671c5f01b2fSopenharmony_ci // M+ = buffer * 10^n + (p1 + p2 * 2^e) 672c5f01b2fSopenharmony_ci // pow10 = 10^n 673c5f01b2fSopenharmony_ci // 674c5f01b2fSopenharmony_ci 675c5f01b2fSopenharmony_ci // Now check if enough digits have been generated. 676c5f01b2fSopenharmony_ci // Compute 677c5f01b2fSopenharmony_ci // 678c5f01b2fSopenharmony_ci // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e 679c5f01b2fSopenharmony_ci // 680c5f01b2fSopenharmony_ci // Note: 681c5f01b2fSopenharmony_ci // Since rest and delta share the same exponent e, it suffices to 682c5f01b2fSopenharmony_ci // compare the significands. 683c5f01b2fSopenharmony_ci const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; 684c5f01b2fSopenharmony_ci if (rest <= delta) 685c5f01b2fSopenharmony_ci { 686c5f01b2fSopenharmony_ci // V = buffer * 10^n, with M- <= V <= M+. 687c5f01b2fSopenharmony_ci 688c5f01b2fSopenharmony_ci decimal_exponent += n; 689c5f01b2fSopenharmony_ci 690c5f01b2fSopenharmony_ci // We may now just stop. But instead look if the buffer could be 691c5f01b2fSopenharmony_ci // decremented to bring V closer to w. 692c5f01b2fSopenharmony_ci // 693c5f01b2fSopenharmony_ci // pow10 = 10^n is now 1 ulp in the decimal representation V. 694c5f01b2fSopenharmony_ci // The rounding procedure works with diyfp's with an implicit 695c5f01b2fSopenharmony_ci // exponent of e. 696c5f01b2fSopenharmony_ci // 697c5f01b2fSopenharmony_ci // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e 698c5f01b2fSopenharmony_ci // 699c5f01b2fSopenharmony_ci const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; 700c5f01b2fSopenharmony_ci grisu2_round(buffer, length, dist, delta, rest, ten_n); 701c5f01b2fSopenharmony_ci 702c5f01b2fSopenharmony_ci return; 703c5f01b2fSopenharmony_ci } 704c5f01b2fSopenharmony_ci 705c5f01b2fSopenharmony_ci pow10 /= 10; 706c5f01b2fSopenharmony_ci // 707c5f01b2fSopenharmony_ci // pow10 = 10^(n-1) <= p1 < 10^n 708c5f01b2fSopenharmony_ci // Invariants restored. 709c5f01b2fSopenharmony_ci } 710c5f01b2fSopenharmony_ci 711c5f01b2fSopenharmony_ci // 2) 712c5f01b2fSopenharmony_ci // 713c5f01b2fSopenharmony_ci // The digits of the integral part have been generated: 714c5f01b2fSopenharmony_ci // 715c5f01b2fSopenharmony_ci // M+ = d[k-1]...d[1]d[0] + p2 * 2^e 716c5f01b2fSopenharmony_ci // = buffer + p2 * 2^e 717c5f01b2fSopenharmony_ci // 718c5f01b2fSopenharmony_ci // Now generate the digits of the fractional part p2 * 2^e. 719c5f01b2fSopenharmony_ci // 720c5f01b2fSopenharmony_ci // Note: 721c5f01b2fSopenharmony_ci // No decimal point is generated: the exponent is adjusted instead. 722c5f01b2fSopenharmony_ci // 723c5f01b2fSopenharmony_ci // p2 actually represents the fraction 724c5f01b2fSopenharmony_ci // 725c5f01b2fSopenharmony_ci // p2 * 2^e 726c5f01b2fSopenharmony_ci // = p2 / 2^-e 727c5f01b2fSopenharmony_ci // = d[-1] / 10^1 + d[-2] / 10^2 + ... 728c5f01b2fSopenharmony_ci // 729c5f01b2fSopenharmony_ci // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) 730c5f01b2fSopenharmony_ci // 731c5f01b2fSopenharmony_ci // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m 732c5f01b2fSopenharmony_ci // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) 733c5f01b2fSopenharmony_ci // 734c5f01b2fSopenharmony_ci // using 735c5f01b2fSopenharmony_ci // 736c5f01b2fSopenharmony_ci // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) 737c5f01b2fSopenharmony_ci // = ( d) * 2^-e + ( r) 738c5f01b2fSopenharmony_ci // 739c5f01b2fSopenharmony_ci // or 740c5f01b2fSopenharmony_ci // 10^m * p2 * 2^e = d + r * 2^e 741c5f01b2fSopenharmony_ci // 742c5f01b2fSopenharmony_ci // i.e. 743c5f01b2fSopenharmony_ci // 744c5f01b2fSopenharmony_ci // M+ = buffer + p2 * 2^e 745c5f01b2fSopenharmony_ci // = buffer + 10^-m * (d + r * 2^e) 746c5f01b2fSopenharmony_ci // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e 747c5f01b2fSopenharmony_ci // 748c5f01b2fSopenharmony_ci // and stop as soon as 10^-m * r * 2^e <= delta * 2^e 749c5f01b2fSopenharmony_ci 750c5f01b2fSopenharmony_ci JSON_ASSERT(p2 > delta); 751c5f01b2fSopenharmony_ci 752c5f01b2fSopenharmony_ci int m = 0; 753c5f01b2fSopenharmony_ci for (;;) 754c5f01b2fSopenharmony_ci { 755c5f01b2fSopenharmony_ci // Invariant: 756c5f01b2fSopenharmony_ci // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e 757c5f01b2fSopenharmony_ci // = buffer * 10^-m + 10^-m * (p2 ) * 2^e 758c5f01b2fSopenharmony_ci // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e 759c5f01b2fSopenharmony_ci // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e 760c5f01b2fSopenharmony_ci // 761c5f01b2fSopenharmony_ci JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10); 762c5f01b2fSopenharmony_ci p2 *= 10; 763c5f01b2fSopenharmony_ci const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e 764c5f01b2fSopenharmony_ci const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e 765c5f01b2fSopenharmony_ci // 766c5f01b2fSopenharmony_ci // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e 767c5f01b2fSopenharmony_ci // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) 768c5f01b2fSopenharmony_ci // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e 769c5f01b2fSopenharmony_ci // 770c5f01b2fSopenharmony_ci JSON_ASSERT(d <= 9); 771c5f01b2fSopenharmony_ci buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 772c5f01b2fSopenharmony_ci // 773c5f01b2fSopenharmony_ci // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e 774c5f01b2fSopenharmony_ci // 775c5f01b2fSopenharmony_ci p2 = r; 776c5f01b2fSopenharmony_ci m++; 777c5f01b2fSopenharmony_ci // 778c5f01b2fSopenharmony_ci // M+ = buffer * 10^-m + 10^-m * p2 * 2^e 779c5f01b2fSopenharmony_ci // Invariant restored. 780c5f01b2fSopenharmony_ci 781c5f01b2fSopenharmony_ci // Check if enough digits have been generated. 782c5f01b2fSopenharmony_ci // 783c5f01b2fSopenharmony_ci // 10^-m * p2 * 2^e <= delta * 2^e 784c5f01b2fSopenharmony_ci // p2 * 2^e <= 10^m * delta * 2^e 785c5f01b2fSopenharmony_ci // p2 <= 10^m * delta 786c5f01b2fSopenharmony_ci delta *= 10; 787c5f01b2fSopenharmony_ci dist *= 10; 788c5f01b2fSopenharmony_ci if (p2 <= delta) 789c5f01b2fSopenharmony_ci { 790c5f01b2fSopenharmony_ci break; 791c5f01b2fSopenharmony_ci } 792c5f01b2fSopenharmony_ci } 793c5f01b2fSopenharmony_ci 794c5f01b2fSopenharmony_ci // V = buffer * 10^-m, with M- <= V <= M+. 795c5f01b2fSopenharmony_ci 796c5f01b2fSopenharmony_ci decimal_exponent -= m; 797c5f01b2fSopenharmony_ci 798c5f01b2fSopenharmony_ci // 1 ulp in the decimal representation is now 10^-m. 799c5f01b2fSopenharmony_ci // Since delta and dist are now scaled by 10^m, we need to do the 800c5f01b2fSopenharmony_ci // same with ulp in order to keep the units in sync. 801c5f01b2fSopenharmony_ci // 802c5f01b2fSopenharmony_ci // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e 803c5f01b2fSopenharmony_ci // 804c5f01b2fSopenharmony_ci const std::uint64_t ten_m = one.f; 805c5f01b2fSopenharmony_ci grisu2_round(buffer, length, dist, delta, p2, ten_m); 806c5f01b2fSopenharmony_ci 807c5f01b2fSopenharmony_ci // By construction this algorithm generates the shortest possible decimal 808c5f01b2fSopenharmony_ci // number (Loitsch, Theorem 6.2) which rounds back to w. 809c5f01b2fSopenharmony_ci // For an input number of precision p, at least 810c5f01b2fSopenharmony_ci // 811c5f01b2fSopenharmony_ci // N = 1 + ceil(p * log_10(2)) 812c5f01b2fSopenharmony_ci // 813c5f01b2fSopenharmony_ci // decimal digits are sufficient to identify all binary floating-point 814c5f01b2fSopenharmony_ci // numbers (Matula, "In-and-Out conversions"). 815c5f01b2fSopenharmony_ci // This implies that the algorithm does not produce more than N decimal 816c5f01b2fSopenharmony_ci // digits. 817c5f01b2fSopenharmony_ci // 818c5f01b2fSopenharmony_ci // N = 17 for p = 53 (IEEE double precision) 819c5f01b2fSopenharmony_ci // N = 9 for p = 24 (IEEE single precision) 820c5f01b2fSopenharmony_ci} 821c5f01b2fSopenharmony_ci 822c5f01b2fSopenharmony_ci/*! 823c5f01b2fSopenharmony_civ = buf * 10^decimal_exponent 824c5f01b2fSopenharmony_cilen is the length of the buffer (number of decimal digits) 825c5f01b2fSopenharmony_ciThe buffer must be large enough, i.e. >= max_digits10. 826c5f01b2fSopenharmony_ci*/ 827c5f01b2fSopenharmony_ciJSON_HEDLEY_NON_NULL(1) 828c5f01b2fSopenharmony_ciinline void grisu2(char* buf, int& len, int& decimal_exponent, 829c5f01b2fSopenharmony_ci diyfp m_minus, diyfp v, diyfp m_plus) 830c5f01b2fSopenharmony_ci{ 831c5f01b2fSopenharmony_ci JSON_ASSERT(m_plus.e == m_minus.e); 832c5f01b2fSopenharmony_ci JSON_ASSERT(m_plus.e == v.e); 833c5f01b2fSopenharmony_ci 834c5f01b2fSopenharmony_ci // --------(-----------------------+-----------------------)-------- (A) 835c5f01b2fSopenharmony_ci // m- v m+ 836c5f01b2fSopenharmony_ci // 837c5f01b2fSopenharmony_ci // --------------------(-----------+-----------------------)-------- (B) 838c5f01b2fSopenharmony_ci // m- v m+ 839c5f01b2fSopenharmony_ci // 840c5f01b2fSopenharmony_ci // First scale v (and m- and m+) such that the exponent is in the range 841c5f01b2fSopenharmony_ci // [alpha, gamma]. 842c5f01b2fSopenharmony_ci 843c5f01b2fSopenharmony_ci const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); 844c5f01b2fSopenharmony_ci 845c5f01b2fSopenharmony_ci const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k 846c5f01b2fSopenharmony_ci 847c5f01b2fSopenharmony_ci // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] 848c5f01b2fSopenharmony_ci const diyfp w = diyfp::mul(v, c_minus_k); 849c5f01b2fSopenharmony_ci const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); 850c5f01b2fSopenharmony_ci const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); 851c5f01b2fSopenharmony_ci 852c5f01b2fSopenharmony_ci // ----(---+---)---------------(---+---)---------------(---+---)---- 853c5f01b2fSopenharmony_ci // w- w w+ 854c5f01b2fSopenharmony_ci // = c*m- = c*v = c*m+ 855c5f01b2fSopenharmony_ci // 856c5f01b2fSopenharmony_ci // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and 857c5f01b2fSopenharmony_ci // w+ are now off by a small amount. 858c5f01b2fSopenharmony_ci // In fact: 859c5f01b2fSopenharmony_ci // 860c5f01b2fSopenharmony_ci // w - v * 10^k < 1 ulp 861c5f01b2fSopenharmony_ci // 862c5f01b2fSopenharmony_ci // To account for this inaccuracy, add resp. subtract 1 ulp. 863c5f01b2fSopenharmony_ci // 864c5f01b2fSopenharmony_ci // --------+---[---------------(---+---)---------------]---+-------- 865c5f01b2fSopenharmony_ci // w- M- w M+ w+ 866c5f01b2fSopenharmony_ci // 867c5f01b2fSopenharmony_ci // Now any number in [M-, M+] (bounds included) will round to w when input, 868c5f01b2fSopenharmony_ci // regardless of how the input rounding algorithm breaks ties. 869c5f01b2fSopenharmony_ci // 870c5f01b2fSopenharmony_ci // And digit_gen generates the shortest possible such number in [M-, M+]. 871c5f01b2fSopenharmony_ci // Note that this does not mean that Grisu2 always generates the shortest 872c5f01b2fSopenharmony_ci // possible number in the interval (m-, m+). 873c5f01b2fSopenharmony_ci const diyfp M_minus(w_minus.f + 1, w_minus.e); 874c5f01b2fSopenharmony_ci const diyfp M_plus (w_plus.f - 1, w_plus.e ); 875c5f01b2fSopenharmony_ci 876c5f01b2fSopenharmony_ci decimal_exponent = -cached.k; // = -(-k) = k 877c5f01b2fSopenharmony_ci 878c5f01b2fSopenharmony_ci grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); 879c5f01b2fSopenharmony_ci} 880c5f01b2fSopenharmony_ci 881c5f01b2fSopenharmony_ci/*! 882c5f01b2fSopenharmony_civ = buf * 10^decimal_exponent 883c5f01b2fSopenharmony_cilen is the length of the buffer (number of decimal digits) 884c5f01b2fSopenharmony_ciThe buffer must be large enough, i.e. >= max_digits10. 885c5f01b2fSopenharmony_ci*/ 886c5f01b2fSopenharmony_citemplate<typename FloatType> 887c5f01b2fSopenharmony_ciJSON_HEDLEY_NON_NULL(1) 888c5f01b2fSopenharmony_civoid grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) 889c5f01b2fSopenharmony_ci{ 890c5f01b2fSopenharmony_ci static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, 891c5f01b2fSopenharmony_ci "internal error: not enough precision"); 892c5f01b2fSopenharmony_ci 893c5f01b2fSopenharmony_ci JSON_ASSERT(std::isfinite(value)); 894c5f01b2fSopenharmony_ci JSON_ASSERT(value > 0); 895c5f01b2fSopenharmony_ci 896c5f01b2fSopenharmony_ci // If the neighbors (and boundaries) of 'value' are always computed for double-precision 897c5f01b2fSopenharmony_ci // numbers, all float's can be recovered using strtod (and strtof). However, the resulting 898c5f01b2fSopenharmony_ci // decimal representations are not exactly "short". 899c5f01b2fSopenharmony_ci // 900c5f01b2fSopenharmony_ci // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) 901c5f01b2fSopenharmony_ci // says "value is converted to a string as if by std::sprintf in the default ("C") locale" 902c5f01b2fSopenharmony_ci // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' 903c5f01b2fSopenharmony_ci // does. 904c5f01b2fSopenharmony_ci // On the other hand, the documentation for 'std::to_chars' requires that "parsing the 905c5f01b2fSopenharmony_ci // representation using the corresponding std::from_chars function recovers value exactly". That 906c5f01b2fSopenharmony_ci // indicates that single precision floating-point numbers should be recovered using 907c5f01b2fSopenharmony_ci // 'std::strtof'. 908c5f01b2fSopenharmony_ci // 909c5f01b2fSopenharmony_ci // NB: If the neighbors are computed for single-precision numbers, there is a single float 910c5f01b2fSopenharmony_ci // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision 911c5f01b2fSopenharmony_ci // value is off by 1 ulp. 912c5f01b2fSopenharmony_ci#if 0 913c5f01b2fSopenharmony_ci const boundaries w = compute_boundaries(static_cast<double>(value)); 914c5f01b2fSopenharmony_ci#else 915c5f01b2fSopenharmony_ci const boundaries w = compute_boundaries(value); 916c5f01b2fSopenharmony_ci#endif 917c5f01b2fSopenharmony_ci 918c5f01b2fSopenharmony_ci grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); 919c5f01b2fSopenharmony_ci} 920c5f01b2fSopenharmony_ci 921c5f01b2fSopenharmony_ci/*! 922c5f01b2fSopenharmony_ci@brief appends a decimal representation of e to buf 923c5f01b2fSopenharmony_ci@return a pointer to the element following the exponent. 924c5f01b2fSopenharmony_ci@pre -1000 < e < 1000 925c5f01b2fSopenharmony_ci*/ 926c5f01b2fSopenharmony_ciJSON_HEDLEY_NON_NULL(1) 927c5f01b2fSopenharmony_ciJSON_HEDLEY_RETURNS_NON_NULL 928c5f01b2fSopenharmony_ciinline char* append_exponent(char* buf, int e) 929c5f01b2fSopenharmony_ci{ 930c5f01b2fSopenharmony_ci JSON_ASSERT(e > -1000); 931c5f01b2fSopenharmony_ci JSON_ASSERT(e < 1000); 932c5f01b2fSopenharmony_ci 933c5f01b2fSopenharmony_ci if (e < 0) 934c5f01b2fSopenharmony_ci { 935c5f01b2fSopenharmony_ci e = -e; 936c5f01b2fSopenharmony_ci *buf++ = '-'; 937c5f01b2fSopenharmony_ci } 938c5f01b2fSopenharmony_ci else 939c5f01b2fSopenharmony_ci { 940c5f01b2fSopenharmony_ci *buf++ = '+'; 941c5f01b2fSopenharmony_ci } 942c5f01b2fSopenharmony_ci 943c5f01b2fSopenharmony_ci auto k = static_cast<std::uint32_t>(e); 944c5f01b2fSopenharmony_ci if (k < 10) 945c5f01b2fSopenharmony_ci { 946c5f01b2fSopenharmony_ci // Always print at least two digits in the exponent. 947c5f01b2fSopenharmony_ci // This is for compatibility with printf("%g"). 948c5f01b2fSopenharmony_ci *buf++ = '0'; 949c5f01b2fSopenharmony_ci *buf++ = static_cast<char>('0' + k); 950c5f01b2fSopenharmony_ci } 951c5f01b2fSopenharmony_ci else if (k < 100) 952c5f01b2fSopenharmony_ci { 953c5f01b2fSopenharmony_ci *buf++ = static_cast<char>('0' + k / 10); 954c5f01b2fSopenharmony_ci k %= 10; 955c5f01b2fSopenharmony_ci *buf++ = static_cast<char>('0' + k); 956c5f01b2fSopenharmony_ci } 957c5f01b2fSopenharmony_ci else 958c5f01b2fSopenharmony_ci { 959c5f01b2fSopenharmony_ci *buf++ = static_cast<char>('0' + k / 100); 960c5f01b2fSopenharmony_ci k %= 100; 961c5f01b2fSopenharmony_ci *buf++ = static_cast<char>('0' + k / 10); 962c5f01b2fSopenharmony_ci k %= 10; 963c5f01b2fSopenharmony_ci *buf++ = static_cast<char>('0' + k); 964c5f01b2fSopenharmony_ci } 965c5f01b2fSopenharmony_ci 966c5f01b2fSopenharmony_ci return buf; 967c5f01b2fSopenharmony_ci} 968c5f01b2fSopenharmony_ci 969c5f01b2fSopenharmony_ci/*! 970c5f01b2fSopenharmony_ci@brief prettify v = buf * 10^decimal_exponent 971c5f01b2fSopenharmony_ci 972c5f01b2fSopenharmony_ciIf v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point 973c5f01b2fSopenharmony_cinotation. Otherwise it will be printed in exponential notation. 974c5f01b2fSopenharmony_ci 975c5f01b2fSopenharmony_ci@pre min_exp < 0 976c5f01b2fSopenharmony_ci@pre max_exp > 0 977c5f01b2fSopenharmony_ci*/ 978c5f01b2fSopenharmony_ciJSON_HEDLEY_NON_NULL(1) 979c5f01b2fSopenharmony_ciJSON_HEDLEY_RETURNS_NON_NULL 980c5f01b2fSopenharmony_ciinline char* format_buffer(char* buf, int len, int decimal_exponent, 981c5f01b2fSopenharmony_ci int min_exp, int max_exp) 982c5f01b2fSopenharmony_ci{ 983c5f01b2fSopenharmony_ci JSON_ASSERT(min_exp < 0); 984c5f01b2fSopenharmony_ci JSON_ASSERT(max_exp > 0); 985c5f01b2fSopenharmony_ci 986c5f01b2fSopenharmony_ci const int k = len; 987c5f01b2fSopenharmony_ci const int n = len + decimal_exponent; 988c5f01b2fSopenharmony_ci 989c5f01b2fSopenharmony_ci // v = buf * 10^(n-k) 990c5f01b2fSopenharmony_ci // k is the length of the buffer (number of decimal digits) 991c5f01b2fSopenharmony_ci // n is the position of the decimal point relative to the start of the buffer. 992c5f01b2fSopenharmony_ci 993c5f01b2fSopenharmony_ci if (k <= n && n <= max_exp) 994c5f01b2fSopenharmony_ci { 995c5f01b2fSopenharmony_ci // digits[000] 996c5f01b2fSopenharmony_ci // len <= max_exp + 2 997c5f01b2fSopenharmony_ci 998c5f01b2fSopenharmony_ci std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k)); 999c5f01b2fSopenharmony_ci // Make it look like a floating-point number (#362, #378) 1000c5f01b2fSopenharmony_ci buf[n + 0] = '.'; 1001c5f01b2fSopenharmony_ci buf[n + 1] = '0'; 1002c5f01b2fSopenharmony_ci return buf + (static_cast<size_t>(n) + 2); 1003c5f01b2fSopenharmony_ci } 1004c5f01b2fSopenharmony_ci 1005c5f01b2fSopenharmony_ci if (0 < n && n <= max_exp) 1006c5f01b2fSopenharmony_ci { 1007c5f01b2fSopenharmony_ci // dig.its 1008c5f01b2fSopenharmony_ci // len <= max_digits10 + 1 1009c5f01b2fSopenharmony_ci 1010c5f01b2fSopenharmony_ci JSON_ASSERT(k > n); 1011c5f01b2fSopenharmony_ci 1012c5f01b2fSopenharmony_ci std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n)); 1013c5f01b2fSopenharmony_ci buf[n] = '.'; 1014c5f01b2fSopenharmony_ci return buf + (static_cast<size_t>(k) + 1U); 1015c5f01b2fSopenharmony_ci } 1016c5f01b2fSopenharmony_ci 1017c5f01b2fSopenharmony_ci if (min_exp < n && n <= 0) 1018c5f01b2fSopenharmony_ci { 1019c5f01b2fSopenharmony_ci // 0.[000]digits 1020c5f01b2fSopenharmony_ci // len <= 2 + (-min_exp - 1) + max_digits10 1021c5f01b2fSopenharmony_ci 1022c5f01b2fSopenharmony_ci std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k)); 1023c5f01b2fSopenharmony_ci buf[0] = '0'; 1024c5f01b2fSopenharmony_ci buf[1] = '.'; 1025c5f01b2fSopenharmony_ci std::memset(buf + 2, '0', static_cast<size_t>(-n)); 1026c5f01b2fSopenharmony_ci return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k)); 1027c5f01b2fSopenharmony_ci } 1028c5f01b2fSopenharmony_ci 1029c5f01b2fSopenharmony_ci if (k == 1) 1030c5f01b2fSopenharmony_ci { 1031c5f01b2fSopenharmony_ci // dE+123 1032c5f01b2fSopenharmony_ci // len <= 1 + 5 1033c5f01b2fSopenharmony_ci 1034c5f01b2fSopenharmony_ci buf += 1; 1035c5f01b2fSopenharmony_ci } 1036c5f01b2fSopenharmony_ci else 1037c5f01b2fSopenharmony_ci { 1038c5f01b2fSopenharmony_ci // d.igitsE+123 1039c5f01b2fSopenharmony_ci // len <= max_digits10 + 1 + 5 1040c5f01b2fSopenharmony_ci 1041c5f01b2fSopenharmony_ci std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1); 1042c5f01b2fSopenharmony_ci buf[1] = '.'; 1043c5f01b2fSopenharmony_ci buf += 1 + static_cast<size_t>(k); 1044c5f01b2fSopenharmony_ci } 1045c5f01b2fSopenharmony_ci 1046c5f01b2fSopenharmony_ci *buf++ = 'e'; 1047c5f01b2fSopenharmony_ci return append_exponent(buf, n - 1); 1048c5f01b2fSopenharmony_ci} 1049c5f01b2fSopenharmony_ci 1050c5f01b2fSopenharmony_ci} // namespace dtoa_impl 1051c5f01b2fSopenharmony_ci 1052c5f01b2fSopenharmony_ci/*! 1053c5f01b2fSopenharmony_ci@brief generates a decimal representation of the floating-point number value in [first, last). 1054c5f01b2fSopenharmony_ci 1055c5f01b2fSopenharmony_ciThe format of the resulting decimal representation is similar to printf's %g 1056c5f01b2fSopenharmony_ciformat. Returns an iterator pointing past-the-end of the decimal representation. 1057c5f01b2fSopenharmony_ci 1058c5f01b2fSopenharmony_ci@note The input number must be finite, i.e. NaN's and Inf's are not supported. 1059c5f01b2fSopenharmony_ci@note The buffer must be large enough. 1060c5f01b2fSopenharmony_ci@note The result is NOT null-terminated. 1061c5f01b2fSopenharmony_ci*/ 1062c5f01b2fSopenharmony_citemplate<typename FloatType> 1063c5f01b2fSopenharmony_ciJSON_HEDLEY_NON_NULL(1, 2) 1064c5f01b2fSopenharmony_ciJSON_HEDLEY_RETURNS_NON_NULL 1065c5f01b2fSopenharmony_cichar* to_chars(char* first, const char* last, FloatType value) 1066c5f01b2fSopenharmony_ci{ 1067c5f01b2fSopenharmony_ci static_cast<void>(last); // maybe unused - fix warning 1068c5f01b2fSopenharmony_ci JSON_ASSERT(std::isfinite(value)); 1069c5f01b2fSopenharmony_ci 1070c5f01b2fSopenharmony_ci // Use signbit(value) instead of (value < 0) since signbit works for -0. 1071c5f01b2fSopenharmony_ci if (std::signbit(value)) 1072c5f01b2fSopenharmony_ci { 1073c5f01b2fSopenharmony_ci value = -value; 1074c5f01b2fSopenharmony_ci *first++ = '-'; 1075c5f01b2fSopenharmony_ci } 1076c5f01b2fSopenharmony_ci 1077c5f01b2fSopenharmony_ci#ifdef __GNUC__ 1078c5f01b2fSopenharmony_ci#pragma GCC diagnostic push 1079c5f01b2fSopenharmony_ci#pragma GCC diagnostic ignored "-Wfloat-equal" 1080c5f01b2fSopenharmony_ci#endif 1081c5f01b2fSopenharmony_ci if (value == 0) // +-0 1082c5f01b2fSopenharmony_ci { 1083c5f01b2fSopenharmony_ci *first++ = '0'; 1084c5f01b2fSopenharmony_ci // Make it look like a floating-point number (#362, #378) 1085c5f01b2fSopenharmony_ci *first++ = '.'; 1086c5f01b2fSopenharmony_ci *first++ = '0'; 1087c5f01b2fSopenharmony_ci return first; 1088c5f01b2fSopenharmony_ci } 1089c5f01b2fSopenharmony_ci#ifdef __GNUC__ 1090c5f01b2fSopenharmony_ci#pragma GCC diagnostic pop 1091c5f01b2fSopenharmony_ci#endif 1092c5f01b2fSopenharmony_ci 1093c5f01b2fSopenharmony_ci JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10); 1094c5f01b2fSopenharmony_ci 1095c5f01b2fSopenharmony_ci // Compute v = buffer * 10^decimal_exponent. 1096c5f01b2fSopenharmony_ci // The decimal digits are stored in the buffer, which needs to be interpreted 1097c5f01b2fSopenharmony_ci // as an unsigned decimal integer. 1098c5f01b2fSopenharmony_ci // len is the length of the buffer, i.e. the number of decimal digits. 1099c5f01b2fSopenharmony_ci int len = 0; 1100c5f01b2fSopenharmony_ci int decimal_exponent = 0; 1101c5f01b2fSopenharmony_ci dtoa_impl::grisu2(first, len, decimal_exponent, value); 1102c5f01b2fSopenharmony_ci 1103c5f01b2fSopenharmony_ci JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10); 1104c5f01b2fSopenharmony_ci 1105c5f01b2fSopenharmony_ci // Format the buffer like printf("%.*g", prec, value) 1106c5f01b2fSopenharmony_ci constexpr int kMinExp = -4; 1107c5f01b2fSopenharmony_ci // Use digits10 here to increase compatibility with version 2. 1108c5f01b2fSopenharmony_ci constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10; 1109c5f01b2fSopenharmony_ci 1110c5f01b2fSopenharmony_ci JSON_ASSERT(last - first >= kMaxExp + 2); 1111c5f01b2fSopenharmony_ci JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10); 1112c5f01b2fSopenharmony_ci JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6); 1113c5f01b2fSopenharmony_ci 1114c5f01b2fSopenharmony_ci return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); 1115c5f01b2fSopenharmony_ci} 1116c5f01b2fSopenharmony_ci 1117c5f01b2fSopenharmony_ci} // namespace detail 1118c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_END 1119