float_common.hpp 22 KB

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