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

source code of boost/libs/charconv/include/boost/charconv/detail/fast_float/float_common.hpp