GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: detail/charconv/detail/fast_float/float_common.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 52 83 62.7%
Functions: 21 25 84.0%
Branches: 20 192 10.4%

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