Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-10 08:41:18

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