1// Copyright 2020-2022 Junekey Jeon
2//
3// The contents of this file may be used under the terms of
4// the Apache License v2.0 with LLVM Exceptions.
5//
6// (See accompanying file LICENSE-Apache or copy at
7// https://llvm.org/foundation/relicensing/LICENSE.txt)
8//
9// Alternatively, the contents of this file may be used under the terms of
10// the Boost Software License, Version 1.0.
11// (See accompanying file LICENSE-Boost or copy at
12// https://www.boost.org/LICENSE_1_0.txt)
13//
14// Unless required by applicable law or agreed to in writing, this software
15// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16// KIND, either express or implied.
17//
18// Copyright 2023 Matt Borland
19// Distributed under the Boost Software License, Version 1.0.
20// https://www.boost.org/LICENSE_1_0.txt
21
22#ifndef BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP
23#define BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP
24
25#include <boost/charconv/detail/config.hpp>
26#include <boost/charconv/detail/dragonbox/dragonbox_common.hpp>
27#include <boost/charconv/detail/bit_layouts.hpp>
28#include <boost/charconv/detail/emulated128.hpp>
29#include <boost/charconv/detail/buffer_sizing.hpp>
30#include <boost/charconv/detail/to_chars_result.hpp>
31#include <boost/charconv/chars_format.hpp>
32#include <boost/core/bit.hpp>
33#include <type_traits>
34#include <limits>
35#include <cstdint>
36#include <cstring>
37
38#ifdef BOOST_MSVC
39# pragma warning(push)
40# pragma warning(disable: 4127) // Conditional expression is constant (e.g. BOOST_IF_CONSTEXPR statements)
41# pragma warning(disable: 4307) // Integral constant overflow (Only MSVC-14.1 issued this warning)
42#endif
43
44namespace boost { namespace charconv { namespace detail {
45
46// A floating-point traits class defines ways to interpret a bit pattern of given size as an
47// encoding of floating-point number. This is a default implementation of such a traits class,
48// supporting ways to interpret 32-bits into a binary32-encoded floating-point number and to
49// interpret 64-bits into a binary64-encoded floating-point number. Users might specialize this
50// class to change the default behavior for certain types.
51
52template <typename T>
53struct dragonbox_float_traits
54{
55 // I don't know if there is a truly reliable way of detecting
56 // IEEE-754 binary32/binary64 formats; I just did my best here.
57 static_assert(std::numeric_limits<T>::is_iec559 && std::numeric_limits<T>::radix == 2 &&
58 (physical_bits<T>::value == 32 || physical_bits<T>::value == 64),
59 "default_ieee754_traits only works for 32-bits or 64-bits types "
60 "supporting binary32 or binary64 formats!");
61
62 // The type that is being viewed.
63 using type = T;
64
65 // Refers to the format specification class.
66 using format = typename std::conditional<physical_bits<T>::value == 32, ieee754_binary32, ieee754_binary64>::type;
67
68 // Defines an unsigned integer type that is large enough to carry a variable of type T.
69 // Most of the operations will be done on this integer type.
70 using carrier_uint =
71 typename std::conditional<physical_bits<T>::value == 32, std::uint32_t, std::uint64_t>::type;
72
73 static_assert(sizeof(carrier_uint) == sizeof(T), "Type T must have a unsigned type with the same number of bits");
74
75 // Number of bits in the above unsigned integer type.
76 static constexpr int carrier_bits = static_cast<int>(physical_bits<carrier_uint>::value);
77
78 // Convert from carrier_uint into the original type.
79 // Depending on the floating-point encoding format, this operation might not be possible for
80 // some specific bit patterns. However, the contract is that u always denotes a
81 // valid bit pattern, so this function must be assumed to be noexcept.
82 static T carrier_to_float(carrier_uint u) noexcept
83 {
84 T x;
85 std::memcpy(dest: &x, src: &u, n: sizeof(carrier_uint));
86 return x;
87 }
88
89 // Same as above.
90 static carrier_uint float_to_carrier(T x) noexcept
91 {
92 carrier_uint u;
93 std::memcpy(dest: &u, src: &x, n: sizeof(carrier_uint));
94 return u;
95 }
96
97 // Extract exponent bits from a bit pattern.
98 // The result must be aligned to the LSB so that there is no additional zero paddings
99 // on the right. This function does not do bias adjustment.
100 static constexpr unsigned extract_exponent_bits(carrier_uint u) noexcept
101 {
102 return static_cast<unsigned>(u >> format::significand_bits) & ((static_cast<unsigned int>(1) << format::exponent_bits) - 1);
103 }
104
105 // Extract significand bits from a bit pattern.
106 // The result must be aligned to the LSB so that there is no additional zero paddings
107 // on the right. The result does not contain the implicit bit.
108 static constexpr carrier_uint extract_significand_bits(carrier_uint u) noexcept
109 {
110 return carrier_uint(u & carrier_uint((carrier_uint(1) << format::significand_bits) - 1));
111 }
112
113 // Remove the exponent bits and extract significand bits together with the sign bit.
114 static constexpr carrier_uint remove_exponent_bits(carrier_uint u, unsigned int exponent_bits) noexcept
115 {
116 return u ^ (carrier_uint(exponent_bits) << format::significand_bits);
117 }
118
119 // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
120 static constexpr carrier_uint remove_sign_bit_and_shift(carrier_uint u) noexcept {
121 return carrier_uint(carrier_uint(u) << 1);
122 }
123
124 // The actual value of exponent is obtained by adding this value to the extracted exponent
125 // bits.
126 static constexpr int exponent_bias = 1 - (1 << (carrier_bits - format::significand_bits - 2));
127
128 // Obtain the actual value of the binary exponent from the extracted exponent bits.
129 static constexpr int binary_exponent(unsigned exponent_bits) noexcept
130 {
131 return static_cast<int>(exponent_bits == 0 ? format::min_exponent : int(exponent_bits) + format::exponent_bias);
132 }
133
134 // Obtain the actual value of the binary exponent from the extracted significand bits and
135 // exponent bits.
136 static constexpr carrier_uint binary_significand(carrier_uint significand_bits, unsigned exponent_bits) noexcept
137 {
138 return exponent_bits == 0 ? significand_bits : significand_bits | (carrier_uint(1) << format::significand_bits);
139 }
140
141 /* Various boolean observer functions */
142
143 static constexpr bool is_nonzero(carrier_uint u) noexcept
144 {
145 return (u << 1) != 0;
146 }
147
148 static constexpr bool is_positive(carrier_uint u) noexcept
149 {
150 return u < (carrier_uint(1) << (format::significand_bits + format::exponent_bits));
151 }
152
153 static constexpr bool is_negative(carrier_uint u) noexcept
154 {
155 return !is_positive(u);
156 }
157
158 static constexpr bool is_finite(unsigned exponent_bits) noexcept
159 {
160 return exponent_bits != ((1u << format::exponent_bits) - 1);
161 }
162
163 static constexpr bool has_all_zero_significand_bits(carrier_uint u) noexcept
164 {
165 return (u << 1) == 0;
166 }
167
168 static constexpr bool has_even_significand_bits(carrier_uint u) noexcept
169 {
170 return u % 2 == 0;
171 }
172};
173
174// Convenient wrappers for floating-point traits classes.
175// In order to reduce the argument passing overhead, these classes should be as simple as
176// possible (e.g., no inheritance, no private non-static data member, etc.; this is an
177// unfortunate fact about common ABI convention).
178
179template <typename T, typename Traits = dragonbox_float_traits<T>>
180struct dragonbox_float_bits;
181
182template <typename T, typename Traits = dragonbox_float_traits<T>>
183struct dragonbox_signed_significand_bits;
184
185template <typename T, typename Traits>
186struct dragonbox_float_bits
187{
188 using type = T;
189 using traits_type = Traits;
190 using carrier_uint = typename traits_type::carrier_uint;
191
192 carrier_uint u;
193
194 dragonbox_float_bits() = default;
195 constexpr explicit dragonbox_float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
196 constexpr explicit dragonbox_float_bits(T float_value) noexcept
197 : u{traits_type::float_to_carrier(float_value)} {}
198
199 T to_float() const noexcept
200 {
201 return traits_type::carrier_to_float(u);
202 }
203
204 // Extract exponent bits from a bit pattern.
205 // The result must be aligned to the LSB so that there is no additional zero paddings
206 // on the right. This function does not do bias adjustment.
207 constexpr unsigned int extract_exponent_bits() const noexcept
208 {
209 return traits_type::extract_exponent_bits(u);
210 }
211
212 // Extract significand bits from a bit pattern.
213 // The result must be aligned to the LSB so that there is no additional zero paddings
214 // on the right. The result does not contain the implicit bit.
215 constexpr carrier_uint extract_significand_bits() const noexcept
216 {
217 return traits_type::extract_significand_bits(u);
218 }
219
220 // Remove the exponent bits and extract significand bits together with the sign bit.
221 constexpr auto remove_exponent_bits(unsigned int exponent_bits) const noexcept -> dragonbox_signed_significand_bits<type, traits_type>
222 {
223 return dragonbox_signed_significand_bits<type, traits_type>(traits_type::remove_exponent_bits(u, exponent_bits));
224 }
225
226 // Obtain the actual value of the binary exponent from the extracted exponent bits.
227 static constexpr int binary_exponent(unsigned exponent_bits) noexcept
228 {
229 return traits_type::binary_exponent(exponent_bits);
230 }
231
232 constexpr int binary_exponent() const noexcept
233 {
234 return binary_exponent(extract_exponent_bits());
235 }
236
237 // Obtain the actual value of the binary exponent from the extracted significand bits and
238 // exponent bits.
239 static constexpr carrier_uint binary_significand(carrier_uint significand_bits, unsigned exponent_bits) noexcept
240 {
241 return traits_type::binary_significand(significand_bits, exponent_bits);
242 }
243
244 constexpr carrier_uint binary_significand() const noexcept
245 {
246 return binary_significand(extract_significand_bits(), extract_exponent_bits());
247 }
248
249 constexpr bool is_nonzero() const noexcept
250 {
251 return traits_type::is_nonzero(u);
252 }
253
254 constexpr bool is_positive() const noexcept
255 {
256 return traits_type::is_positive(u);
257 }
258
259 constexpr bool is_negative() const noexcept
260 {
261 return traits_type::is_negative(u);
262 }
263
264 constexpr bool is_finite(unsigned exponent_bits) const noexcept
265 {
266 return traits_type::is_finite(exponent_bits);
267 }
268
269 constexpr bool is_finite() const noexcept
270 {
271 return traits_type::is_finite(extract_exponent_bits());
272 }
273
274 constexpr bool has_even_significand_bits() const noexcept
275 {
276 return traits_type::has_even_significand_bits(u);
277 }
278};
279
280template <typename T, typename Traits>
281struct dragonbox_signed_significand_bits
282{
283 using type = T;
284 using traits_type = Traits;
285 using carrier_uint = typename traits_type::carrier_uint;
286
287 carrier_uint u;
288
289 dragonbox_signed_significand_bits() = default;
290 constexpr explicit dragonbox_signed_significand_bits(carrier_uint bit_pattern) noexcept
291 : u{bit_pattern} {}
292
293 // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
294 constexpr carrier_uint remove_sign_bit_and_shift() const noexcept
295 {
296 return traits_type::remove_sign_bit_and_shift(u);
297 }
298
299 constexpr bool is_positive() const noexcept
300 {
301 return traits_type::is_positive(u);
302 }
303
304 constexpr bool is_negative() const noexcept
305 {
306 return traits_type::is_negative(u);
307 }
308
309 constexpr bool has_all_zero_significand_bits() const noexcept
310 {
311 return traits_type::has_all_zero_significand_bits(u);
312 }
313
314 constexpr bool has_even_significand_bits() const noexcept
315 {
316 return traits_type::has_even_significand_bits(u);
317 }
318};
319
320 ////////////////////////////////////////////////////////////////////////////////////////
321 // Utilities for fast divisibility tests.
322 ////////////////////////////////////////////////////////////////////////////////////////
323
324 namespace div {
325 // Replace n by floor(n / 10^N).
326 // Returns true if and only if n is divisible by 10^N.
327 // Precondition: n <= 10^(N+1)
328 // !!It takes an in-out parameter!!
329 template <int N>
330 struct divide_by_pow10_info;
331
332 template <>
333 struct divide_by_pow10_info<1>
334 {
335 static constexpr std::uint32_t magic_number = 6554;
336 static constexpr int shift_amount = 16;
337 };
338
339 template <>
340 struct divide_by_pow10_info<2>
341 {
342 static constexpr std::uint32_t magic_number = 656;
343 static constexpr int shift_amount = 16;
344 };
345
346 template <int N>
347 BOOST_CXX14_CONSTEXPR bool check_divisibility_and_divide_by_pow10(std::uint32_t& n) noexcept
348 {
349 // Make sure the computation for max_n does not overflow.
350 // static_assert(N + 1 <= log::floor_log10_pow2(31));
351 BOOST_CHARCONV_ASSERT(n <= compute_power(UINT32_C(10), N + 1));
352
353 using info = divide_by_pow10_info<N>;
354 n *= info::magic_number;
355
356 constexpr auto mask = std::uint32_t(std::uint32_t(1) << info::shift_amount) - 1;
357 bool result = ((n & mask) < info::magic_number);
358
359 n >>= info::shift_amount;
360 return result;
361 }
362
363 // Compute floor(n / 10^N) for small n and N.
364 // Precondition: n <= 10^(N+1)
365 template <int N>
366 BOOST_CXX14_CONSTEXPR std::uint32_t small_division_by_pow10(std::uint32_t n) noexcept
367 {
368 // Make sure the computation for max_n does not overflow.
369 // static_assert(N + 1 <= log::floor_log10_pow2(31));
370 BOOST_CHARCONV_ASSERT(n <= compute_power(UINT32_C(10), N + 1));
371
372 return (n * divide_by_pow10_info<N>::magic_number) >> divide_by_pow10_info<N>::shift_amount;
373 }
374
375 // Compute floor(n / 10^N) for small N.
376 // Precondition: n <= n_max
377 template <unsigned N, typename UInt, UInt n_max>
378 BOOST_CXX14_CONSTEXPR UInt divide_by_pow10(UInt n) noexcept
379 {
380
381 // Specialize for 32-bit division by 100.
382 // Compiler is supposed to generate the identical code for just writing
383 // "n / 100", but for some reason MSVC generates an inefficient code
384 // (mul + mov for no apparent reason, instead of single imul),
385 // so we does this manually.
386 BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint32_t>::value && N == 2)
387 {
388 return static_cast<UInt>(umul64(x: static_cast<std::uint32_t>(n), UINT32_C(1374389535)) >> 37);
389 }
390 // Specialize for 64-bit division by 1000.
391 // Ensure that the correctness condition is met.
392 else BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint64_t>::value && N == 3 && n_max <= UINT64_C(15534100272597517998))
393 {
394 return static_cast<UInt>(umul128_upper64(n, UINT64_C(2361183241434822607)) >> 7);
395 }
396 else
397 {
398 BOOST_CXX14_CONSTEXPR auto divisor = compute_power(static_cast<UInt>(10), N);
399 return n / divisor;
400 }
401 }
402
403 #ifdef BOOST_MSVC
404 # pragma warning(push)
405 # pragma warning(disable: 4100) // MSVC 14.0 does not have BOOST_ATTRIBUTE_UNUSED so we disable the warning
406 #endif
407
408 template <typename UInt>
409 BOOST_CXX14_CONSTEXPR UInt divide_by_pow10(unsigned N, BOOST_ATTRIBUTE_UNUSED UInt n_max, UInt n) noexcept
410 {
411 BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint32_t>::value && N == 2)
412 {
413 return static_cast<UInt>(umul64(x: static_cast<std::uint32_t>(n), y: static_cast<std::uint32_t>(1374389535)) >> UINT32_C(37));
414 }
415 // Specialize for 64-bit division by 1000.
416 // Ensure that the correctness condition is met.
417 else BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint64_t>::value && N == 3 && n_max <= UINT64_C(15534100272597517998))
418 {
419 return static_cast<UInt>(umul128_upper64(n, UINT64_C(2361183241434822607)) >> 7);
420 }
421 else
422 {
423 auto divisor = compute_power(static_cast<UInt>(10), N);
424 return n / divisor;
425 }
426 }
427
428 #ifdef BOOST_MSVC
429 # pragma warning(pop)
430 #endif
431 }
432
433////////////////////////////////////////////////////////////////////////////////////////
434// Return types for the main interface function.
435////////////////////////////////////////////////////////////////////////////////////////
436
437template <typename UInt, bool is_signed, bool trailing_zero_flag>
438struct decimal_fp;
439
440template <typename UInt>
441struct decimal_fp<UInt, false, false>
442{
443 using carrier_uint = UInt;
444
445 carrier_uint significand;
446 int exponent;
447};
448
449template <typename UInt>
450struct decimal_fp<UInt, true, false>
451{
452 using carrier_uint = UInt;
453
454 carrier_uint significand;
455 int exponent;
456 bool is_negative;
457};
458
459template <typename UInt>
460struct decimal_fp<UInt, false, true>
461{
462 using carrier_uint = UInt;
463
464 carrier_uint significand;
465 int exponent;
466 bool may_have_trailing_zeros;
467};
468
469template <typename UInt>
470struct decimal_fp<UInt, true, true>
471{
472 using carrier_uint = UInt;
473
474 carrier_uint significand;
475 int exponent;
476 bool is_negative;
477 bool may_have_trailing_zeros;
478};
479
480template <typename UInt>
481using unsigned_decimal_fp = decimal_fp<UInt, false, false>;
482
483template <typename UInt>
484using signed_decimal_fp = decimal_fp<UInt, true, false>;
485
486////////////////////////////////////////////////////////////////////////////////////////
487// Computed cache entries.
488////////////////////////////////////////////////////////////////////////////////////////
489
490#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
491template <bool b>
492struct cache_holder_ieee754_binary32_impl
493#else
494struct cache_holder_ieee754_binary32
495#endif
496{
497 using cache_entry_type = std::uint64_t;
498 static constexpr int cache_bits = 64;
499 static constexpr int min_k = -31;
500 static constexpr int max_k = 46;
501 static constexpr cache_entry_type cache[] = {
502 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, 0xfd87b5f28300ca0e,
503 0x9e74d1b791e07e49, 0xc612062576589ddb, 0xf79687aed3eec552, 0x9abe14cd44753b53,
504 0xc16d9a0095928a28, 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb,
505 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, 0xe69594bec44de15c,
506 0x901d7cf73ab0acda, 0xb424dc35095cd810, 0xe12e13424bb40e14, 0x8cbccc096f5088cc,
507 0xafebff0bcb24aaff, 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd,
508 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, 0xd1b71758e219652c,
509 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, 0xcccccccccccccccd, 0x8000000000000000,
510 0xa000000000000000, 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,
511 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, 0xbebc200000000000,
512 0xee6b280000000000, 0x9502f90000000000, 0xba43b74000000000, 0xe8d4a51000000000,
513 0x9184e72a00000000, 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,
514 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, 0xad78ebc5ac620000,
515 0xd8d726b7177a8000, 0x878678326eac9000, 0xa968163f0a57b400, 0xd3c21bcecceda100,
516 0x84595161401484a0, 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940985,
517 0xa18f07d736b90be6, 0xc9f2c9cd04674edf, 0xfc6f7c4045812297, 0x9dc5ada82b70b59e,
518 0xc5371912364ce306, 0xf684df56c3e01bc7, 0x9a130b963a6c115d, 0xc097ce7bc90715b4,
519 0xf0bdc21abb48db21, 0x96769950b50d88f5, 0xbc143fa4e250eb32, 0xeb194f8e1ae525fe,
520 0x92efd1b8d0cf37bf, 0xb7abc627050305ae, 0xe596b7b0c643c71a, 0x8f7e32ce7bea5c70,
521 0xb35dbf821ae4f38c, 0xe0352f62a19e306f};
522};
523
524#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
525
526template <bool b> constexpr int cache_holder_ieee754_binary32_impl<b>::cache_bits;
527template <bool b> constexpr int cache_holder_ieee754_binary32_impl<b>::min_k;
528template <bool b> constexpr int cache_holder_ieee754_binary32_impl<b>::max_k;
529template <bool b> constexpr typename cache_holder_ieee754_binary32_impl<b>::cache_entry_type cache_holder_ieee754_binary32_impl<b>::cache[];
530
531#endif
532
533#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
534using cache_holder_ieee754_binary32 = cache_holder_ieee754_binary32_impl<true>;
535#endif
536
537#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
538template <bool b>
539struct cache_holder_ieee754_binary64_impl
540#else
541struct cache_holder_ieee754_binary64
542#endif
543{
544 using cache_entry_type = uint128;
545 static constexpr int cache_bits = 128;
546 static constexpr int min_k = -292;
547 static constexpr int max_k = 326;
548 static constexpr cache_entry_type cache[] = {
549 {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, {0x9faacf3df73609b1, 0x77b191618c54e9ad},
550 {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},
551 {0x9becce62836ac577, 0x4ee367f9430aec33}, {0xc2e801fb244576d5, 0x229c41f793cda740},
552 {0xf3a20279ed56d48a, 0x6b43527578c11110}, {0x9845418c345644d6, 0x830a13896b78aaaa},
553 {0xbe5691ef416bd60c, 0x23cc986bc656d554}, {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},
554 {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},
555 {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, {0x91376c36d99995be, 0x23100809b9c21fa2},
556 {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},
557 {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},
558 {0xdd95317f31c7fa1d, 0x40405643d711d584}, {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},
559 {0xad1c8eab5ee43b66, 0xda3243650005eed0}, {0xd863b256369d4a40, 0x90bed43e40076a83},
560 {0x873e4f75e2224e68, 0x5a7744a6e804a292}, {0xa90de3535aaae202, 0x711515d0a205cb37},
561 {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, {0x8412d9991ed58091, 0xe858790afe9486c3},
562 {0xa5178fff668ae0b6, 0x626e974dbe39a873}, {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
563 {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},
564 {0xc987434744ac874e, 0xa327ffb266b56221}, {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},
565 {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, {0xc4ce17b399107c22, 0xcb550fb4384d21d4},
566 {0xf6019da07f549b2b, 0x7e2a53a146606a49}, {0x99c102844f94e0fb, 0x2eda7444cbfc426e},
567 {0xc0314325637a1939, 0xfa911155fefb5309}, {0xf03d93eebc589f88, 0x793555ab7eba27cb},
568 {0x96267c7535b763b5, 0x4bc1558b2f3458df}, {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},
569 {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, {0x92a1958a7675175f, 0x0bfacd89ec191eca},
570 {0xb749faed14125d36, 0xcef980ec671f667c}, {0xe51c79a85916f484, 0x82b7e12780e7401b},
571 {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},
572 {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},
573 {0xaecc49914078536d, 0x58fae9f773886e19}, {0xda7f5bf590966848, 0xaf39a475506a899f},
574 {0x888f99797a5e012d, 0x6d8406c952429604}, {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},
575 {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
576 {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, {0xd0601d8efc57b08b, 0xf13b94daf124da27},
577 {0x823c12795db6ce57, 0x76c53d08d6b70859}, {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},
578 {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},
579 {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},
580 {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},
581 {0xc21094364dfb5636, 0x985915fc12f542e5}, {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},
582 {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, {0xbd8430bd08277231, 0x50c6ff782a838354},
583 {0xece53cec4a314ebd, 0xa4f8bf5635246429}, {0x940f4613ae5ed136, 0x871b7795e136be9a},
584 {0xb913179899f68584, 0x28e2557b59846e40}, {0xe757dd7ec07426e5, 0x331aeada2fe589d0},
585 {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, {0xb4bca50b065abe63, 0x0fed077a756b53aa},
586 {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},
587 {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, {0xdca04777f541c567, 0xecf0d7a0fc5583a1},
588 {0x89e42caaf9491b60, 0xf41686c49db57245}, {0xac5d37d5b79b6239, 0x311c2875c522ced6},
589 {0xd77485cb25823ac7, 0x7d633293366b828c}, {0x86a8d39ef77164bc, 0xae5dff9c02033198},
590 {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, {0xd267caa862a12d66, 0xd072df63c324fd7c},
591 {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, {0xa46116538d0deb78, 0x52d9be85f074e609},
592 {0xcd795be870516656, 0x67902e276c921f8c}, {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},
593 {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},
594 {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},
595 {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, {0xf4f1b4d515acb93b, 0xee92fb5515482d45},
596 {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},
597 {0xef340a98172aace4, 0x86fb897116c87c35}, {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},
598 {0xbae0a846d2195712, 0x8974836059cca10a}, {0xe998d258869facd7, 0x2bd1a438703fc94c},
599 {0x91ff83775423cc06, 0x7b6306a34627ddd0}, {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},
600 {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, {0x8e938662882af53e, 0x547eb47b7282ee9d},
601 {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},
602 {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, {0xae0b158b4738705e, 0x9624ab50b148d446},
603 {0xd98ddaee19068c76, 0x3badd624dd9b0958}, {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},
604 {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, {0xd47487cc8470652b, 0x7647c32000696720},
605 {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, {0xa5fb0a17c777cf09, 0xf468107100525891},
606 {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, {0x81ac1fe293d599bf, 0xc6f14cd848405531},
607 {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},
608 {0xfd442e4688bd304a, 0x908f4a166d1da664}, {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},
609 {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, {0xf7549530e188c128, 0xd12bee59e68ef47d},
610 {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, {0xc13a148e3032d6e7, 0xe36a52363c1faf02},
611 {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},
612 {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, {0xebdf661791d60f56, 0x111b495b3464ad22},
613 {0x936b9fcebb25c995, 0xcab10dd900beec35}, {0xb84687c269ef3bfb, 0x3d5d514f40eea743},
614 {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},
615 {0xb3f4e093db73a093, 0x59ed216765690f57}, {0xe0f218b8d25088b8, 0x306869c13ec3532d},
616 {0x8c974f7383725573, 0x1e414218c73a13fc}, {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
617 {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, {0x894bc396ce5da772, 0x6b8bba8c328eb784},
618 {0xab9eb47c81f5114f, 0x066ea92f3f326565}, {0xd686619ba27255a2, 0xc80a537b0efefebe},
619 {0x8613fd0145877585, 0xbd06742ce95f5f37}, {0xa798fc4196e952e7, 0x2c48113823b73705},
620 {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, {0x82ef85133de648c4, 0x9a984d73dbe722fc},
621 {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, {0xcc963fee10b7d1b3, 0x318df905079926a9},
622 {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},
623 {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},
624 {0x9c1661a651213e2d, 0x06bea10ca65c084f}, {0xc31bfa0fe5698db8, 0x486e494fcff30a63},
625 {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},
626 {0xbe89523386091465, 0xf6bbb397f1135824}, {0xee2ba6c0678b597f, 0x746aa07ded582e2d},
627 {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, {0xba121a4650e4ddeb, 0x92f34d62616ce414},
628 {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, {0x915e2486ef32cd60, 0x0ace1474dc1d122f},
629 {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
630 {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},
631 {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},
632 {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, {0xd89d64d57a607744, 0xe871c7bf077ba8b8},
633 {0x87625f056c7c4a8b, 0x11471cd764ad4973}, {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},
634 {0xd389b47879823479, 0x4aff1d108d4ec2c4}, {0x843610cb4bf160cb, 0xcedf722a585139bb},
635 {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, {0xce947a3da6a9273e, 0x733d226229feea33},
636 {0x811ccc668829b887, 0x0806357d5a3f5260}, {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},
637 {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},
638 {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, {0xc5029163f384a931, 0x0a9e795e65d4df12},
639 {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, {0x99ea0196163fa42e, 0x504bced1bf8e4e46},
640 {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, {0xf07da27a82c37088, 0x5d767327bb4e5a4d},
641 {0x964e858c91ba2655, 0x3a6a07f8d510f870}, {0xbbe226efb628afea, 0x890489f70a55368c},
642 {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},
643 {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, {0xe55990879ddcaabd, 0xcc420a6a101d0516},
644 {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, {0xb32df8e9f3546564, 0x47939822dc96abfa},
645 {0xdff9772470297ebd, 0x59787e2b93bc56f8}, {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},
646 {0xaefae51477a06b03, 0xede622920b6b23f2}, {0xdab99e59958885c4, 0xe95fab368e45ecee},
647 {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},
648 {0xd59944a37c0752a2, 0x4be76d3346f04960}, {0x857fcae62d8493a5, 0x6f70a4400c562ddc},
649 {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},
650 {0x825ecc24c873782f, 0x8ed400668c0c28c9}, {0xa2f67f2dfa90563b, 0x728900802f0f32fb},
651 {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, {0xfea126b7d78186bc, 0xe2f610c84987bfa9},
652 {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, {0xc6ede63fa05d3143, 0x91503d1c79720dbc},
653 {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},
654 {0xc24452da229b021b, 0xfbe85badce996169}, {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},
655 {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},
656 {0xed246723473e3813, 0x290123e9aab23b69}, {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
657 {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},
658 {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},
659 {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, {0x8d590723948a535f, 0x579c487e5a38ad0f},
660 {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, {0xdcdb1b2798182244, 0xf8e431456cf88e66},
661 {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, {0xac8b2d36eed2dac5, 0xe272467e3d222f40},
662 {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},
663 {0xa87fea27a539e9a5, 0x3f2398d747b36225}, {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},
664 {0x83a3eeeef9153e89, 0x1953cf68300424ad}, {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},
665 {0xcdb02555653131b6, 0x3792f412cb06794e}, {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},
666 {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, {0xc8de047564d20a8b, 0xf245825a5a445276},
667 {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, {0x9ced737bb6c4183d, 0x55464dd69685606c},
668 {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, {0xf53304714d9265df, 0xd53dd99f4b3066a9},
669 {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, {0xbf8fdb78849a5f96, 0xde98520472bdd034},
670 {0xef73d256a5c0f77c, 0x963e66858f6d4441}, {0x95a8637627989aad, 0xdde7001379a44aa9},
671 {0xbb127c53b17ec159, 0x5560c018580d5d53}, {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},
672 {0x9226712162ab070d, 0xcab3961304ca70e9}, {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},
673 {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},
674 {0xb267ed1940f1c61c, 0x55f038b237591ed4}, {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},
675 {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, {0xae397d8aa96c1b77, 0xabec975e0a0d081b},
676 {0xd9c7dced53c72255, 0x96e7bd358c904a22}, {0x881cea14545c7575, 0x7e50d64177da2e55},
677 {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},
678 {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},
679 {0xcfb11ead453994ba, 0x67de18eda5814af3}, {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},
680 {0xa2425ff75e14fc31, 0xa1258379a94d028e}, {0xcad2f7f5359a3b3e, 0x096ee45813a04331},
681 {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, {0x9e74d1b791e07e48, 0x775ea264cf55347e},
682 {0xc612062576589dda, 0x95364afe032a819e}, {0xf79687aed3eec551, 0x3a83ddbd83f52205},
683 {0x9abe14cd44753b52, 0xc4926a9672793543}, {0xc16d9a0095928a27, 0x75b7053c0f178294},
684 {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, {0x971da05074da7bee, 0xd3f6fc16ebca5e04},
685 {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},
686 {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, {0xb877aa3236a4b449, 0x09befeb9fad487c3},
687 {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},
688 {0xb424dc35095cd80f, 0x538484c19ef38c95}, {0xe12e13424bb40e13, 0x2865a5f206b06fba},
689 {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, {0xafebff0bcb24aafe, 0xf78f69a51539d749},
690 {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, {0x89705f4136b4a597, 0x31680a88f8953031},
691 {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},
692 {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, {0xa7c5ac471b478423, 0x0fcf80dc33721d54},
693 {0xd1b71758e219652b, 0xd3c36113404ea4a9}, {0x83126e978d4fdf3b, 0x645a1cac083126ea},
694 {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, {0xcccccccccccccccc, 0xcccccccccccccccd},
695 {0x8000000000000000, 0x0000000000000000}, {0xa000000000000000, 0x0000000000000000},
696 {0xc800000000000000, 0x0000000000000000}, {0xfa00000000000000, 0x0000000000000000},
697 {0x9c40000000000000, 0x0000000000000000}, {0xc350000000000000, 0x0000000000000000},
698 {0xf424000000000000, 0x0000000000000000}, {0x9896800000000000, 0x0000000000000000},
699 {0xbebc200000000000, 0x0000000000000000}, {0xee6b280000000000, 0x0000000000000000},
700 {0x9502f90000000000, 0x0000000000000000}, {0xba43b74000000000, 0x0000000000000000},
701 {0xe8d4a51000000000, 0x0000000000000000}, {0x9184e72a00000000, 0x0000000000000000},
702 {0xb5e620f480000000, 0x0000000000000000}, {0xe35fa931a0000000, 0x0000000000000000},
703 {0x8e1bc9bf04000000, 0x0000000000000000}, {0xb1a2bc2ec5000000, 0x0000000000000000},
704 {0xde0b6b3a76400000, 0x0000000000000000}, {0x8ac7230489e80000, 0x0000000000000000},
705 {0xad78ebc5ac620000, 0x0000000000000000}, {0xd8d726b7177a8000, 0x0000000000000000},
706 {0x878678326eac9000, 0x0000000000000000}, {0xa968163f0a57b400, 0x0000000000000000},
707 {0xd3c21bcecceda100, 0x0000000000000000}, {0x84595161401484a0, 0x0000000000000000},
708 {0xa56fa5b99019a5c8, 0x0000000000000000}, {0xcecb8f27f4200f3a, 0x0000000000000000},
709 {0x813f3978f8940984, 0x4000000000000000}, {0xa18f07d736b90be5, 0x5000000000000000},
710 {0xc9f2c9cd04674ede, 0xa400000000000000}, {0xfc6f7c4045812296, 0x4d00000000000000},
711 {0x9dc5ada82b70b59d, 0xf020000000000000}, {0xc5371912364ce305, 0x6c28000000000000},
712 {0xf684df56c3e01bc6, 0xc732000000000000}, {0x9a130b963a6c115c, 0x3c7f400000000000},
713 {0xc097ce7bc90715b3, 0x4b9f100000000000}, {0xf0bdc21abb48db20, 0x1e86d40000000000},
714 {0x96769950b50d88f4, 0x1314448000000000}, {0xbc143fa4e250eb31, 0x17d955a000000000},
715 {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, {0x92efd1b8d0cf37be, 0x5aa1cae500000000},
716 {0xb7abc627050305ad, 0xf14a3d9e40000000}, {0xe596b7b0c643c719, 0x6d9ccd05d0000000},
717 {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, {0xb35dbf821ae4f38b, 0xdda2802c8a800000},
718 {0xe0352f62a19e306e, 0xd50b2037ad200000}, {0x8c213d9da502de45, 0x4526f422cc340000},
719 {0xaf298d050e4395d6, 0x9670b12b7f410000}, {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},
720 {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, {0xab0e93b6efee0053, 0x8eea0d047a457a00},
721 {0xd5d238a4abe98068, 0x72a4904598d6d880}, {0x85a36366eb71f041, 0x47a6da2b7f864750},
722 {0xa70c3c40a64e6c51, 0x999090b65f67d924}, {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},
723 {0x82818f1281ed449f, 0xbff8f10e7a8921a5}, {0xa321f2d7226895c7, 0xaff72d52192b6a0e},
724 {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491}, {0xfee50b7025c36a08, 0x02f236d04753d5b5},
725 {0x9f4f2726179a2245, 0x01d762422c946591}, {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6},
726 {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3}, {0x9b934c3b330c8577, 0x63cc55f49f88eb30},
727 {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc}, {0xf316271c7fc3908a, 0x8bef464e3945ef7b},
728 {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad}, {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318},
729 {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde}, {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b},
730 {0xb975d6b6ee39e436, 0xb3e2fd538e122b45}, {0xe7d34c64a9c85d44, 0x60dbbca87196b617},
731 {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce}, {0xb51d13aea4a488dd, 0x6babab6398bdbe42},
732 {0xe264589a4dcdab14, 0xc696963c7eed2dd2}, {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3},
733 {0xb0de65388cc8ada8, 0x3b25a55f43294bcc}, {0xdd15fe86affad912, 0x49ef0eb713f39ebf},
734 {0x8a2dbf142dfcc7ab, 0x6e3569326c784338}, {0xacb92ed9397bf996, 0x49c2c37f07965405},
735 {0xd7e77a8f87daf7fb, 0xdc33745ec97be907}, {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4},
736 {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d}, {0xd2d80db02aabd62b, 0xf50a3fa490c30191},
737 {0x83c7088e1aab65db, 0x792667c6da79e0fb}, {0xa4b8cab1a1563f52, 0x577001b891185939},
738 {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, {0x80b05e5ac60b6178, 0x544f8158315b05b5},
739 {0xa0dc75f1778e39d6, 0x696361ae3db1c722}, {0xc913936dd571c84c, 0x03bc3a19cd1e38ea},
740 {0xfb5878494ace3a5f, 0x04ab48a04065c724}, {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77},
741 {0xc45d1df942711d9a, 0x3ba5d0bd324f8395}, {0xf5746577930d6500, 0xca8f44ec7ee3647a},
742 {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc}, {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f},
743 {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f}, {0x95d04aee3b80ece5, 0xbba1f1d158724a13},
744 {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98}, {0xea1575143cf97226, 0xf52d09d71a3293be},
745 {0x924d692ca61be758, 0x593c2626705f9c57}, {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d},
746 {0xe498f455c38b997a, 0x0b6dfb9c0f956448}, {0x8edf98b59a373fec, 0x4724bd4189bd5ead},
747 {0xb2977ee300c50fe7, 0x58edec91ec2cb658}, {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee},
748 {0x8b865b215899f46c, 0xbd79e0d20082ee75}, {0xae67f1e9aec07187, 0xecd8590680a3aa12},
749 {0xda01ee641a708de9, 0xe80e6f4820cc9496}, {0x884134fe908658b2, 0x3109058d147fdcde},
750 {0xaa51823e34a7eede, 0xbd4b46f0599fd416}, {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b},
751 {0x850fadc09923329e, 0x03e2cf6bc604ddb1}, {0xa6539930bf6bff45, 0x84db8346b786151d},
752 {0xcfe87f7cef46ff16, 0xe612641865679a64}, {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f},
753 {0xa26da3999aef7749, 0xe3be5e330f38f09e}, {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6},
754 {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7}, {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb},
755 {0xc646d63501a1511d, 0xb281e1fd541501b9}, {0xf7d88bc24209a565, 0x1f225a7ca91a4227},
756 {0x9ae757596946075f, 0x3375788de9b06959}, {0xc1a12d2fc3978937, 0x0052d6b1641c83af},
757 {0xf209787bb47d6b84, 0xc0678c5dbd23a49b}, {0x9745eb4d50ce6332, 0xf840b7ba963646e1},
758 {0xbd176620a501fbff, 0xb650e5a93bc3d899}, {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf},
759 {0x93ba47c980e98cdf, 0xc66f336c36b10138}, {0xb8a8d9bbe123f017, 0xb80b0047445d4185},
760 {0xe6d3102ad96cec1d, 0xa60dc059157491e6}, {0x9043ea1ac7e41392, 0x87c89837ad68db30},
761 {0xb454e4a179dd1877, 0x29babe4598c311fc}, {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b},
762 {0x8ce2529e2734bb1d, 0x1899e4a65f58660d}, {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90},
763 {0xdc21a1171d42645d, 0x76707543f4fa1f74}, {0x899504ae72497eba, 0x6a06494a791c53a9},
764 {0xabfa45da0edbde69, 0x0487db9d17636893}, {0xd6f8d7509292d603, 0x45a9d2845d3c42b7},
765 {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, {0xa7f26836f282b732, 0x8e6cac7768d7141f},
766 {0xd1ef0244af2364ff, 0x3207d795430cd927}, {0x8335616aed761f1f, 0x7f44e6bd49e807b9},
767 {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7}, {0xcd036837130890a1, 0x36dba887c37a8c10},
768 {0x802221226be55a64, 0xc2494954da2c978a}, {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d},
769 {0xc83553c5c8965d3d, 0x6f92829494e5acc8}, {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa},
770 {0x9c69a97284b578d7, 0xff2a760414536efc}, {0xc38413cf25e2d70d, 0xfef5138519684abb},
771 {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a}, {0x98bf2f79d5993802, 0xef2f773ffbd97a62},
772 {0xbeeefb584aff8603, 0xaafb550ffacfd8fb}, {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39},
773 {0x952ab45cfa97a0b2, 0xdd945a747bf26184}, {0xba756174393d88df, 0x94f971119aeef9e5},
774 {0xe912b9d1478ceb17, 0x7a37cd5601aab85e}, {0x91abb422ccb812ee, 0xac62e055c10ab33b},
775 {0xb616a12b7fe617aa, 0x577b986b314d600a}, {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c},
776 {0x8e41ade9fbebc27d, 0x14588f13be847308}, {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9},
777 {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc}, {0x8aec23d680043bee, 0x25de7bb9480d5855},
778 {0xada72ccc20054ae9, 0xaf561aa79a10ae6b}, {0xd910f7ff28069da4, 0x1b2ba1518094da05},
779 {0x87aa9aff79042286, 0x90fb44d2f05d0843}, {0xa99541bf57452b28, 0x353a1607ac744a54},
780 {0xd3fa922f2d1675f2, 0x42889b8997915ce9}, {0x847c9b5d7c2e09b7, 0x69956135febada12},
781 {0xa59bc234db398c25, 0x43fab9837e699096}, {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc},
782 {0x8161afb94b44f57d, 0x1d1be0eebac278f6}, {0xa1ba1ba79e1632dc, 0x6462d92a69731733},
783 {0xca28a291859bbf93, 0x7d7b8f7503cfdcff}, {0xfcb2cb35e702af78, 0x5cda735244c3d43f},
784 {0x9defbf01b061adab, 0x3a0888136afa64a8}, {0xc56baec21c7a1916, 0x088aaa1845b8fdd1},
785 {0xf6c69a72a3989f5b, 0x8aad549e57273d46}, {0x9a3c2087a63f6399, 0x36ac54e2f678864c},
786 {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de}, {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6},
787 {0x969eb7c47859e743, 0x9f644ae5a4b1b326}, {0xbc4665b596706114, 0x873d5d9f0dde1fef},
788 {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb}, {0x9316ff75dd87cbd8, 0x09a7f12442d588f3},
789 {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30}, {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb},
790 {0x8fa475791a569d10, 0xf96e017d694487bd}, {0xb38d92d760ec4455, 0x37c981dcc395a9ad},
791 {0xe070f78d3927556a, 0x85bbe253f47b1418}, {0x8c469ab843b89562, 0x93956d7478ccec8f},
792 {0xaf58416654a6babb, 0x387ac8d1970027b3}, {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f},
793 {0x88fcf317f22241e2, 0x441fece3bdf81f04}, {0xab3c2fddeeaad25a, 0xd527e81cad7626c4},
794 {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075}, {0x85c7056562757456, 0xf6872d5667844e4a},
795 {0xa738c6bebb12d16c, 0xb428f8ac016561dc}, {0xd106f86e69d785c7, 0xe13336d701beba53},
796 {0x82a45b450226b39c, 0xecc0024661173474}, {0xa34d721642b06084, 0x27f002d7f95d0191},
797 {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5}, {0xff290242c83396ce, 0x7e67047175a15272},
798 {0x9f79a169bd203e41, 0x0f0062c6e984d387}, {0xc75809c42c684dd1, 0x52c07b78a3e60869},
799 {0xf92e0c3537826145, 0xa7709a56ccdf8a83}, {0x9bbcc7a142b17ccb, 0x88a66076400bb692},
800 {0xc2abf989935ddbfe, 0x6acff893d00ea436}, {0xf356f7ebf83552fe, 0x0583f6b8c4124d44},
801 {0x98165af37b2153de, 0xc3727a337a8b704b}, {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d},
802 {0xeda2ee1c7064130c, 0x1162def06f79df74}, {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9},
803 {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693}, {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438},
804 {0x910ab1d4db9914a0, 0x1d9c9892400a22a3}, {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c},
805 {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e}, {0x8da471a9de737e24, 0x5ceaecfed289e5d3},
806 {0xb10d8e1456105dad, 0x7425a83e872c5f48}, {0xdd50f1996b947518, 0xd12f124e28f7771a},
807 {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70}, {0xace73cbfdc0bfb7b, 0x636cc64d1001550c},
808 {0xd8210befd30efa5a, 0x3c47f7e05401aa4f}, {0x8714a775e3e95c78, 0x65acfaec34810a72},
809 {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e}, {0xd31045a8341ca07c, 0x1ede48111209a051},
810 {0x83ea2b892091e44d, 0x934aed0aab460433}, {0xa4e4b66b68b65d60, 0xf81da84d56178540},
811 {0xce1de40642e3f4b9, 0x36251260ab9d668f}, {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a},
812 {0xa1075a24e4421730, 0xb24cf65b8612f820}, {0xc94930ae1d529cfc, 0xdee033f26797b628},
813 {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2}, {0x9d412e0806e88aa5, 0x8e1f289560ee864f},
814 {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3}, {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc},
815 {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a}, {0xbff610b0cc6edd3f, 0x17fd090a58d32af4},
816 {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1}, {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f},
817 {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2}, {0xea53df5fd18d5513, 0x84c86189216dc5ee},
818 {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5}, {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2},
819 {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f},
820 {0xb2c71d5bca9023f8, 0x743e20e9ef511013}, {0xdf78e4b2bd342cf6, 0x914da9246b255417},
821 {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f}, {0xae9672aba3d0c320, 0xa184ac2473b529b2},
822 {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f}, {0x8865899617fb1871, 0x7e2fa67c7a658893},
823 {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8}, {0xd51ea6fa85785631, 0x552a74227f3ea566},
824 {0x8533285c936b35de, 0xd53a88958f872760}, {0xa67ff273b8460356, 0x8a892abaf368f138},
825 {0xd01fef10a657842c, 0x2d2b7569b0432d86}, {0x8213f56a67f6b29b, 0x9c3b29620e29fc74},
826 {0xa298f2c501f45f42, 0x8349f3ba91b47b90}, {0xcb3f2f7642717713, 0x241c70a936219a74},
827 {0xfe0efb53d30dd4d7, 0xed238cd383aa0111}, {0x9ec95d1463e8a506, 0xf4363804324a40ab},
828 {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6}, {0xf81aa16fdc1b81da, 0xdd94b7868e94050b},
829 {0x9b10a4e5e9913128, 0xca7cf2b4191c8327}, {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1},
830 {0xf24a01a73cf2dccf, 0xbc633b39673c8ced}, {0x976e41088617ca01, 0xd5be0503e085d814},
831 {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19}, {0xec9c459d51852ba2, 0xddf8e7d60ed1219f},
832 {0x93e1ab8252f33b45, 0xcabb90e5c942b504}, {0xb8da1662e7b00a17, 0x3d6a751f3b936244},
833 {0xe7109bfba19c0c9d, 0x0cc512670a783ad5}, {0x906a617d450187e2, 0x27fb2b80668b24c6},
834 {0xb484f9dc9641e9da, 0xb1f9f660802dedf7}, {0xe1a63853bbd26451, 0x5e7873f8a0396974},
835 {0x8d07e33455637eb2, 0xdb0b487b6423e1e9}, {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63},
836 {0xdc5c5301c56b75f7, 0x7641a140cc7810fc}, {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e},
837 {0xac2820d9623bf429, 0x546345fa9fbdcd45}, {0xd732290fbacaf133, 0xa97c177947ad4096},
838 {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e}, {0xa81f301449ee8c70, 0x5c68f256bfff5a75},
839 {0xd226fc195c6a2f8c, 0x73832eec6fff3112}, {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac},
840 {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56}, {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec},
841 {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4}, {0xa0555e361951c366, 0xd7e105bcc3326220},
842 {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8}, {0xfa856334878fc150, 0xb14f98f6f0feb952},
843 {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4}, {0xc3b8358109e84f07, 0x0a862f80ec4700c9},
844 {0xf4a642e14c6262c8, 0xcd27bb612758c0fb}, {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d},
845 {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4}, {0xeeea5d5004981478, 0x1858ccfce06cac75},
846 {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, {0xbaa718e68396cffd, 0xd30560258f54e6bb},
847 {0xe950df20247c83fd, 0x47c6b82ef32a206a}, {0x91d28b7416cdd27e, 0x4cdc331d57fa5442},
848 {0xb6472e511c81471d, 0xe0133fe4adf8e953}, {0xe3d8f9e563a198e5, 0x58180fddd97723a7},
849 {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649}, {0xb201833b35d63f73, 0x2cd2cc6551e513db},
850 {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2}, {0x8b112e86420f6191, 0xfb04afaf27faf783},
851 {0xadd57a27d29339f6, 0x79c5db9af1f9b564}, {0xd94ad8b1c7380874, 0x18375281ae7822bd},
852 {0x87cec76f1c830548, 0x8f2293910d0b15b6}, {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23},
853 {0xd433179d9c8cb841, 0x5fa60692a46151ec}, {0x849feec281d7f328, 0xdbc7c41ba6bcd334},
854 {0xa5c7ea73224deff3, 0x12b9b522906c0801}, {0xcf39e50feae16bef, 0xd768226b34870a01},
855 {0x81842f29f2cce375, 0xe6a1158300d46641}, {0xa1e53af46f801c53, 0x60495ae3c1097fd1},
856 {0xca5e89b18b602368, 0x385bb19cb14bdfc5}, {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6},
857 {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, {0xc5a05277621be293, 0xc7098b7305241886},
858 {0xf70867153aa2db38, 0xb8cbee4fc66d1ea8}};
859};
860
861#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
862
863template <bool b> constexpr int cache_holder_ieee754_binary64_impl<b>::cache_bits;
864template <bool b> constexpr int cache_holder_ieee754_binary64_impl<b>::min_k;
865template <bool b> constexpr int cache_holder_ieee754_binary64_impl<b>::max_k;
866template <bool b> constexpr typename cache_holder_ieee754_binary64_impl<b>::cache_entry_type cache_holder_ieee754_binary64_impl<b>::cache[];
867
868#endif
869
870#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
871using cache_holder_ieee754_binary64 = cache_holder_ieee754_binary64_impl<true>;
872#endif
873
874////////////////////////////////////////////////////////////////////////////////////////
875// Policies.
876////////////////////////////////////////////////////////////////////////////////////////
877
878// Forward declare the implementation class.
879template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>>
880struct impl;
881
882namespace policy_impl {
883// Sign policies.
884namespace sign {
885 struct base {};
886
887 struct ignore : base
888 {
889 using sign_policy = ignore;
890 static constexpr bool return_has_sign = false;
891
892 template <typename SignedSignificandBits, typename ReturnType>
893 static BOOST_CXX14_CONSTEXPR void handle_sign(SignedSignificandBits, ReturnType&) noexcept {}
894 };
895
896 struct return_sign : base
897 {
898 using sign_policy = return_sign;
899 static constexpr bool return_has_sign = true;
900
901 template <typename SignedSignificandBits, typename ReturnType>
902 static BOOST_CXX14_CONSTEXPR void handle_sign(SignedSignificandBits s, ReturnType& r) noexcept
903 {
904 r.is_negative = s.is_negative();
905 }
906 };
907}
908
909// Trailing zero policies.
910namespace trailing_zero {
911 struct base {};
912
913 struct ignore : base
914 {
915 using trailing_zero_policy = ignore;
916 static constexpr bool report_trailing_zeros = false;
917
918 template <typename Impl, typename ReturnType>
919 static BOOST_CXX14_CONSTEXPR void on_trailing_zeros(ReturnType&) noexcept {}
920
921 template <typename Impl, typename ReturnType>
922 static BOOST_CXX14_CONSTEXPR void no_trailing_zeros(ReturnType&) noexcept {}
923 };
924
925 struct remove : base
926 {
927 using trailing_zero_policy = remove;
928 static constexpr bool report_trailing_zeros = false;
929
930 template <typename Impl, typename ReturnType>
931 BOOST_FORCEINLINE static void on_trailing_zeros(ReturnType& r) noexcept
932 {
933 r.exponent += Impl::remove_trailing_zeros(r.significand);
934 }
935
936 template <typename Impl, typename ReturnType>
937 static BOOST_CXX14_CONSTEXPR void no_trailing_zeros(ReturnType&) noexcept {}
938 };
939
940 struct report : base
941 {
942 using trailing_zero_policy = report;
943 static constexpr bool report_trailing_zeros = true;
944
945 template <typename Impl, typename ReturnType>
946 static BOOST_CXX14_CONSTEXPR void on_trailing_zeros(ReturnType& r) noexcept
947 {
948 r.may_have_trailing_zeros = true;
949 }
950
951 template <typename Impl, typename ReturnType>
952 static BOOST_CXX14_CONSTEXPR void no_trailing_zeros(ReturnType& r) noexcept
953 {
954 r.may_have_trailing_zeros = false;
955 }
956 };
957}
958
959// Decimal-to-binary rounding mode policies.
960namespace decimal_to_binary_rounding {
961 struct base {};
962
963 enum class tag_t
964 {
965 to_nearest,
966 left_closed_directed,
967 right_closed_directed
968 };
969
970 namespace interval_type {
971 struct symmetric_boundary
972 {
973 static constexpr bool is_symmetric = true;
974 bool is_closed;
975 constexpr bool include_left_endpoint() const noexcept { return is_closed; }
976 constexpr bool include_right_endpoint() const noexcept { return is_closed; }
977 };
978
979 struct asymmetric_boundary
980 {
981 static constexpr bool is_symmetric = false;
982 bool is_left_closed;
983 constexpr bool include_left_endpoint() const noexcept { return is_left_closed; }
984 constexpr bool include_right_endpoint() const noexcept { return !is_left_closed; }
985 };
986
987 struct closed
988 {
989 static constexpr bool is_symmetric = true;
990 static constexpr bool include_left_endpoint() noexcept { return true; }
991 static constexpr bool include_right_endpoint() noexcept { return true; }
992 };
993
994 struct open
995 {
996 static constexpr bool is_symmetric = true;
997 static constexpr bool include_left_endpoint() noexcept { return false; }
998 static constexpr bool include_right_endpoint() noexcept { return false; }
999 };
1000
1001 struct left_closed_right_open
1002 {
1003 static constexpr bool is_symmetric = false;
1004 static constexpr bool include_left_endpoint() noexcept { return true; }
1005 static constexpr bool include_right_endpoint() noexcept { return false; }
1006 };
1007
1008 struct right_closed_left_open
1009 {
1010 static constexpr bool is_symmetric = false;
1011 static constexpr bool include_left_endpoint() noexcept { return false; }
1012 static constexpr bool include_right_endpoint() noexcept { return true; }
1013 };
1014 }
1015
1016 template <typename T>
1017 struct return_type : return_type<decltype(&T::operator())>
1018 {};
1019
1020 struct nearest_to_even : base
1021 {
1022 using decimal_to_binary_rounding_policy = nearest_to_even;
1023 static constexpr auto tag = tag_t::to_nearest;
1024 using normal_interval_type = interval_type::symmetric_boundary;
1025 using shorter_interval_type = interval_type::closed;
1026
1027 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1028 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func f) noexcept
1029 {
1030 return f(nearest_to_even{});
1031 }
1032
1033 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1034 BOOST_FORCEINLINE static constexpr ReturnType
1035 invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
1036 {
1037 return f(s.has_even_significand_bits());
1038 }
1039
1040 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1041 BOOST_FORCEINLINE static constexpr ReturnType
1042 invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
1043 {
1044 return f();
1045 }
1046 };
1047
1048 struct nearest_to_odd : base
1049 {
1050 using decimal_to_binary_rounding_policy = nearest_to_odd;
1051 static constexpr auto tag = tag_t::to_nearest;
1052 using normal_interval_type = interval_type::symmetric_boundary;
1053 using shorter_interval_type = interval_type::open;
1054
1055 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1056 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1057 {
1058 return f(nearest_to_odd{});
1059 }
1060
1061 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1062 BOOST_FORCEINLINE static constexpr ReturnType
1063 invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
1064 {
1065 return f(!s.has_even_significand_bits());
1066 }
1067
1068 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1069 BOOST_FORCEINLINE static constexpr ReturnType
1070 invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
1071 {
1072 return f();
1073 }
1074 };
1075
1076 struct nearest_toward_plus_infinity : base
1077 {
1078 using decimal_to_binary_rounding_policy = nearest_toward_plus_infinity;
1079 static constexpr auto tag = tag_t::to_nearest;
1080 using normal_interval_type = interval_type::asymmetric_boundary;
1081 using shorter_interval_type = interval_type::asymmetric_boundary;
1082
1083 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1084 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1085 {
1086 return f(nearest_toward_plus_infinity{});
1087 }
1088
1089 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1090 BOOST_FORCEINLINE static constexpr ReturnType
1091 invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
1092 {
1093 return f(!s.is_negative());
1094 }
1095
1096 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1097 BOOST_FORCEINLINE static constexpr ReturnType
1098 invoke_shorter_interval_case(SignedSignificandBits s, Func&& f) noexcept
1099 {
1100 return f(!s.is_negative());
1101 }
1102 };
1103
1104 struct nearest_toward_minus_infinity : base
1105 {
1106 using decimal_to_binary_rounding_policy = nearest_toward_minus_infinity;
1107 static constexpr auto tag = tag_t::to_nearest;
1108 using normal_interval_type = interval_type::asymmetric_boundary;
1109 using shorter_interval_type = interval_type::asymmetric_boundary;
1110
1111 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1112 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1113 {
1114 return f(nearest_toward_minus_infinity{});
1115 }
1116
1117 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1118 BOOST_FORCEINLINE static constexpr ReturnType
1119 invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
1120 {
1121 return f(s.is_negative());
1122 }
1123
1124 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1125 BOOST_FORCEINLINE static constexpr ReturnType
1126 invoke_shorter_interval_case(SignedSignificandBits s, Func&& f) noexcept
1127 {
1128 return f(s.is_negative());
1129 }
1130 };
1131
1132 struct nearest_toward_zero : base
1133 {
1134 using decimal_to_binary_rounding_policy = nearest_toward_zero;
1135 static constexpr auto tag = tag_t::to_nearest;
1136 using normal_interval_type = interval_type::right_closed_left_open;
1137 using shorter_interval_type = interval_type::right_closed_left_open;
1138
1139 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1140 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1141 {
1142 return f(nearest_toward_zero{});
1143 }
1144
1145 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1146 BOOST_FORCEINLINE static constexpr ReturnType
1147 invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
1148 {
1149 return f();
1150 }
1151
1152 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1153 BOOST_FORCEINLINE static constexpr ReturnType
1154 invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
1155 {
1156 return f();
1157 }
1158 };
1159
1160 struct nearest_away_from_zero : base
1161 {
1162 using decimal_to_binary_rounding_policy = nearest_away_from_zero;
1163 static constexpr auto tag = tag_t::to_nearest;
1164 using normal_interval_type = interval_type::left_closed_right_open;
1165 using shorter_interval_type = interval_type::left_closed_right_open;
1166
1167 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1168 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1169 {
1170 return f(nearest_away_from_zero{});
1171 }
1172
1173 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1174 BOOST_FORCEINLINE static constexpr ReturnType
1175 invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
1176 {
1177 return f();
1178 }
1179
1180 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1181 BOOST_FORCEINLINE static constexpr ReturnType
1182 invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
1183 {
1184 return f();
1185 }
1186 };
1187
1188 struct nearest_always_closed
1189 {
1190 static constexpr auto tag = tag_t::to_nearest;
1191 using normal_interval_type = interval_type::closed;
1192 using shorter_interval_type = interval_type::closed;
1193
1194 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1195 BOOST_FORCEINLINE static constexpr ReturnType
1196 invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
1197 {
1198 return f();
1199 }
1200
1201 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1202 BOOST_FORCEINLINE static constexpr ReturnType
1203 invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
1204 {
1205 return f();
1206 }
1207 };
1208
1209 struct nearest_always_open
1210 {
1211 static constexpr auto tag = tag_t::to_nearest;
1212 using normal_interval_type = interval_type::open;
1213 using shorter_interval_type = interval_type::open;
1214
1215 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1216 BOOST_FORCEINLINE static constexpr ReturnType
1217 invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
1218 {
1219 return f();
1220 }
1221
1222 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1223 BOOST_FORCEINLINE static constexpr ReturnType
1224 invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
1225 {
1226 return f();
1227 }
1228 };
1229
1230 struct nearest_to_even_static_boundary : base
1231 {
1232 using decimal_to_binary_rounding_policy = nearest_to_even_static_boundary;
1233
1234 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1235 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
1236 {
1237 if (s.has_even_significand_bits())
1238 {
1239 return f(nearest_always_closed{});
1240 }
1241 else
1242 {
1243 return f(nearest_always_open{});
1244 }
1245 }
1246 };
1247
1248 struct nearest_to_odd_static_boundary : base
1249 {
1250 using decimal_to_binary_rounding_policy = nearest_to_odd_static_boundary;
1251
1252 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1253 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
1254 {
1255 if (s.has_even_significand_bits())
1256 {
1257 return f(nearest_always_open{});
1258 }
1259 else
1260 {
1261 return f(nearest_always_closed{});
1262 }
1263 }
1264 };
1265 struct nearest_toward_plus_infinity_static_boundary : base
1266 {
1267 using decimal_to_binary_rounding_policy = nearest_toward_plus_infinity_static_boundary;
1268
1269 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1270 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
1271 {
1272 if (s.is_negative())
1273 {
1274 return f(nearest_toward_zero{});
1275 }
1276 else
1277 {
1278 return f(nearest_away_from_zero{});
1279 }
1280 }
1281 };
1282
1283 struct nearest_toward_minus_infinity_static_boundary : base
1284 {
1285 using decimal_to_binary_rounding_policy = nearest_toward_minus_infinity_static_boundary;
1286
1287 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1288 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
1289 {
1290 if (s.is_negative())
1291 {
1292 return f(nearest_away_from_zero{});
1293 }
1294 else
1295 {
1296 return f(nearest_toward_zero{});
1297 }
1298 }
1299 };
1300
1301 struct left_closed_directed
1302 {
1303 static constexpr auto tag = tag_t::left_closed_directed;
1304 };
1305 struct right_closed_directed
1306 {
1307 static constexpr auto tag = tag_t::right_closed_directed;
1308 };
1309
1310 struct toward_plus_infinity : base
1311 {
1312 using decimal_to_binary_rounding_policy = toward_plus_infinity;
1313
1314 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1315 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
1316 {
1317 if (s.is_negative())
1318 {
1319 return f(left_closed_directed{});
1320 }
1321 else
1322 {
1323 return f(right_closed_directed{});
1324 }
1325 }
1326 };
1327
1328 struct toward_minus_infinity : base
1329 {
1330 using decimal_to_binary_rounding_policy = toward_minus_infinity;
1331
1332 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1333 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
1334 {
1335 if (s.is_negative())
1336 {
1337 return f(right_closed_directed{});
1338 }
1339 else
1340 {
1341 return f(left_closed_directed{});
1342 }
1343 }
1344 };
1345
1346 struct toward_zero : base
1347 {
1348 using decimal_to_binary_rounding_policy = toward_zero;
1349
1350 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1351 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1352 {
1353 return f(left_closed_directed{});
1354 }
1355 };
1356
1357 struct away_from_zero : base
1358 {
1359 using decimal_to_binary_rounding_policy = away_from_zero;
1360
1361 template <typename ReturnType, typename SignedSignificandBits, typename Func>
1362 BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
1363 {
1364 return f(right_closed_directed{});
1365 }
1366 };
1367}
1368
1369// Binary-to-decimal rounding policies.
1370// (Always assumes nearest rounding modes.)
1371namespace binary_to_decimal_rounding {
1372 struct base {};
1373
1374 enum class tag_t
1375 {
1376 do_not_care,
1377 to_even,
1378 to_odd,
1379 away_from_zero,
1380 toward_zero
1381 };
1382
1383 struct do_not_care : base
1384 {
1385 using binary_to_decimal_rounding_policy = do_not_care;
1386 static constexpr auto tag = tag_t::do_not_care;
1387
1388 template <typename ReturnType>
1389 static constexpr bool prefer_round_down(ReturnType const&) noexcept
1390 {
1391 return false;
1392 }
1393 };
1394
1395 struct to_even : base
1396 {
1397 using binary_to_decimal_rounding_policy = to_even;
1398 static constexpr auto tag = tag_t::to_even;
1399
1400 template <typename ReturnType>
1401 static constexpr bool prefer_round_down(ReturnType const& r) noexcept
1402 {
1403 return r.significand % 2 != 0;
1404 }
1405 };
1406
1407 struct to_odd : base
1408 {
1409 using binary_to_decimal_rounding_policy = to_odd;
1410 static constexpr auto tag = tag_t::to_odd;
1411
1412 template <typename ReturnType>
1413 static constexpr bool prefer_round_down(ReturnType const& r) noexcept
1414 {
1415 return r.significand % 2 == 0;
1416 }
1417 };
1418
1419 struct away_from_zero : base
1420 {
1421 using binary_to_decimal_rounding_policy = away_from_zero;
1422 static constexpr auto tag = tag_t::away_from_zero;
1423
1424 template <typename ReturnType>
1425 static constexpr bool prefer_round_down(ReturnType const&) noexcept
1426 {
1427 return false;
1428 }
1429 };
1430
1431 struct toward_zero : base
1432 {
1433 using binary_to_decimal_rounding_policy = toward_zero;
1434 static constexpr auto tag = tag_t::toward_zero;
1435
1436 template <typename ReturnType>
1437 static constexpr bool prefer_round_down(ReturnType const&) noexcept
1438 {
1439 return true;
1440 }
1441 };
1442}
1443
1444// Cache policies.
1445namespace cache {
1446 struct base {};
1447
1448 struct full : base
1449 {
1450 using cache_policy = full;
1451
1452 template <typename FloatFormat, typename cache_format = typename std::conditional<std::is_same<FloatFormat, ieee754_binary32>::value,
1453 cache_holder_ieee754_binary32,
1454 cache_holder_ieee754_binary64>::type>
1455 static constexpr typename cache_format::cache_entry_type get_cache(int k) noexcept
1456 {
1457 return cache_format::cache[std::size_t(k - cache_format::min_k)];
1458 }
1459 };
1460}
1461}
1462
1463namespace policy {
1464namespace sign {
1465 BOOST_INLINE_VARIABLE constexpr auto ignore = detail::policy_impl::sign::ignore{};
1466 BOOST_INLINE_VARIABLE constexpr auto return_sign = detail::policy_impl::sign::return_sign{};
1467}
1468
1469namespace trailing_zero {
1470 BOOST_INLINE_VARIABLE constexpr auto ignore = detail::policy_impl::trailing_zero::ignore{};
1471 BOOST_INLINE_VARIABLE constexpr auto remove = detail::policy_impl::trailing_zero::remove{};
1472 BOOST_INLINE_VARIABLE constexpr auto report = detail::policy_impl::trailing_zero::report{};
1473}
1474
1475namespace decimal_to_binary_rounding {
1476 BOOST_INLINE_VARIABLE constexpr auto nearest_to_even =
1477 detail::policy_impl::decimal_to_binary_rounding::nearest_to_even{};
1478 BOOST_INLINE_VARIABLE constexpr auto nearest_to_odd =
1479 detail::policy_impl::decimal_to_binary_rounding::nearest_to_odd{};
1480 BOOST_INLINE_VARIABLE constexpr auto nearest_toward_plus_infinity =
1481 detail::policy_impl::decimal_to_binary_rounding::nearest_toward_plus_infinity{};
1482 BOOST_INLINE_VARIABLE constexpr auto nearest_toward_minus_infinity =
1483 detail::policy_impl::decimal_to_binary_rounding::nearest_toward_minus_infinity{};
1484 BOOST_INLINE_VARIABLE constexpr auto nearest_toward_zero =
1485 detail::policy_impl::decimal_to_binary_rounding::nearest_toward_zero{};
1486 BOOST_INLINE_VARIABLE constexpr auto nearest_away_from_zero =
1487 detail::policy_impl::decimal_to_binary_rounding::nearest_away_from_zero{};
1488
1489 BOOST_INLINE_VARIABLE constexpr auto nearest_to_even_static_boundary =
1490 detail::policy_impl::decimal_to_binary_rounding::nearest_to_even_static_boundary{};
1491 BOOST_INLINE_VARIABLE constexpr auto nearest_to_odd_static_boundary =
1492 detail::policy_impl::decimal_to_binary_rounding::nearest_to_odd_static_boundary{};
1493 BOOST_INLINE_VARIABLE constexpr auto nearest_toward_plus_infinity_static_boundary =
1494 detail::policy_impl::decimal_to_binary_rounding::
1495 nearest_toward_plus_infinity_static_boundary{};
1496 BOOST_INLINE_VARIABLE constexpr auto nearest_toward_minus_infinity_static_boundary =
1497 detail::policy_impl::decimal_to_binary_rounding::
1498 nearest_toward_minus_infinity_static_boundary{};
1499
1500 BOOST_INLINE_VARIABLE constexpr auto toward_plus_infinity =
1501 detail::policy_impl::decimal_to_binary_rounding::toward_plus_infinity{};
1502 BOOST_INLINE_VARIABLE constexpr auto toward_minus_infinity =
1503 detail::policy_impl::decimal_to_binary_rounding::toward_minus_infinity{};
1504 BOOST_INLINE_VARIABLE constexpr auto toward_zero =
1505 detail::policy_impl::decimal_to_binary_rounding::toward_zero{};
1506 BOOST_INLINE_VARIABLE constexpr auto away_from_zero =
1507 detail::policy_impl::decimal_to_binary_rounding::away_from_zero{};
1508}
1509
1510namespace binary_to_decimal_rounding {
1511 BOOST_INLINE_VARIABLE constexpr auto do_not_care =
1512 detail::policy_impl::binary_to_decimal_rounding::do_not_care{};
1513 BOOST_INLINE_VARIABLE constexpr auto to_even =
1514 detail::policy_impl::binary_to_decimal_rounding::to_even{};
1515 BOOST_INLINE_VARIABLE constexpr auto to_odd =
1516 detail::policy_impl::binary_to_decimal_rounding::to_odd{};
1517 BOOST_INLINE_VARIABLE constexpr auto away_from_zero =
1518 detail::policy_impl::binary_to_decimal_rounding::away_from_zero{};
1519 BOOST_INLINE_VARIABLE constexpr auto toward_zero =
1520 detail::policy_impl::binary_to_decimal_rounding::toward_zero{};
1521}
1522
1523namespace cache {
1524 BOOST_INLINE_VARIABLE constexpr auto full = detail::policy_impl::cache::full{};
1525}
1526} // Namespace Policy
1527
1528////////////////////////////////////////////////////////////////////////////////////////
1529// The main algorithm.
1530////////////////////////////////////////////////////////////////////////////////////////
1531
1532template <typename Float, typename FloatTraits>
1533struct impl : private FloatTraits, private FloatTraits::format
1534{
1535 using format = typename FloatTraits::format;
1536 using carrier_uint = typename FloatTraits::carrier_uint;
1537
1538 using FloatTraits::carrier_bits;
1539 using format::significand_bits;
1540 using format::min_exponent;
1541 using format::max_exponent;
1542 using format::exponent_bias;
1543 using format::decimal_digits;
1544
1545 static constexpr int kappa = std::is_same<format, ieee754_binary32>::value ? 1 : 2;
1546 static_assert(kappa >= 1, "Kappa must be >= 1");
1547 // static_assert(carrier_bits >= significand_bits + 2 + log::floor_log2_pow10(kappa + 1));
1548
1549 static constexpr int min_k_a = -log::floor_log10_pow2_minus_log10_4_over_3(e: int(max_exponent - significand_bits));
1550 static constexpr int min_k_b = -log::floor_log10_pow2(e: int(max_exponent - significand_bits)) + kappa;
1551 static constexpr int min_k = min_k_a < min_k_b ? min_k_a : min_k_b;
1552 // static_assert(min_k >= cache_holder<format>::min_k, "Min k is not in the cache");
1553
1554 static constexpr int max_k_a = -log::floor_log10_pow2_minus_log10_4_over_3(e: int(min_exponent - significand_bits /*+ 1*/));
1555 static constexpr int max_k_b = -log::floor_log10_pow2(e: int(min_exponent - significand_bits)) + kappa;
1556 static constexpr int max_k = max_k_a > max_k_b ? max_k_a : max_k_b;
1557
1558 using cache_format = typename std::conditional<std::is_same<format, ieee754_binary32>::value,
1559 cache_holder_ieee754_binary32,
1560 cache_holder_ieee754_binary64>::type;
1561 using cache_entry_type = typename cache_format::cache_entry_type;
1562 static constexpr auto cache_bits = cache_format::cache_bits;
1563
1564 static constexpr int case_shorter_interval_left_endpoint_lower_threshold = 2;
1565 static BOOST_CXX14_CONSTEXPR const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1566 //2 + log::floor_log2(compute_power(10, count_factors<5>((carrier_uint(1) << (significand_bits + 2)) - 1) + 1) / 3);
1567
1568 static constexpr int case_shorter_interval_right_endpoint_lower_threshold = 0;
1569 static BOOST_CXX14_CONSTEXPR const int case_shorter_interval_right_endpoint_upper_threshold = 3;
1570 //2 + log::floor_log2(compute_power(10, count_factors<5>((carrier_uint(1) << (significand_bits + 1)) + 1) + 1) / 3);
1571
1572 static constexpr int shorter_interval_tie_lower_threshold =
1573 -log::floor_log5_pow2_minus_log5_3(e: significand_bits + 4) - 2 - significand_bits;
1574 static constexpr int shorter_interval_tie_upper_threshold =
1575 -log::floor_log5_pow2(e: significand_bits + 2) - 2 - significand_bits;
1576
1577 struct compute_mul_result
1578 {
1579 carrier_uint result;
1580 bool is_integer;
1581 };
1582
1583 struct compute_mul_parity_result
1584 {
1585 bool parity;
1586 bool is_integer;
1587 };
1588
1589 //// The main algorithm assumes the input is a normal/subnormal finite number
1590
1591 #if defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)
1592 # pragma GCC diagnostic push
1593 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
1594 #endif
1595
1596 template <typename ReturnType, typename IntervalType, typename TrailingZeroPolicy,
1597 typename BinaryToDecimalRoundingPolicy, typename CachePolicy, typename... AdditionalArgs>
1598 BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_nearest_normal(carrier_uint const two_fc, const int exponent,
1599 AdditionalArgs... additional_args) noexcept
1600 {
1601 //////////////////////////////////////////////////////////////////////
1602 // Step 1: Schubfach multiplier calculation
1603 //////////////////////////////////////////////////////////////////////
1604
1605 ReturnType ret_value = {};
1606 IntervalType interval_type{additional_args...};
1607
1608 // Compute k and beta.
1609 const int minus_k = log::floor_log10_pow2(e: exponent) - kappa;
1610 const auto cache = CachePolicy::template get_cache<format>(-minus_k);
1611 const int beta = exponent + log::floor_log2_pow10(e: -minus_k);
1612
1613 // Compute zi and deltai.
1614 // 10^kappa <= deltai < 10^(kappa + 1)
1615 const auto deltai = compute_delta(cache, beta);
1616 // For the case of binary32, the result of integer check is not correct for
1617 // 29711844 * 2^-82
1618 // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
1619 // and 29711844 * 2^-81
1620 // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17,
1621 // and they are the unique counterexamples. However, since 29711844 is even,
1622 // this does not cause any problem for the endpoints calculations; it can only
1623 // cause a problem when we need to perform integer check for the center.
1624 // Fortunately, with these inputs, that branch is never executed, so we are fine.
1625 //const auto [zi, is_z_integer] = compute_mul((two_fc | 1) << beta, cache);
1626 const auto z_res = compute_mul((two_fc | 1) << beta, cache);
1627 const auto zi = z_res.result;
1628 const auto is_z_integer = z_res.is_integer;
1629
1630 //////////////////////////////////////////////////////////////////////
1631 // Step 2: Try larger divisor; remove trailing zeros if necessary
1632 //////////////////////////////////////////////////////////////////////
1633
1634 BOOST_CXX14_CONSTEXPR auto big_divisor = compute_power(a: std::uint32_t(10), exp: kappa + 1);
1635 BOOST_CXX14_CONSTEXPR auto small_divisor = compute_power(a: std::uint32_t(10), exp: kappa);
1636
1637 // Using an upper bound on zi, we might be able to optimize the division
1638 // better than the compiler; we are computing zi / big_divisor here.
1639 #ifdef BOOST_NO_CXX14_CONSTEXPR
1640 ret_value.significand = div::divide_by_pow10<carrier_uint>(kappa + 1, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1, zi);
1641 #else
1642 ret_value.significand = div::divide_by_pow10<kappa + 1, carrier_uint, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1>(zi);
1643 #endif
1644
1645 auto r = std::uint32_t(zi - big_divisor * ret_value.significand);
1646
1647 if (r < deltai)
1648 {
1649 // Exclude the right endpoint if necessary.
1650 if (r == 0 && (is_z_integer & !interval_type.include_right_endpoint()))
1651 {
1652 BOOST_IF_CONSTEXPR (BinaryToDecimalRoundingPolicy::tag == policy_impl::binary_to_decimal_rounding::tag_t::do_not_care)
1653 {
1654 ret_value.significand *= 10;
1655 ret_value.exponent = minus_k + kappa;
1656 --ret_value.significand;
1657 TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
1658
1659 return ret_value;
1660 }
1661 else
1662 {
1663 --ret_value.significand;
1664 r = big_divisor;
1665
1666 goto small_divisor_case_label;
1667 }
1668 }
1669 }
1670 else if (r > deltai)
1671 {
1672 goto small_divisor_case_label;
1673 }
1674 else
1675 {
1676 // r == deltai; compare fractional parts.
1677 // const auto [xi_parity, x_is_integer] =
1678 // compute_mul_parity(two_fc - 1, cache, beta);
1679 const auto x_res = compute_mul_parity(two_fc - 1, cache, beta);
1680 const auto xi_parity = x_res.parity;
1681 const auto x_is_integer = x_res.is_integer;
1682
1683 if (!(xi_parity | (x_is_integer & interval_type.include_left_endpoint())))
1684 {
1685 goto small_divisor_case_label;
1686 }
1687 }
1688 ret_value.exponent = minus_k + kappa + 1;
1689
1690 // We may need to remove trailing zeros.
1691 TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
1692 return ret_value;
1693
1694
1695 //////////////////////////////////////////////////////////////////////
1696 // Step 3: Find the significand with the smaller divisor
1697 //////////////////////////////////////////////////////////////////////
1698
1699 small_divisor_case_label:
1700 TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
1701 ret_value.significand *= 10;
1702 ret_value.exponent = minus_k + kappa;
1703
1704 BOOST_IF_CONSTEXPR (BinaryToDecimalRoundingPolicy::tag == policy_impl::binary_to_decimal_rounding::tag_t::do_not_care)
1705 {
1706 // Normally, we want to compute
1707 // ret_value.significand += r / small_divisor
1708 // and return, but we need to take care of the case that the resulting
1709 // value is exactly the right endpoint, while that is not included in the
1710 // interval.
1711 if (!interval_type.include_right_endpoint())
1712 {
1713 // Is r divisible by 10^kappa?
1714 if (is_z_integer && div::check_divisibility_and_divide_by_pow10<kappa>(r))
1715 {
1716 // This should be in the interval.
1717 ret_value.significand += r - 1;
1718 }
1719 else
1720 {
1721 ret_value.significand += r;
1722 }
1723 }
1724 else
1725 {
1726 ret_value.significand += div::small_division_by_pow10<kappa>(r);
1727 }
1728 }
1729 else
1730 {
1731 auto dist = r - (deltai / 2) + (small_divisor / 2);
1732 const bool approx_y_parity = ((dist ^ (small_divisor / 2)) & 1) != 0;
1733
1734 // Is dist divisible by 10^kappa?
1735 const bool divisible_by_small_divisor = div::check_divisibility_and_divide_by_pow10<kappa>(dist);
1736
1737 // Add dist / 10^kappa to the significand.
1738 ret_value.significand += dist;
1739
1740 if (divisible_by_small_divisor)
1741 {
1742 // Check z^(f) >= epsilon^(f).
1743 // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
1744 // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
1745 // Since there are only 2 possibilities, we only need to care about the
1746 // parity. Also, zi and r should have the same parity since the divisor is
1747 // an even number.
1748 //const auto [yi_parity, is_y_integer] =
1749 // compute_mul_parity(two_fc, cache, beta);
1750 const auto y_res = compute_mul_parity(two_fc, cache, beta);
1751 const auto yi_parity = y_res.parity;
1752 const auto is_y_integer = y_res.is_integer;
1753
1754 if (yi_parity != approx_y_parity)
1755 {
1756 --ret_value.significand;
1757 }
1758 else
1759 {
1760 // If z^(f) >= epsilon^(f), we might have a tie
1761 // when z^(f) == epsilon^(f), or equivalently, when y is an integer.
1762 // For tie-to-up case, we can just choose the upper one.
1763 if (BinaryToDecimalRoundingPolicy::prefer_round_down(ret_value) & is_y_integer)
1764 {
1765 --ret_value.significand;
1766 }
1767 }
1768 }
1769 }
1770
1771 return ret_value;
1772 }
1773
1774 template <typename ReturnType, typename IntervalType, typename TrailingZeroPolicy,
1775 typename BinaryToDecimalRoundingPolicy, typename CachePolicy, typename... AdditionalArgs>
1776 BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_nearest_shorter(const int exponent, AdditionalArgs... additional_args) noexcept
1777 {
1778 ReturnType ret_value = {};
1779 IntervalType interval_type{additional_args...};
1780
1781 // Compute k and beta.
1782 const int minus_k = log::floor_log10_pow2_minus_log10_4_over_3(e: exponent);
1783 const int beta = exponent + log::floor_log2_pow10(e: -minus_k);
1784
1785 // Compute xi and zi.
1786 const auto cache = CachePolicy::template get_cache<format>(-minus_k);
1787
1788 auto xi = compute_left_endpoint_for_shorter_interval_case(cache, beta);
1789 auto zi = compute_right_endpoint_for_shorter_interval_case(cache, beta);
1790
1791 // If we don't accept the right endpoint and
1792 // if the right endpoint is an integer, decrease it.
1793 if (!interval_type.include_right_endpoint() && is_right_endpoint_integer_shorter_interval(exponent))
1794 {
1795 --zi;
1796 }
1797 // If we don't accept the left endpoint or
1798 // if the left endpoint is not an integer, increase it.
1799 if (!interval_type.include_left_endpoint() || !is_left_endpoint_integer_shorter_interval(exponent))
1800 {
1801 ++xi;
1802 }
1803
1804 // Try bigger divisor.
1805 ret_value.significand = zi / 10;
1806
1807 // If succeed, remove trailing zeros if necessary and return.
1808 if (ret_value.significand * 10 >= xi)
1809 {
1810 ret_value.exponent = minus_k + 1;
1811 TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
1812 return ret_value;
1813 }
1814
1815 // Otherwise, compute the round-up of y.
1816 TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
1817 ret_value.significand = compute_round_up_for_shorter_interval_case(cache, beta);
1818 ret_value.exponent = minus_k;
1819
1820 // When tie occurs, choose one of them according to the rule.
1821 if (BinaryToDecimalRoundingPolicy::prefer_round_down(ret_value) &&
1822 exponent >= shorter_interval_tie_lower_threshold &&
1823 exponent <= shorter_interval_tie_upper_threshold)
1824 {
1825 --ret_value.significand;
1826 }
1827 else if (ret_value.significand < xi)
1828 {
1829 ++ret_value.significand;
1830 }
1831
1832 return ret_value;
1833 }
1834
1835 #if defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)
1836 # pragma GCC diagnostic pop
1837 #endif
1838
1839 template <class ReturnType, class TrailingZeroPolicy, class CachePolicy>
1840 BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_left_closed_directed(carrier_uint const two_fc, int exponent) noexcept
1841 {
1842 //////////////////////////////////////////////////////////////////////
1843 // Step 1: Schubfach multiplier calculation
1844 //////////////////////////////////////////////////////////////////////
1845
1846 ReturnType ret_value;
1847
1848 // Compute k and beta.
1849 const int minus_k = log::floor_log10_pow2(e: exponent) - kappa;
1850 const auto cache = CachePolicy::template get_cache<format>(-minus_k);
1851 const int beta = exponent + log::floor_log2_pow10(e: -minus_k);
1852
1853 // Compute xi and deltai.
1854 // 10^kappa <= deltai < 10^(kappa + 1)
1855 const auto deltai = compute_delta(cache, beta);
1856 //auto [xi, is_x_integer] = compute_mul(two_fc << beta, cache);
1857 const auto x_res = compute_mul(two_fc << beta, cache);
1858 auto xi = x_res.result;
1859 auto is_x_integer = x_res.is_integer;
1860
1861 // Deal with the unique exceptional cases
1862 // 29711844 * 2^-82
1863 // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
1864 // and 29711844 * 2^-81
1865 // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17
1866 // for binary32.
1867 BOOST_IF_CONSTEXPR (std::is_same<format, ieee754_binary32>::value)
1868 {
1869 if (exponent <= -80)
1870 {
1871 is_x_integer = false;
1872 }
1873 }
1874
1875 if (!is_x_integer)
1876 {
1877 ++xi;
1878 }
1879
1880 //////////////////////////////////////////////////////////////////////
1881 // Step 2: Try larger divisor; remove trailing zeros if necessary
1882 //////////////////////////////////////////////////////////////////////
1883
1884 BOOST_CXX14_CONSTEXPR auto big_divisor = compute_power(a: std::uint32_t(10), exp: kappa + 1);
1885
1886 // Using an upper bound on xi, we might be able to optimize the division
1887 // better than the compiler; we are computing xi / big_divisor here.
1888
1889 #ifdef BOOST_NO_CXX14_CONSTEXPR
1890 ret_value.significand = div::divide_by_pow10<carrier_uint>(kappa + 1, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1, xi);
1891 #else
1892 ret_value.significand = div::divide_by_pow10<kappa + 1, carrier_uint, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1>(xi);
1893 #endif
1894
1895 auto r = std::uint32_t(xi - big_divisor * ret_value.significand);
1896
1897 if (r != 0)
1898 {
1899 ++ret_value.significand;
1900 r = big_divisor - r;
1901 }
1902
1903 if (r > deltai)
1904 {
1905 goto small_divisor_case_label;
1906 }
1907 else if (r == deltai)
1908 {
1909 // Compare the fractional parts.
1910 // This branch is never taken for the exceptional cases
1911 // 2f_c = 29711482, e = -81
1912 // (6.1442649164096937243516663440523473127541365101933479309082... * 10^-18)
1913 // and 2f_c = 29711482, e = -80
1914 // (1.2288529832819387448703332688104694625508273020386695861816... * 10^-17).
1915 //const auto [zi_parity, is_z_integer] =
1916 // compute_mul_parity(two_fc + 2, cache, beta);
1917 const auto z_res = compute_mul_parity(two_fc + 2, cache, beta);
1918 if (z_res.parity || z_res.is_integer)
1919 {
1920 goto small_divisor_case_label;
1921 }
1922 }
1923
1924 // The ceiling is inside, so we are done.
1925 ret_value.exponent = minus_k + kappa + 1;
1926 TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
1927 return ret_value;
1928
1929
1930 //////////////////////////////////////////////////////////////////////
1931 // Step 3: Find the significand with the smaller divisor
1932 //////////////////////////////////////////////////////////////////////
1933
1934 small_divisor_case_label:
1935 ret_value.significand *= 10;
1936 ret_value.significand -= div::small_division_by_pow10<kappa>(r);
1937 ret_value.exponent = minus_k + kappa;
1938 TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
1939 return ret_value;
1940 }
1941
1942 template <typename ReturnType, typename TrailingZeroPolicy, typename CachePolicy>
1943 BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_right_closed_directed(carrier_uint const two_fc, const int exponent, bool shorter_interval) noexcept
1944 {
1945 //////////////////////////////////////////////////////////////////////
1946 // Step 1: Schubfach multiplier calculation
1947 //////////////////////////////////////////////////////////////////////
1948
1949 ReturnType ret_value;
1950
1951 // Compute k and beta.
1952 const int minus_k = log::floor_log10_pow2(e: exponent - (shorter_interval ? 1 : 0)) - kappa;
1953 const auto cache = CachePolicy::template get_cache<format>(-minus_k);
1954 const int beta = exponent + log::floor_log2_pow10(e: -minus_k);
1955
1956 // Compute zi and deltai.
1957 // 10^kappa <= deltai < 10^(kappa + 1)
1958 const auto deltai = shorter_interval ? compute_delta(cache, beta - 1) : compute_delta(cache, beta);
1959 carrier_uint const zi = compute_mul(two_fc << beta, cache).result;
1960
1961
1962 //////////////////////////////////////////////////////////////////////
1963 // Step 2: Try larger divisor; remove trailing zeros if necessary
1964 //////////////////////////////////////////////////////////////////////
1965
1966 BOOST_CXX14_CONSTEXPR auto big_divisor = compute_power(a: std::uint32_t(10), exp: kappa + 1);
1967
1968 // Using an upper bound on zi, we might be able to optimize the division better than
1969 // the compiler; we are computing zi / big_divisor here.
1970 #ifdef BOOST_NO_CXX14_CONSTEXPR
1971 ret_value.significand = div::divide_by_pow10<carrier_uint>(kappa + 1, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1, zi);
1972 #else
1973 ret_value.significand = div::divide_by_pow10<kappa + 1, carrier_uint, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1>(zi);
1974 #endif
1975
1976 const auto r = std::uint32_t(zi - big_divisor * ret_value.significand);
1977
1978 if (r > deltai)
1979 {
1980 goto small_divisor_case_label;
1981 }
1982 else if (r == deltai)
1983 {
1984 // Compare the fractional parts.
1985 if (!compute_mul_parity(two_fc - (shorter_interval ? 1 : 2), cache, beta).parity)
1986 {
1987 goto small_divisor_case_label;
1988 }
1989 }
1990
1991 // The floor is inside, so we are done.
1992 ret_value.exponent = minus_k + kappa + 1;
1993 TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
1994 return ret_value;
1995
1996
1997 //////////////////////////////////////////////////////////////////////
1998 // Step 3: Find the significand with the small divisor
1999 //////////////////////////////////////////////////////////////////////
2000
2001 small_divisor_case_label:
2002 ret_value.significand *= 10;
2003 ret_value.significand += div::small_division_by_pow10<kappa>(r);
2004 ret_value.exponent = minus_k + kappa;
2005 TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
2006
2007 return ret_value;
2008 }
2009
2010 // Remove trailing zeros from n and return the number of zeros removed.
2011 BOOST_FORCEINLINE static int remove_trailing_zeros(carrier_uint& n) noexcept
2012 {
2013 if (n == 0)
2014 {
2015 return 0;
2016 }
2017
2018 BOOST_IF_CONSTEXPR (std::is_same<format, ieee754_binary32>::value)
2019 {
2020 constexpr auto mod_inv_5 = UINT32_C(0xcccccccd);
2021 constexpr auto mod_inv_25 = mod_inv_5 * mod_inv_5;
2022
2023 int s = 0;
2024 while (true)
2025 {
2026 auto q = boost::core::rotr(n * mod_inv_25, 2);
2027 if (q <= (std::numeric_limits<std::uint32_t>::max)() / 100)
2028 {
2029 n = q;
2030 s += 2;
2031 }
2032 else
2033 {
2034 break;
2035 }
2036 }
2037 auto q = boost::core::rotr(n * mod_inv_5, 1);
2038 if (q <= (std::numeric_limits<std::uint32_t>::max)() / 10)
2039 {
2040 n = q;
2041 s |= 1;
2042 }
2043
2044 return s;
2045 }
2046 else
2047 {
2048 // Static assertion does not work unless if constexpr is supported
2049 // static_assert(std::is_same<format, ieee754_binary64>::value, "Must be a double type");
2050
2051 // Divide by 10^8 and reduce to 32-bits if divisible.
2052 // Since ret_value.significand <= (2^53 * 1000 - 1) / 1000 < 10^16,
2053 // n is at most of 16 digits.
2054
2055 // This magic number is ceil(2^90 / 10^8).
2056 constexpr auto magic_number = UINT64_C(12379400392853802749);
2057 auto nm = umul128(n, magic_number);
2058
2059 // Is n is divisible by 10^8?
2060 if ((nm.high & ((std::uint64_t(1) << (90 - 64)) - 1)) == 0 &&
2061 nm.low < magic_number) {
2062 // If yes, work with the quotient.
2063 auto n32 = static_cast<std::uint32_t>(nm.high >> (90 - 64));
2064
2065 constexpr auto mod_inv_5 = UINT32_C(0xcccccccd);
2066 constexpr auto mod_inv_25 = mod_inv_5 * mod_inv_5;
2067
2068 int s = 8;
2069 while (true)
2070 {
2071 auto q = boost::core::rotr(x: n32 * mod_inv_25, s: 2);
2072 if (q <= (std::numeric_limits<std::uint32_t>::max)() / 100)
2073 {
2074 n32 = q;
2075 s += 2;
2076 }
2077 else
2078 {
2079 break;
2080 }
2081 }
2082
2083 auto q = boost::core::rotr(x: n32 * mod_inv_5, s: 1);
2084 if (q <= (std::numeric_limits<std::uint32_t>::max)() / 10)
2085 {
2086 n32 = q;
2087 s |= 1;
2088 }
2089
2090 n = n32;
2091 return s;
2092 }
2093
2094 // If n is not divisible by 10^8, work with n itself.
2095 constexpr auto mod_inv_5 = UINT64_C(0xcccccccccccccccd);
2096 constexpr auto mod_inv_25 = mod_inv_5 * mod_inv_5;
2097
2098 int s = 0;
2099 while (true)
2100 {
2101 auto q = static_cast<carrier_uint>(boost::core::rotr(n * mod_inv_25, 2));
2102 if (q <= (std::numeric_limits<std::uint64_t>::max)() / 100)
2103 {
2104 n = q;
2105 s += 2;
2106 }
2107 else
2108 {
2109 break;
2110 }
2111 }
2112
2113 auto q = static_cast<carrier_uint>(boost::core::rotr(n * mod_inv_5, 1));
2114 if (q <= (std::numeric_limits<std::uint64_t>::max)() / 10)
2115 {
2116 n = q;
2117 s |= 1;
2118 }
2119
2120 return s;
2121 }
2122 }
2123
2124 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
2125 static compute_mul_result compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept
2126 {
2127 auto r = umul96_upper64(u, cache);
2128 return {carrier_uint(r >> 32), carrier_uint(r) == 0};
2129 }
2130
2131 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
2132 static compute_mul_result compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept
2133 {
2134 auto r = umul192_upper128(u, cache);
2135 return {r.high, r.low == 0};
2136 }
2137
2138 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
2139 static constexpr std::uint32_t compute_delta(cache_entry_type const& cache,
2140 int beta) noexcept
2141 {
2142 return std::uint32_t(cache >> (cache_bits - 1 - beta));
2143 }
2144
2145 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
2146 static constexpr std::uint32_t compute_delta(cache_entry_type const& cache,
2147 int beta) noexcept
2148 {
2149 return std::uint32_t(cache.high >> (carrier_bits - 1 - beta));
2150 }
2151
2152 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
2153 static compute_mul_parity_result compute_mul_parity(carrier_uint two_f,
2154 cache_entry_type const& cache,
2155 int beta) noexcept
2156 {
2157 auto r = umul96_lower64(two_f, cache);
2158 return {((r >> (64 - beta)) & 1) != 0, std::uint32_t(r >> (32 - beta)) == 0};
2159 }
2160
2161 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
2162 static compute_mul_parity_result compute_mul_parity(carrier_uint two_f,
2163 cache_entry_type const& cache,
2164 int beta) noexcept
2165 {
2166 auto r = umul192_lower128(two_f, cache);
2167 return {((r.high >> (64 - beta)) & 1) != 0, ((r.high << beta) | (r.low >> (64 - beta))) == 0};
2168 }
2169
2170 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
2171 static constexpr carrier_uint compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
2172 {
2173 return carrier_uint((cache - (cache >> (significand_bits + 2))) >> (cache_bits - significand_bits - 1 - beta));
2174 }
2175
2176 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
2177 static constexpr carrier_uint compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
2178 {
2179 return (cache.high - (cache.high >> (significand_bits + 2))) >> (carrier_bits - significand_bits - 1 - beta);
2180 }
2181
2182 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
2183 static constexpr carrier_uint compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
2184 {
2185 return carrier_uint((cache + (cache >> (significand_bits + 1))) >> (cache_bits - significand_bits - 1 - beta));
2186 }
2187
2188 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
2189 static constexpr carrier_uint compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
2190 {
2191 return (cache.high + (cache.high >> (significand_bits + 1))) >> (carrier_bits - significand_bits - 1 - beta);
2192 }
2193
2194 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
2195 static constexpr carrier_uint compute_round_up_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
2196 {
2197 return (carrier_uint(cache >> (cache_bits - significand_bits - 2 - beta)) + 1) / 2;
2198 }
2199
2200 template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
2201 static constexpr carrier_uint compute_round_up_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
2202 {
2203 return ((cache.high >> (carrier_bits - significand_bits - 2 - beta)) + 1) / 2;
2204 }
2205
2206 static constexpr bool is_right_endpoint_integer_shorter_interval(int exponent) noexcept
2207 {
2208 return exponent >= case_shorter_interval_right_endpoint_lower_threshold &&
2209 exponent <= case_shorter_interval_right_endpoint_upper_threshold;
2210 }
2211
2212 static constexpr bool is_left_endpoint_integer_shorter_interval(int exponent) noexcept
2213 {
2214 return exponent >= case_shorter_interval_left_endpoint_lower_threshold &&
2215 exponent <= case_shorter_interval_left_endpoint_upper_threshold;
2216 }
2217};
2218
2219
2220////////////////////////////////////////////////////////////////////////////////////////
2221// Policy holder.
2222////////////////////////////////////////////////////////////////////////////////////////
2223
2224namespace policy_impl {
2225 // The library will specify a list of accepted kinds of policies and their defaults, and
2226 // the user will pass a list of policies. The aim of helper classes/functions here is to
2227 // do the following:
2228 // 1. Check if the policy parameters given by the user are all valid; that means,
2229 // each of them should be of the kinds specified by the library.
2230 // If that's not the case, then the compilation fails.
2231 // 2. Check if multiple policy parameters for the same kind is specified by the user.
2232 // If that's the case, then the compilation fails.
2233 // 3. Build a class deriving from all policies the user have given, and also from
2234 // the default policies if the user did not specify one for some kinds.
2235 // A policy belongs to a certain kind if it is deriving from a base class.
2236
2237 // For a given kind, find a policy belonging to that kind.
2238 // Check if there are more than one such policies.
2239 enum class policy_found_info
2240 {
2241 not_found,
2242 unique,
2243 repeated
2244 };
2245
2246 template <typename Policy, policy_found_info info>
2247 struct found_policy_pair
2248 {
2249 using policy = Policy;
2250 static constexpr auto found_info = info;
2251 };
2252
2253 template <typename Base, typename DefaultPolicy>
2254 struct base_default_pair
2255 {
2256 using base = Base;
2257
2258 template <class FoundPolicyInfo>
2259 static constexpr FoundPolicyInfo get_policy_impl(FoundPolicyInfo)
2260 {
2261 return {};
2262 }
2263
2264 template <typename FoundPolicyInfo, typename FirstPolicy, typename... RemainingPolicies,
2265 typename std::enable_if<std::is_base_of<Base, FirstPolicy>::value && (FoundPolicyInfo::found_info == policy_found_info::not_found), bool>::type = true>
2266 static constexpr auto get_policy_impl(FoundPolicyInfo, FirstPolicy, RemainingPolicies... remainings) noexcept -> found_policy_pair<FirstPolicy, policy_found_info::unique>
2267 {
2268 return get_policy_impl(found_policy_pair<FirstPolicy, policy_found_info::unique>{}, remainings...);
2269 }
2270
2271 template <typename FoundPolicyInfo, typename FirstPolicy, typename... RemainingPolicies,
2272 typename std::enable_if<std::is_base_of<Base, FirstPolicy>::value && !(FoundPolicyInfo::found_info == policy_found_info::not_found), bool>::type = true>
2273 static constexpr auto get_policy_impl(FoundPolicyInfo, FirstPolicy, RemainingPolicies... remainings) noexcept -> found_policy_pair<FirstPolicy, policy_found_info::repeated>
2274 {
2275 return get_policy_impl(found_policy_pair<FirstPolicy, policy_found_info::repeated>{}, remainings...);
2276 }
2277
2278 template <typename FoundPolicyInfo, typename FirstPolicy, typename... RemainingPolicies,
2279 typename std::enable_if<!std::is_base_of<Base, FirstPolicy>::value, bool>::type = true>
2280 static constexpr auto get_policy_impl(FoundPolicyInfo, FirstPolicy, RemainingPolicies... remainings) noexcept -> found_policy_pair<FirstPolicy, FoundPolicyInfo::found_info>
2281 {
2282 return get_policy_impl(FoundPolicyInfo{}, remainings...);
2283 }
2284
2285 template <typename... Policies>
2286 static constexpr auto get_policy(Policies... policies) -> found_policy_pair<DefaultPolicy, policy_found_info::not_found>
2287 {
2288 return get_policy_impl(found_policy_pair<DefaultPolicy, policy_found_info::not_found>{}, policies...);
2289 }
2290 };
2291
2292 template <typename... BaseDefaultPairs>
2293 struct base_default_pair_list {};
2294
2295 // Check if a given policy belongs to one of the kinds specified by the library.
2296 template <typename Policy>
2297 constexpr bool check_policy_validity(Policy, base_default_pair_list<>)
2298 {
2299 return false;
2300 }
2301
2302 template <typename Policy, typename FirstBaseDefaultPair, typename... RemainingBaseDefaultPairs>
2303 constexpr bool check_policy_validity(Policy, base_default_pair_list<FirstBaseDefaultPair, RemainingBaseDefaultPairs...>)
2304 {
2305 return std::is_base_of<typename FirstBaseDefaultPair::base, Policy>::value ||
2306 check_policy_validity(Policy{}, base_default_pair_list<RemainingBaseDefaultPairs...>{});
2307 }
2308
2309 template <typename BaseDefaultPairList>
2310 constexpr bool check_policy_list_validity(BaseDefaultPairList)
2311 {
2312 return true;
2313 }
2314
2315 template <typename BaseDefaultPairList, typename FirstPolicy, typename... RemainingPolicies>
2316 constexpr bool check_policy_list_validity(BaseDefaultPairList, FirstPolicy, RemainingPolicies... remaining_policies)
2317 {
2318 return check_policy_validity(FirstPolicy{}, BaseDefaultPairList{}) &&
2319 check_policy_list_validity(BaseDefaultPairList{}, remaining_policies...);
2320 }
2321
2322 // Build policy_holder.
2323 template <bool repeated_, typename... FoundPolicyPairs>
2324 struct found_policy_pair_list
2325 {
2326 static constexpr bool repeated = repeated_;
2327 };
2328
2329 template <typename... Policies>
2330 struct policy_holder : Policies... {};
2331
2332 #ifndef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
2333
2334 template <bool repeated, typename... FoundPolicyPairs, typename... Policies>
2335 constexpr auto make_policy_holder_impl(base_default_pair_list<>, found_policy_pair_list<repeated, FoundPolicyPairs...>, Policies...)
2336 -> found_policy_pair_list<repeated, FoundPolicyPairs...>
2337 {
2338 return found_policy_pair_list<repeated, FoundPolicyPairs...>{};
2339 }
2340
2341 template <typename FirstBaseDefaultPair, typename... RemainingBaseDefaultPairs, bool repeated,
2342 typename... FoundPolicyPairs, typename... Policies>
2343 constexpr auto make_policy_holder_impl(base_default_pair_list<FirstBaseDefaultPair, RemainingBaseDefaultPairs...>,
2344 found_policy_pair_list<repeated, FoundPolicyPairs...>, Policies... policies)
2345 {
2346 using new_found_policy_pair = decltype(FirstBaseDefaultPair::get_policy(policies...));
2347
2348 return make_policy_holder_impl(base_default_pair_list<RemainingBaseDefaultPairs...>{},
2349 found_policy_pair_list < repeated || new_found_policy_pair::found_info == policy_found_info::repeated,
2350 new_found_policy_pair, FoundPolicyPairs... > {}, policies...);
2351 }
2352
2353 template <bool repeated, typename... RawPolicies>
2354 constexpr auto convert_to_policy_holder(found_policy_pair_list<repeated>, RawPolicies...) -> policy_holder<RawPolicies...>
2355 {
2356 return policy_holder<RawPolicies...>{};
2357 }
2358
2359 template <bool repeated, typename FirstFoundPolicyPair, typename... RemainingFoundPolicyPairs, typename... RawPolicies>
2360 constexpr auto convert_to_policy_holder(found_policy_pair_list<repeated, FirstFoundPolicyPair, RemainingFoundPolicyPairs...>,
2361 RawPolicies... policies)
2362 {
2363 return convert_to_policy_holder(found_policy_pair_list<repeated, RemainingFoundPolicyPairs...>{}, typename FirstFoundPolicyPair::policy{}, policies...);
2364 }
2365
2366 template <typename BaseDefaultPairList, typename... Policies>
2367 constexpr auto make_policy_holder(BaseDefaultPairList, Policies... policies)
2368 {
2369 static_assert(check_policy_list_validity(BaseDefaultPairList{}, Policies{}...),
2370 "jkj::dragonbox: an invalid policy is specified");
2371
2372 using policy_pair_list = decltype(make_policy_holder_impl(
2373 BaseDefaultPairList{}, found_policy_pair_list<false>{}, policies...));
2374
2375 static_assert(!policy_pair_list::repeated,
2376 "jkj::dragonbox: each policy should be specified at most once");
2377
2378 return convert_to_policy_holder(policy_pair_list{});
2379 }
2380 #endif
2381}
2382////////////////////////////////////////////////////////////////////////////////////////
2383// The interface function.
2384////////////////////////////////////////////////////////////////////////////////////////
2385
2386#ifdef BOOST_MSVC
2387# pragma warning(push)
2388# pragma warning(disable: 4100) // Unreferenced formal parameter (interval_type_provider)
2389# pragma warning(disable: 4189) // Local variable is initializaed but unused (tag)
2390#endif
2391
2392template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
2393BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto
2394to_decimal(dragonbox_signed_significand_bits<Float, FloatTraits> dragonbox_signed_significand_bits,
2395 unsigned int exponent_bits, BOOST_ATTRIBUTE_UNUSED Policies... policies) noexcept
2396 #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
2397 -> decimal_fp<typename FloatTraits::carrier_uint, true, false>
2398 #endif
2399{
2400 // Build policy holder type.
2401 using namespace policy_impl;
2402
2403 #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
2404 // For C++11 we hardcode the policy holder
2405 using policy_holder = policy_holder<decimal_to_binary_rounding::nearest_to_even, binary_to_decimal_rounding::to_even, cache::full, sign::return_sign, trailing_zero::remove>;
2406
2407 #else
2408
2409 using policy_holder = decltype(make_policy_holder(
2410 base_default_pair_list<base_default_pair<sign::base, sign::return_sign>,
2411 base_default_pair<trailing_zero::base, trailing_zero::remove>,
2412 base_default_pair<decimal_to_binary_rounding::base,
2413 decimal_to_binary_rounding::nearest_to_even>,
2414 base_default_pair<binary_to_decimal_rounding::base,
2415 binary_to_decimal_rounding::to_even>,
2416 base_default_pair<cache::base, cache::full>>{},
2417 policies...));
2418
2419 #endif
2420
2421 using return_type = decimal_fp<typename FloatTraits::carrier_uint, policy_holder::return_has_sign, policy_holder::report_trailing_zeros>;
2422
2423 return_type ret = policy_holder::template delegate<return_type>(dragonbox_signed_significand_bits,
2424 [exponent_bits, dragonbox_signed_significand_bits](policy_impl::decimal_to_binary_rounding::nearest_to_even interval_type_provider) {
2425 using format = typename FloatTraits::format;
2426 constexpr auto tag = decltype(interval_type_provider)::tag;
2427
2428 auto two_fc = dragonbox_signed_significand_bits.remove_sign_bit_and_shift();
2429 auto exponent = int(exponent_bits);
2430
2431 BOOST_IF_CONSTEXPR (tag == decimal_to_binary_rounding::tag_t::to_nearest) { // NOLINT: if constexpr not always false
2432 // Is the input a normal number?
2433 if (exponent != 0) {
2434 exponent += format::exponent_bias - format::significand_bits;
2435
2436 // Shorter interval case; proceed like Schubfach.
2437 // One might think this condition is wrong, since when exponent_bits == 1
2438 // and two_fc == 0, the interval is actually regular. However, it turns out
2439 // that this seemingly wrong condition is actually fine, because the end
2440 // result is anyway the same.
2441 //
2442 // [binary32]
2443 // (fc-1/2) * 2^e = 1.175'494'28... * 10^-38
2444 // (fc-1/4) * 2^e = 1.175'494'31... * 10^-38
2445 // fc * 2^e = 1.175'494'35... * 10^-38
2446 // (fc+1/2) * 2^e = 1.175'494'42... * 10^-38
2447 //
2448 // Hence, shorter_interval_case will return 1.175'494'4 * 10^-38.
2449 // 1.175'494'3 * 10^-38 is also a correct shortest representation that will
2450 // be rejected if we assume shorter interval, but 1.175'494'4 * 10^-38 is
2451 // closer to the true value so it doesn't matter.
2452 //
2453 // [binary64]
2454 // (fc-1/2) * 2^e = 2.225'073'858'507'201'13... * 10^-308
2455 // (fc-1/4) * 2^e = 2.225'073'858'507'201'25... * 10^-308
2456 // fc * 2^e = 2.225'073'858'507'201'38... * 10^-308
2457 // (fc+1/2) * 2^e = 2.225'073'858'507'201'63... * 10^-308
2458 //
2459 // Hence, shorter_interval_case will return 2.225'073'858'507'201'4 *
2460 // 10^-308. This is indeed of the shortest length, and it is the unique one
2461 // closest to the true value among valid representations of the same length.
2462 static_assert(std::is_same<format, ieee754_binary32>::value ||
2463 std::is_same<format, ieee754_binary64>::value, "Format must be IEEE754 binary 32 or 64");
2464
2465 if (two_fc == 0) {
2466 return decltype(interval_type_provider)::template invoke_shorter_interval_case<return_type>(
2467 dragonbox_signed_significand_bits, [exponent]() {
2468 return detail::impl<Float, FloatTraits>::
2469 template compute_nearest_shorter<
2470 return_type,
2471 typename decltype(interval_type_provider)::
2472 shorter_interval_type,
2473 typename policy_holder::trailing_zero_policy,
2474 typename policy_holder::
2475 binary_to_decimal_rounding_policy,
2476 typename policy_holder::cache_policy>(
2477 exponent);
2478 });
2479 }
2480
2481 two_fc |= (decltype(two_fc)(1) << (format::significand_bits + 1));
2482 }
2483 // Is the input a subnormal number?
2484 else {
2485 exponent = format::min_exponent - format::significand_bits;
2486 }
2487
2488 return decltype(interval_type_provider)::template invoke_normal_interval_case<return_type>(
2489 dragonbox_signed_significand_bits, [two_fc, exponent](bool additional_args) {
2490 return detail::impl<Float, FloatTraits>::
2491 template compute_nearest_normal<
2492 return_type,
2493 typename decltype(interval_type_provider)::normal_interval_type,
2494 typename policy_holder::trailing_zero_policy,
2495 typename policy_holder::binary_to_decimal_rounding_policy,
2496 typename policy_holder::cache_policy>(two_fc, exponent, additional_args);
2497 });
2498 }
2499 else BOOST_IF_CONSTEXPR (tag == decimal_to_binary_rounding::tag_t::left_closed_directed) // NOLINT: if constexpr not always false
2500 {
2501 // Is the input a normal number?
2502 if (exponent != 0) {
2503 exponent += format::exponent_bias - format::significand_bits;
2504 two_fc |= (decltype(two_fc)(1) << (format::significand_bits + 1));
2505 }
2506 // Is the input a subnormal number?
2507 else {
2508 exponent = format::min_exponent - format::significand_bits;
2509 }
2510
2511 return detail::impl<Float>::template compute_left_closed_directed<
2512 return_type, typename policy_holder::trailing_zero_policy,
2513 typename policy_holder::cache_policy>(two_fc, exponent);
2514 }
2515 else
2516 {
2517 // Assertion does not work unless if constexpr is defined
2518 // static_assert(tag == decimal_to_binary_rounding::tag_t::right_closed_directed, "Tag should be right_closed_direction");
2519
2520 bool shorter_interval = false;
2521
2522 // Is the input a normal number?
2523 if (exponent != 0) {
2524 if (two_fc == 0 && exponent != 1) {
2525 shorter_interval = true;
2526 }
2527 exponent += format::exponent_bias - format::significand_bits;
2528 two_fc |= (decltype(two_fc)(1) << (format::significand_bits + 1));
2529 }
2530 // Is the input a subnormal number?
2531 else {
2532 exponent = format::min_exponent - format::significand_bits;
2533 }
2534
2535 return detail::impl<Float>::template compute_right_closed_directed<
2536 return_type, typename policy_holder::trailing_zero_policy,
2537 typename policy_holder::cache_policy>(two_fc, exponent, shorter_interval);
2538 }
2539 });
2540
2541 policy_holder::handle_sign(dragonbox_signed_significand_bits, ret);
2542 return ret;
2543}
2544
2545#ifdef BOOST_MSVC
2546# pragma warning(pop)
2547#endif
2548
2549template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
2550BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto to_decimal(Float x, Policies... policies) noexcept
2551 #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
2552 -> decimal_fp<typename FloatTraits::carrier_uint, true, false>
2553 #endif
2554{
2555 const auto br = dragonbox_float_bits<Float, FloatTraits>(x);
2556 const auto exponent_bits = br.extract_exponent_bits();
2557 const auto s = br.remove_exponent_bits(exponent_bits);
2558 BOOST_CHARCONV_ASSERT(br.is_finite());
2559
2560 return to_decimal<Float, FloatTraits>(s, exponent_bits, policies...);
2561}
2562
2563namespace to_chars_detail {
2564 template <class Float, class FloatTraits>
2565 extern to_chars_result dragon_box_print_chars(typename FloatTraits::carrier_uint significand, int exponent, char* first, char* last, chars_format fmt) noexcept;
2566
2567 // Avoid needless ABI overhead incurred by tag dispatch.
2568 template <class PolicyHolder, class Float, class FloatTraits>
2569 to_chars_result to_chars_n_impl(dragonbox_float_bits<Float, FloatTraits> br, char* first, char* last, chars_format fmt) noexcept
2570 {
2571 const auto exponent_bits = br.extract_exponent_bits();
2572 const auto s = br.remove_exponent_bits(exponent_bits);
2573
2574 auto buffer = first;
2575 const auto buffer_size = last - first;
2576
2577 if (br.is_finite(exponent_bits))
2578 {
2579 if (s.is_negative())
2580 {
2581 *buffer = '-';
2582 ++buffer;
2583 }
2584 if (br.is_nonzero())
2585 {
2586 auto result = to_decimal<Float, FloatTraits>(
2587 s, exponent_bits, policy::sign::ignore, policy::trailing_zero::ignore,
2588 typename PolicyHolder::decimal_to_binary_rounding_policy{},
2589 typename PolicyHolder::binary_to_decimal_rounding_policy{},
2590 typename PolicyHolder::cache_policy{});
2591 return to_chars_detail::dragon_box_print_chars<Float, FloatTraits>(result.significand, result.exponent, buffer, last, fmt);
2592 }
2593 else
2594 {
2595 if (fmt != chars_format::scientific)
2596 {
2597 std::memcpy(dest: buffer, src: "0", n: 1); // NOLINT: Specifically not null-terminated
2598 return {.ptr: buffer + 1, .ec: std::errc()};
2599 }
2600
2601 if (buffer_size >= 5)
2602 {
2603 std::memcpy(dest: buffer, src: "0e+00", n: 5); // NOLINT: Specifically not null-terminated
2604 return {.ptr: buffer + 5, .ec: std::errc()};
2605 }
2606 else
2607 {
2608 return {.ptr: last, .ec: std::errc::value_too_large};
2609 }
2610 }
2611 }
2612 else
2613 {
2614 bool is_negative = false;
2615 if (s.is_negative())
2616 {
2617 *buffer = '-';
2618 ++buffer;
2619 is_negative = true;
2620 }
2621
2622 if (s.has_all_zero_significand_bits())
2623 {
2624 if (buffer_size >= 3 + static_cast<std::ptrdiff_t>(is_negative))
2625 {
2626 std::memcpy(dest: buffer, src: "inf", n: 3); // NOLINT: Specifically not null-terminated
2627 return {.ptr: buffer + 3, .ec: std::errc()};
2628 }
2629 else
2630 {
2631 return {.ptr: last, .ec: std::errc::value_too_large};
2632 }
2633 }
2634 else
2635 {
2636 // Doubles:
2637 // qNaN = 2251799813685248
2638 // sNaN = 1125899906842624
2639 //
2640 // Floats:
2641 // qNaN = 4194304
2642 // sNaN = 2097152
2643 //
2644 // use 1 for qNaN and 0 for sNaN
2645 int nan_type;
2646 BOOST_IF_CONSTEXPR (std::is_same<typename FloatTraits::format, ieee754_binary32>::value)
2647 {
2648 if (br.extract_significand_bits() == UINT32_C(4194304))
2649 {
2650 nan_type = 1;
2651 }
2652 else
2653 {
2654 nan_type = 0;
2655 }
2656 }
2657 else
2658 {
2659 if (br.extract_significand_bits() == UINT64_C(2251799813685248))
2660 {
2661 nan_type = 1;
2662 }
2663 else
2664 {
2665 nan_type = 0;
2666 }
2667 }
2668
2669 if (nan_type == 1)
2670 {
2671 if (!s.is_negative())
2672 {
2673 if (buffer_size >= 3 + static_cast<std::ptrdiff_t>(is_negative))
2674 {
2675 std::memcpy(dest: buffer, src: "nan", n: 3); // NOLINT: Specifically not null-terminated
2676 return {.ptr: buffer + 3, .ec: std::errc()};
2677 }
2678 else
2679 {
2680 return {.ptr: last, .ec: std::errc::value_too_large};
2681 }
2682 }
2683 else
2684 {
2685 if (buffer_size >= 8 + static_cast<std::ptrdiff_t>(is_negative))
2686 {
2687 std::memcpy(dest: buffer, src: "nan(ind)", n: 8); // NOLINT: Specifically not null-terminated
2688 return {.ptr: buffer + 8, .ec: std::errc()};
2689 }
2690 else
2691 {
2692 return {.ptr: last, .ec: std::errc::value_too_large};
2693 }
2694 }
2695 }
2696 else
2697 {
2698 if (buffer_size >= 9 + static_cast<std::ptrdiff_t>(is_negative))
2699 {
2700 std::memcpy(dest: buffer, src: "nan(snan)", n: 9); // NOLINT: Specifically not null-terminated
2701 return {.ptr: buffer + 9, .ec: std::errc()};
2702 }
2703 else
2704 {
2705 return {.ptr: last, .ec: std::errc::value_too_large};
2706 }
2707 }
2708 }
2709 }
2710 }
2711}
2712
2713// Returns the next-to-end position
2714template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
2715to_chars_result to_chars_n(Float x, char* first, char* last, chars_format fmt, BOOST_ATTRIBUTE_UNUSED Policies... policies) noexcept
2716{
2717 using namespace policy_impl;
2718
2719 #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
2720 // For C++11 we hardcode the policy holder
2721 using policy_holder = policy_holder<decimal_to_binary_rounding::nearest_to_even, binary_to_decimal_rounding::to_even, cache::full, sign::return_sign, trailing_zero::remove>;
2722
2723 #else
2724
2725 using policy_holder = decltype(make_policy_holder(
2726 base_default_pair_list<base_default_pair<sign::base, sign::return_sign>,
2727 base_default_pair<trailing_zero::base, trailing_zero::remove>,
2728 base_default_pair<decimal_to_binary_rounding::base,
2729 decimal_to_binary_rounding::nearest_to_even>,
2730 base_default_pair<binary_to_decimal_rounding::base,
2731 binary_to_decimal_rounding::to_even>,
2732 base_default_pair<cache::base, cache::full>>{},
2733 policies...));
2734
2735 #endif
2736
2737 return to_chars_detail::to_chars_n_impl<policy_holder>(dragonbox_float_bits<Float, FloatTraits>(x), first, last, fmt);
2738}
2739
2740// Null-terminate and bypass the return value of fp_to_chars_n
2741template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
2742to_chars_result dragonbox_to_chars(Float x, char* first, char* last, chars_format fmt, Policies... policies) noexcept
2743{
2744 return to_chars_n<Float, FloatTraits>(x, first, last, fmt, policies...);
2745}
2746
2747}}} // Namespaces
2748
2749#ifdef BOOST_MSVC
2750# pragma warning(pop)
2751#endif
2752
2753#endif // BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP
2754

source code of boost/libs/charconv/include/boost/charconv/detail/dragonbox/dragonbox.hpp