float_common.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  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) || \
  221. (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
  222. unsigned long long high;
  223. answer.low = _umul128(a, b, &high); // _umul128 not available on ARM64
  224. answer.high = static_cast<uint64_t>(high);
  225. #elif defined(BOOST_CHARCONV_FASTFLOAT_64BIT)
  226. __uint128_t r = (static_cast<__uint128_t>(a)) * b;
  227. answer.low = uint64_t(r);
  228. answer.high = uint64_t(r >> 64);
  229. #else
  230. answer.low = umul128_generic(a, b, &answer.high);
  231. #endif
  232. return answer;
  233. }
  234. struct adjusted_mantissa {
  235. uint64_t mantissa{0};
  236. int32_t power2{0}; // a negative value indicates an invalid result
  237. adjusted_mantissa() = default;
  238. constexpr bool operator==(const adjusted_mantissa &o) const {
  239. return mantissa == o.mantissa && power2 == o.power2;
  240. }
  241. constexpr bool operator!=(const adjusted_mantissa &o) const {
  242. return mantissa != o.mantissa || power2 != o.power2;
  243. }
  244. };
  245. // Bias so we can get the real exponent with an invalid adjusted_mantissa.
  246. constexpr static int32_t invalid_am_bias = -0x8000;
  247. // used for binary_format_lookup_tables<T>::max_mantissa
  248. constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
  249. template <typename T, typename U = void>
  250. struct binary_format_lookup_tables;
  251. template <typename T> struct binary_format : binary_format_lookup_tables<T> {
  252. using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;
  253. static inline constexpr int mantissa_explicit_bits();
  254. static inline constexpr int minimum_exponent();
  255. static inline constexpr int infinite_power();
  256. static inline constexpr int sign_index();
  257. static inline constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST
  258. static inline constexpr int max_exponent_fast_path();
  259. static inline constexpr int max_exponent_round_to_even();
  260. static inline constexpr int min_exponent_round_to_even();
  261. static inline constexpr uint64_t max_mantissa_fast_path(int64_t power);
  262. static inline constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST
  263. static inline constexpr int largest_power_of_ten();
  264. static inline constexpr int smallest_power_of_ten();
  265. static inline constexpr T exact_power_of_ten(int64_t power);
  266. static inline constexpr size_t max_digits();
  267. static inline constexpr equiv_uint exponent_mask();
  268. static inline constexpr equiv_uint mantissa_mask();
  269. static inline constexpr equiv_uint hidden_bit_mask();
  270. };
  271. template <typename U>
  272. struct binary_format_lookup_tables<double, U> {
  273. static constexpr double powers_of_ten[] = {
  274. 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
  275. 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
  276. // Largest integer value v so that (5**index * v) <= 1<<53.
  277. // 0x10000000000000 == 1 << 53
  278. static constexpr std::uint64_t max_mantissa[] = {
  279. UINT64_C(0x10000000000000),
  280. UINT64_C(0x10000000000000) / UINT64_C(5),
  281. UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5)),
  282. UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  283. UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  284. UINT64_C(0x10000000000000) / (constant_55555),
  285. UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5)),
  286. UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
  287. UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  288. UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  289. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555),
  290. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5)),
  291. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
  292. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  293. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555),
  294. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
  295. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * 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)),
  297. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  298. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555),
  299. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
  300. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 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)),
  302. UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5))};
  303. };
  304. template <typename U>
  305. constexpr double binary_format_lookup_tables<double, U>::powers_of_ten[];
  306. template <typename U>
  307. constexpr uint64_t binary_format_lookup_tables<double, U>::max_mantissa[];
  308. template <typename U>
  309. struct binary_format_lookup_tables<float, U> {
  310. static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
  311. 1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
  312. // Largest integer value v so that (5**index * v) <= 1<<24.
  313. // 0x1000000 == 1<<24
  314. static constexpr uint64_t max_mantissa[] = {
  315. UINT64_C(0x1000000),
  316. UINT64_C(0x1000000) / UINT64_C(5),
  317. UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5)),
  318. UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  319. UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  320. UINT64_C(0x1000000) / (constant_55555),
  321. UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5)),
  322. UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
  323. UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  324. UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
  325. UINT64_C(0x1000000) / (constant_55555 * constant_55555),
  326. UINT64_C(0x1000000) / (constant_55555 * constant_55555 * UINT64_C(5))};
  327. };
  328. template <typename U>
  329. constexpr float binary_format_lookup_tables<float, U>::powers_of_ten[];
  330. template <typename U>
  331. constexpr uint64_t binary_format_lookup_tables<float, U>::max_mantissa[];
  332. template <> inline constexpr int binary_format<double>::min_exponent_fast_path() {
  333. #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
  334. return 0;
  335. #else
  336. return -22;
  337. #endif
  338. }
  339. template <> inline constexpr int binary_format<float>::min_exponent_fast_path() {
  340. #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
  341. return 0;
  342. #else
  343. return -10;
  344. #endif
  345. }
  346. template <> inline constexpr int binary_format<double>::mantissa_explicit_bits() {
  347. return 52;
  348. }
  349. template <> inline constexpr int binary_format<float>::mantissa_explicit_bits() {
  350. return 23;
  351. }
  352. template <> inline constexpr int binary_format<double>::max_exponent_round_to_even() {
  353. return 23;
  354. }
  355. template <> inline constexpr int binary_format<float>::max_exponent_round_to_even() {
  356. return 10;
  357. }
  358. template <> inline constexpr int binary_format<double>::min_exponent_round_to_even() {
  359. return -4;
  360. }
  361. template <> inline constexpr int binary_format<float>::min_exponent_round_to_even() {
  362. return -17;
  363. }
  364. template <> inline constexpr int binary_format<double>::minimum_exponent() {
  365. return -1023;
  366. }
  367. template <> inline constexpr int binary_format<float>::minimum_exponent() {
  368. return -127;
  369. }
  370. template <> inline constexpr int binary_format<double>::infinite_power() {
  371. return 0x7FF;
  372. }
  373. template <> inline constexpr int binary_format<float>::infinite_power() {
  374. return 0xFF;
  375. }
  376. template <> inline constexpr int binary_format<double>::sign_index() { return 63; }
  377. template <> inline constexpr int binary_format<float>::sign_index() { return 31; }
  378. template <> inline constexpr int binary_format<double>::max_exponent_fast_path() {
  379. return 22;
  380. }
  381. template <> inline constexpr int binary_format<float>::max_exponent_fast_path() {
  382. return 10;
  383. }
  384. template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
  385. return uint64_t(2) << mantissa_explicit_bits();
  386. }
  387. template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) {
  388. // caller is responsible to ensure that
  389. // power >= 0 && power <= 22
  390. //
  391. // Work around clang bug https://godbolt.org/z/zedh7rrhc
  392. return (void)max_mantissa[0], max_mantissa[power];
  393. }
  394. template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {
  395. return uint64_t(2) << mantissa_explicit_bits();
  396. }
  397. template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) {
  398. // caller is responsible to ensure that
  399. // power >= 0 && power <= 10
  400. //
  401. // Work around clang bug https://godbolt.org/z/zedh7rrhc
  402. return (void)max_mantissa[0], max_mantissa[power];
  403. }
  404. template <>
  405. inline constexpr double binary_format<double>::exact_power_of_ten(int64_t power) {
  406. // Work around clang bug https://godbolt.org/z/zedh7rrhc
  407. return (void)powers_of_ten[0], powers_of_ten[power];
  408. }
  409. template <>
  410. inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
  411. // Work around clang bug https://godbolt.org/z/zedh7rrhc
  412. return (void)powers_of_ten[0], powers_of_ten[power];
  413. }
  414. template <>
  415. inline constexpr int binary_format<double>::largest_power_of_ten() {
  416. return 308;
  417. }
  418. template <>
  419. inline constexpr int binary_format<float>::largest_power_of_ten() {
  420. return 38;
  421. }
  422. template <>
  423. inline constexpr int binary_format<double>::smallest_power_of_ten() {
  424. return -342;
  425. }
  426. template <>
  427. inline constexpr int binary_format<float>::smallest_power_of_ten() {
  428. return -65;
  429. }
  430. template <> inline constexpr size_t binary_format<double>::max_digits() {
  431. return 769;
  432. }
  433. template <> inline constexpr size_t binary_format<float>::max_digits() {
  434. return 114;
  435. }
  436. template <> inline constexpr binary_format<float>::equiv_uint
  437. binary_format<float>::exponent_mask() {
  438. return 0x7F800000;
  439. }
  440. template <> inline constexpr binary_format<double>::equiv_uint
  441. binary_format<double>::exponent_mask() {
  442. return 0x7FF0000000000000;
  443. }
  444. template <> inline constexpr binary_format<float>::equiv_uint
  445. binary_format<float>::mantissa_mask() {
  446. return 0x007FFFFF;
  447. }
  448. template <> inline constexpr binary_format<double>::equiv_uint
  449. binary_format<double>::mantissa_mask() {
  450. return 0x000FFFFFFFFFFFFF;
  451. }
  452. template <> inline constexpr binary_format<float>::equiv_uint
  453. binary_format<float>::hidden_bit_mask() {
  454. return 0x00800000;
  455. }
  456. template <> inline constexpr binary_format<double>::equiv_uint
  457. binary_format<double>::hidden_bit_mask() {
  458. return 0x0010000000000000;
  459. }
  460. template<typename T>
  461. BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
  462. void to_float(bool negative, adjusted_mantissa am, T &value) {
  463. using uint = typename binary_format<T>::equiv_uint;
  464. uint word = static_cast<uint>(am.mantissa);
  465. word |= uint(am.power2) << binary_format<T>::mantissa_explicit_bits();
  466. word |= uint(negative) << binary_format<T>::sign_index();
  467. #if BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST
  468. value = std::bit_cast<T>(word);
  469. #else
  470. ::memcpy(&value, &word, sizeof(T));
  471. #endif
  472. }
  473. #ifdef BOOST_CHARCONV_FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
  474. template <typename = void>
  475. struct space_lut {
  476. static constexpr bool value[] = {
  477. 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  478. 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0,
  487. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  488. };
  489. template <typename T>
  490. constexpr bool space_lut<T>::value[];
  491. inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; }
  492. #endif
  493. template<typename UC>
  494. static constexpr uint64_t int_cmp_zeros()
  495. {
  496. static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), "Unsupported character size");
  497. 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'));
  498. }
  499. template<typename UC>
  500. static constexpr int int_cmp_len()
  501. {
  502. return sizeof(uint64_t) / sizeof(UC);
  503. }
  504. template<typename UC>
  505. static constexpr UC const * str_const_nan()
  506. {
  507. return nullptr;
  508. }
  509. template<>
  510. constexpr char const * str_const_nan<char>()
  511. {
  512. return "nan";
  513. }
  514. template<>
  515. constexpr wchar_t const * str_const_nan<wchar_t>()
  516. {
  517. return L"nan";
  518. }
  519. template<>
  520. constexpr char16_t const * str_const_nan<char16_t>()
  521. {
  522. return u"nan";
  523. }
  524. template<>
  525. constexpr char32_t const * str_const_nan<char32_t>()
  526. {
  527. return U"nan";
  528. }
  529. template<typename UC>
  530. static constexpr UC const * str_const_inf()
  531. {
  532. return nullptr;
  533. }
  534. template<>
  535. constexpr char const * str_const_inf<char>()
  536. {
  537. return "infinity";
  538. }
  539. template<>
  540. constexpr wchar_t const * str_const_inf<wchar_t>()
  541. {
  542. return L"infinity";
  543. }
  544. template<>
  545. constexpr char16_t const * str_const_inf<char16_t>()
  546. {
  547. return u"infinity";
  548. }
  549. template<>
  550. constexpr char32_t const * str_const_inf<char32_t>()
  551. {
  552. return U"infinity";
  553. }
  554. }}}} // namespaces
  555. #endif