LCOV - code coverage report
Current view: top level - json/detail/charconv/detail/fast_float - float_common.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 62.7 % 83 52 31
Test Date: 2026-07-09 14:05:02 Functions: 84.0 % 25 21 4

           TLA  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 HIT     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 MIS           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 HIT     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 MIS           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 HIT     2008629 :   assert(input_num > 0);
     148         2008629 :   if (cpp20_and_in_constexpr()) {
     149 MIS           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 HIT     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 MIS           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 HIT     2010874 :   if (cpp20_and_in_constexpr()) {
     200 MIS           0 :     value128 answer;
     201               0 :     answer.low = umul128_generic(a, b, &answer.high);
     202               0 :     return answer;
     203                 :   }
     204 HIT     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 MIS           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 HIT        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 MIS           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