Line data Source code
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 0 : fastfloat_strncasecmp(UC const * input1, UC const * input2, size_t length) {
94 0 : char running_diff{0};
95 0 : for (size_t i = 0; i < length; ++i) {
96 0 : running_diff |= (char(input1[i]) ^ char(input2[i]));
97 : }
98 0 : 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 2028274 : constexpr span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {}
111 : constexpr span() : ptr(nullptr), length(0) {}
112 :
113 1155768 : constexpr size_t len() const noexcept {
114 1155768 : return length;
115 : }
116 :
117 36365 : BOOST_JSON_CXX14_CONSTEXPR const T& operator[](size_t index) const noexcept {
118 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 0 : ((input_num & uint64_t(0xffffffff00000000)) && (input_num >>= 32, last_bit |= 32)),
135 0 : ((input_num & uint64_t( 0xffff0000)) && (input_num >>= 16, last_bit |= 16)),
136 0 : ((input_num & uint64_t( 0xff00)) && (input_num >>= 8, last_bit |= 8)),
137 0 : ((input_num & uint64_t( 0xf0)) && (input_num >>= 4, last_bit |= 4)),
138 0 : ((input_num & uint64_t( 0xc)) && (input_num >>= 2, last_bit |= 2)),
139 0 : ((input_num & uint64_t( 0x2)) && (input_num >>= 1, last_bit |= 1)),
140 : 63 - last_bit
141 0 : );
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 2008629 : assert(input_num > 0);
148 2008629 : if (cpp20_and_in_constexpr()) {
149 0 : 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 0 : 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 0 : uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd);
174 0 : uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd);
175 0 : uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32));
176 0 : uint64_t adbc_carry = !!(adbc < ad);
177 0 : uint64_t lo = bd + (adbc << 32);
178 0 : *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
179 0 : (adbc_carry << 32) + !!(lo < bd);
180 0 : 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 2010874 : if (cpp20_and_in_constexpr()) {
200 0 : value128 answer;
201 0 : answer.low = umul128_generic(a, b, &answer.high);
202 0 : 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 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 0 : 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 0 : 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 0 : constexpr char const * str_const_nan<char>()
517 : {
518 0 : 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 0 : constexpr char const * str_const_inf<char>()
542 : {
543 0 : 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
|