LCOV - code coverage report
Current view: top level - json/detail/charconv/detail/fast_float - float_common.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 62.7 % 83 52
Test Date: 2026-02-13 18:42:28 Functions: 84.0 % 25 21

            Line data    Source code
       1              : // Copyright 2020-2023 Daniel Lemire
       2              : // Copyright 2023 Matt Borland
       3              : // Distributed under the Boost Software License, Version 1.0.
       4              : // https://www.boost.org/LICENSE_1_0.txt
       5              : //
       6              : // Derivative of: https://github.com/fastfloat/fast_float
       7              : 
       8              : #ifndef BOOST_JSON_DETAIL_CHARCONV_DETAIL_FASTFLOAT_FLOAT_COMMON_HPP
       9              : #define BOOST_JSON_DETAIL_CHARCONV_DETAIL_FASTFLOAT_FLOAT_COMMON_HPP
      10              : 
      11              : #include <boost/json/detail/charconv/detail/fast_float/constexpr_feature_detect.hpp>
      12              : #include <boost/json/detail/charconv/detail/from_chars_result.hpp>
      13              : #include <boost/json/detail/charconv/detail/config.hpp>
      14              : #include <boost/json/detail/charconv/chars_format.hpp>
      15              : #include <cfloat>
      16              : #include <cstdint>
      17              : #include <cassert>
      18              : #include <cstring>
      19              : #include <type_traits>
      20              : #include <system_error>
      21              : 
      22              : namespace boost { namespace json { namespace detail { namespace charconv { namespace detail { namespace fast_float {
      23              : 
      24              : 
      25              : template <typename UC>
      26              : struct parse_options_t {
      27      1009310 :   constexpr explicit parse_options_t(chars_format fmt = chars_format::general,
      28              :     UC dot = UC('.'))
      29      1009310 :     : format(fmt), decimal_point(dot) {}
      30              : 
      31              :   /** Which number formats are accepted */
      32              :   chars_format format;
      33              :   /** The character used as decimal point */
      34              :   UC decimal_point;
      35              : };
      36              : using parse_options = parse_options_t<char>;
      37              : 
      38              : }}}}}}
      39              : 
      40              : #ifdef BOOST_JSON_HAS_BIT_CAST
      41              : #include <bit>
      42              : #endif
      43              : 
      44              : #if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)   \
      45              :        || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \
      46              :        || defined(__MINGW64__)                                          \
      47              :        || defined(__s390x__)                                            \
      48              :        || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) )
      49              : #define BOOST_JSON_FASTFLOAT_64BIT 1
      50              : #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86)   \
      51              :      || defined(__arm__) || defined(_M_ARM) || defined(__ppc__)   \
      52              :      || defined(__MINGW32__) || defined(__EMSCRIPTEN__))
      53              : #define BOOST_JSON_FASTFLOAT_32BIT 1
      54              : #else
      55              :   // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.
      56              :   // We can never tell the register width, but the SIZE_MAX is a good approximation.
      57              :   // UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max portability.
      58              :   #if SIZE_MAX == 0xffff
      59              :     #error Unknown platform (16-bit, unsupported)
      60              :   #elif SIZE_MAX == 0xffffffff
      61              :     #define BOOST_JSON_FASTFLOAT_32BIT 1
      62              :   #elif SIZE_MAX == 0xffffffffffffffff
      63              :     #define BOOST_JSON_FASTFLOAT_64BIT 1
      64              :   #else
      65              :     #error Unknown platform (not 32-bit, not 64-bit?)
      66              :   #endif
      67              : #endif
      68              : 
      69              : #if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__))
      70              : #include <intrin.h>
      71              : #endif
      72              : 
      73              : #if defined(_MSC_VER) && !defined(__clang__)
      74              : #define BOOST_JSON_FASTFLOAT_VISUAL_STUDIO 1
      75              : #endif
      76              : 
      77              : // rust style `try!()` macro, or `?` operator
      78              : #define BOOST_JSON_FASTFLOAT_TRY(x) { if (!(x)) return false; }
      79              : 
      80              : namespace boost { namespace json { namespace detail { namespace charconv { namespace detail { namespace fast_float {
      81              : 
      82              : BOOST_FORCEINLINE constexpr bool cpp20_and_in_constexpr() {
      83              : #ifdef BOOST_JSON_HAS_IS_CONSTANT_EVALUATED
      84              :   return std::is_constant_evaluated();
      85              : #else
      86      8902634 :   return false;
      87              : #endif
      88              : }
      89              : 
      90              : // Compares two ASCII strings in a case insensitive manner.
      91              : template <typename UC>
      92              : inline BOOST_JSON_CXX14_CONSTEXPR_NO_INLINE bool
      93            0 : fastfloat_strncasecmp(UC const * input1, UC const * input2, size_t length) {
      94            0 :   char running_diff{0};
      95            0 :   for (size_t i = 0; i < length; ++i) {
      96            0 :     running_diff |= (char(input1[i]) ^ char(input2[i]));
      97              :   }
      98            0 :   return (running_diff == 0) || (running_diff == 32);
      99              : }
     100              : 
     101              : #ifndef FLT_EVAL_METHOD
     102              : #error "FLT_EVAL_METHOD should be defined, please include cfloat."
     103              : #endif
     104              : 
     105              : // a pointer and a length to a contiguous block of memory
     106              : template <typename T>
     107              : struct span {
     108              :   const T* ptr;
     109              :   size_t length;
     110      2028274 :   constexpr span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {}
     111              :   constexpr span() : ptr(nullptr), length(0) {}
     112              : 
     113      1155768 :   constexpr size_t len() const noexcept {
     114      1155768 :     return length;
     115              :   }
     116              : 
     117        36365 :   BOOST_JSON_CXX14_CONSTEXPR const T& operator[](size_t index) const noexcept {
     118        36365 :     BOOST_ASSERT(index < length);
     119        36365 :     return ptr[index];
     120              :   }
     121              : };
     122              : 
     123              : struct value128 {
     124              :   uint64_t low;
     125              :   uint64_t high;
     126              :   constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
     127              :   constexpr value128() : low(0), high(0) {}
     128              : };
     129              : 
     130              : /* Helper C++11 constexpr generic implementation of leading_zeroes */
     131              : BOOST_FORCEINLINE constexpr
     132              : int leading_zeroes_generic(uint64_t input_num, int last_bit = 0) {
     133              :   return (
     134            0 :     ((input_num & uint64_t(0xffffffff00000000)) && (input_num >>= 32, last_bit |= 32)),
     135            0 :     ((input_num & uint64_t(        0xffff0000)) && (input_num >>= 16, last_bit |= 16)),
     136            0 :     ((input_num & uint64_t(            0xff00)) && (input_num >>=  8, last_bit |=  8)),
     137            0 :     ((input_num & uint64_t(              0xf0)) && (input_num >>=  4, last_bit |=  4)),
     138            0 :     ((input_num & uint64_t(               0xc)) && (input_num >>=  2, last_bit |=  2)),
     139            0 :     ((input_num & uint64_t(               0x2)) && (input_num >>=  1, last_bit |=  1)),
     140              :     63 - last_bit
     141            0 :   );
     142              : }
     143              : 
     144              : /* result might be undefined when input_num is zero */
     145              : BOOST_FORCEINLINE BOOST_JSON_FASTFLOAT_CONSTEXPR20
     146              : int leading_zeroes(uint64_t input_num) {
     147      2008629 :   assert(input_num > 0);
     148      2008629 :   if (cpp20_and_in_constexpr()) {
     149            0 :     return leading_zeroes_generic(input_num);
     150              :   }
     151              : #ifdef BOOST_JSON_FASTFLOAT_VISUAL_STUDIO
     152              :   #if defined(_M_X64) || defined(_M_ARM64)
     153              :   unsigned long leading_zero = 0;
     154              :   // Search the mask data from most significant bit (MSB)
     155              :   // to least significant bit (LSB) for a set bit (1).
     156              :   _BitScanReverse64(&leading_zero, input_num);
     157              :   return (int)(63 - leading_zero);
     158              :   #else
     159              :   return leading_zeroes_generic(input_num);
     160              :   #endif
     161              : #else
     162      2008629 :   return __builtin_clzll(input_num);
     163              : #endif
     164              : }
     165              : 
     166              : // slow emulation routine for 32-bit
     167              : BOOST_FORCEINLINE constexpr uint64_t emulu(uint32_t x, uint32_t y) {
     168            0 :     return x * (uint64_t)y;
     169              : }
     170              : 
     171              : BOOST_FORCEINLINE BOOST_JSON_CXX14_CONSTEXPR_NO_INLINE
     172              : uint64_t umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) {
     173            0 :   uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd);
     174            0 :   uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd);
     175            0 :   uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32));
     176            0 :   uint64_t adbc_carry = !!(adbc < ad);
     177            0 :   uint64_t lo = bd + (adbc << 32);
     178            0 :   *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
     179            0 :         (adbc_carry << 32) + !!(lo < bd);
     180            0 :   return lo;
     181              : }
     182              : 
     183              : #ifdef BOOST_JSON_FASTFLOAT_32BIT
     184              : 
     185              : // slow emulation routine for 32-bit
     186              : #if !defined(__MINGW64__)
     187              : BOOST_FORCEINLINE BOOST_JSON_CXX14_CONSTEXPR_NO_INLINE
     188              : uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
     189              :   return umul128_generic(ab, cd, hi);
     190              : }
     191              : #endif // !__MINGW64__
     192              : 
     193              : #endif // BOOST_JSON_FASTFLOAT_32BIT
     194              : 
     195              : 
     196              : // compute 64-bit a*b
     197              : BOOST_FORCEINLINE BOOST_JSON_FASTFLOAT_CONSTEXPR20
     198              : value128 full_multiplication(uint64_t a, uint64_t b) {
     199      2010874 :   if (cpp20_and_in_constexpr()) {
     200            0 :     value128 answer;
     201            0 :     answer.low = umul128_generic(a, b, &answer.high);
     202            0 :     return answer;
     203              :   }
     204      2010874 :   value128 answer;
     205              : #if defined(_M_ARM64) && !defined(__MINGW32__)
     206              :   // ARM64 has native support for 64-bit multiplications, no need to emulate
     207              :   // But MinGW on ARM64 doesn't have native support for 64-bit multiplications
     208              :   answer.high = __umulh(a, b);
     209              :   answer.low = a * b;
     210              : #elif defined(BOOST_JSON_FASTFLOAT_32BIT) ||                            \
     211              :     (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
     212              :   unsigned long long high;
     213              :   answer.low = _umul128(a, b, &high); // _umul128 not available on ARM64
     214              :   answer.high = static_cast<uint64_t>(high);
     215              : #elif defined(BOOST_JSON_FASTFLOAT_64BIT)
     216      2010874 :   __uint128_t r = ((__uint128_t)a) * b;
     217      2010874 :   answer.low = uint64_t(r);
     218      2010874 :   answer.high = uint64_t(r >> 64);
     219              : #else
     220              :   answer.low = umul128_generic(a, b, &answer.high);
     221              : #endif
     222      2010874 :   return answer;
     223              : }
     224              : 
     225              : struct adjusted_mantissa {
     226              :   uint64_t mantissa{0};
     227              :   int32_t power2{0}; // a negative value indicates an invalid result
     228              :   adjusted_mantissa() = default;
     229              :   constexpr bool operator==(const adjusted_mantissa &o) const {
     230              :     return mantissa == o.mantissa && power2 == o.power2;
     231              :   }
     232      1000712 :   constexpr bool operator!=(const adjusted_mantissa &o) const {
     233      1000712 :     return mantissa != o.mantissa || power2 != o.power2;
     234              :   }
     235              : };
     236              : 
     237              : // Bias so we can get the real exponent with an invalid adjusted_mantissa.
     238              : constexpr static int32_t invalid_am_bias = -0x8000;
     239              : 
     240              : // used for binary_format_lookup_tables<T>::max_mantissa
     241              : constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
     242              : 
     243              : template <typename T, typename U = void>
     244              : struct binary_format_lookup_tables;
     245              : 
     246              : template <typename T> struct binary_format : binary_format_lookup_tables<T> {
     247              :   using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;
     248              : 
     249              :   static inline constexpr int mantissa_explicit_bits();
     250              :   static inline constexpr int minimum_exponent();
     251              :   static inline constexpr int infinite_power();
     252              :   static inline constexpr int sign_index();
     253              :   static inline constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST
     254              :   static inline constexpr int max_exponent_fast_path();
     255              :   static inline constexpr int max_exponent_round_to_even();
     256              :   static inline constexpr int min_exponent_round_to_even();
     257              :   static inline constexpr uint64_t max_mantissa_fast_path(int64_t power);
     258              :   static inline constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST
     259              :   static inline constexpr int largest_power_of_ten();
     260              :   static inline constexpr int smallest_power_of_ten();
     261              :   static inline constexpr T exact_power_of_ten(int64_t power);
     262              :   static inline constexpr size_t max_digits();
     263              :   static inline constexpr equiv_uint exponent_mask();
     264              :   static inline constexpr equiv_uint mantissa_mask();
     265              :   static inline constexpr equiv_uint hidden_bit_mask();
     266              : };
     267              : 
     268              : template <typename U>
     269              : struct binary_format_lookup_tables<double, U> {
     270              :   static constexpr double powers_of_ten[] = {
     271              :       1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,  1e10, 1e11,
     272              :       1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
     273              : 
     274              :   // Largest integer value v so that (5**index * v) <= 1<<53.
     275              :   // 0x10000000000000 == 1 << 53
     276              :   static constexpr std::uint64_t max_mantissa[] = {
     277              :     UINT64_C(0x10000000000000),
     278              :     UINT64_C(0x10000000000000) / UINT64_C(5),
     279              :     UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5)),
     280              :     UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     281              :     UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     282              :     UINT64_C(0x10000000000000) / (constant_55555),
     283              :     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5)),
     284              :     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
     285              :     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     286              :     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     287              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555),
     288              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5)),
     289              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
     290              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     291              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555),
     292              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
     293              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
     294              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     295              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     296              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555),
     297              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
     298              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
     299              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     300              :     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5))};
     301              : };
     302              : 
     303              : template <typename U>
     304              : constexpr double binary_format_lookup_tables<double, U>::powers_of_ten[];
     305              : 
     306              : template <typename U>
     307              : constexpr uint64_t binary_format_lookup_tables<double, U>::max_mantissa[];
     308              : 
     309              : template <typename U>
     310              : struct binary_format_lookup_tables<float, U> {
     311              :   static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
     312              :                                      1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
     313              : 
     314              :   // Largest integer value v so that (5**index * v) <= 1<<24.
     315              :   // 0x1000000 == 1<<24
     316              :   static constexpr uint64_t max_mantissa[] = {
     317              :     UINT64_C(0x1000000),
     318              :     UINT64_C(0x1000000) / UINT64_C(5),
     319              :     UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5)),
     320              :     UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     321              :     UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     322              :     UINT64_C(0x1000000) / (constant_55555),
     323              :     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5)),
     324              :     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
     325              :     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     326              :     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
     327              :     UINT64_C(0x1000000) / (constant_55555 * constant_55555),
     328              :     UINT64_C(0x1000000) / (constant_55555 * constant_55555 * UINT64_C(5))};
     329              : };
     330              : 
     331              : template <typename U>
     332              : constexpr float binary_format_lookup_tables<float, U>::powers_of_ten[];
     333              : 
     334              : template <typename U>
     335              : constexpr uint64_t binary_format_lookup_tables<float, U>::max_mantissa[];
     336              : 
     337      1009310 : template <> inline constexpr int binary_format<double>::min_exponent_fast_path() {
     338              : #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
     339              :   return 0;
     340              : #else
     341      1009310 :   return -22;
     342              : #endif
     343              : }
     344              : 
     345              : template <> inline constexpr int binary_format<float>::min_exponent_fast_path() {
     346              : #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
     347              :   return 0;
     348              : #else
     349              :   return -10;
     350              : #endif
     351              : }
     352              : 
     353      7032865 : template <> inline constexpr int binary_format<double>::mantissa_explicit_bits() {
     354      7032865 :   return 52;
     355              : }
     356              : template <> inline constexpr int binary_format<float>::mantissa_explicit_bits() {
     357              :   return 23;
     358              : }
     359              : 
     360         8893 : template <> inline constexpr int binary_format<double>::max_exponent_round_to_even() {
     361         8893 :   return 23;
     362              : }
     363              : 
     364              : template <> inline constexpr int binary_format<float>::max_exponent_round_to_even() {
     365              :   return 10;
     366              : }
     367              : 
     368         9255 : template <> inline constexpr int binary_format<double>::min_exponent_round_to_even() {
     369         9255 :   return -4;
     370              : }
     371              : 
     372              : template <> inline constexpr int binary_format<float>::min_exponent_round_to_even() {
     373              :   return -17;
     374              : }
     375              : 
     376      2002893 : template <> inline constexpr int binary_format<double>::minimum_exponent() {
     377      2002893 :   return -1023;
     378              : }
     379              : template <> inline constexpr int binary_format<float>::minimum_exponent() {
     380              :   return -127;
     381              : }
     382              : 
     383      3072364 : template <> inline constexpr int binary_format<double>::infinite_power() {
     384      3072364 :   return 0x7FF;
     385              : }
     386              : template <> inline constexpr int binary_format<float>::infinite_power() {
     387              :   return 0xFF;
     388              : }
     389              : 
     390      1005351 : template <> inline constexpr int binary_format<double>::sign_index() { return 63; }
     391              : template <> inline constexpr int binary_format<float>::sign_index() { return 31; }
     392              : 
     393       546058 : template <> inline constexpr int binary_format<double>::max_exponent_fast_path() {
     394       546058 :   return 22;
     395              : }
     396              : template <> inline constexpr int binary_format<float>::max_exponent_fast_path() {
     397              :   return 10;
     398              : }
     399              : 
     400         5895 : template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
     401         5895 :   return uint64_t(2) << mantissa_explicit_bits();
     402              : }
     403            0 : template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) {
     404              :   // caller is responsible to ensure that
     405              :   // power >= 0 && power <= 22
     406              :   //
     407              :   // Work around clang bug https://godbolt.org/z/zedh7rrhc
     408            0 :   return (void)max_mantissa[0], max_mantissa[power];
     409              : }
     410              : template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {
     411              :   return uint64_t(2) << mantissa_explicit_bits();
     412              : }
     413              : template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) {
     414              :   // caller is responsible to ensure that
     415              :   // power >= 0 && power <= 10
     416              :   //
     417              :   // Work around clang bug https://godbolt.org/z/zedh7rrhc
     418              :   return (void)max_mantissa[0], max_mantissa[power];
     419              : }
     420              : 
     421              : template <>
     422         5570 : inline constexpr double binary_format<double>::exact_power_of_ten(int64_t power) {
     423              :   // Work around clang bug https://godbolt.org/z/zedh7rrhc
     424         5570 :   return (void)powers_of_ten[0], powers_of_ten[power];
     425              : }
     426              : template <>
     427              : inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
     428              :   // Work around clang bug https://godbolt.org/z/zedh7rrhc
     429              :   return (void)powers_of_ten[0], powers_of_ten[power];
     430              : }
     431              : 
     432              : 
     433              : template <>
     434      2004451 : inline constexpr int binary_format<double>::largest_power_of_ten() {
     435      2004451 :   return 308;
     436              : }
     437              : template <>
     438              : inline constexpr int binary_format<float>::largest_power_of_ten() {
     439              :   return 38;
     440              : }
     441              : 
     442              : template <>
     443      2004451 : inline constexpr int binary_format<double>::smallest_power_of_ten() {
     444      2004451 :   return -342;
     445              : }
     446              : template <>
     447              : inline constexpr int binary_format<float>::smallest_power_of_ten() {
     448              :   return -65;
     449              : }
     450              : 
     451              : template <> inline constexpr size_t binary_format<double>::max_digits() {
     452              :   return 769;
     453              : }
     454              : template <> inline constexpr size_t binary_format<float>::max_digits() {
     455              :   return 114;
     456              : }
     457              : 
     458              : template <> inline constexpr binary_format<float>::equiv_uint
     459              :     binary_format<float>::exponent_mask() {
     460              :   return 0x7F800000;
     461              : }
     462              : template <> inline constexpr binary_format<double>::equiv_uint
     463              :     binary_format<double>::exponent_mask() {
     464              :   return 0x7FF0000000000000;
     465              : }
     466              : 
     467              : template <> inline constexpr binary_format<float>::equiv_uint
     468              :     binary_format<float>::mantissa_mask() {
     469              :   return 0x007FFFFF;
     470              : }
     471              : template <> inline constexpr binary_format<double>::equiv_uint
     472              :     binary_format<double>::mantissa_mask() {
     473              :   return 0x000FFFFFFFFFFFFF;
     474              : }
     475              : 
     476              : template <> inline constexpr binary_format<float>::equiv_uint
     477              :     binary_format<float>::hidden_bit_mask() {
     478              :   return 0x00800000;
     479              : }
     480              : template <> inline constexpr binary_format<double>::equiv_uint
     481              :     binary_format<double>::hidden_bit_mask() {
     482              :   return 0x0010000000000000;
     483              : }
     484              : 
     485              : template<typename T>
     486              : BOOST_FORCEINLINE BOOST_JSON_FASTFLOAT_CONSTEXPR20
     487              : void to_float(bool negative, adjusted_mantissa am, T &value) {
     488              :   using uint = typename binary_format<T>::equiv_uint;
     489      1005351 :   uint word = (uint)am.mantissa;
     490      1005351 :   word |= uint(am.power2) << binary_format<T>::mantissa_explicit_bits();
     491      1005351 :   word |= uint(negative) << binary_format<T>::sign_index();
     492              : #ifdef BOOST_JSON_HAS_BIT_CAST
     493              :   value = std::bit_cast<T>(word);
     494              : #else
     495      1005351 :   ::memcpy(&value, &word, sizeof(T));
     496              : #endif
     497      1005351 : }
     498              : 
     499              : template<typename UC>
     500         2986 : static constexpr uint64_t int_cmp_zeros()
     501              : {
     502              :     static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), "Unsupported character size");
     503         2986 :     return (sizeof(UC) == 1) ? 0x3030303030303030 : (sizeof(UC) == 2) ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | uint64_t(UC('0')) << 16 | UC('0')) : (uint64_t(UC('0')) << 32 | UC('0'));
     504              : }
     505              : template<typename UC>
     506         2986 : static constexpr int int_cmp_len()
     507              : {
     508         2986 :     return sizeof(uint64_t) / sizeof(UC);
     509              : }
     510              : template<typename UC>
     511              : static constexpr UC const * str_const_nan()
     512              : {
     513              :     return nullptr;
     514              : }
     515              : template<>
     516            0 : constexpr char const * str_const_nan<char>()
     517              : {
     518            0 :     return "nan";
     519              : }
     520              : template<>
     521              : constexpr wchar_t const * str_const_nan<wchar_t>()
     522              : {
     523              :     return L"nan";
     524              : }
     525              : template<>
     526              : constexpr char16_t const * str_const_nan<char16_t>()
     527              : {
     528              :     return u"nan";
     529              : }
     530              : template<>
     531              : constexpr char32_t const * str_const_nan<char32_t>()
     532              : {
     533              :     return U"nan";
     534              : }
     535              : template<typename UC>
     536              : static constexpr UC const * str_const_inf()
     537              : {
     538              :     return nullptr;
     539              : }
     540              : template<>
     541            0 : constexpr char const * str_const_inf<char>()
     542              : {
     543            0 :     return "infinity";
     544              : }
     545              : template<>
     546              : constexpr wchar_t const * str_const_inf<wchar_t>()
     547              : {
     548              :     return L"infinity";
     549              : }
     550              : template<>
     551              : constexpr char16_t const * str_const_inf<char16_t>()
     552              : {
     553              :     return u"infinity";
     554              : }
     555              : template<>
     556              : constexpr char32_t const * str_const_inf<char32_t>()
     557              : {
     558              :     return U"infinity";
     559              : }
     560              : 
     561              : }}}}}} // namespaces
     562              : 
     563              : #endif
        

Generated by: LCOV version 2.3