Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 08:19:38

0001 // Copyright 2020-2023 Daniel Lemire
0002 // Copyright 2023 Matt Borland
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // https://www.boost.org/LICENSE_1_0.txt
0005 //
0006 // Derivative of: https://github.com/fastfloat/fast_float
0007 
0008 #ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_FLOAT_COMMON_HPP
0009 #define BOOST_CHARCONV_DETAIL_FASTFLOAT_FLOAT_COMMON_HPP
0010 
0011 #include <boost/charconv/detail/fast_float/constexpr_feature_detect.hpp>
0012 #include <boost/charconv/detail/from_chars_result.hpp>
0013 #include <boost/charconv/detail/config.hpp>
0014 #include <boost/charconv/chars_format.hpp>
0015 #include <cfloat>
0016 #include <cstdint>
0017 #include <cassert>
0018 #include <cstring>
0019 #include <type_traits>
0020 #include <system_error>
0021 
0022 namespace boost { namespace charconv { namespace detail { namespace fast_float {
0023 
0024 
0025 template <typename UC>
0026 struct parse_options_t {
0027   constexpr explicit parse_options_t(chars_format fmt = chars_format::general,
0028     UC dot = UC('.'))
0029     : format(fmt), decimal_point(dot) {}
0030 
0031   /** Which number formats are accepted */
0032   chars_format format;
0033   /** The character used as decimal point */
0034   UC decimal_point;
0035 };
0036 using parse_options = parse_options_t<char>;
0037 
0038 }}}}
0039 
0040 #if BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST
0041 #include <bit>
0042 #endif
0043 
0044 #if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)   \
0045        || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \
0046        || defined(__MINGW64__)                                          \
0047        || defined(__s390x__)                                            \
0048        || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) )
0049 #define BOOST_CHARCONV_FASTFLOAT_64BIT 1
0050 #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86)   \
0051      || defined(__arm__) || defined(_M_ARM) || defined(__ppc__)   \
0052      || defined(__MINGW32__) || defined(__EMSCRIPTEN__))
0053 #define BOOST_CHARCONV_FASTFLOAT_32BIT 1
0054 #else
0055   // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.
0056   // We can never tell the register width, but the SIZE_MAX is a good approximation.
0057   // UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max portability.
0058   #if SIZE_MAX == 0xffff
0059     #error Unknown platform (16-bit, unsupported)
0060   #elif SIZE_MAX == 0xffffffff
0061     #define BOOST_CHARCONV_FASTFLOAT_32BIT 1
0062   #elif SIZE_MAX == 0xffffffffffffffff
0063     #define BOOST_CHARCONV_FASTFLOAT_64BIT 1
0064   #else
0065     #error Unknown platform (not 32-bit, not 64-bit?)
0066   #endif
0067 #endif
0068 
0069 #if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__))
0070 #include <intrin.h>
0071 #endif
0072 
0073 #if defined(_MSC_VER) && !defined(__clang__)
0074 #define BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO 1
0075 #endif
0076 
0077 #if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
0078 #define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
0079 #elif defined _WIN32
0080 #define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
0081 #else
0082 #if defined(__APPLE__) || defined(__FreeBSD__)
0083 #include <machine/endian.h>
0084 #elif defined(sun) || defined(__sun)
0085 #include <sys/byteorder.h>
0086 #else
0087 #ifdef __has_include
0088 #if __has_include(<endian.h>)
0089 #include <endian.h>
0090 #endif //__has_include(<endian.h>)
0091 #endif //__has_include
0092 #endif
0093 #
0094 #ifndef __BYTE_ORDER__
0095 // safe choice
0096 #define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
0097 #endif
0098 #
0099 #ifndef __ORDER_LITTLE_ENDIAN__
0100 // safe choice
0101 #define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
0102 #endif
0103 #
0104 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0105 #define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
0106 #else
0107 #define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 1
0108 #endif
0109 #endif
0110 
0111 #ifndef BOOST_CHARCONV_FASTFLOAT_ASSERT
0112 #define BOOST_CHARCONV_FASTFLOAT_ASSERT(x)  { ((void)(x)); }
0113 #endif
0114 
0115 #ifndef BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT
0116 #define BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(x) { ((void)(x)); }
0117 #endif
0118 
0119 // rust style `try!()` macro, or `?` operator
0120 #define BOOST_CHARCONV_FASTFLOAT_TRY(x) { if (!(x)) return false; }
0121 
0122 namespace boost { namespace charconv { namespace detail { namespace fast_float {
0123 
0124 BOOST_FORCEINLINE constexpr bool cpp20_and_in_constexpr() {
0125 #if BOOST_CHARCONV_FASTFLOAT_HAS_IS_CONSTANT_EVALUATED
0126   return std::is_constant_evaluated();
0127 #else
0128   return false;
0129 #endif
0130 }
0131 
0132 // Compares two ASCII strings in a case insensitive manner.
0133 template <typename UC>
0134 inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 bool
0135 fastfloat_strncasecmp(UC const * input1, UC const * input2, size_t length) {
0136   char running_diff{0};
0137   for (size_t i = 0; i < length; ++i) {
0138     running_diff |= (char(input1[i]) ^ char(input2[i]));
0139   }
0140   return (running_diff == 0) || (running_diff == 32);
0141 }
0142 
0143 #ifndef FLT_EVAL_METHOD
0144 #error "FLT_EVAL_METHOD should be defined, please include cfloat."
0145 #endif
0146 
0147 // a pointer and a length to a contiguous block of memory
0148 template <typename T>
0149 struct span {
0150   const T* ptr;
0151   size_t length;
0152   constexpr span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {}
0153   constexpr span() : ptr(nullptr), length(0) {}
0154 
0155   constexpr size_t len() const noexcept {
0156     return length;
0157   }
0158 
0159   BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 const T& operator[](size_t index) const noexcept {
0160     BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(index < length);
0161     return ptr[index];
0162   }
0163 };
0164 
0165 struct value128 {
0166   uint64_t low;
0167   uint64_t high;
0168   constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
0169   constexpr value128() : low(0), high(0) {}
0170 };
0171 
0172 /* Helper C++11 constexpr generic implementation of leading_zeroes */
0173 BOOST_FORCEINLINE constexpr
0174 int leading_zeroes_generic(uint64_t input_num, int last_bit = 0) {
0175   return (
0176     ((input_num & uint64_t(0xffffffff00000000)) && (input_num >>= 32, last_bit |= 32)),
0177     ((input_num & uint64_t(        0xffff0000)) && (input_num >>= 16, last_bit |= 16)),
0178     ((input_num & uint64_t(            0xff00)) && (input_num >>=  8, last_bit |=  8)),
0179     ((input_num & uint64_t(              0xf0)) && (input_num >>=  4, last_bit |=  4)),
0180     ((input_num & uint64_t(               0xc)) && (input_num >>=  2, last_bit |=  2)),
0181     ((input_num & uint64_t(               0x2)) && (input_num >>=  1, last_bit |=  1)),
0182     63 - last_bit
0183   );
0184 }
0185 
0186 /* result might be undefined when input_num is zero */
0187 BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
0188 int leading_zeroes(uint64_t input_num) {
0189   assert(input_num > 0);
0190   if (cpp20_and_in_constexpr()) {
0191     return leading_zeroes_generic(input_num);
0192   }
0193 #ifdef BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO
0194   #if defined(_M_X64) || defined(_M_ARM64)
0195   unsigned long leading_zero = 0;
0196   // Search the mask data from most significant bit (MSB)
0197   // to least significant bit (LSB) for a set bit (1).
0198   _BitScanReverse64(&leading_zero, input_num);
0199   return (int)(63 - leading_zero);
0200   #else
0201   return leading_zeroes_generic(input_num);
0202   #endif
0203 #else
0204   return __builtin_clzll(input_num);
0205 #endif
0206 }
0207 
0208 // slow emulation routine for 32-bit
0209 BOOST_FORCEINLINE constexpr uint64_t emulu(uint32_t x, uint32_t y) {
0210     return x * static_cast<uint64_t>(y);
0211 }
0212 
0213 BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
0214 uint64_t umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) {
0215   uint64_t ad = emulu(static_cast<uint32_t>(ab >> 32), static_cast<uint32_t>(cd));
0216   uint64_t bd = emulu(static_cast<uint32_t>(ab), static_cast<uint32_t>(cd));
0217   uint64_t adbc = ad + emulu(static_cast<uint32_t>(ab), static_cast<uint32_t>(cd >> 32));
0218   uint64_t adbc_carry = !!(adbc < ad);
0219   uint64_t lo = bd + (adbc << 32);
0220   *hi = emulu(static_cast<uint32_t>(ab >> 32), static_cast<uint32_t>(cd >> 32)) + (adbc >> 32) +
0221         (adbc_carry << 32) + !!(lo < bd);
0222   return lo;
0223 }
0224 
0225 #ifdef BOOST_CHARCONV_FASTFLOAT_32BIT
0226 
0227 // slow emulation routine for 32-bit
0228 #if !defined(__MINGW64__)
0229 BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
0230 uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
0231   return umul128_generic(ab, cd, hi);
0232 }
0233 #endif // !__MINGW64__
0234 
0235 #endif // BOOST_CHARCONV_FASTFLOAT_32BIT
0236 
0237 
0238 // compute 64-bit a*b
0239 BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
0240 value128 full_multiplication(uint64_t a, uint64_t b) {
0241   if (cpp20_and_in_constexpr()) {
0242     value128 answer;
0243     answer.low = umul128_generic(a, b, &answer.high);
0244     return answer;
0245   }
0246   value128 answer;
0247 #if defined(_M_ARM64) && !defined(__MINGW32__)
0248   // ARM64 has native support for 64-bit multiplications, no need to emulate
0249   // But MinGW on ARM64 doesn't have native support for 64-bit multiplications
0250   answer.high = __umulh(a, b);
0251   answer.low = a * b;
0252 #elif defined(BOOST_CHARCONV_FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__))
0253   unsigned long long high;
0254   answer.low = _umul128(a, b, &high); // _umul128 not available on ARM64
0255   answer.high = static_cast<uint64_t>(high);
0256 #elif defined(BOOST_CHARCONV_FASTFLOAT_64BIT)
0257   __uint128_t r = (static_cast<__uint128_t>(a)) * b;
0258   answer.low = uint64_t(r);
0259   answer.high = uint64_t(r >> 64);
0260 #else
0261   answer.low = umul128_generic(a, b, &answer.high);
0262 #endif
0263   return answer;
0264 }
0265 
0266 struct adjusted_mantissa {
0267   uint64_t mantissa{0};
0268   int32_t power2{0}; // a negative value indicates an invalid result
0269   adjusted_mantissa() = default;
0270   constexpr bool operator==(const adjusted_mantissa &o) const {
0271     return mantissa == o.mantissa && power2 == o.power2;
0272   }
0273   constexpr bool operator!=(const adjusted_mantissa &o) const {
0274     return mantissa != o.mantissa || power2 != o.power2;
0275   }
0276 };
0277 
0278 // Bias so we can get the real exponent with an invalid adjusted_mantissa.
0279 constexpr static int32_t invalid_am_bias = -0x8000;
0280 
0281 // used for binary_format_lookup_tables<T>::max_mantissa
0282 constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
0283 
0284 template <typename T, typename U = void>
0285 struct binary_format_lookup_tables;
0286 
0287 template <typename T> struct binary_format : binary_format_lookup_tables<T> {
0288   using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;
0289 
0290   static inline constexpr int mantissa_explicit_bits();
0291   static inline constexpr int minimum_exponent();
0292   static inline constexpr int infinite_power();
0293   static inline constexpr int sign_index();
0294   static inline constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST
0295   static inline constexpr int max_exponent_fast_path();
0296   static inline constexpr int max_exponent_round_to_even();
0297   static inline constexpr int min_exponent_round_to_even();
0298   static inline constexpr uint64_t max_mantissa_fast_path(int64_t power);
0299   static inline constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST
0300   static inline constexpr int largest_power_of_ten();
0301   static inline constexpr int smallest_power_of_ten();
0302   static inline constexpr T exact_power_of_ten(int64_t power);
0303   static inline constexpr size_t max_digits();
0304   static inline constexpr equiv_uint exponent_mask();
0305   static inline constexpr equiv_uint mantissa_mask();
0306   static inline constexpr equiv_uint hidden_bit_mask();
0307 };
0308 
0309 template <typename U>
0310 struct binary_format_lookup_tables<double, U> {
0311   static constexpr double powers_of_ten[] = {
0312       1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,  1e10, 1e11,
0313       1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
0314 
0315   // Largest integer value v so that (5**index * v) <= 1<<53.
0316   // 0x10000000000000 == 1 << 53
0317   static constexpr std::uint64_t max_mantissa[] = {
0318     UINT64_C(0x10000000000000),
0319     UINT64_C(0x10000000000000) / UINT64_C(5),
0320     UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5)),
0321     UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0322     UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0323     UINT64_C(0x10000000000000) / (constant_55555),
0324     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5)),
0325     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
0326     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0327     UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0328     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555),
0329     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5)),
0330     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
0331     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0332     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555),
0333     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
0334     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
0335     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0336     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0337     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555),
0338     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
0339     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
0340     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0341     UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5))};
0342 };
0343 
0344 template <typename U>
0345 constexpr double binary_format_lookup_tables<double, U>::powers_of_ten[];
0346 
0347 template <typename U>
0348 constexpr uint64_t binary_format_lookup_tables<double, U>::max_mantissa[];
0349 
0350 template <typename U>
0351 struct binary_format_lookup_tables<float, U> {
0352   static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
0353                                      1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
0354 
0355   // Largest integer value v so that (5**index * v) <= 1<<24.
0356   // 0x1000000 == 1<<24
0357   static constexpr uint64_t max_mantissa[] = {
0358     UINT64_C(0x1000000),
0359     UINT64_C(0x1000000) / UINT64_C(5),
0360     UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5)),
0361     UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0362     UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0363     UINT64_C(0x1000000) / (constant_55555),
0364     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5)),
0365     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
0366     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0367     UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
0368     UINT64_C(0x1000000) / (constant_55555 * constant_55555),
0369     UINT64_C(0x1000000) / (constant_55555 * constant_55555 * UINT64_C(5))};
0370 };
0371 
0372 template <typename U>
0373 constexpr float binary_format_lookup_tables<float, U>::powers_of_ten[];
0374 
0375 template <typename U>
0376 constexpr uint64_t binary_format_lookup_tables<float, U>::max_mantissa[];
0377 
0378 template <> inline constexpr int binary_format<double>::min_exponent_fast_path() {
0379 #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
0380   return 0;
0381 #else
0382   return -22;
0383 #endif
0384 }
0385 
0386 template <> inline constexpr int binary_format<float>::min_exponent_fast_path() {
0387 #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
0388   return 0;
0389 #else
0390   return -10;
0391 #endif
0392 }
0393 
0394 template <> inline constexpr int binary_format<double>::mantissa_explicit_bits() {
0395   return 52;
0396 }
0397 template <> inline constexpr int binary_format<float>::mantissa_explicit_bits() {
0398   return 23;
0399 }
0400 
0401 template <> inline constexpr int binary_format<double>::max_exponent_round_to_even() {
0402   return 23;
0403 }
0404 
0405 template <> inline constexpr int binary_format<float>::max_exponent_round_to_even() {
0406   return 10;
0407 }
0408 
0409 template <> inline constexpr int binary_format<double>::min_exponent_round_to_even() {
0410   return -4;
0411 }
0412 
0413 template <> inline constexpr int binary_format<float>::min_exponent_round_to_even() {
0414   return -17;
0415 }
0416 
0417 template <> inline constexpr int binary_format<double>::minimum_exponent() {
0418   return -1023;
0419 }
0420 template <> inline constexpr int binary_format<float>::minimum_exponent() {
0421   return -127;
0422 }
0423 
0424 template <> inline constexpr int binary_format<double>::infinite_power() {
0425   return 0x7FF;
0426 }
0427 template <> inline constexpr int binary_format<float>::infinite_power() {
0428   return 0xFF;
0429 }
0430 
0431 template <> inline constexpr int binary_format<double>::sign_index() { return 63; }
0432 template <> inline constexpr int binary_format<float>::sign_index() { return 31; }
0433 
0434 template <> inline constexpr int binary_format<double>::max_exponent_fast_path() {
0435   return 22;
0436 }
0437 template <> inline constexpr int binary_format<float>::max_exponent_fast_path() {
0438   return 10;
0439 }
0440 
0441 template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
0442   return uint64_t(2) << mantissa_explicit_bits();
0443 }
0444 template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) {
0445   // caller is responsible to ensure that
0446   // power >= 0 && power <= 22
0447   //
0448   // Work around clang bug https://godbolt.org/z/zedh7rrhc
0449   return (void)max_mantissa[0], max_mantissa[power];
0450 }
0451 template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {
0452   return uint64_t(2) << mantissa_explicit_bits();
0453 }
0454 template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) {
0455   // caller is responsible to ensure that
0456   // power >= 0 && power <= 10
0457   //
0458   // Work around clang bug https://godbolt.org/z/zedh7rrhc
0459   return (void)max_mantissa[0], max_mantissa[power];
0460 }
0461 
0462 template <>
0463 inline constexpr double binary_format<double>::exact_power_of_ten(int64_t power) {
0464   // Work around clang bug https://godbolt.org/z/zedh7rrhc
0465   return (void)powers_of_ten[0], powers_of_ten[power];
0466 }
0467 template <>
0468 inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
0469   // Work around clang bug https://godbolt.org/z/zedh7rrhc
0470   return (void)powers_of_ten[0], powers_of_ten[power];
0471 }
0472 
0473 
0474 template <>
0475 inline constexpr int binary_format<double>::largest_power_of_ten() {
0476   return 308;
0477 }
0478 template <>
0479 inline constexpr int binary_format<float>::largest_power_of_ten() {
0480   return 38;
0481 }
0482 
0483 template <>
0484 inline constexpr int binary_format<double>::smallest_power_of_ten() {
0485   return -342;
0486 }
0487 template <>
0488 inline constexpr int binary_format<float>::smallest_power_of_ten() {
0489   return -65;
0490 }
0491 
0492 template <> inline constexpr size_t binary_format<double>::max_digits() {
0493   return 769;
0494 }
0495 template <> inline constexpr size_t binary_format<float>::max_digits() {
0496   return 114;
0497 }
0498 
0499 template <> inline constexpr binary_format<float>::equiv_uint
0500     binary_format<float>::exponent_mask() {
0501   return 0x7F800000;
0502 }
0503 template <> inline constexpr binary_format<double>::equiv_uint
0504     binary_format<double>::exponent_mask() {
0505   return 0x7FF0000000000000;
0506 }
0507 
0508 template <> inline constexpr binary_format<float>::equiv_uint
0509     binary_format<float>::mantissa_mask() {
0510   return 0x007FFFFF;
0511 }
0512 template <> inline constexpr binary_format<double>::equiv_uint
0513     binary_format<double>::mantissa_mask() {
0514   return 0x000FFFFFFFFFFFFF;
0515 }
0516 
0517 template <> inline constexpr binary_format<float>::equiv_uint
0518     binary_format<float>::hidden_bit_mask() {
0519   return 0x00800000;
0520 }
0521 template <> inline constexpr binary_format<double>::equiv_uint
0522     binary_format<double>::hidden_bit_mask() {
0523   return 0x0010000000000000;
0524 }
0525 
0526 template<typename T>
0527 BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
0528 void to_float(bool negative, adjusted_mantissa am, T &value) {
0529   using uint = typename binary_format<T>::equiv_uint;
0530   uint word = static_cast<uint>(am.mantissa);
0531   word |= uint(am.power2) << binary_format<T>::mantissa_explicit_bits();
0532   word |= uint(negative) << binary_format<T>::sign_index();
0533 #if BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST
0534   value = std::bit_cast<T>(word);
0535 #else
0536   ::memcpy(&value, &word, sizeof(T));
0537 #endif
0538 }
0539 
0540 #ifdef BOOST_CHARCONV_FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
0541 template <typename = void>
0542 struct space_lut {
0543   static constexpr bool value[] = {
0544     0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0545     0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0546     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0547     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0548     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0549     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0550     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0551     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0552     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0553     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0554     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
0555 };
0556 
0557 template <typename T>
0558 constexpr bool space_lut<T>::value[];
0559 
0560 inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; }
0561 #endif
0562 
0563 template<typename UC>
0564 static constexpr uint64_t int_cmp_zeros()
0565 {
0566     static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), "Unsupported character size");
0567     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'));
0568 }
0569 template<typename UC>
0570 static constexpr int int_cmp_len()
0571 {
0572     return sizeof(uint64_t) / sizeof(UC);
0573 }
0574 template<typename UC>
0575 static constexpr UC const * str_const_nan()
0576 {
0577     return nullptr;
0578 }
0579 template<>
0580 constexpr char const * str_const_nan<char>()
0581 {
0582     return "nan";
0583 }
0584 template<>
0585 constexpr wchar_t const * str_const_nan<wchar_t>()
0586 {
0587     return L"nan";
0588 }
0589 template<>
0590 constexpr char16_t const * str_const_nan<char16_t>()
0591 {
0592     return u"nan";
0593 }
0594 template<>
0595 constexpr char32_t const * str_const_nan<char32_t>()
0596 {
0597     return U"nan";
0598 }
0599 template<typename UC>
0600 static constexpr UC const * str_const_inf()
0601 {
0602     return nullptr;
0603 }
0604 template<>
0605 constexpr char const * str_const_inf<char>()
0606 {
0607     return "infinity";
0608 }
0609 template<>
0610 constexpr wchar_t const * str_const_inf<wchar_t>()
0611 {
0612     return L"infinity";
0613 }
0614 template<>
0615 constexpr char16_t const * str_const_inf<char16_t>()
0616 {
0617     return u"infinity";
0618 }
0619 template<>
0620 constexpr char32_t const * str_const_inf<char32_t>()
0621 {
0622     return U"infinity";
0623 }
0624 
0625 }}}} // namespaces
0626 
0627 #endif