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// Some parts are copied from Dragonbox project.
19//
20// Copyright 2023 Matt Borland
21// Distributed under the Boost Software License, Version 1.0.
22// https://www.boost.org/LICENSE_1_0.txt
23
24#ifndef BOOST_CHARCONV_DETAIL_FLOFF
25#define BOOST_CHARCONV_DETAIL_FLOFF
26
27#include <boost/charconv/detail/config.hpp>
28#include <boost/charconv/detail/bit_layouts.hpp>
29#include <boost/charconv/detail/emulated128.hpp>
30#include <boost/charconv/detail/dragonbox/dragonbox_common.hpp>
31#include <boost/charconv/detail/to_chars_result.hpp>
32#include <boost/charconv/chars_format.hpp>
33#include <boost/core/bit.hpp>
34#include <type_traits>
35#include <limits>
36#include <cstdint>
37#include <cstring>
38#include <cstddef>
39#include <climits>
40
41#ifdef BOOST_MSVC
42# pragma warning(push)
43# pragma warning(disable: 4127) // Extensive use of BOOST_IF_CONSTEXPR emits warnings under C++11 and 14
44# pragma warning(disable: 4554) // parentheses are used be warning is still emitted
45#endif
46
47namespace boost { namespace charconv { namespace detail {
48
49#ifdef BOOST_MSVC
50# pragma warning(push)
51# pragma warning(disable: 4702) // use of BOOST_IF_CONSTEXPR can result in unreachable code if max_blocks is 3
52 // Other older compilers will emit warnings if the unreachable code is wrapped
53 // in an else block (e.g. no return statment)
54#endif
55
56template <std::size_t max_blocks>
57struct fixed_point_calculator
58{
59 static_assert(1 < max_blocks, "Max blocks must be greater than 1");
60
61 // Multiply multiplier to the fractional blocks and take the resulting integer part.
62 // The fractional blocks are updated.
63 template <typename MultiplierType>
64 BOOST_FORCEINLINE static MultiplierType generate(MultiplierType multiplier,
65 std::uint64_t* blocks_ptr,
66 std::size_t number_of_blocks) noexcept
67 {
68 BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
69
70 BOOST_IF_CONSTEXPR (max_blocks == 3)
71 {
72 uint128 mul_result;
73 std::uint64_t carry = 0;
74
75 switch (number_of_blocks)
76 {
77 case 3:
78 mul_result = umul128(blocks_ptr[2], multiplier);
79 blocks_ptr[2] = mul_result.low;
80 carry = mul_result.high;
81 BOOST_FALLTHROUGH;
82
83 case 2:
84 mul_result = umul128(blocks_ptr[1], multiplier);
85 mul_result += carry;
86 blocks_ptr[1] = mul_result.low;
87 carry = mul_result.high;
88 BOOST_FALLTHROUGH;
89
90 case 1:
91 mul_result = umul128(blocks_ptr[0], multiplier);
92 mul_result += carry;
93 blocks_ptr[0] = mul_result.low;
94 return mul_result.high;
95
96 default:
97 BOOST_UNREACHABLE_RETURN(carry); // NOLINT : Macro for unreachable can expand to be empty
98 }
99 }
100
101 auto mul_result = umul128(blocks_ptr[number_of_blocks - 1], multiplier);
102 blocks_ptr[number_of_blocks - 1] = mul_result.low;
103 auto carry = mul_result.high;
104 for (std::size_t i = 1; i < number_of_blocks; ++i)
105 {
106 mul_result = umul128(blocks_ptr[number_of_blocks - i - 1], multiplier);
107 mul_result += carry;
108 blocks_ptr[number_of_blocks - i - 1] = mul_result.low;
109 carry = mul_result.high;
110 }
111
112 return MultiplierType(carry);
113 }
114
115 // Multiply multiplier to the fractional blocks and discard the resulting integer part.
116 // The fractional blocks are updated.
117 template <typename MultiplierType>
118 BOOST_FORCEINLINE static void discard_upper(MultiplierType multiplier,
119 std::uint64_t* blocks_ptr,
120 std::size_t number_of_blocks) noexcept
121 {
122 BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
123
124 blocks_ptr[0] *= multiplier;
125 if (number_of_blocks > 1)
126 {
127 BOOST_IF_CONSTEXPR (max_blocks == 3)
128 {
129 uint128 mul_result;
130 std::uint64_t carry = 0;
131
132 if (number_of_blocks > 2)
133 {
134 mul_result = umul128(multiplier, blocks_ptr[2]);
135 blocks_ptr[2] = mul_result.low;
136 carry = mul_result.high;
137 }
138
139 mul_result = umul128(multiplier, blocks_ptr[1]);
140 mul_result += carry;
141 blocks_ptr[1] = mul_result.low;
142 blocks_ptr[0] += mul_result.high;
143 }
144 else
145 {
146 auto mul_result = umul128(multiplier, blocks_ptr[number_of_blocks - 1]);
147 blocks_ptr[number_of_blocks - 1] = mul_result.low;
148 auto carry = mul_result.high;
149
150 for (std::size_t i = 2; i < number_of_blocks; ++i)
151 {
152 mul_result = umul128(multiplier, blocks_ptr[number_of_blocks - i]);
153 mul_result += carry;
154 blocks_ptr[number_of_blocks - i] = mul_result.low;
155 carry = mul_result.high;
156 }
157
158 blocks_ptr[0] += carry;
159 }
160 }
161 }
162
163 // Multiply multiplier to the fractional blocks and take the resulting integer part.
164 // Don't care about what happens to the fractional blocks.
165 template <typename MultiplierType>
166 BOOST_FORCEINLINE static MultiplierType
167 generate_and_discard_lower(MultiplierType multiplier, std::uint64_t* blocks_ptr,
168 std::size_t number_of_blocks) noexcept
169 {
170 BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
171
172 BOOST_IF_CONSTEXPR (max_blocks == 3)
173 {
174 uint128 mul_result;
175 std::uint64_t carry = 0;
176
177 switch (number_of_blocks)
178 {
179 case 3:
180 mul_result = umul128(x: blocks_ptr[2], y: static_cast<std::uint64_t>(multiplier));
181 carry = mul_result.high;
182 BOOST_FALLTHROUGH;
183
184 case 2:
185 mul_result = umul128(x: blocks_ptr[1], y: static_cast<std::uint64_t>(multiplier));
186 mul_result += carry;
187 carry = mul_result.high;
188 BOOST_FALLTHROUGH;
189
190 case 1:
191 mul_result = umul128(x: blocks_ptr[0], y: static_cast<std::uint64_t>(multiplier));
192 mul_result += carry;
193 return static_cast<MultiplierType>(mul_result.high);
194
195 default:
196 BOOST_UNREACHABLE_RETURN(carry); // NOLINT
197 }
198 }
199
200 auto mul_result = umul128(x: blocks_ptr[number_of_blocks - 1], y: static_cast<std::uint64_t>(multiplier));
201 auto carry = mul_result.high;
202 for (std::size_t i = 1; i < number_of_blocks; ++i)
203 {
204 mul_result = umul128(x: blocks_ptr[number_of_blocks - i - 1], y: static_cast<std::uint64_t>(multiplier));
205 mul_result += carry;
206 carry = mul_result.high;
207 }
208
209 return static_cast<MultiplierType>(carry);
210 }
211};
212
213#ifdef BOOST_MSVC
214# pragma warning(pop)
215#endif
216
217template <bool b>
218struct additional_static_data_holder_impl
219{
220 static constexpr char radix_100_table[] = {
221 '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', //
222 '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', //
223 '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', //
224 '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', //
225 '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', //
226 '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', //
227 '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', //
228 '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', //
229 '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', //
230 '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', //
231 '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', //
232 '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', //
233 '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', //
234 '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', //
235 '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', //
236 '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', //
237 '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', //
238 '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', //
239 '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', //
240 '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' //
241 };
242
243 static constexpr std::uint32_t fractional_part_rounding_thresholds32[] = {
244 UINT32_C(2576980378), UINT32_C(2190433321), UINT32_C(2151778616), UINT32_C(2147913145),
245 UINT32_C(2147526598), UINT32_C(2147487943), UINT32_C(2147484078), UINT32_C(2147483691)
246 };
247
248 static constexpr std::uint64_t fractional_part_rounding_thresholds64[] = {
249 UINT64_C(11068046444225730970), UINT64_C(9407839477591871325), UINT64_C(9241818780928485360),
250 UINT64_C(9225216711262146764), UINT64_C(9223556504295512904), UINT64_C(9223390483598849518),
251 UINT64_C(9223373881529183179), UINT64_C(9223372221322216546), UINT64_C(9223372055301519882),
252 UINT64_C(9223372038699450216), UINT64_C(9223372037039243249), UINT64_C(9223372036873222553),
253 UINT64_C(9223372036856620483), UINT64_C(9223372036854960276), UINT64_C(9223372036854794255),
254 UINT64_C(9223372036854777653), UINT64_C(9223372036854775993), UINT64_C(9223372036854775827)
255 };
256};
257
258#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
259
260template <bool b> constexpr char additional_static_data_holder_impl<b>::radix_100_table[];
261template <bool b> constexpr std::uint32_t additional_static_data_holder_impl<b>::fractional_part_rounding_thresholds32[];
262template <bool b> constexpr std::uint64_t additional_static_data_holder_impl<b>::fractional_part_rounding_thresholds64[];
263
264#endif
265
266using additional_static_data_holder = additional_static_data_holder_impl<true>;
267
268struct compute_mul_result
269{
270 std::uint64_t result;
271 bool is_integer;
272};
273
274// Load the necessary bits into blocks_ptr and then return the number of cache blocks
275// loaded. The most significant block is loaded into blocks_ptr[0].
276template <typename ExtendedCache, bool zero_out,
277 typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type,
278 typename std::enable_if<(ExtendedCache::constant_block_count), bool>::type = true>
279inline std::uint8_t cache_block_count_helper(CacheBlockType*, int, int, std::uint32_t) noexcept
280{
281 return static_cast<std::uint8_t>(ExtendedCache::max_cache_blocks);
282}
283
284template <typename ExtendedCache, bool zero_out,
285 typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type,
286 typename std::enable_if<!(ExtendedCache::constant_block_count), bool>::type = true>
287inline std::uint8_t cache_block_count_helper(CacheBlockType*, int e, int, std::uint32_t multiplier_index) noexcept
288{
289 const auto mul_info = ExtendedCache::multiplier_index_info_table[multiplier_index];
290
291 const auto cache_block_count_index =
292 mul_info.cache_block_count_index_offset +
293 static_cast<std::uint32_t>(e - ExtendedCache::e_min) / ExtendedCache::collapse_factor -
294 ExtendedCache::cache_block_count_offset_base;
295
296 BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks < 3)
297 {
298 // 1-bit packing.
299 return static_cast<std::uint8_t>(
300 (ExtendedCache::cache_block_counts[cache_block_count_index /
301 8] >>
302 (cache_block_count_index % 8)) &
303 0x1) +
304 1;
305 }
306 else BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks < 4)
307 {
308 // 2-bit packing.
309 return static_cast<std::uint8_t>(
310 (ExtendedCache::cache_block_counts[cache_block_count_index / 4] >>
311 (2 * (cache_block_count_index % 4))) &
312 0x3);
313 }
314 else
315 {
316 // 4-bit packing.
317 return std::uint8_t(
318 (ExtendedCache::cache_block_counts[cache_block_count_index / 2] >>
319 (4 * (cache_block_count_index % 2))) &
320 0xf);
321 }
322}
323
324template <typename ExtendedCache, bool zero_out,
325 typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type>
326BOOST_FORCEINLINE std::uint8_t load_extended_cache(CacheBlockType* blocks_ptr, int e, int k,
327 std::uint32_t multiplier_index) noexcept
328{
329 BOOST_IF_CONSTEXPR (zero_out)
330 {
331 std::memset(s: blocks_ptr, c: 0, n: sizeof(CacheBlockType) * ExtendedCache::max_cache_blocks);
332 }
333
334 const auto mul_info = ExtendedCache::multiplier_index_info_table[multiplier_index];
335
336 std::uint32_t number_of_leading_zero_blocks;
337 std::uint32_t first_cache_block_index;
338 std::uint32_t bit_offset;
339 std::uint32_t excessive_bits_to_left;
340 std::uint32_t excessive_bits_to_right;
341 std::uint8_t cache_block_count = cache_block_count_helper<ExtendedCache, zero_out, CacheBlockType>(blocks_ptr, e, k, multiplier_index);
342
343 // The request window starting/ending positions.
344 auto start_bit_index = static_cast<int>(mul_info.cache_bit_index_offset) + e - ExtendedCache::cache_bit_index_offset_base;
345 auto end_bit_index = start_bit_index + cache_block_count * static_cast<int>(ExtendedCache::cache_bits_unit);
346
347 // The source window starting/ending positions.
348 const auto src_start_bit_index = static_cast<int>(mul_info.first_cache_bit_index);
349 const auto src_end_bit_index = static_cast<int>(ExtendedCache::multiplier_index_info_table[multiplier_index + 1].first_cache_bit_index);
350
351 // If the request window goes further than the left boundary of the source window,
352 if (start_bit_index < src_start_bit_index)
353 {
354 number_of_leading_zero_blocks =
355 static_cast<std::uint32_t>(src_start_bit_index - start_bit_index) /
356 static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
357 excessive_bits_to_left = static_cast<std::uint32_t>(src_start_bit_index - start_bit_index) %
358 static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
359
360 BOOST_IF_CONSTEXPR (!zero_out)
361 {
362 std::memset(s: blocks_ptr, c: 0, n: number_of_leading_zero_blocks * sizeof(CacheBlockType));
363 }
364
365 start_bit_index += static_cast<int>(number_of_leading_zero_blocks * ExtendedCache::cache_bits_unit);
366
367 const auto src_start_block_index =
368 static_cast<int>(static_cast<std::uint32_t>(src_start_bit_index) /
369 static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit));
370
371 const auto src_start_block_bit_index =
372 src_start_block_index * static_cast<int>(ExtendedCache::cache_bits_unit);
373
374 first_cache_block_index = static_cast<std::uint32_t>(src_start_block_index);
375
376 if (start_bit_index < src_start_block_bit_index)
377 {
378 auto shift_amount = src_start_block_bit_index - start_bit_index;
379 BOOST_CHARCONV_ASSERT(shift_amount >= 0 && shift_amount < static_cast<int>(ExtendedCache::cache_bits_unit));
380
381 blocks_ptr[number_of_leading_zero_blocks] =
382 ((ExtendedCache::cache[src_start_block_index] >> shift_amount) &
383 (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) >>
384 excessive_bits_to_left));
385
386 ++number_of_leading_zero_blocks;
387 bit_offset = static_cast<std::uint32_t>(static_cast<int>(ExtendedCache::cache_bits_unit) - shift_amount);
388 excessive_bits_to_left = 0;
389 }
390 else
391 {
392 bit_offset = static_cast<std::uint32_t>(start_bit_index - src_start_block_bit_index);
393 }
394 }
395 else
396 {
397 number_of_leading_zero_blocks = 0;
398 first_cache_block_index =
399 static_cast<std::uint32_t>(start_bit_index) / static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
400 bit_offset =
401 static_cast<std::uint32_t>(start_bit_index) % static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
402 excessive_bits_to_left = 0;
403 }
404
405 // If the request window goes further than the right boundary of the source window,
406 if (end_bit_index > src_end_bit_index)
407 {
408 const std::uint8_t number_of_trailing_zero_blocks =
409 static_cast<std::uint8_t>(end_bit_index - src_end_bit_index) / ExtendedCache::cache_bits_unit;
410 excessive_bits_to_right = static_cast<std::uint32_t>(end_bit_index - src_end_bit_index) %
411 static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
412
413 cache_block_count -= number_of_trailing_zero_blocks;
414 }
415 else
416 {
417 excessive_bits_to_right = 0;
418 }
419
420 // Load blocks.
421 const auto number_of_blocks_to_load = cache_block_count - number_of_leading_zero_blocks;
422 auto* const dst_ptr = blocks_ptr + number_of_leading_zero_blocks;
423 if (bit_offset == 0)
424 {
425 BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks == 3)
426 {
427 switch (number_of_blocks_to_load)
428 {
429 case 3:
430 std::memcpy(dest: dst_ptr, src: ExtendedCache::cache + first_cache_block_index, n: 3 * sizeof(CacheBlockType));
431 break;
432 case 2:
433 std::memcpy(dest: dst_ptr, src: ExtendedCache::cache + first_cache_block_index, n: 2 * sizeof(CacheBlockType));
434 break;
435 case 1:
436 std::memcpy(dest: dst_ptr, src: ExtendedCache::cache + first_cache_block_index, n: 1 * sizeof(CacheBlockType));
437 break;
438 case 0:
439 break;
440 default:
441 BOOST_UNREACHABLE_RETURN(dst_ptr); // NOLINT
442 }
443 }
444 else
445 {
446 std::memcpy(dest: dst_ptr, src: ExtendedCache::cache + first_cache_block_index, n: number_of_blocks_to_load * sizeof(CacheBlockType));
447 }
448 }
449 else
450 {
451 BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks == 3)
452 {
453 switch (number_of_blocks_to_load)
454 {
455 case 3:
456 *(dst_ptr + 2) =
457 (ExtendedCache::cache[first_cache_block_index + 2] << bit_offset) |
458 (ExtendedCache::cache[first_cache_block_index + 3] >>
459 (ExtendedCache::cache_bits_unit - bit_offset));
460 BOOST_FALLTHROUGH;
461 case 2:
462 *(dst_ptr + 1) =
463 (ExtendedCache::cache[first_cache_block_index + 1] << bit_offset) |
464 (ExtendedCache::cache[first_cache_block_index + 2] >>
465 (ExtendedCache::cache_bits_unit - bit_offset));
466 BOOST_FALLTHROUGH;
467 case 1:
468 *dst_ptr = (ExtendedCache::cache[first_cache_block_index] << bit_offset) |
469 (ExtendedCache::cache[first_cache_block_index + 1] >>
470 (ExtendedCache::cache_bits_unit - bit_offset));
471 case 0:
472 break;
473 default:
474 BOOST_UNREACHABLE_RETURN(dst_ptr); // NOLINT
475 }
476 }
477 else
478 {
479 for (std::uint8_t i = 0; i < number_of_blocks_to_load; ++i)
480 {
481 *(dst_ptr + i) =
482 (ExtendedCache::cache[first_cache_block_index + i] << bit_offset) |
483 (ExtendedCache::cache[first_cache_block_index + i + 1] >>
484 (ExtendedCache::cache_bits_unit - bit_offset));
485 }
486 }
487 }
488
489 // Remove possible flooding bits from adjacent entries.
490 *dst_ptr &= (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) >> excessive_bits_to_left);
491
492 blocks_ptr[cache_block_count - 1] &= (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) << excessive_bits_to_right);
493
494 // To compute ceil(2^Q * x / D), we need to check if
495 // 2^Q * x / D = 2^(Q + e + k - eta - 1) * 5^(k - eta) is an integer or not.
496 if (k < ExtendedCache::segment_length ||
497 e + k + static_cast<int>(cache_block_count * ExtendedCache::cache_bits_unit) -
498 static_cast<int>(excessive_bits_to_right) <
499 ExtendedCache::segment_length + 1) {
500 blocks_ptr[cache_block_count - 1] += (CacheBlockType(1) << excessive_bits_to_right);
501 BOOST_CHARCONV_ASSERT(blocks_ptr[cache_block_count - 1] != 0);
502 }
503
504 return cache_block_count;
505}
506
507template <bool constant_block_count, std::uint8_t max_cache_blocks>
508struct cache_block_count_t;
509
510template <std::uint8_t max_cache_blocks>
511struct cache_block_count_t<false, max_cache_blocks>
512{
513 std::uint8_t value;
514
515 operator std::uint8_t() const noexcept { return value; } // NOLINT : implicit conversions are ok for block count
516 cache_block_count_t& operator=(std::uint8_t new_value) noexcept
517 {
518 value = new_value;
519 return *this;
520 }
521};
522
523template <std::uint8_t max_cache_blocks>
524struct cache_block_count_t<true, max_cache_blocks>
525{
526 static constexpr std::uint8_t value = max_cache_blocks;
527 operator std::uint8_t() const noexcept { return value; } // NOLINT : implicit conversions are ok for block count
528 cache_block_count_t& operator=(std::uint8_t) noexcept
529 {
530 // Don't do anything.
531 return *this;
532 }
533};
534
535template <unsigned n>
536struct uconst
537{
538 constexpr uconst() {}; // NOLINT : Clang 3.x does not support = default
539 static constexpr unsigned value = n;
540};
541
542BOOST_INLINE_VARIABLE constexpr uconst<0> uconst0;
543BOOST_INLINE_VARIABLE constexpr uconst<1> uconst1;
544BOOST_INLINE_VARIABLE constexpr uconst<6> uconst6;
545BOOST_INLINE_VARIABLE constexpr uconst<9> uconst9;
546BOOST_INLINE_VARIABLE constexpr uconst<14> uconst14;
547BOOST_INLINE_VARIABLE constexpr uconst<16> uconst16;
548
549#ifdef __clang__
550# pragma clang diagnostic push
551# pragma clang diagnostic ignored "-Wsign-conversion"
552#elif defined(__GNUC__)
553# pragma GCC diagnostic push
554# pragma GCC diagnostic ignored "-Wsign-conversion"
555#elif defined(BOOST_MSVC)
556# pragma warning(push)
557# pragma warning(disable: 4365 4267)
558#endif
559
560template <unsigned digits, bool dummy = (digits <= 9)>
561struct uint_with_known_number_of_digits;
562
563template <unsigned digits_>
564struct uint_with_known_number_of_digits<digits_, true>
565{
566 static constexpr auto digits = digits_;
567 std::uint32_t value;
568};
569
570template <unsigned digits_>
571struct uint_with_known_number_of_digits<digits_, false>
572{
573 static constexpr auto digits = digits_;
574 std::uint64_t value;
575};
576
577template <typename HasFurtherDigits, typename... Args, typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
578static BOOST_FORCEINLINE bool check_rounding_condition_inside_subsegment(
579 std::uint32_t current_digits, std::uint32_t fractional_part,
580 int remaining_digits_in_the_current_subsegment, HasFurtherDigits has_further_digits,
581 Args...) noexcept
582{
583 if (fractional_part >= additional_static_data_holder::fractional_part_rounding_thresholds32[remaining_digits_in_the_current_subsegment - 1])
584 {
585 return true;
586 }
587
588 return ((fractional_part >> 31) & ((current_digits & 1) | has_further_digits)) != 0;
589}
590
591template <typename HasFurtherDigits, typename... Args,
592 typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
593static BOOST_FORCEINLINE bool check_rounding_condition_inside_subsegment(
594 std::uint32_t current_digits, std::uint32_t fractional_part,
595 int remaining_digits_in_the_current_subsegment, HasFurtherDigits has_further_digits,
596 Args... args) noexcept
597{
598 if (fractional_part >= additional_static_data_holder::fractional_part_rounding_thresholds32[remaining_digits_in_the_current_subsegment - 1])
599 {
600 return true;
601 }
602
603 return fractional_part >= 0x80000000 && ((current_digits & 1) != 0 || has_further_digits(args...));
604}
605
606template <typename HasFurtherDigits, typename... Args,
607 typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
608static BOOST_FORCEINLINE bool check_rounding_condition_with_next_bit(std::uint32_t current_digits, bool next_bit,
609 HasFurtherDigits has_further_digits, Args...) noexcept
610{
611 if (!next_bit)
612 {
613 return false;
614 }
615
616 return ((current_digits & 1) | has_further_digits) != 0;
617}
618
619template <typename HasFurtherDigits, typename... Args,
620 typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
621static BOOST_FORCEINLINE bool check_rounding_condition_with_next_bit(std::uint32_t current_digits, bool next_bit,
622 HasFurtherDigits has_further_digits, Args... args) noexcept
623{
624 if (!next_bit)
625 {
626 return false;
627 }
628
629 return (current_digits & 1) != 0 || has_further_digits(args...);
630}
631
632template <typename UintWithKnownDigits, typename HasFurtherDigits, typename... Args,
633 typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
634static BOOST_FORCEINLINE bool check_rounding_condition_subsegment_boundary_with_next_subsegment(
635 std::uint32_t current_digits, UintWithKnownDigits next_subsegment,
636 HasFurtherDigits has_further_digits, Args...) noexcept
637{
638 if (next_subsegment.value > power_of_10[decltype(next_subsegment)::digits] / 2)
639 {
640 return true;
641 }
642
643 return next_subsegment.value == power_of_10[decltype(next_subsegment)::digits] / 2 &&
644 ((current_digits & 1) | has_further_digits) != 0;
645}
646
647template <typename UintWithKnownDigits, typename HasFurtherDigits, typename... Args,
648 typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
649static BOOST_FORCEINLINE bool check_rounding_condition_subsegment_boundary_with_next_subsegment(
650 std::uint32_t current_digits, UintWithKnownDigits next_subsegment,
651 HasFurtherDigits has_further_digits, Args... args) noexcept
652{
653 if (next_subsegment.value > power_of_10[decltype(next_subsegment)::digits] / 2)
654 {
655 return true;
656 }
657
658 return next_subsegment.value == power_of_10[decltype(next_subsegment)::digits] / 2 &&
659 ((current_digits & 1) != 0 || has_further_digits(args...));
660}
661
662#ifdef __clang__
663# pragma clang diagnostic pop
664#elif defined(__GNUC__)
665# pragma GCC diagnostic pop
666#elif defined(BOOST_MSVC)
667# pragma warning(pop)
668#endif
669
670#ifdef BOOST_MSVC
671# pragma warning(push)
672# pragma warning(disable: 4307) // MSVC 14.1 emits warnings for uint64_t constants
673#endif
674
675namespace has_further_digits_impl {
676template <int k_right_threshold, int additional_neg_exp_of_2>
677bool no_neg_k_can_be_integer(int k, int exp2_base) noexcept
678{
679 return k < k_right_threshold || exp2_base + k < additional_neg_exp_of_2;
680}
681
682template <int k_left_threshold, int k_right_threshold, int additional_neg_exp_of_2, int min_neg_exp_of_5, typename SignificandType>
683bool only_one_neg_k_can_be_integer(int k, int exp2_base, SignificandType significand) noexcept
684{
685 // Supposed to be k - additional_neg_exp_of_5_v < -min_neg_exp_of_5 || ...
686 if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2)
687 {
688 return true;
689 }
690 // Supposed to be k - additional_neg_exp_of_5_v >= 0.
691 if (k >= k_right_threshold)
692 {
693 return false;
694 }
695
696 BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv = compute_power(UINT64_C(0xcccccccccccccccd), exp: static_cast<unsigned>(min_neg_exp_of_5));
697 BOOST_CXX14_CONSTEXPR std::uint64_t max_quot = UINT64_C(0xffffffffffffffff) / compute_power(UINT64_C(5), exp: static_cast<unsigned>(min_neg_exp_of_5));
698
699 return (significand * mod_inv) > max_quot;
700}
701
702template <int k_left_threshold, int k_middle_threshold, int k_right_threshold,
703 int additional_neg_exp_of_2, int min_neg_exp_of_5, int segment_length,
704 typename SignificandType>
705bool only_two_neg_k_can_be_integer(int k, int exp2_base,
706 SignificandType significand) noexcept {
707 // Supposed to be k - additional_neg_exp_of_5_v < -min_neg_exp_of_5 - segment_length
708 // || ...
709 if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2) {
710 return true;
711 }
712 // Supposed to be k - additional_neg_exp_of_5_v >= 0.
713 if (k >= k_right_threshold) {
714 return false;
715 }
716
717 if (k >= k_middle_threshold) {
718 BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv =
719 compute_power(UINT64_C(0xcccccccccccccccd), exp: static_cast<unsigned>(min_neg_exp_of_5));
720 BOOST_CXX14_CONSTEXPR std::uint64_t max_quot =
721 UINT64_C(0xffffffffffffffff) /
722 compute_power(UINT64_C(5), exp: static_cast<unsigned>(min_neg_exp_of_5));
723
724 return (significand * mod_inv) > max_quot;
725 }
726 else {
727 BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv = compute_power(
728 UINT64_C(0xcccccccccccccccd), exp: static_cast<unsigned>(min_neg_exp_of_5 + segment_length));
729 BOOST_CXX14_CONSTEXPR std::uint64_t max_quot =
730 UINT64_C(0xffffffffffffffff) /
731 compute_power(UINT64_C(5),
732 exp: static_cast<unsigned>(min_neg_exp_of_5 + segment_length));
733
734 return (significand * mod_inv) > max_quot;
735 }
736}
737} // Namespace has_further_digits_impl
738
739#ifdef BOOST_MSVC
740#pragma warning(pop)
741#endif
742
743inline void print_1_digit(std::uint32_t n, char* buffer) noexcept
744{
745 *buffer = char('0' + n);
746}
747
748inline void print_2_digits(std::uint32_t n, char* buffer) noexcept
749{
750 std::memcpy(dest: buffer, src: additional_static_data_holder::radix_100_table + n * 2, n: 2);
751}
752
753inline void print_6_digits(std::uint32_t n, char* buffer) noexcept
754{
755 // 429497 = ceil(2^32/10^4)
756 auto prod = (n * UINT64_C(429497)) + 1;
757 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
758
759 for (int i = 0; i < 2; ++i)
760 {
761 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
762 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer: buffer + 2 + i * 2);
763 }
764}
765
766inline void print_7_digits(std::uint32_t n, char* buffer) noexcept
767{
768 // 17592187 = ceil(2^(32+12)/10^6)
769 auto prod = ((n * UINT64_C(17592187)) >> 12) + 1;
770 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
771
772 for (int i = 0; i < 3; ++i)
773 {
774 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
775 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer: buffer + 1 + i * 2);
776 }
777}
778
779inline void print_8_digits(std::uint32_t n, char* buffer) noexcept
780{
781 // 140737489 = ceil(2^(32+15)/10^6)
782 auto prod = ((n * UINT64_C(140737489)) >> 15) + 1;
783 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
784
785 for (int i = 0; i < 3; ++i)
786 {
787 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
788 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer: buffer + 2 + i * 2);
789 }
790}
791
792inline void print_9_digits(std::uint32_t n, char* buffer) noexcept
793{
794 // 1441151881 = ceil(2^(32+25)/10^8)
795 auto prod = ((n * UINT64_C(1441151881)) >> 25) + 1;
796 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
797
798 for (int i = 0; i < 4; ++i)
799 {
800 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
801 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer: buffer + 1 + i * 2);
802 }
803}
804
805struct main_cache_full
806{
807 template <typename FloatFormat>
808 static constexpr typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
809 {
810 return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
811 }
812};
813
814struct main_cache_compressed
815{
816 template <typename FloatFormat>
817 static BOOST_CHARCONV_CXX14_CONSTEXPR typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
818 {
819 BOOST_CHARCONV_ASSERT(k >= main_cache_holder::min_k && k <= main_cache_holder::max_k);
820
821 BOOST_IF_CONSTEXPR (std::is_same<FloatFormat, ieee754_binary64>::value)
822 {
823 // Compute the base index.
824 const auto cache_index =
825 static_cast<int>(static_cast<std::uint32_t>(k - main_cache_holder::min_k) /
826 compressed_cache_detail::compression_ratio);
827
828 const auto kb = cache_index * compressed_cache_detail::compression_ratio +
829 main_cache_holder::min_k;
830
831 const auto offset = k - kb;
832
833 // Get the base cache.
834 const auto base_cache = compressed_cache_detail::cache_holder_t::table[cache_index];
835
836 if (offset == 0)
837 {
838 return base_cache;
839 }
840 else
841 {
842
843 // Compute the required amount of bit-shift.
844 const auto alpha = log::floor_log2_pow10(e: kb + offset) - log::floor_log2_pow10(e: kb) - offset;
845 BOOST_CHARCONV_ASSERT(alpha > 0 && alpha < 64);
846
847 // Try to recover the real cache.
848 const auto pow5 = compressed_cache_detail::pow5_holder_t::table[offset];
849 auto recovered_cache = umul128(x: base_cache.high, y: pow5);
850 const auto middle_low = umul128(x: base_cache.low, y: pow5);
851
852 recovered_cache += middle_low.high;
853
854 const auto high_to_middle = recovered_cache.high << (64 - alpha);
855 const auto middle_to_low = recovered_cache.low << (64 - alpha);
856
857 recovered_cache = uint128{(recovered_cache.low >> alpha) | high_to_middle, ((middle_low.low >> alpha) | middle_to_low)};
858
859 BOOST_CHARCONV_ASSERT(recovered_cache.low + 1 != 0);
860 recovered_cache = uint128(recovered_cache.high, recovered_cache.low + 1);
861
862 return recovered_cache;
863 }
864 }
865 else
866 {
867 // Just use the full cache for anything other than binary64
868 return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
869 }
870 }
871};
872
873template <bool b>
874struct extended_cache_long_impl
875{
876 static constexpr std::size_t max_cache_blocks = 3;
877 static constexpr std::size_t cache_bits_unit = 64;
878 static constexpr int segment_length = 22;
879 static constexpr bool constant_block_count = true;
880 static constexpr int e_min = -1074;
881 static constexpr int k_min = -272;
882 static constexpr int cache_bit_index_offset_base = 977;
883 static constexpr std::uint64_t cache[] = {
884 0xa37fce126597973c, 0xe50ff107bab528a0, 0x8f1ba3f17395a391, 0xd56bdc876cdb4648,
885 0x6ca000bdd9e33bd4, 0x23cf34bbf983f78b, 0x8737d87296e93f5d, 0xa2824ba6d9df301d,
886 0x8ce3eccf7cfb42ab, 0xe5ecdc0b78109f00, 0xa620c9995c9c5c3a, 0xa0f79c97ac210943,
887 0x64dfb5636985915f, 0xc12f542e4c7ea6ee, 0x34de81232784ea17, 0xd0cbde7fac4643f2,
888 0x5d9400de8fef7552, 0x81214f68696d9af2, 0xb7d0e0a2ccaccf20, 0x5c4ed9243f16193d,
889 0xf71838486e60b926, 0x48892047ec1a8bf4, 0x14ff2faa9c32befa, 0x666fbaa24ddbb8e9,
890 0x436682c807652a58, 0xed98ddaee19068c7, 0x63badd624dd9b095, 0x72dbb637d5b77493,
891 0xd01998fb8d9e8861, 0xacb39418dce017b9, 0x8db8f2f13eed81cf, 0xfd699fbb7d0a737a,
892 0x011cd67160923d91, 0x9a66fd7732c14d98, 0x235857d065a52d18, 0x895288951dab0d8e,
893 0x59041cb66e4f0e68, 0x5e7c68240249e750, 0x8881a2a6ab00987b, 0x5fc8c32c863aaeac,
894 0x3bafbe662a7f81a8, 0xd47692705ae76b64, 0xeb1cc7d99143fb53, 0xcf8be24f7b0fc499,
895 0x6a276e8f0fbf33eb, 0x63b2d61966fa7243, 0x0970327d2cc58011, 0x43ff09410ec24aae,
896 0x0bdb6f345ea1851d, 0x409c37132c5836ff, 0xf3150f74a6190324, 0x5c358d6c07453d23,
897 0x7207012ad7846ba7, 0x61ad5d0772604733, 0x19a20a6e21c2018d, 0x5f568fd497ef18b2,
898 0xeda5815eed00749f, 0x029531461bc483d8, 0xb8789d7784875911, 0x6fc40572236f2ba5,
899 0x9c2a50a76ace3168, 0xbf4815c2bea56741, 0xf84e8f2fe9b211f5, 0x689033182d2ea7ed,
900 0x5bcb3a3230a68f47, 0xa848403d116805ef, 0xfaeaa73623b79604, 0x31d76828d2181b64,
901 0x7c4eabddc7dd634b, 0xc2b13231eeff6fda, 0x8094743db32bf251, 0x2df07391bde052d2,
902 0xffd9bdbf321ad8ae, 0x06b2c6d1cf6cf742, 0xf32a54ce1598fe8f, 0x1cc2e3082d28897e,
903 0x0485f2e46b488584, 0xe3f6965b145a49cb, 0x406eaa1217aefe69, 0x0777373638de456b,
904 0xcde91853b592212b, 0x3faf7b46d7f79c18, 0x558d83afb7127381, 0x5f490259c7957aeb,
905 0x76e6540e246d73cc, 0x5098a935a866dc75, 0xc50d9c29002d9e73, 0xcc8f8252faac0b7f,
906 0xb759afb688f8251d, 0x6a2934d3036c85d3, 0x570eb3ce4c86407f, 0x036f2b68794754af,
907 0x57661a5d6993fe2c, 0x6d07b7fabe546a80, 0x38efe4029259743c, 0x548f417ebaa61c6c,
908 0xb0c31fa64a3fcc9e, 0x7dab825964fb7100, 0xd0c92ae8207d6f22, 0xf1e38a8a9c541144,
909 0x2139951c68d0385b, 0x9d9e22c42f139287, 0x4fea4d670876b800, 0x35f293a9a62252d4,
910 0x4b606b26f1922c5c, 0x8e5660b37505cb11, 0x868138391855da81, 0x6e95f6c9b45c7aa2,
911 0x425ff75e14fc31a1, 0x258379a94d028d18, 0xdf2ccd1fe00a03b6, 0x398471c1ff970f83,
912 0x8c36b2214a3db8e7, 0x431dd42c3fe7f4fb, 0xb09bcf0fffb5b849, 0xc47dd13da60fb5a1,
913 0x8fdad56516fe9d75, 0xc317e1025a7e1c63, 0x9ddcb98cbb384fda, 0x80adccda993bf70e,
914 0x667f1622e4052ae4, 0xa41598d58f777363, 0x704b93d675808501, 0xaf046d3fd448aaf3,
915 0x1dc4611873bf3f70, 0x834acdae9f0f4f53, 0x4f5d60585a5f1c1a, 0x3ced1b4be0d415c1,
916 0x5d57f4de8ec12376, 0x51c0e7e72f799542, 0x46f7604940e6a510, 0x1a546a0f9345ed75,
917 0x0df4097cab773ca2, 0x72b122774e4029e6, 0xae4a55b99aebd424, 0x04163a291bad2fa3,
918 0x86ad58be322a49aa, 0x98f051614696e839, 0x64d08f241fc4ec58, 0xae41f23dca90dd5d,
919 0x68bbd62f5af3107a, 0x7025f39ef241c56c, 0xd2e7c72fa9be33ac, 0x0aece66fd3e29a7d,
920 0xd91241cebf3bd47c, 0x3ed7bfdee19ba2f6, 0x4bdf483194c7444e, 0xc99d83c931e8ab87,
921 0x1732f416dbf7381f, 0x2ac88e244de13b96, 0x2cab688bd86c8bf8, 0x9f209787bb47d6b8,
922 0x4c0678c5dbd23a49, 0xa0612c3c5ce15e55, 0x4dccc6ca29b3e9df, 0x0dc079c918022212,
923 0x26be55a64c249495, 0x4da2c9789dd268b0, 0xe975528c76435158, 0xa6cb8a4d2356f9cf,
924 0xdcafd2279c77d987, 0xaa9aff7904228690, 0xfb44d2f05d0842fb, 0x118fc9c217a1d2b2,
925 0x04b3d9686f55b572, 0xbd9cb3625ef1cfc3, 0x2eba0e25e938e6c3, 0x1f48eaf234ad3a21,
926 0xf2dc02fad2890f79, 0xace340325d4a7f9b, 0xe9e051f540b239dc, 0x221091f05abb8687,
927 0x7e08deb014db8afe, 0x4711e1e9d9a094cc, 0x0b2d79bd90a9ef61, 0xb93d19bd45b82515,
928 0x45e9e31d63c1afe1, 0x2c5f0a596005c216, 0xe687cc2331b14a12, 0x51963a2412b6f60c,
929 0x91aeb77c8fe68eaa, 0xd6e18e8cc6841d68, 0x9391085cc2c933d9, 0x6e184be07e68df49,
930 0x4fe4e52edb0dce60, 0x6cda31e8617f0ca2, 0xf8b9374fda7e7c95, 0x8032c603725e774d,
931 0x222b6aa27e007612, 0xf7b7f47cf096afad, 0xe6a9fbafee77e77a, 0x3776ee406e63fbaa,
932 0xde147932fcf78be6, 0x2ab9e031ffaa071e, 0x2169ad0e8a9b1256, 0xe33358135938b76a,
933 0xcaec07e7a5373835, 0xef2863090a97c3ec, 0x6ccfb95f69c3adcc, 0x173e00da427cee4b,
934 0x20f4ed58fcfb3040, 0x16f6fb326a60c32c, 0x2968fa04270ed545, 0x70673adfac0eabc4,
935 0x6ff3c9364ff4e873, 0xde09ed35f13325d3, 0x2396e863b18c500f, 0xe22d253cc031e3ff,
936 0x756d97a61247798d, 0xc9fc8d937e43c880, 0x0759ba59c08e14c7, 0xcd7aad86a4a45810,
937 0x9f91c21c571dbe84, 0xd52d936f44abe8a3, 0xd5b48c100959d9d0, 0xb6cc856b3adc93b6,
938 0x7aea8f8e067d2c8d, 0x04bc177f7b4287a6, 0xe3fcda36fa3b3342, 0xeaeb442e15d45095,
939 0x2f4dd1ca5e89b18b, 0x602368385bb19cb1, 0x4bdfc434d3028181, 0x0b5a92cb80ac8150,
940 0xb95953a97b1578ab, 0x46e6a18b01781b92, 0xdfd31585f38d7433, 0x0b1084b96009370b,
941 0x9a81808e52462ba3, 0xff83368ace4af235, 0xb4e5d8a647e05e95, 0xf848cfc90df4b231,
942 0x9919c68cf3576038, 0x1e89dad8a6790435, 0x7ac9361379139511, 0x7b5f9b6b937a7760,
943 0x6e42e395fde0c1f7, 0x430cef1679799f8f, 0x0ad21cc1b4828074, 0x8982577d0ea42349,
944 0xb1aca6185a7d0d0d, 0x4085c6db106c3d74, 0xba6f7a86e728a418, 0x0325a28758a974d2,
945 0x57ea317f731817ed, 0xbd1e8e00b215a6eb, 0xb39f323742948e87, 0x9f9b0f873784cef4,
946 0xa8c83d26585c5377, 0x837ba337bfcf893c, 0x0a7eeca62a23b805, 0xba4925a9e7f7346f,
947 0xa574eebb90c8da6d, 0x5db7ff0e8d0b8d2d, 0x1562834c52c048d8, 0x0b2e577a853bcafc,
948 0xdecef97a3524ff97, 0xeec053c8fd537066, 0xeaf2b1df83d600e4, 0x5be8b9ab7717eccf,
949 0x05905b91ecbba038, 0xabacba5b373029ed, 0x22fb2283c0ee1267, 0x9c32b2ec3634c580,
950 0x5186c586b6e5611c, 0x71eb0de5e91bb0a0, 0x89e969b42975ef08, 0x2ba0958bc44e322f,
951 0x626d033cb828ba7d, 0xe5fbb65c7776509d, 0xb1403ae51ae9bc82, 0x5d773f0d9753a966,
952 0x4a06feadd4ec8585, 0xda58a710fccd7b76, 0x6061ba4cd3d80d59, 0xf4824f5cfa2ba71c,
953 0xfce622bba0ece756, 0x7d9c738486bc6842, 0x5f629d33c99db969, 0x855ff7c9b79362e6,
954 0x892188a87c7de231, 0x85fea7caf30e2b5e, 0xbefeb221543782c5, 0x769ca33d280842f6,
955 0x3974ebaf71353e52, 0xed0577283980f0cb, 0x7c37d689ab6b0662, 0x5037aeffcd3db52d,
956 0x11bb0a5f64fbdcb5, 0xf5fd5aa5f2b7e974, 0xe1aa07ba7074367b, 0x4b5c14aa1c6a0d28,
957 0xe9fc8c9c36f73953, 0x2609ad2cd0f99b76, 0x8d4f1d6bb589844f, 0xde09f066714fa909,
958 0xe004c5d7adad3747, 0xd5ac81a94dfdefe3, 0xfd3e0083658a13c2, 0xf5512f25dd6e39a7,
959 0xeb7204042ffa181d, 0x046d9254242d06e3, 0x91a5ca94f8706fab, 0xf5c58cc57af63c98,
960 0x04e7ff1e23474908, 0xe4a9bec5c5818324, 0x1edfb105cc3084dd, 0x82431ec76e72a87a,
961 0xe0b215be32c51083, 0x0d9942e3b5245098, 0xa49f1aad5723fd7e, 0xad45edba25a4bde8,
962 0x241f0adc0cd56771, 0xf09bf2de59df3274, 0x090db856bbc020f2, 0x6aa4efb2d2ecb9bb,
963 0xc6be4224ba04c233, 0x557a1760bde90850, 0x23090117938cb921, 0xcbec34da23f3e9c2,
964 0xdfe2d55daad85c54, 0xa7932be700067f48, 0xfb7874535e2d76a4, 0x5161ba088056e74f,
965 0xc275a8435be6cdb2, 0x05fcb771cab5aa15, 0x7f18a4382c9565a8, 0x4244c2cb833d6710,
966 0x884e2b7a4a3db4d0, 0x08ded459d3edf2c2, 0x1616df531fee90cd, 0x9531c65800a97aaa,
967 0x881ba77ab7e5d63a, 0x606d27428df4edd3, 0x294063ed78e305c7, 0x7de2b12f8a8cceb5,
968 0xe6b01cc54a494437, 0x0cdecbe5ac90907c, 0xb88496c657d3e644, 0xf3eecf996f9c6b13,
969 0x24aad7949edcde03, 0x304ca88ebfeaa534, 0x7b68a7bd3ef1916b, 0x3cc307a784d9060c,
970 0x5dca03f19b213efd, 0xa380539c235f80c3, 0xf39756fc01d75bd7, 0x39ac6c7281739adb,
971 0x4b606dc4aa036fda, 0x97126cd02a23b97c, 0x98c1e6906230aead, 0xe12d0f696a6bbc36,
972 0x657a202bb6a89a33, 0x6421a07bda47e13d, 0x8d9d21b3c6b1dbee, 0x1f110f3744f13e0d,
973 0x04d86fccb6e77ee8, 0x8c92852d9c9c14b3, 0x56be3cef19b19446, 0x57ceef0e2ebcbcf7,
974 0x230a9328be0144bf, 0x3c1949b98a92aebc, 0x7ed2db80a62003f2, 0x84e609d13c7594f4,
975 0xf8e81b9a9f35b4e8, 0xc2982fde1a087e4b, 0x84b0713cb3b18147, 0x3582530578d1ff08,
976 0x0e5b6538cd61fce4, 0x46867abf4b6e72bc, 0x4fe9652832325e89, 0x7d141d065654745f,
977 0x9bd5c0479188a53d, 0x4ccd47925108c00b, 0xfd3f6c8d961d47e3, 0x9c5c18a96093d2ad,
978 0xa7d91bf008a358c3, 0x3ea3e5629f977d55, 0x80f0fed6a5f06003, 0x21f390e377ee4d68,
979 0x73ed055ec082526b, 0x28482600c10f6ce2, 0x2bff1aaf94c11fe9, 0xde29cb7a943801b8,
980 0x045b0493dd35af0e, 0xaeae25ff7a431c16, 0x78c9d3348f5364b7, 0xf973d1af84bc2476,
981 0x4d2303e11baf18f3, 0xacebdb3fe5efbc7b, 0xd274a5cf5be50678, 0x2d60c40fdf53ac67,
982 0x109592b606139855, 0x612f472a9c09925f, 0x701a035ccd4e7ab0, 0xac881f0db121a709,
983 0xe1ed47438368366d, 0xde2faff8eeb2810a, 0x8eb2188044342ef9, 0x0e3c1aa7b6851548,
984 0x7ce94a6ba4fd843f, 0x0da503676ee5ebb2, 0xf3bc7bb2cb8669e8, 0xd4b9e44de392fe64,
985 0x81e470ebf207fdea, 0xdd53b09d49a0e5b5, 0xf78e23167a350d5a, 0x706470fc2d84423b,
986 0x816ee82b19a29476, 0x35a9d218ba7cd4a1, 0xf590f12fb09b3fe3, 0x5e574140b302f8b7,
987 0x6cb237a2021f77c3, 0x30a29037231a861e, 0xff4bb07af553a606, 0x831412ee2690d92c,
988 0xf6d2d725ef14ff67, 0x2f79f810928a40ff, 0x2857d91ea9b04f71, 0xd063066f0ed78f3c,
989 0xbf4b8dbc8a34017d, 0x6230f319f8b1f9c4, 0x061b0e25d8899834, 0x4071de32ef7ff0bf,
990 0xbc546a0793fcfcd3, 0xd5881f5d968cf898, 0x0e21c0674cdda190, 0x0000000000000000};
991
992 struct multiplier_index_info
993 {
994 std::uint16_t first_cache_bit_index;
995 std::uint16_t cache_bit_index_offset;
996 };
997
998 static constexpr multiplier_index_info multiplier_index_info_table[] = {
999 {0, 0}, {171, 244}, {419, 565}, {740, 959}, {1135, 1427},
1000 {1604, 1969}, {2141, 2579}, {2750, 3261}, {3434, 4019}, {4191, 4849},
1001 {5019, 5750}, {5924, 6728}, {6904, 7781}, {7922, 8872}, {8993, 10016},
1002 {9026, 10122}, {9110, 10279}, {9245, 10487}, {9431, 10746}, {9668, 11056},
1003 {9956, 11418}, {10296, 11831}, {10687, 12295}, {11129, 12810}, {11622, 13376},
1004 {12166, 13993}, {12761, 14661}, {13407, 15380}, {14104, 16150}, {14852, 16902},
1005 {15582, 17627}, {16285, 18332}, {16968, 19019}, {17633, 19683}, {18275, 20326},
1006 {18896, 20947}, {19495, 21546}, {20072, 22122}, {20626, 22669}, {21151, 23202},
1007 {21662, 23713}, {22151, 24202}, {22618, 24669}, {23063, 25114}, {23486, 25535},
1008 {23885, 25936}, {24264, 26313}, {24619, 26670}, {24954, 27004}, {25266, 27316},
1009 {25556, 27603}, {25821, 27870}, {26066, 28117}, {26291, 28340}, {26492, 28543},
1010 {26673, 28723}, {26831, 28881}, {26967, 29018}, {27082, 29133}, {27175, 29225},
1011 {27245, 29296}, {27294, 29344}, {27320, 29370}, {27324, 0}};
1012};
1013
1014#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
1015
1016template <bool b> constexpr std::size_t extended_cache_long_impl<b>::max_cache_blocks;
1017template <bool b> constexpr std::size_t extended_cache_long_impl<b>::cache_bits_unit;
1018template <bool b> constexpr int extended_cache_long_impl<b>::segment_length;
1019template <bool b> constexpr bool extended_cache_long_impl<b>::constant_block_count;
1020template <bool b> constexpr int extended_cache_long_impl<b>::e_min;
1021template <bool b> constexpr int extended_cache_long_impl<b>::k_min;
1022template <bool b> constexpr int extended_cache_long_impl<b>::cache_bit_index_offset_base;
1023template <bool b> constexpr std::uint64_t extended_cache_long_impl<b>::cache[];
1024template <bool b> constexpr typename extended_cache_long_impl<b>::multiplier_index_info extended_cache_long_impl<b>::multiplier_index_info_table[];
1025
1026#endif
1027
1028using extended_cache_long = extended_cache_long_impl<true>;
1029
1030struct extended_cache_compact
1031{
1032 static constexpr std::size_t max_cache_blocks = 6;
1033 static constexpr std::size_t cache_bits_unit = 64;
1034 static constexpr int segment_length = 80;
1035 static constexpr bool constant_block_count = false;
1036 static constexpr int collapse_factor = 64;
1037 static constexpr int e_min = -1074;
1038 static constexpr int k_min = -211;
1039 static constexpr int cache_bit_index_offset_base = 967;
1040 static constexpr int cache_block_count_offset_base = 27;
1041
1042 static constexpr std::uint64_t cache[] = {
1043 0x9faacf3df73609b1, 0x77b191618c54e9ac, 0xcbc0fe19cae9528c, 0x8164d034592c3d4e,
1044 0x04c42d46c9d7a229, 0x7ee39007a5bc8cc3, 0x5469cf7bb8b25e57, 0x2effce010198cb81,
1045 0x642eb5bc0d8169e0, 0x91356aed1f5cd514, 0xe1c8f30156868b8c, 0xd1201a2b857f5cc5,
1046 0x15c07ee55715eff8, 0x8530360cd386f94f, 0xeb706c10ea02c329, 0x3cb22680f921f59e,
1047 0x3231912d5bf60e61, 0x0e1fff697ed6c695, 0xa8bed97c2f3b63fc, 0xda96e93c07538a6d,
1048 0xc1c4e34ccd6fdbc5, 0x85c09fd1d0f79834, 0x485f3a5d03622bba, 0xe640b09cca5b9d50,
1049 0x19a80913a40927a9, 0x4d82d751a5cf886d, 0x325c9cd793b9977b, 0x4896c18501fb9e0c,
1050 0xa9993bfdf3ea7275, 0xcb7d257a3ee7c9d8, 0xcbf8fdb78849a5f9, 0x6de98520472bdd03,
1051 0x36efd14b69b311de, 0x694fa387dcf3e78f, 0xdccfbfc61d1662ef, 0xbe3a4d4104fb75a2,
1052 0x289ccaebae5c6d2d, 0x436915952987fa63, 0x830446728505ab75, 0x3ad8772923e4e0c0,
1053 0xca946600436f3894, 0x0faae7895e3885f0, 0xadf6b773b1ebf8e0, 0x52473dd5e8218647,
1054 0x5e6b5121ca3b747c, 0x217399923cd80bc0, 0x0a56ced144bb2f9f, 0xb856e82eea863c1f,
1055 0x5cdae42f9562104d, 0x3fa421962c8c4241, 0x63451ff73769a3d2, 0xb0895649e11affd6,
1056 0xe5dd7be415e5d3ef, 0x282a242e818f1668, 0xc8a86da5faf0b5cc, 0xf5176ecc7cbb19db,
1057 0x2a9a282e49b4da0e, 0x59e22f9ed2cb3a4b, 0xc010afa26505a7e7, 0xee47b3ab83a99c3e,
1058 0xc7eafae5fa385ec2, 0x3ec747e06293a148, 0x4b8a8260baf424a7, 0x63079a1ac7709a4e,
1059 0x7fd0cd567aa4a0fa, 0x6909d0e0cfc6ce8d, 0xe0c965770d1491dd, 0xa6d4449e3a3e13ea,
1060 0x73e06d2253c6b584, 0x9f95a4b69679998d, 0x0cc8cc76a8234060, 0xd3da311bb4fc0aae,
1061 0x670614382f45f33c, 0x21f68425f4189fbf, 0x557ce28d58d9a8bd, 0x1f16d908907d0a0e,
1062 0x929415f993b9a2c2, 0x95e0878748988052, 0xc4a104701f794a31, 0xe7d2d2b0c3c31b19,
1063 0x1e6a68d5574b3d9d, 0x5727ec70c7681154, 0xe4b2adae8ac5259e, 0x1cefff5ed639205f,
1064 0xf9410ba5daeb3af5, 0x21b0ad30acb4b8d2, 0xd324604028bf6fac, 0x349a5d2dc4bdc6e0,
1065 0xc77223714aff22d9, 0x5b18ce4aabb5b369, 0xb8a6d609b15ecab7, 0x2111dbce86023643,
1066 0x2a5717a571b96b6c, 0x8039783af28427bf, 0x5bbadd6a1a3fb931, 0xe8564a7a3e3ff2dc,
1067 0xd0868939e541158e, 0xc57d0b8a8af06dde, 0xf1706d329def96c1, 0xbe74f435713bb7d5,
1068 0x8dcdaef5bfb0242c, 0x73b5a1c8c8ec33c7, 0x4ab726d9dac95550, 0x210cf3b3ddfa00ae,
1069 0x559d5e65eefbfa04, 0xe5d1f67c5f9de0ec, 0x6ad4699ea2d0efd6, 0x9590c0f05024f29a,
1070 0x917d5715e6e20913, 0xb13124a40bffe5ba, 0x5248ce22e40406e5, 0xb844b16596551ded,
1071 0xad4c4c5140496c58, 0x458562ae335689b6, 0x269441e13a195ad3, 0x7a5e32a8baf53ea8,
1072 0x6d1469edb474b5f6, 0xe87b554829f6ee5b, 0xbf824a42bae3bdef, 0xed12ec6937744feb,
1073 0x2ca544e624e048f9, 0x1bab8d5ee0c61285, 0x8863eaef018d32d9, 0x98f37ac46669f7ea,
1074 0xa9a0573cb5501b2b, 0xf25c3a8e08a5694d, 0x42355a8000000000, 0x0000000000000000};
1075
1076 struct multiplier_index_info
1077 {
1078 std::uint16_t first_cache_bit_index;
1079 std::uint16_t cache_bit_index_offset;
1080 std::uint16_t cache_block_count_index_offset;
1081 };
1082
1083 static constexpr multiplier_index_info multiplier_index_info_table[] = {
1084 {.first_cache_bit_index: 0, .cache_bit_index_offset: 0, .cache_block_count_index_offset: 0}, {.first_cache_bit_index: 377, .cache_bit_index_offset: 643, .cache_block_count_index_offset: 9}, {.first_cache_bit_index: 1020, .cache_bit_index_offset: 1551, .cache_block_count_index_offset: 22}, {.first_cache_bit_index: 1924, .cache_bit_index_offset: 2721, .cache_block_count_index_offset: 39},
1085 {.first_cache_bit_index: 3046, .cache_bit_index_offset: 4109, .cache_block_count_index_offset: 60}, {.first_cache_bit_index: 3114, .cache_bit_index_offset: 4443, .cache_block_count_index_offset: 70}, {.first_cache_bit_index: 3368, .cache_bit_index_offset: 4962, .cache_block_count_index_offset: 84}, {.first_cache_bit_index: 3807, .cache_bit_index_offset: 5667, .cache_block_count_index_offset: 98},
1086 {.first_cache_bit_index: 4432, .cache_bit_index_offset: 6473, .cache_block_count_index_offset: 111}, {.first_cache_bit_index: 5158, .cache_bit_index_offset: 7199, .cache_block_count_index_offset: 123}, {.first_cache_bit_index: 5804, .cache_bit_index_offset: 7845, .cache_block_count_index_offset: 134}, {.first_cache_bit_index: 6370, .cache_bit_index_offset: 8411, .cache_block_count_index_offset: 143},
1087 {.first_cache_bit_index: 6856, .cache_bit_index_offset: 8896, .cache_block_count_index_offset: 151}, {.first_cache_bit_index: 7261, .cache_bit_index_offset: 9302, .cache_block_count_index_offset: 158}, {.first_cache_bit_index: 7587, .cache_bit_index_offset: 9628, .cache_block_count_index_offset: 164}, {.first_cache_bit_index: 7833, .cache_bit_index_offset: 9874, .cache_block_count_index_offset: 168},
1088 {.first_cache_bit_index: 7999, .cache_bit_index_offset: 10039, .cache_block_count_index_offset: 171}, {.first_cache_bit_index: 8084, .cache_bit_index_offset: 10124, .cache_block_count_index_offset: 173}, {.first_cache_bit_index: 8089, .cache_bit_index_offset: 0, .cache_block_count_index_offset: 0}};
1089
1090 static constexpr std::uint8_t cache_block_counts[] = {
1091 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1092 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x34, 0x12, 0x66,
1093 0x66, 0x45, 0x23, 0x61, 0x66, 0x66, 0x66, 0x45, 0x23, 0x61, 0x66, 0x66, 0x66,
1094 0x56, 0x34, 0x12, 0x66, 0x66, 0x66, 0x56, 0x34, 0x12, 0x66, 0x66, 0x66, 0x45,
1095 0x23, 0x61, 0x66, 0x56, 0x34, 0x12, 0x66, 0x56, 0x34, 0x12, 0x66, 0x45, 0x23,
1096 0x61, 0x45, 0x23, 0x41, 0x23, 0x31, 0x12, 0x12, 0x01};
1097};
1098
1099#ifdef BOOST_CXX17_INLINE_VARIABLES
1100
1101constexpr std::size_t extended_cache_compact::max_cache_blocks;
1102constexpr std::size_t extended_cache_compact::cache_bits_unit;
1103constexpr int extended_cache_compact::segment_length;
1104constexpr bool extended_cache_compact::constant_block_count;
1105constexpr int extended_cache_compact::collapse_factor;
1106constexpr int extended_cache_compact::e_min;
1107constexpr int extended_cache_compact::k_min;
1108constexpr int extended_cache_compact::cache_bit_index_offset_base;
1109constexpr int extended_cache_compact::cache_block_count_offset_base;
1110constexpr extended_cache_compact::multiplier_index_info extended_cache_compact::multiplier_index_info_table[];
1111constexpr std::uint8_t extended_cache_compact::cache_block_counts[];
1112
1113#endif
1114
1115struct extended_cache_super_compact
1116{
1117 static constexpr std::size_t max_cache_blocks = 15;
1118 static constexpr std::size_t cache_bits_unit = 64;
1119 static constexpr int segment_length = 252;
1120 static constexpr bool constant_block_count = false;
1121 static constexpr int collapse_factor = 128;
1122 static constexpr int e_min = -1074;
1123 static constexpr int k_min = -65;
1124 static constexpr int cache_bit_index_offset_base = 1054;
1125 static constexpr int cache_block_count_offset_base = 10;
1126
1127 static constexpr std::uint64_t cache[] = {
1128 0xf712b443bbd52b7b, 0xa5e9ec7501d523e4, 0x6f99ee8b281c132a, 0x1c7262e905287f33,
1129 0xbf4f71a69f411989, 0xe95fb0bf35d5c518, 0x00d875ffe81c1457, 0x31f0fcb03c200323,
1130 0x6f64d6af592895a0, 0x45c073ee14c78fb0, 0x8744404cbdba226c, 0x8dbe2386885f0c74,
1131 0x279b6693e94ab813, 0x6df0a4a86ccbb52e, 0xa94baea98e947129, 0xfc2b4e9bb4cbe9a4,
1132 0x73bbc273e753c4ad, 0xc70c8ff8c19c1059, 0xb7da754b6db8b578, 0x5214cf7f2274988c,
1133 0x39b5c4db3b36b321, 0xda6f355441d9f234, 0x01ab018d850bd7e2, 0x36517c3f140b3bcf,
1134 0xd0e52375d8d125a7, 0xaf9709f49f3b8404, 0x022dd12dd219aa3f, 0x46e2ecebe43f459e,
1135 0xa428ebddeecd6636, 0x3a7d11bff7e2a722, 0xd35d40e9d3b97c7d, 0x60ef65c4478901f1,
1136 0x945301feb0da841a, 0x2028c054ab187f51, 0xbe94b1f686a8b684, 0x09c13fdc1c4868c9,
1137 0xf2325ac2bf88a4ce, 0x92980d8fa53b6888, 0x8f6e17c7572a3359, 0x2964c5bfdd7761f2,
1138 0xf60269fc4910b562, 0x3ca164c4a2183ab0, 0x13f4f9e5a06a95c9, 0xf75022e39380598a,
1139 0x0d3f3c870002ab76, 0x24a4beb4780b78ef, 0x17a59a8f5696d625, 0x0ad76de884cb489d,
1140 0x559d3d0681553d6a, 0x813dcf205788af76, 0xf42f9c3ad707bf72, 0x770d63ceb129026c,
1141 0xa604d413fc14c7c2, 0x3cfc19e01239c784, 0xec7ef19965cedd56, 0x7303dcb3b300b6fd,
1142 0x118059e1139c0f3c, 0x97097186308c91f7, 0x2ad91d77379dce42, 0xad396c61acbe15ec,
1143 0x728518461b5722b6, 0xb85c5bb1ed805ecd, 0x816abc04592a4974, 0x1866b17c7cfbd0d0,
1144 0x0000000000000000};
1145
1146 struct multiplier_index_info
1147 {
1148 std::uint16_t first_cache_bit_index;
1149 std::uint16_t cache_bit_index_offset;
1150 std::uint16_t cache_block_count_index_offset;
1151 };
1152
1153 static constexpr multiplier_index_info multiplier_index_info_table[] = {
1154 {.first_cache_bit_index: 0, .cache_bit_index_offset: 0, .cache_block_count_index_offset: 0}, {.first_cache_bit_index: 860, .cache_bit_index_offset: 1698, .cache_block_count_index_offset: 13}, {.first_cache_bit_index: 2506, .cache_bit_index_offset: 4181, .cache_block_count_index_offset: 29}, {.first_cache_bit_index: 2941, .cache_bit_index_offset: 5069, .cache_block_count_index_offset: 36},
1155 {.first_cache_bit_index: 3577, .cache_bit_index_offset: 5705, .cache_block_count_index_offset: 41}, {.first_cache_bit_index: 3961, .cache_bit_index_offset: 6088, .cache_block_count_index_offset: 44}, {.first_cache_bit_index: 4092, .cache_bit_index_offset: 0, .cache_block_count_index_offset: 0}};
1156
1157 static constexpr std::uint8_t cache_block_counts[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xee,
1158 0xee, 0xee, 0xee, 0xee, 0xac, 0x68,
1159 0x24, 0x8a, 0x46, 0x62, 0x24, 0x13};
1160};
1161
1162#ifdef BOOST_CXX17_INLINE_VARIABLES
1163
1164constexpr std::size_t extended_cache_super_compact::max_cache_blocks;
1165constexpr std::size_t extended_cache_super_compact::cache_bits_unit;
1166constexpr int extended_cache_super_compact::segment_length;
1167constexpr bool extended_cache_super_compact::constant_block_count;
1168constexpr int extended_cache_super_compact::collapse_factor;
1169constexpr int extended_cache_super_compact::e_min;
1170constexpr int extended_cache_super_compact::k_min;
1171constexpr int extended_cache_super_compact::cache_bit_index_offset_base;
1172constexpr int extended_cache_super_compact::cache_block_count_offset_base;
1173constexpr std::uint64_t extended_cache_super_compact::cache[];
1174constexpr extended_cache_super_compact::multiplier_index_info extended_cache_super_compact::multiplier_index_info_table[];
1175constexpr std::uint8_t extended_cache_super_compact::cache_block_counts[];
1176
1177#endif
1178
1179#ifdef BOOST_MSVC
1180# pragma warning(push)
1181# pragma warning(disable: 4100) // MSVC 14.0 warning of unused formal parameter is incorrect
1182#endif
1183
1184template <unsigned v1, unsigned v2, typename ExtendedCache>
1185bool has_further_digits(std::uint64_t significand, int exp2_base, int& k, boost::charconv::detail::uconst<v1> additional_neg_exp_of_2_c, boost::charconv::detail::uconst<v2> additional_neg_exp_of_10_c) noexcept
1186{
1187 constexpr auto additional_neg_exp_of_2_v = static_cast<int>(decltype(additional_neg_exp_of_2_c)::value +
1188 decltype(additional_neg_exp_of_10_c)::value);
1189
1190 constexpr auto additional_neg_exp_of_5_v = static_cast<int>(decltype(additional_neg_exp_of_10_c)::value);
1191
1192 constexpr auto min_neg_exp_of_5 = (-ExtendedCache::k_min + additional_neg_exp_of_5_v) % ExtendedCache::segment_length;
1193
1194 // k >= k_right_threshold iff k - k1 >= 0.
1195 static_assert(additional_neg_exp_of_5_v + ExtendedCache::segment_length >= 1 + ExtendedCache::k_min,
1196 "additional_neg_exp_of_5_v + ExtendedCache::segment_length >= 1 + ExtendedCache::k_min");
1197
1198 constexpr auto k_right_threshold = ExtendedCache::k_min +
1199 ((additional_neg_exp_of_5_v + ExtendedCache::segment_length - 1 -
1200 ExtendedCache::k_min) /
1201 ExtendedCache::segment_length) *
1202 ExtendedCache::segment_length;
1203
1204 // When the smallest absolute value of negative exponent for 5 is too big,
1205 // so whenever the exponent for 5 is negative, the result cannot be an
1206 // integer.
1207 BOOST_IF_CONSTEXPR (min_neg_exp_of_5 > 23)
1208 {
1209 return boost::charconv::detail::has_further_digits_impl::no_neg_k_can_be_integer<
1210 k_right_threshold, additional_neg_exp_of_2_v>(k, exp2_base);
1211 }
1212 // When the smallest absolute value of negative exponent for 5 is big enough, so
1213 // the only negative exponent for 5 that allows the result to be an integer is the
1214 // smallest one.
1215 else BOOST_IF_CONSTEXPR (min_neg_exp_of_5 + ExtendedCache::segment_length > 23)
1216 {
1217 // k < k_left_threshold iff k - k1 < -min_neg_exp_of_5.
1218 static_assert(additional_neg_exp_of_5_v + ExtendedCache::segment_length >= min_neg_exp_of_5 + 1 + ExtendedCache::k_min,
1219 "additional_neg_exp_of_5_v + ExtendedCache::segment_length >= min_neg_exp_of_5 + 1 + ExtendedCache::k_min");
1220
1221 constexpr auto k_left_threshold =
1222 ExtendedCache::k_min +
1223 ((additional_neg_exp_of_5_v - min_neg_exp_of_5 +
1224 ExtendedCache::segment_length - 1 - ExtendedCache::k_min) /
1225 ExtendedCache::segment_length) *
1226 ExtendedCache::segment_length;
1227
1228 return boost::charconv::detail::has_further_digits_impl::only_one_neg_k_can_be_integer<
1229 k_left_threshold, k_right_threshold, additional_neg_exp_of_2_v,
1230 min_neg_exp_of_5>(k, exp2_base, significand);
1231 }
1232 // When the smallest absolute value of negative exponent for 5 is big enough, so
1233 // the only negative exponents for 5 that allows the result to be an integer are the
1234 // smallest one and the next smallest one.
1235 else
1236 {
1237 static_assert(min_neg_exp_of_5 + 2 * ExtendedCache::segment_length > 23,
1238 "min_neg_exp_of_5 + 2 * ExtendedCache::segment_length > 23");
1239
1240 constexpr auto k_left_threshold =
1241 ExtendedCache::k_min +
1242 ((additional_neg_exp_of_5_v - min_neg_exp_of_5 - 1 - ExtendedCache::k_min) /
1243 ExtendedCache::segment_length) *
1244 ExtendedCache::segment_length;
1245
1246 constexpr auto k_middle_threshold =
1247 ExtendedCache::k_min +
1248 ((additional_neg_exp_of_5_v - min_neg_exp_of_5 +
1249 ExtendedCache::segment_length - 1 - ExtendedCache::k_min) /
1250 ExtendedCache::segment_length) *
1251 ExtendedCache::segment_length;
1252
1253 return boost::charconv::detail::has_further_digits_impl::only_two_neg_k_can_be_integer<
1254 k_left_threshold, k_middle_threshold, k_right_threshold,
1255 additional_neg_exp_of_2_v, min_neg_exp_of_5, ExtendedCache::segment_length>(
1256 k, exp2_base, significand);
1257 }
1258}
1259
1260template <unsigned v1, unsigned v2, typename ExtendedCache>
1261inline bool has_further_digits(std::uint64_t significand, int exp2_base, int& k)
1262{
1263 boost::charconv::detail::uconst<v1> additional_neg_exp_of_2_c;
1264 boost::charconv::detail::uconst<v2> additional_neg_exp_of_10_c;
1265
1266 return has_further_digits<v1, v2, ExtendedCache>(significand, exp2_base, k, additional_neg_exp_of_2_c, additional_neg_exp_of_10_c);
1267}
1268
1269template <unsigned additional_neg_exp_of_2, unsigned additional_neg_exp_of_10, typename ExtendedCache>
1270bool compute_has_further_digits(unsigned remaining_subsegment_pairs, std::uint64_t significand, int exp2_base, int& k) noexcept
1271{
1272 #define BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(n) \
1273 case n: \
1274 return has_further_digits<additional_neg_exp_of_2, additional_neg_exp_of_10 + (n - 1) * 18, ExtendedCache>(significand, exp2_base, k)
1275 switch (remaining_subsegment_pairs) {
1276 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(1);
1277 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(2);
1278 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(3);
1279 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(4);
1280 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(5);
1281 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(6);
1282 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(7);
1283 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(8);
1284 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(9);
1285 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(10);
1286 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(11);
1287 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(12);
1288 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(13);
1289 BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(14);
1290
1291 default:
1292 BOOST_UNREACHABLE_RETURN(remaining_subsegment_pairs); // NOLINT
1293 }
1294 #undef BOOST_CHARCONV_252_HAS_FURTHER_DIGITS
1295
1296 BOOST_UNREACHABLE_RETURN(false); // NOLINT
1297}
1298
1299#ifdef BOOST_MSVC
1300# pragma warning(pop)
1301#endif
1302
1303// Print 0.000...0 where precision is the number of 0's after the decimal dot.
1304inline to_chars_result print_zero_fixed(char* buffer, std::size_t buffer_size, const int precision) noexcept
1305{
1306 // No trailing decimal dot.
1307 if (precision == 0)
1308 {
1309 *buffer = '0';
1310 return {.ptr: buffer + 1, .ec: std::errc()};
1311 }
1312
1313 if (buffer_size < static_cast<std::size_t>(precision) + 2U)
1314 {
1315 return {.ptr: buffer + buffer_size, .ec: std::errc::value_too_large};
1316 }
1317
1318 std::memcpy(dest: buffer, src: "0.", n: 2); // NOLINT : Specifically not null-terminating
1319 std::memset(s: buffer + 2, c: '0', n: static_cast<std::size_t>(precision)); // NOLINT : Specifically not null-terminating
1320 return {.ptr: buffer + 2 + precision, .ec: std::errc()};
1321}
1322
1323// precision means the number of decimal significand digits minus 1.
1324// Assumes round-to-nearest, tie-to-even rounding.
1325template <typename MainCache = main_cache_full, typename ExtendedCache>
1326BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision, char* first, char* last,
1327 boost::charconv::chars_format fmt) noexcept
1328{
1329 if (first >= last)
1330 {
1331 return {.ptr: last, .ec: std::errc::value_too_large};
1332 }
1333
1334 auto buffer_size = static_cast<std::size_t>(last - first);
1335 auto buffer = first;
1336
1337 BOOST_CHARCONV_ASSERT(precision >= 0);
1338 using namespace detail;
1339
1340 std::uint64_t br = default_float_traits<double>::float_to_carrier(x);
1341 bool is_negative = ((br >> 63) != 0);
1342 br <<= 1;
1343 int e = static_cast<int>(br >> (ieee754_binary64::significand_bits + 1));
1344 auto significand = (br & ((UINT64_C(1) << (ieee754_binary64::significand_bits + 1)) - 1)); // shifted by 1-bit.
1345
1346 if (is_negative)
1347 {
1348 *buffer = '-';
1349 ++buffer;
1350 --buffer_size;
1351
1352 if (buffer_size == 0)
1353 {
1354 return {.ptr: buffer, .ec: std::errc::value_too_large};
1355 }
1356 }
1357
1358 // Infinities or NaN
1359 if (e == ((UINT32_C(1) << ieee754_binary64::exponent_bits) - 1))
1360 {
1361 if (significand == 0)
1362 {
1363 constexpr std::size_t inf_chars = 3;
1364
1365 if (buffer_size < inf_chars)
1366 {
1367 return {.ptr: last, .ec: std::errc::value_too_large};
1368 }
1369
1370 std::memcpy(dest: buffer, src: "inf", n: inf_chars); // NOLINT : Specifically not null-terminating
1371 return {.ptr: buffer + inf_chars, .ec: std::errc()};
1372 }
1373 else
1374 {
1375 // Significand values for NaN by type
1376 // qNaN = 4503599627370496
1377 // sNaN = 2251799813685248
1378 //
1379 if (significand == UINT64_C(4503599627370496))
1380 {
1381 if (!is_negative)
1382 {
1383 constexpr std::size_t nan_chars = 3;
1384
1385 if (buffer_size < nan_chars)
1386 {
1387 return {.ptr: last, .ec: std::errc::value_too_large};
1388 }
1389
1390 std::memcpy(dest: buffer, src: "nan", n: nan_chars); // NOLINT : Specifically not null-terminating
1391 return {.ptr: buffer + nan_chars, .ec: std::errc()};
1392 }
1393 else
1394 {
1395 constexpr std::size_t neg_nan_chars = 8;
1396
1397 if (buffer_size < neg_nan_chars)
1398 {
1399 return {.ptr: last, .ec: std::errc::value_too_large};
1400 }
1401
1402 std::memcpy(dest: buffer, src: "nan(ind)", n: neg_nan_chars); // NOLINT : Specifically not null-terminating
1403 return {.ptr: buffer + neg_nan_chars, .ec: std::errc()};
1404 }
1405 }
1406 else
1407 {
1408 constexpr std::size_t snan_chars = 9;
1409
1410 if (buffer_size < snan_chars)
1411 {
1412 return {.ptr: last, .ec: std::errc::value_too_large};
1413 }
1414
1415 std::memcpy(dest: buffer, src: "nan(snan)", n: snan_chars); // NOLINT : Specifically not null-terminating
1416 return {.ptr: buffer + snan_chars, .ec: std::errc()};
1417 }
1418 }
1419 }
1420 else
1421 {
1422 // Normal numbers.
1423 if (e != 0)
1424 {
1425 significand |= (decltype(significand)(1) << (ieee754_binary64::significand_bits + 1));
1426 e += (ieee754_binary64::exponent_bias - ieee754_binary64::significand_bits);
1427 }
1428 // Subnormal numbers.
1429 else
1430 {
1431 // Zero
1432 if (significand == 0)
1433 {
1434 if (fmt == boost::charconv::chars_format::general)
1435 {
1436 // For the case of chars_format::general, 0 is always printed as 0.
1437 *buffer = '0';
1438 return {.ptr: buffer + 1, .ec: std::errc()};
1439 }
1440 else if (fmt == boost::charconv::chars_format::fixed)
1441 {
1442 return print_zero_fixed(buffer, buffer_size, precision);
1443 }
1444 // For the case of chars_format::scientific, print as many 0's as requested after the decimal dot, and then print e+00.
1445 if (precision == 0)
1446 {
1447 constexpr std::size_t zero_chars = 5;
1448
1449 if (buffer_size < zero_chars)
1450 {
1451 return {.ptr: last, .ec: std::errc::value_too_large};
1452 }
1453
1454 std::memcpy(dest: buffer, src: "0e+00", n: zero_chars);
1455 return {.ptr: buffer + zero_chars, .ec: std::errc()};
1456 }
1457 else
1458 {
1459 if (buffer_size < static_cast<std::size_t>(precision) + 6U)
1460 {
1461 return {.ptr: last, .ec: std::errc::value_too_large};
1462 }
1463
1464 std::memcpy(dest: buffer, src: "0.", n: 2); // NOLINT : Specifically not null-terminating
1465 std::memset(s: buffer + 2, c: '0', n: static_cast<std::size_t>(precision)); // NOLINT : Specifically not null-terminating
1466 std::memcpy(dest: buffer + 2 + precision, src: "e+00", n: 4); // NOLINT : Specifically not null-terminating
1467 return {.ptr: buffer + precision + 6, .ec: std::errc()};
1468 }
1469 }
1470 // Nonzero
1471 e = ieee754_binary64::min_exponent - ieee754_binary64::significand_bits;
1472 }
1473 }
1474
1475 constexpr int kappa = 2;
1476 int k = kappa - log::floor_log10_pow2(e);
1477 std::uint32_t current_digits {};
1478 char* const buffer_starting_pos = buffer;
1479 char* decimal_dot_pos = buffer; // decimal_dot_pos == buffer_starting_pos indicates that there should be no decimal dot.
1480 int decimal_exponent_normalized {};
1481
1482 // Number of digits to be printed.
1483 int remaining_digits {};
1484
1485 /////////////////////////////////////////////////////////////////////////////////////////////////
1486 /// Phase 1 - Print the first digit segment computed with the Dragonbox table.
1487 /////////////////////////////////////////////////////////////////////////////////////////////////
1488
1489 {
1490 // Compute the first digit segment.
1491 const auto main_cache = MainCache::template get_cache<ieee754_binary64>(k);
1492 const int beta = e + log::floor_log2_pow10(e: k);
1493
1494 // Integer check is okay for binary64.
1495 //auto [first_segment, has_more_segments]
1496 compute_mul_result segments = [&] {
1497 const auto r = umul192_upper128(significand << beta, main_cache);
1498 return compute_mul_result{r.high, r.low == 0};
1499 }();
1500
1501 auto first_segment = segments.result;
1502 auto has_more_segments = !segments.is_integer;
1503
1504 // The first segment can be up to 19 digits. It is in fact always of either 18 or 19
1505 // digits except when the input is a subnormal number. For subnormal numbers, the
1506 // smallest possible value of the first segment is 10^kappa, so it is of at least
1507 // kappa+1 digits (i.e., 3 in this case).
1508
1509 int first_segment_length = 19;
1510 auto first_segment_aligned = first_segment; // Aligned to have 19 digits.
1511 while (first_segment_aligned < UINT64_C(10000000000000000))
1512 {
1513 first_segment_aligned *= 100;
1514 first_segment_length -= 2;
1515 }
1516 if (first_segment_aligned < UINT64_C(1000000000000000000))
1517 {
1518 first_segment_aligned *= 10;
1519 first_segment_length -= 1;
1520 }
1521 // The decimal exponent when written as X.XXXX.... x 10^XX.
1522 decimal_exponent_normalized = first_segment_length - k - 1;
1523
1524 // Figure out the correct value of remaining_digits.
1525 if (fmt == boost::charconv::chars_format::scientific)
1526 {
1527 remaining_digits = precision + 1;
1528 int exponent_print_length =
1529 decimal_exponent_normalized >= 100 ? 5 :
1530 decimal_exponent_normalized <= -100 ? 6 :
1531 decimal_exponent_normalized >= 0 ? 4 : 5;
1532
1533 // No trailing decimal dot.
1534 auto minimum_required_buffer_size =
1535 static_cast<std::size_t>(remaining_digits + exponent_print_length + (precision != 0 ? 1 : 0));
1536 if (buffer_size < minimum_required_buffer_size)
1537 {
1538 return {.ptr: last, .ec: std::errc::value_too_large};
1539 }
1540
1541 if (precision != 0)
1542 {
1543 // Reserve a place for the decimal dot.
1544 *buffer = '0';
1545 ++buffer;
1546 ++decimal_dot_pos;
1547 }
1548 }
1549 else if (fmt == boost::charconv::chars_format::fixed)
1550 {
1551 if (decimal_exponent_normalized >= 0)
1552 {
1553 remaining_digits = precision + decimal_exponent_normalized + 1;
1554
1555 // No trailing decimal dot.
1556 auto minimum_required_buffer_size =
1557 static_cast<std::size_t>(remaining_digits + (precision != 0 ? 1 : 0));
1558
1559 // We need one more space if the rounding changes the exponent,
1560 // but since we don't know at this point if that will actually happen, handle such a case later.
1561
1562 if (buffer_size < minimum_required_buffer_size)
1563 {
1564 return {.ptr: last, .ec: std::errc::value_too_large};
1565 }
1566
1567 if (precision != 0)
1568 {
1569 // Reserve a place for the decimal dot.
1570 *buffer = '0';
1571 ++buffer;
1572 decimal_dot_pos += decimal_exponent_normalized + 1;
1573 }
1574 }
1575 else
1576 {
1577 int number_of_leading_zeros = -decimal_exponent_normalized - 1;
1578
1579 // When there are more than precision number of leading zeros,
1580 // all the digits we need to print are 0.
1581 if (number_of_leading_zeros > precision)
1582 {
1583 return print_zero_fixed(buffer, buffer_size, precision);
1584 }
1585 // When the number of leading zeros is exactly precision,
1586 // then we might need to print 1 at the last digit due to rounding.
1587 if (number_of_leading_zeros == precision)
1588 {
1589 // Since the last digit before rounding is 0,
1590 // according to the "round-to-nearest, tie-to-even" rule, we round-up
1591 // if and only if the input is strictly larger than the midpoint.
1592 bool round_up = (first_segment_aligned + (has_more_segments ? 1 : 0)) > UINT64_C(5000000000000000000);
1593 if (!round_up)
1594 {
1595 return print_zero_fixed(buffer, buffer_size, precision);
1596 }
1597
1598 // No trailing decimal dot.
1599 if (precision == 0)
1600 {
1601 *buffer = '1';
1602 return {.ptr: buffer + 1, .ec: std::errc()};
1603 }
1604
1605 if (buffer_size < static_cast<std::size_t>(precision) + 2U)
1606 {
1607 return {.ptr: buffer + buffer_size, .ec: std::errc::value_too_large};
1608 }
1609
1610 std::memcpy(dest: buffer, src: "0.", n: 2); // NOLINT : Specifically not null-terminating
1611 std::memset(s: buffer + 2, c: '0', n: static_cast<std::size_t>(precision - 1)); // NOLINT : Specifically not null-terminating
1612 buffer[1 + precision] = '1';
1613 return {.ptr: buffer + 2 + precision, .ec: std::errc()};
1614 }
1615
1616 remaining_digits = precision - number_of_leading_zeros;
1617
1618 // Always have decimal dot.
1619 BOOST_CHARCONV_ASSERT(precision > 0);
1620 auto minimum_required_buffer_size = static_cast<std::size_t>(precision + 2);
1621 if (buffer_size < minimum_required_buffer_size)
1622 {
1623 return {.ptr: last, .ec: std::errc::value_too_large};
1624 }
1625
1626 // Print leading zeros.
1627 std::memset(s: buffer, c: '0', n: static_cast<std::size_t>(number_of_leading_zeros + 2));
1628 buffer += number_of_leading_zeros + 2;
1629 ++decimal_dot_pos;
1630 }
1631 }
1632 else
1633 {
1634 // fmt == boost::charconv::chars_format::general
1635 if (precision == 0)
1636 {
1637 // For general format, precision = 0 is interpreted as precision = 1.
1638 precision = 1;
1639 }
1640 remaining_digits = precision;
1641
1642 // Use scientific format if decimal_exponent_normalized <= -6 or decimal_exponent_normalized >= precision.
1643 // Use fixed format if -4 <= decimal_exponent_normalized <= precision - 2.
1644 // If decimal_exponent_normalized == -5, use fixed format if and only if the rounding increases the exponent.
1645 // If decimal_exponent_normalized == precision - 1, use scientific format if and only if the rounding increases the exponent.
1646 // Since we cannot reliably decide which format to use, necessary corrections will be made in the last phase.
1647
1648 // We may end up not printing the decimal dot if fixed format is chosen, but reserve a place anyway.
1649 *buffer = '0';
1650 ++buffer;
1651 decimal_dot_pos += (0 < decimal_exponent_normalized && decimal_exponent_normalized < precision)
1652 ? decimal_exponent_normalized + 1 : 1;
1653 }
1654
1655 if (remaining_digits <= 2)
1656 {
1657 uint128 prod;
1658 std::uint64_t fractional_part64;
1659 std::uint64_t fractional_part_rounding_threshold64;
1660
1661 // Convert to fixed-point form with 64/32-bit boundary for the fractional part.
1662
1663 if (remaining_digits == 1)
1664 {
1665 prod = umul128(x: first_segment_aligned, UINT64_C(1329227995784915873));
1666 // ceil(2^63 + 2^64/10^18)
1667 fractional_part_rounding_threshold64 = additional_static_data_holder::fractional_part_rounding_thresholds64[17];
1668 }
1669 else
1670 {
1671 prod = umul128(x: first_segment_aligned, UINT64_C(13292279957849158730));
1672 // ceil(2^63 + 2^64/10^17)
1673 fractional_part_rounding_threshold64 = additional_static_data_holder::
1674 fractional_part_rounding_thresholds64[16];
1675 }
1676 fractional_part64 = (prod.low >> 56) | (prod.high << 8);
1677 current_digits = static_cast<std::uint32_t>(prod.high >> 56);
1678
1679 // Perform rounding, print the digit, and return.
1680 if (remaining_digits == 1)
1681 {
1682 if (fractional_part64 >= fractional_part_rounding_threshold64 ||
1683 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1684 {
1685 goto round_up_one_digit;
1686 }
1687
1688 print_1_digit(n: current_digits, buffer);
1689 ++buffer;
1690 }
1691 else
1692 {
1693 if (fractional_part64 >= fractional_part_rounding_threshold64 ||
1694 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1695 {
1696 goto round_up_two_digits;
1697 }
1698
1699 print_2_digits(n: current_digits, buffer);
1700 buffer += 2;
1701 }
1702
1703 goto insert_decimal_dot;
1704 } // remaining_digits <= 2
1705
1706 // At this point, there are at least 3 digits to print.
1707 // We split the segment into three chunks, each consisting of 9 digits, 8 digits,
1708 // and 2 digits.
1709
1710 // MSVC doesn't know how to do Grandlund-Montgomery for large 64-bit integers.
1711 // 7922816251426433760 = ceil(2^96/10^10) = floor(2^96*(10^9/(10^19 - 1)))
1712 const auto first_subsegment =
1713 static_cast<std::uint32_t>(umul128_upper64(x: first_segment, UINT64_C(7922816251426433760)) >> 32);
1714
1715 const auto second_third_subsegments =
1716 first_segment - first_subsegment * UINT64_C(10000000000);
1717
1718 BOOST_CHARCONV_ASSERT(first_subsegment < UINT64_C(1000000000));
1719 BOOST_CHARCONV_ASSERT(second_third_subsegments < UINT64_C(10000000000));
1720
1721 int remaining_digits_in_the_current_subsegment;
1722 std::uint64_t prod; // holds intermediate values for digit generation.
1723
1724 // Print the first subsegment.
1725 if (first_subsegment != 0)
1726 {
1727 // 9 digits (19 digits in total).
1728 if (first_subsegment >= 100000000)
1729 {
1730 // 1441151882 = ceil(2^57 / 10^8) + 1
1731 prod = first_subsegment * UINT64_C(1441151882);
1732 prod >>= 25;
1733 remaining_digits_in_the_current_subsegment = 8;
1734 }
1735 // 7 or 8 digits (17 or 18 digits in total).
1736 else if (first_subsegment >= 1000000)
1737 {
1738 // 281474978 = ceil(2^48 / 10^6) + 1
1739 prod = first_subsegment * UINT64_C(281474978);
1740 prod >>= 16;
1741 remaining_digits_in_the_current_subsegment = 6;
1742 }
1743 // 5 or 6 digits (15 or 16 digits in total).
1744 else if (first_subsegment >= 10000)
1745 {
1746 // 429497 = ceil(2^32 / 10^4)
1747 prod = first_subsegment * UINT64_C(429497);
1748 remaining_digits_in_the_current_subsegment = 4;
1749 }
1750 // 3 or 4 digits (13 or 14 digits in total).
1751 else if (first_subsegment >= 100)
1752 {
1753 // 42949673 = ceil(2^32 / 10^2)
1754 prod = first_subsegment * UINT64_C(42949673);
1755 remaining_digits_in_the_current_subsegment = 2;
1756 }
1757 // 1 or 2 digits (11 or 12 digits in total).
1758 else
1759 {
1760 prod = std::uint64_t(first_subsegment) << 32;
1761 remaining_digits_in_the_current_subsegment = 0;
1762 }
1763
1764 const auto initial_digits = static_cast<std::uint32_t>(prod >> 32);
1765
1766 buffer -= (initial_digits < 10 ? 1 : 0);
1767 remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
1768 print_2_digits(n: initial_digits, buffer);
1769 buffer += 2;
1770
1771 if (remaining_digits > remaining_digits_in_the_current_subsegment)
1772 {
1773 remaining_digits -= remaining_digits_in_the_current_subsegment;
1774
1775 for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2)
1776 {
1777 // Write next two digits.
1778 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1779 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
1780 buffer += 2;
1781 }
1782 }
1783 else
1784 {
1785 for (int i = 0; i < (remaining_digits - 1) / 2; ++i)
1786 {
1787 // Write next two digits.
1788 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1789 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
1790 buffer += 2;
1791 }
1792
1793 // Distinguish two cases of rounding.
1794 if (remaining_digits_in_the_current_subsegment > remaining_digits)
1795 {
1796 if ((remaining_digits & 1) != 0)
1797 {
1798 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
1799 }
1800 else
1801 {
1802 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1803 }
1804
1805 current_digits = static_cast<std::uint32_t>(prod >> 32);
1806
1807 if (check_rounding_condition_inside_subsegment(
1808 current_digits, fractional_part: static_cast<std::uint32_t>(prod),
1809 remaining_digits_in_the_current_subsegment: remaining_digits_in_the_current_subsegment - remaining_digits,
1810 has_further_digits: second_third_subsegments != 0 || has_more_segments))
1811 {
1812 goto round_up;
1813 }
1814
1815 goto print_last_digits;
1816 }
1817 else
1818 {
1819 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1820 current_digits = static_cast<std::uint32_t>(prod >> 32);
1821
1822 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
1823 current_digits,
1824 next_subsegment: uint_with_known_number_of_digits<10>{.value: second_third_subsegments},
1825 has_further_digits: has_more_segments))
1826 {
1827 goto round_up_two_digits;
1828 }
1829
1830 goto print_last_two_digits;
1831 }
1832 }
1833 }
1834
1835 // Print the second subsegment.
1836 // The second subsegment cannot be zero even for subnormal numbers.
1837
1838 if (remaining_digits <= 2)
1839 {
1840 // In this case the first subsegment must be nonzero.
1841
1842 if (remaining_digits == 1)
1843 {
1844 const auto prod128 = umul128(x: second_third_subsegments, UINT64_C(18446744074));
1845
1846 current_digits = static_cast<std::uint32_t>(prod128.high);
1847 const auto fractional_part64 = prod128.low + 1;
1848 // 18446744074 is even, so prod.low cannot be equal to 2^64 - 1.
1849 BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
1850
1851 if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[8] ||
1852 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1853 {
1854 goto round_up_one_digit;
1855 }
1856
1857 goto print_last_one_digit;
1858 } // remaining_digits == 1
1859 else
1860 {
1861 const auto prod128 = umul128(x: second_third_subsegments, UINT64_C(184467440738));
1862
1863 current_digits = static_cast<std::uint32_t>(prod128.high);
1864 const auto fractional_part64 = prod128.low + 1;
1865 // 184467440738 is even, so prod.low cannot be equal to 2^64 - 1.
1866 BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
1867
1868 if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[7] ||
1869 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1870 {
1871 goto round_up_two_digits;
1872 }
1873
1874 goto print_last_two_digits;
1875 }
1876 } // remaining_digits <= 2
1877
1878 // Compilers are not aware of how to leverage the maximum value of
1879 // second_third_subsegments to find out a better magic number which allows us to
1880 // eliminate an additional shift.
1881 // 184467440737095517 = ceil(2^64/100) < floor(2^64*(10^8/(10^10 - 1))).
1882 const auto second_subsegment = static_cast<std::uint32_t>(
1883 umul128_upper64(x: second_third_subsegments, UINT64_C(184467440737095517)));
1884
1885 // Since the final result is of 2 digits, we can do the computation in 32-bits.
1886 const auto third_subsegment =
1887 static_cast<std::uint32_t>(second_third_subsegments) - second_subsegment * 100;
1888
1889 BOOST_CHARCONV_ASSERT(second_subsegment < 100000000);
1890 BOOST_CHARCONV_ASSERT(third_subsegment < 100);
1891
1892 {
1893 std::uint32_t initial_digits;
1894 if (first_subsegment != 0)
1895 {
1896 prod = ((second_subsegment * UINT64_C(281474977)) >> 16) + 1;
1897 remaining_digits_in_the_current_subsegment = 6;
1898
1899 initial_digits = static_cast<std::uint32_t>(prod >> 32);
1900 remaining_digits -= 2;
1901 }
1902 else
1903 {
1904 // 7 or 8 digits (9 or 10 digits in total).
1905 if (second_subsegment >= 1000000)
1906 {
1907 prod = (second_subsegment * UINT64_C(281474978)) >> 16;
1908 remaining_digits_in_the_current_subsegment = 6;
1909 }
1910 // 5 or 6 digits (7 or 8 digits in total).
1911 else if (second_subsegment >= 10000)
1912 {
1913 prod = second_subsegment * UINT64_C(429497);
1914 remaining_digits_in_the_current_subsegment = 4;
1915 }
1916 // 3 or 4 digits (5 or 6 digits in total).
1917 else if (second_subsegment >= 100)
1918 {
1919 prod = second_subsegment * UINT64_C(42949673);
1920 remaining_digits_in_the_current_subsegment = 2;
1921 }
1922 // 1 or 2 digits (3 or 4 digits in total).
1923 else
1924 {
1925 prod = std::uint64_t(second_subsegment) << 32;
1926 remaining_digits_in_the_current_subsegment = 0;
1927 }
1928
1929 initial_digits = static_cast<std::uint32_t>(prod >> 32);
1930 buffer -= (initial_digits < 10 ? 1 : 0);
1931 remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
1932 }
1933
1934 print_2_digits(n: initial_digits, buffer);
1935 buffer += 2;
1936
1937 if (remaining_digits > remaining_digits_in_the_current_subsegment)
1938 {
1939 remaining_digits -= remaining_digits_in_the_current_subsegment;
1940 for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2)
1941 {
1942 // Write next two digits.
1943 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1944 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
1945 buffer += 2;
1946 }
1947 }
1948 else
1949 {
1950 for (int i = 0; i < (remaining_digits - 1) / 2; ++i)
1951 {
1952 // Write next two digits.
1953 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1954 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
1955 buffer += 2;
1956 }
1957
1958 // Distinguish two cases of rounding.
1959 if (remaining_digits_in_the_current_subsegment > remaining_digits)
1960 {
1961 if ((remaining_digits & 1) != 0)
1962 {
1963 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
1964 }
1965 else
1966 {
1967 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1968 }
1969 current_digits = static_cast<std::uint32_t>(prod >> 32);
1970
1971 if (check_rounding_condition_inside_subsegment(
1972 current_digits, fractional_part: static_cast<std::uint32_t>(prod),
1973 remaining_digits_in_the_current_subsegment: remaining_digits_in_the_current_subsegment - remaining_digits,
1974 has_further_digits: third_subsegment != 0 || has_more_segments))
1975 {
1976 goto round_up;
1977 }
1978
1979 goto print_last_digits;
1980 }
1981 else
1982 {
1983 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1984 current_digits = static_cast<std::uint32_t>(prod >> 32);
1985
1986 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
1987 current_digits,
1988 next_subsegment: uint_with_known_number_of_digits<2>{.value: third_subsegment},
1989 has_further_digits: has_more_segments))
1990 {
1991 goto round_up_two_digits;
1992 }
1993
1994 goto print_last_two_digits;
1995 }
1996 }
1997 }
1998
1999 // Print the third subsegment.
2000 {
2001 if (remaining_digits > 2)
2002 {
2003 print_2_digits(n: third_subsegment, buffer);
2004 buffer += 2;
2005 remaining_digits -= 2;
2006
2007 // If there is no more segment, then fill remaining digits with 0's and return.
2008 if (!has_more_segments)
2009 {
2010 goto fill_remaining_digits_with_0s;
2011 }
2012 }
2013 else if (remaining_digits == 1)
2014 {
2015 prod = third_subsegment * UINT64_C(429496730);
2016 current_digits = static_cast<std::uint32_t>(prod >> 32);
2017
2018 if (check_rounding_condition_inside_subsegment(
2019 current_digits, fractional_part: static_cast<std::uint32_t>(prod), remaining_digits_in_the_current_subsegment: 1, has_further_digits: has_more_segments))
2020 {
2021 goto round_up_one_digit;
2022 }
2023
2024 goto print_last_one_digit;
2025 }
2026 else
2027 {
2028 // remaining_digits == 2.
2029 // If there is no more segment, then print the current two digits and return.
2030 if (!has_more_segments)
2031 {
2032 print_2_digits(n: third_subsegment, buffer);
2033 buffer += 2;
2034 goto insert_decimal_dot;
2035 }
2036
2037 // Otherwise, for performing the rounding, we have to wait until the next
2038 // segment becomes available. This state can be detected afterward by
2039 // inspecting if remaining_digits == 0.
2040 remaining_digits = 0;
2041 current_digits = third_subsegment;
2042 }
2043 }
2044 }
2045
2046 /////////////////////////////////////////////////////////////////////////////////////////////////
2047 /// Phase 2 - Print further digit segments computed with the extended cache table.
2048 /////////////////////////////////////////////////////////////////////////////////////////////////
2049
2050 {
2051 auto multiplier_index =
2052 static_cast<std::uint32_t>(k + ExtendedCache::segment_length - ExtendedCache::k_min) /
2053 static_cast<std::uint32_t>(ExtendedCache::segment_length);
2054
2055 int digits_in_the_second_segment;
2056 {
2057 const auto new_k =
2058 ExtendedCache::k_min + static_cast<int>(multiplier_index) * ExtendedCache::segment_length;
2059 digits_in_the_second_segment = new_k - k;
2060 k = new_k;
2061 }
2062
2063 const auto exp2_base = e + boost::core::countr_zero(x: significand);
2064
2065 using cache_block_type = typename std::decay<decltype(ExtendedCache::cache[0])>::type;
2066
2067 cache_block_type blocks[ExtendedCache::max_cache_blocks];
2068 cache_block_count_t<ExtendedCache::constant_block_count, ExtendedCache::max_cache_blocks> cache_block_count;
2069
2070 // Deal with the second segment. The second segment is special because it can have
2071 // overlapping digits with the first segment. Note that we cannot just move the buffer
2072 // pointer backward and print the whole segment from there, because it may contain
2073 // leading zeros.
2074 {
2075 cache_block_count =
2076 load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(
2077 blocks, e, k, multiplier_index);
2078
2079 // Compute nm mod 2^Q.
2080 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
2081
2082 BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
2083 {
2084 // No rounding, continue.
2085 if (remaining_digits > digits_in_the_second_segment)
2086 {
2087 remaining_digits -= digits_in_the_second_segment;
2088
2089 if (digits_in_the_second_segment <= 2)
2090 {
2091 BOOST_CHARCONV_ASSERT(digits_in_the_second_segment != 0);
2092
2093 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2094 power_of_10[19], blocks, cache_block_count);
2095
2096 auto subsegment =
2097 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2098 generate_and_discard_lower(power_of_10[3], blocks,
2099 cache_block_count);
2100
2101 if (digits_in_the_second_segment == 1)
2102 {
2103 auto prod = subsegment * UINT64_C(429496730);
2104 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2105 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2106 ++buffer;
2107 }
2108 else
2109 {
2110 auto prod = subsegment * UINT64_C(42949673);
2111 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2112 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2113 buffer += 2;
2114 }
2115 } // digits_in_the_second_segment <= 2
2116 else if (digits_in_the_second_segment <= 16)
2117 {
2118 BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
2119
2120 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2121 compute_power(UINT64_C(10), exp: 22 - digits_in_the_second_segment),
2122 blocks, cache_block_count);
2123
2124 // When there are at most 9 digits, we can store them in 32-bits.
2125 if (digits_in_the_second_segment <= 9)
2126 {
2127 // The number of overlapping digits is in the range 13 ~ 19.
2128 const auto subsegment =
2129 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2130 generate_and_discard_lower(power_of_10[9], blocks,
2131 cache_block_count);
2132
2133 std::uint64_t prod;
2134 if ((digits_in_the_second_segment & 1) != 0)
2135 {
2136 prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
2137 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2138 ++buffer;
2139 }
2140 else
2141 {
2142 prod = ((subsegment * UINT64_C(450359963)) >> 20) + 1;
2143 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2144 buffer += 2;
2145 }
2146
2147 for (; digits_in_the_second_segment > 2; digits_in_the_second_segment -= 2)
2148 {
2149 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2150 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2151 buffer += 2;
2152 }
2153 } // digits_in_the_second_segment <= 9
2154 else
2155 {
2156 // The number of digits in the segment is in the range 10 ~ 16.
2157 const auto first_second_subsegments =
2158 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2159 generate_and_discard_lower(power_of_10[16], blocks,
2160 cache_block_count);
2161
2162 // The first segment is of 8 digits, and the second segment is of
2163 // 2 ~ 8 digits.
2164 // ceil(2^(64+14)/10^8) = 3022314549036573
2165 // = floor(2^(64+14)*(10^8/(10^16 - 1)))
2166 const auto first_subsegment =
2167 static_cast<std::uint32_t>(umul128_upper64(first_second_subsegments,
2168 UINT64_C(3022314549036573)) >>
2169 14);
2170 const auto second_subsegment =
2171 static_cast<std::uint32_t>(first_second_subsegments) -
2172 UINT32_C(100000000) * first_subsegment;
2173
2174 // Print the first subsegment.
2175 print_8_digits(n: first_subsegment, buffer);
2176 buffer += 8;
2177
2178 // Print the second subsegment.
2179 // There are at least 2 digits in the second subsegment.
2180 auto prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
2181 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2182 buffer += 2;
2183 digits_in_the_second_segment -= 10;
2184
2185 for (; digits_in_the_second_segment > 1; digits_in_the_second_segment -= 2)
2186 {
2187 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2188 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2189 buffer += 2;
2190 }
2191
2192 if (digits_in_the_second_segment != 0)
2193 {
2194 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2195 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2196 ++buffer;
2197 }
2198 }
2199 } // digits_in_the_second_segment <= 16
2200 else
2201 {
2202 // The number of digits in the segment is in the range 17 ~ 22.
2203 const auto first_subsegment =
2204 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
2205 power_of_10[6], blocks, cache_block_count);
2206
2207 const auto second_third_subsegments =
2208 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2209 generate_and_discard_lower(power_of_10[16], blocks,
2210 cache_block_count);
2211
2212 // ceil(2^(64+14)/10^8) = 3022314549036573
2213 // = floor(2^(64+14)*(10^8/(10^16 - 1)))
2214 const auto second_subsegment =
2215 static_cast<std::uint32_t>(umul128_upper64(second_third_subsegments,
2216 UINT64_C(3022314549036573)) >>
2217 14);
2218 const auto third_subsegment = static_cast<std::uint32_t>(second_third_subsegments) -
2219 UINT32_C(100000000) * second_subsegment;
2220
2221 // Print the first subsegment (1 ~ 6 digits).
2222 std::uint64_t prod {};
2223 auto remaining_digits_in_the_current_subsegment =
2224 digits_in_the_second_segment - 16;
2225
2226 switch (remaining_digits_in_the_current_subsegment)
2227 {
2228 case 1:
2229 prod = first_subsegment * UINT64_C(429496730);
2230 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2231
2232 case 2:
2233 prod = first_subsegment * UINT64_C(42949673);
2234 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2235
2236 case 3:
2237 prod = first_subsegment * UINT64_C(4294968);
2238 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2239
2240 case 4:
2241 prod = first_subsegment * UINT64_C(429497);
2242 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2243
2244 case 5:
2245 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2246 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2247
2248 case 6:
2249 prod = first_subsegment * UINT64_C(429497);
2250 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2251 buffer += 2;
2252 remaining_digits_in_the_current_subsegment = 4;
2253 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2254
2255 default:
2256 BOOST_UNREACHABLE_RETURN(prod); // NOLINT
2257 }
2258
2259 second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining
2260 :
2261 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2262 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2263 ++buffer;
2264
2265 second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining
2266 :
2267 for (; remaining_digits_in_the_current_subsegment > 1;
2268 remaining_digits_in_the_current_subsegment -= 2)
2269 {
2270 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2271 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2272 buffer += 2;
2273 }
2274
2275 // Print the second and third subsegments (8 digits each).
2276 print_8_digits(n: second_subsegment, buffer);
2277 print_8_digits(n: third_subsegment, buffer: buffer + 8);
2278 buffer += 16;
2279 }
2280 } // remaining_digits > digits_in_the_second_segment
2281
2282 // Perform rounding and return.
2283 else
2284 {
2285 if (digits_in_the_second_segment <= 2)
2286 {
2287 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2288 power_of_10[19], blocks, cache_block_count);
2289
2290 // Get one more bit for potential rounding on the segment boundary.
2291 auto subsegment =
2292 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2293 generate_and_discard_lower(2000, blocks, cache_block_count);
2294
2295 bool segment_boundary_rounding_bit = ((subsegment & 1) != 0);
2296 subsegment >>= 1;
2297
2298 if (digits_in_the_second_segment == 2)
2299 {
2300 // Convert subsegment into fixed-point fractional form where the
2301 // integer part is of one digit. The integer part is ignored.
2302 // 42949673 = ceil(2^32/10^2)
2303 auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(42949673);
2304
2305 if (remaining_digits == 1)
2306 {
2307 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2308 current_digits = static_cast<std::uint32_t>(prod >> 32);
2309 const bool has_further_digits_v = has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
2310 if (check_rounding_condition_inside_subsegment(current_digits, fractional_part: static_cast<std::uint32_t>(prod), remaining_digits_in_the_current_subsegment: 1, has_further_digits: has_further_digits_v))
2311 {
2312 goto round_up_one_digit;
2313 }
2314 goto print_last_one_digit;
2315 }
2316
2317 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2318 const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2319
2320 if (remaining_digits == 0)
2321 {
2322 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2323 current_digits,
2324 uint_with_known_number_of_digits<2>{.value: next_digits},
2325 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2326 {
2327 goto round_up_two_digits;
2328 }
2329 goto print_last_two_digits;
2330 }
2331
2332 current_digits = next_digits;
2333 BOOST_CHARCONV_ASSERT(remaining_digits == 2);
2334 }
2335 else
2336 {
2337 BOOST_CHARCONV_ASSERT(digits_in_the_second_segment == 1);
2338 // Convert subsegment into fixed-point fractional form where the
2339 // integer part is of two digits. The integer part is ignored.
2340 // 429496730 = ceil(2^32/10^1)
2341 auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(429496730);
2342 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2343 const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2344
2345 if (remaining_digits == 0)
2346 {
2347 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2348 current_digits,
2349 uint_with_known_number_of_digits<1>{.value: next_digits},
2350 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2351 {
2352 goto round_up_two_digits;
2353 }
2354 goto print_last_two_digits;
2355 }
2356
2357 current_digits = next_digits;
2358 BOOST_CHARCONV_ASSERT(remaining_digits == 1);
2359 }
2360
2361 if (check_rounding_condition_with_next_bit(
2362 current_digits, segment_boundary_rounding_bit,
2363 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
2364 {
2365 goto round_up;
2366 }
2367
2368 goto print_last_digits;
2369 } // digits_in_the_second_segment <= 2
2370
2371 // When there are at most 9 digits in the segment.
2372 if (digits_in_the_second_segment <= 9)
2373 {
2374 // Throw away all overlapping digits.
2375 BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
2376
2377 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2378 compute_power(UINT64_C(10), exp: 22 - digits_in_the_second_segment),
2379 blocks, cache_block_count);
2380
2381 // Get one more bit for potential rounding on the segment boundary.
2382 auto segment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2383 generate_and_discard_lower(power_of_10[9] << 1, blocks,
2384 cache_block_count);
2385
2386 std::uint64_t prod;
2387 digits_in_the_second_segment -= remaining_digits;
2388
2389 if ((remaining_digits & 1) != 0)
2390 {
2391 prod = ((segment * UINT64_C(1441151881)) >> 26) + 1;
2392 current_digits = static_cast<std::uint32_t>(prod >> 32);
2393
2394 if (remaining_digits == 1)
2395 {
2396 goto second_segment22_at_most_9_digits_rounding;
2397 }
2398
2399 print_1_digit(n: current_digits, buffer);
2400 ++buffer;
2401 }
2402 else
2403 {
2404 prod = ((segment * UINT64_C(1801439851)) >> 23) + 1;
2405 const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2406
2407 if (remaining_digits == 0)
2408 {
2409 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2410 current_digits,
2411 uint_with_known_number_of_digits<2>{.value: next_digits}, [&] {
2412 return static_cast<std::uint32_t>(prod) >=
2413 (additional_static_data_holder::
2414 fractional_part_rounding_thresholds32[digits_in_the_second_segment - 1] & 0x7fffffff)
2415 || has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
2416 }))
2417 {
2418 goto round_up_two_digits;
2419 }
2420 goto print_last_two_digits;
2421 }
2422 else if (remaining_digits == 2)
2423 {
2424 current_digits = next_digits;
2425 goto second_segment22_at_most_9_digits_rounding;
2426 }
2427
2428 print_2_digits(n: next_digits, buffer);
2429 buffer += 2;
2430 }
2431
2432 BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2433
2434 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
2435 {
2436 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2437 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2438 buffer += 2;
2439 }
2440
2441 if (digits_in_the_second_segment != 0)
2442 {
2443 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2444 current_digits = static_cast<std::uint32_t>(prod >> 32);
2445 remaining_digits = 0;
2446
2447 second_segment22_at_most_9_digits_rounding:
2448 if (check_rounding_condition_inside_subsegment(
2449 current_digits, static_cast<std::uint32_t>(prod),
2450 digits_in_the_second_segment, has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1,
2451 uconst0)))
2452 {
2453 goto round_up;
2454 }
2455
2456 goto print_last_digits;
2457 }
2458 else
2459 {
2460 prod = static_cast<std::uint32_t>(prod) * UINT64_C(200);
2461 current_digits = static_cast<std::uint32_t>(prod >> 32);
2462 const auto segment_boundary_rounding_bit = (current_digits & 1) != 0;
2463 current_digits >>= 1;
2464
2465 if (check_rounding_condition_with_next_bit(
2466 current_digits, segment_boundary_rounding_bit,
2467 has_further_digits<0, 1, ExtendedCache>(significand, exp2_base, k, uconst0, uconst1)))
2468 {
2469 goto round_up_two_digits;
2470 }
2471 goto print_last_two_digits;
2472 }
2473 } // digits_in_the_second_segment <= 9
2474
2475 // first_second_subsegments is of 1 ~ 13 digits, and third_subsegment is
2476 // of 9 digits.
2477 // Get one more bit for potential rounding condition check.
2478 auto first_second_subsegments =
2479 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
2480 power_of_10[13] << 1, blocks, cache_block_count);
2481
2482 bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
2483 first_second_subsegments >>= 1;
2484
2485 // Compilers are not aware of how to leverage the maximum value of
2486 // first_second_subsegments to find out a better magic number which
2487 // allows us to eliminate an additional shift.
2488 // 1844674407371 = ceil(2^64/10^7) = floor(2^64*(10^6/(10^13 - 1))).
2489 const auto first_subsegment =
2490 static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(
2491 x: first_second_subsegments, y: 1844674407371));
2492
2493 const auto second_subsegment =
2494 static_cast<std::uint32_t>(first_second_subsegments) - 10000000 * first_subsegment;
2495
2496 int digits_in_the_second_subsegment;
2497
2498 // Print the first subsegment (0 ~ 6 digits) if exists.
2499 if (digits_in_the_second_segment > 16)
2500 {
2501 std::uint64_t prod;
2502 int remaining_digits_in_the_current_subsegment = digits_in_the_second_segment - 16;
2503
2504 // No rounding, continue.
2505 if (remaining_digits > remaining_digits_in_the_current_subsegment)
2506 {
2507 remaining_digits -= remaining_digits_in_the_current_subsegment;
2508
2509 // There is no overlap in the second subsegment.
2510 digits_in_the_second_subsegment = 7;
2511
2512 // When there is no overlapping digit.
2513 if (remaining_digits_in_the_current_subsegment == 6)
2514 {
2515 prod = (first_subsegment * UINT64_C(429497)) + 1;
2516 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2517 buffer += 2;
2518 remaining_digits_in_the_current_subsegment -= 2;
2519 }
2520 // If there are overlapping digits, move all overlapping digits
2521 // into the integer part.
2522 else
2523 {
2524 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2525 prod *= compute_power(UINT64_C(10), exp: 5 - remaining_digits_in_the_current_subsegment);
2526
2527 if ((remaining_digits_in_the_current_subsegment & 1) != 0)
2528 {
2529 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2530 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2531 ++buffer;
2532 }
2533 }
2534
2535 for (; remaining_digits_in_the_current_subsegment > 1; remaining_digits_in_the_current_subsegment -= 2)
2536 {
2537 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2538 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2539 buffer += 2;
2540 }
2541 }
2542 // The first subsegment is the last subsegment to print.
2543 else
2544 {
2545 if ((remaining_digits & 1) != 0)
2546 {
2547 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2548
2549 // If there are overlapping digits, move all overlapping digits
2550 // into the integer part and then get the next digit.
2551 if (remaining_digits_in_the_current_subsegment < 6)
2552 {
2553 prod *= compute_power(UINT64_C(10), exp: 5 - remaining_digits_in_the_current_subsegment);
2554 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2555 }
2556 current_digits = static_cast<std::uint32_t>(prod >> 32);
2557 remaining_digits_in_the_current_subsegment -= remaining_digits;
2558
2559 if (remaining_digits == 1)
2560 {
2561 goto second_segment22_more_than_9_digits_first_subsegment_rounding;
2562 }
2563
2564 print_1_digit(n: current_digits, buffer);
2565 ++buffer;
2566 }
2567 else
2568 {
2569 // When there is no overlapping digit.
2570 if (remaining_digits_in_the_current_subsegment == 6)
2571 {
2572 if (remaining_digits == 0)
2573 {
2574 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2575 current_digits,
2576 uint_with_known_number_of_digits<6>{
2577 .value: first_subsegment},
2578 has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
2579 {
2580 goto round_up_two_digits;
2581 }
2582 goto print_last_two_digits;
2583 }
2584
2585 prod = (first_subsegment * UINT64_C(429497)) + 1;
2586 }
2587 // Otherwise, convert the subsegment into a fixed-point
2588 // fraction form, move all overlapping digits into the
2589 // integer part, and then extract the next two digits.
2590 else
2591 {
2592 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2593 prod *= compute_power(UINT64_C(10), exp: 5 - remaining_digits_in_the_current_subsegment);
2594
2595 if (remaining_digits == 0)
2596 {
2597 goto second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment;
2598 }
2599
2600 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2601 }
2602 current_digits = static_cast<std::uint32_t>(prod >> 32);
2603 remaining_digits_in_the_current_subsegment -= remaining_digits;
2604
2605 if (remaining_digits == 2)
2606 {
2607 goto second_segment22_more_than_9_digits_first_subsegment_rounding;
2608 }
2609
2610 print_2_digits(n: current_digits, buffer);
2611 buffer += 2;
2612 }
2613
2614 BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2615
2616 if (remaining_digits > 4)
2617 {
2618 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2619 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2620 buffer += 2;
2621 }
2622
2623 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2624 current_digits = static_cast<std::uint32_t>(prod >> 32);
2625 remaining_digits = 0;
2626
2627 second_segment22_more_than_9_digits_first_subsegment_rounding:
2628 if (remaining_digits_in_the_current_subsegment == 0)
2629 {
2630 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2631 current_digits,
2632 uint_with_known_number_of_digits<7>{.value: second_subsegment},
2633 has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
2634 {
2635 goto round_up;
2636 }
2637 }
2638 else
2639 {
2640 second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment
2641 :
2642 if (check_rounding_condition_inside_subsegment(
2643 current_digits, static_cast<std::uint32_t>(prod),
2644 remaining_digits_in_the_current_subsegment,
2645 has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
2646 {
2647 goto round_up;
2648 }
2649 }
2650 goto print_last_digits;
2651 }
2652 }
2653 else
2654 {
2655 digits_in_the_second_subsegment = digits_in_the_second_segment - 9;
2656 }
2657
2658 // Print the second subsegment (1 ~ 7 digits).
2659 {
2660 // No rounding, continue.
2661 if (remaining_digits > digits_in_the_second_subsegment)
2662 {
2663 auto prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2664 remaining_digits -= digits_in_the_second_subsegment;
2665
2666 // When there is no overlapping digit.
2667 if (digits_in_the_second_subsegment == 7)
2668 {
2669 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2670 ++buffer;
2671 }
2672 // If there are overlapping digits, move all overlapping digits
2673 // into the integer part.
2674 else
2675 {
2676 prod *= compute_power(UINT64_C(10),
2677 exp: 6 - digits_in_the_second_subsegment);
2678
2679 if ((digits_in_the_second_subsegment & 1) != 0)
2680 {
2681 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2682 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2683 ++buffer;
2684 }
2685 }
2686
2687 for (; digits_in_the_second_subsegment > 1; digits_in_the_second_subsegment -= 2)
2688 {
2689 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2690 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2691 buffer += 2;
2692 }
2693 }
2694 // The second subsegment is the last subsegment to print.
2695 else
2696 {
2697 std::uint64_t prod;
2698
2699 if ((remaining_digits & 1) != 0)
2700 {
2701 prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2702
2703 // If there are overlapping digits, move all overlapping digits
2704 // into the integer part and then get the next digit.
2705 if (digits_in_the_second_subsegment < 7)
2706 {
2707 prod *= compute_power(UINT64_C(10), exp: 6 - digits_in_the_second_subsegment);
2708 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2709 }
2710 current_digits = static_cast<std::uint32_t>(prod >> 32);
2711 digits_in_the_second_subsegment -= remaining_digits;
2712
2713 if (remaining_digits == 1)
2714 {
2715 goto second_segment22_more_than_9_digits_second_subsegment_rounding;
2716 }
2717
2718 print_1_digit(n: current_digits, buffer);
2719 ++buffer;
2720 }
2721 else
2722 {
2723 // When there is no overlapping digit.
2724 if (digits_in_the_second_subsegment == 7)
2725 {
2726 if (remaining_digits == 0)
2727 {
2728 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2729 current_digits,
2730 uint_with_known_number_of_digits<7>{
2731 .value: second_subsegment},
2732 has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
2733 {
2734 goto round_up_two_digits;
2735 }
2736 goto print_last_two_digits;
2737 }
2738
2739 prod = ((second_subsegment * UINT64_C(10995117)) >> 8) + 1;
2740 }
2741 // Otherwise, convert the subsegment into a fixed-point
2742 // fraction form, move all overlapping digits into the
2743 // integer part, and then extract the next two digits.
2744 else
2745 {
2746 prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2747 prod *= compute_power(UINT64_C(10), exp: 6 - digits_in_the_second_subsegment);
2748
2749 if (remaining_digits == 0)
2750 {
2751 goto second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment;
2752 }
2753
2754 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2755 }
2756 current_digits = static_cast<std::uint32_t>(prod >> 32);
2757 digits_in_the_second_subsegment -= remaining_digits;
2758
2759 if (remaining_digits == 2)
2760 {
2761 goto second_segment22_more_than_9_digits_second_subsegment_rounding;
2762 }
2763
2764 print_2_digits(n: current_digits, buffer);
2765 buffer += 2;
2766 }
2767
2768 BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2769
2770 if (remaining_digits > 4)
2771 {
2772 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2773 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2774 buffer += 2;
2775 }
2776
2777 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2778 current_digits = static_cast<std::uint32_t>(prod >> 32);
2779 remaining_digits = 0;
2780
2781 second_segment22_more_than_9_digits_second_subsegment_rounding:
2782 if (digits_in_the_second_subsegment == 0)
2783 {
2784 if (check_rounding_condition_with_next_bit(
2785 current_digits, first_bit_of_third_subsegment,
2786 has_further_digits<0, 9, ExtendedCache>(significand, exp2_base, k, uconst0, uconst9)))
2787 {
2788 goto round_up;
2789 }
2790 }
2791 else
2792 {
2793 second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment
2794 :
2795 if (check_rounding_condition_inside_subsegment(
2796 current_digits, static_cast<std::uint32_t>(prod),
2797 digits_in_the_second_subsegment, has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k,
2798 uconst1, uconst9)))
2799 {
2800 goto round_up;
2801 }
2802 }
2803 goto print_last_digits;
2804 }
2805 }
2806
2807 // Print the third subsegment (9 digits).
2808 {
2809 // Get one more bit if we need to check rounding conditions on
2810 // the segment boundary. We already have shifted by 1-bit in the
2811 // computation of first & second subsegments, so here we don't
2812 // shift the multiplier.
2813 auto third_subsegment =
2814 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2815 generate_and_discard_lower(power_of_10[9], blocks,
2816 cache_block_count);
2817
2818 bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
2819 third_subsegment >>= 1;
2820 third_subsegment += (first_bit_of_third_subsegment ? 500000000 : 0);
2821
2822 std::uint64_t prod;
2823 if ((remaining_digits & 1) != 0)
2824 {
2825 prod = ((third_subsegment * UINT64_C(720575941)) >> 24) + 1;
2826 current_digits = static_cast<std::uint32_t>(prod >> 32);
2827
2828 if (remaining_digits == 1)
2829 {
2830 if (check_rounding_condition_inside_subsegment(
2831 current_digits, static_cast<std::uint32_t>(prod), 8,
2832 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2833 {
2834 goto round_up_one_digit;
2835 }
2836 goto print_last_one_digit;
2837 }
2838
2839 print_1_digit(n: current_digits, buffer);
2840 ++buffer;
2841 }
2842 else
2843 {
2844 prod = ((third_subsegment * UINT64_C(450359963)) >> 20) + 1;
2845 current_digits = static_cast<std::uint32_t>(prod >> 32);
2846
2847 if (remaining_digits == 2)
2848 {
2849 goto second_segment22_more_than_9_digits_third_subsegment_rounding;
2850 }
2851
2852 print_2_digits(n: current_digits, buffer);
2853 buffer += 2;
2854 }
2855
2856 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
2857 {
2858 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2859 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2860 buffer += 2;
2861 }
2862
2863 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2864 current_digits = static_cast<std::uint32_t>(prod >> 32);
2865
2866 if (remaining_digits < 9)
2867 {
2868 second_segment22_more_than_9_digits_third_subsegment_rounding:
2869 if (check_rounding_condition_inside_subsegment(
2870 current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
2871 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2872 {
2873 goto round_up_two_digits;
2874 }
2875 }
2876 else
2877 {
2878 if (check_rounding_condition_with_next_bit(
2879 current_digits, segment_boundary_rounding_bit,
2880 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
2881 {
2882 goto round_up_two_digits;
2883 }
2884 }
2885 goto print_last_two_digits;
2886 }
2887 }
2888 } // ExtendedCache::segment_length == 22
2889
2890 else BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 252)
2891 {
2892 int overlapping_digits = 252 - digits_in_the_second_segment;
2893 int remaining_subsegment_pairs = 14;
2894
2895 while (overlapping_digits >= 18)
2896 {
2897 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2898 power_of_10[18], blocks, cache_block_count);
2899 --remaining_subsegment_pairs;
2900 overlapping_digits -= 18;
2901 }
2902
2903 auto subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18] << 1, blocks, cache_block_count);
2904 auto subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
2905 subsegment_pair >>= 1;
2906
2907 // Deal with the first subsegment pair.
2908 {
2909 // Divide it into two 9-digits subsegments.
2910 const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
2911 const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
2912
2913 auto print_subsegment = [&](std::uint32_t subsegment, int digits_in_the_subsegment)
2914 {
2915 remaining_digits -= digits_in_the_subsegment;
2916
2917 // Move all overlapping digits into the integer part.
2918 auto prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
2919 if (digits_in_the_subsegment < 9)
2920 {
2921 prod *= compute_power(UINT32_C(10), exp: 8 - digits_in_the_subsegment);
2922
2923 if ((digits_in_the_subsegment & 1) != 0)
2924 {
2925 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2926 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2927 ++buffer;
2928 }
2929 }
2930 else
2931 {
2932 print_1_digit(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2933 ++buffer;
2934 }
2935
2936 for (; digits_in_the_subsegment > 1; digits_in_the_subsegment -= 2)
2937 {
2938 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2939 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
2940 buffer += 2;
2941 }
2942 };
2943
2944 // When the first part is not completely overlapping with the first segment.
2945 int digits_in_the_second_part;
2946 if (overlapping_digits < 9)
2947 {
2948 int digits_in_the_first_part = 9 - overlapping_digits;
2949
2950 // No rounding, continue.
2951 if (remaining_digits > digits_in_the_first_part)
2952 {
2953 digits_in_the_second_part = 9;
2954 print_subsegment(first_part, digits_in_the_first_part);
2955 }
2956 // Perform rounding and return.
2957 else
2958 {
2959 // When there is no overlapping digit.
2960 std::uint64_t prod;
2961 if (digits_in_the_first_part == 9)
2962 {
2963 if ((remaining_digits & 1) != 0)
2964 {
2965 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
2966 }
2967 else
2968 {
2969 if (remaining_digits == 0)
2970 {
2971 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2972 current_digits,
2973 uint_with_known_number_of_digits<9>{.value: first_part},
2974 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
2975 {
2976 goto round_up_two_digits;
2977 }
2978 goto print_last_two_digits;
2979 }
2980
2981 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
2982 }
2983 }
2984 else
2985 {
2986 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
2987 prod *= compute_power(UINT32_C(10), exp: 8 - digits_in_the_first_part);
2988
2989 if ((remaining_digits & 1) != 0)
2990 {
2991 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2992 }
2993 else
2994 {
2995 if (remaining_digits == 0)
2996 {
2997 goto second_segment252_first_subsegment_rounding_inside_subsegment;
2998 }
2999
3000 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3001 }
3002 }
3003 digits_in_the_first_part -= remaining_digits;
3004 current_digits = static_cast<std::uint32_t>(prod >> 32);
3005
3006 if (remaining_digits > 2)
3007 {
3008 if ((remaining_digits & 1) != 0)
3009 {
3010 print_1_digit(n: current_digits, buffer);
3011 ++buffer;
3012 }
3013 else
3014 {
3015 print_2_digits(n: current_digits, buffer);
3016 buffer += 2;
3017 }
3018
3019 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3020 {
3021 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3022 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3023 buffer += 2;
3024 }
3025
3026 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3027 current_digits = static_cast<std::uint32_t>(prod >> 32);
3028 remaining_digits = 0;
3029 }
3030
3031 if (digits_in_the_first_part != 0)
3032 {
3033 second_segment252_first_subsegment_rounding_inside_subsegment:
3034 if (check_rounding_condition_inside_subsegment(
3035 current_digits, static_cast<std::uint32_t>(prod),
3036 digits_in_the_first_part, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3037 {
3038 goto round_up;
3039 }
3040 }
3041 else
3042 {
3043 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3044 current_digits,
3045 uint_with_known_number_of_digits<9>{.value: static_cast<std::uint32_t>(second_part)},
3046 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3047 {
3048 goto round_up;
3049 }
3050 }
3051 goto print_last_digits;
3052 }
3053 }
3054 else
3055 {
3056 digits_in_the_second_part = 18 - overlapping_digits;
3057 }
3058
3059 // Print the second part.
3060 // No rounding, continue.
3061 if (remaining_digits > digits_in_the_second_part)
3062 {
3063 print_subsegment(second_part, digits_in_the_second_part);
3064 }
3065 // Perform rounding and return.
3066 else
3067 {
3068 // When there is no overlapping digit.
3069 std::uint64_t prod;
3070 if (digits_in_the_second_part == 9)
3071 {
3072 if ((remaining_digits & 1) != 0)
3073 {
3074 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3075 }
3076 else
3077 {
3078 if (remaining_digits == 0)
3079 {
3080 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3081 current_digits,
3082 uint_with_known_number_of_digits<9>{.value: static_cast<std::uint32_t>(second_part)},
3083 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3084 {
3085 goto round_up_two_digits;
3086 }
3087 goto print_last_two_digits;
3088 }
3089
3090 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3091 }
3092 }
3093 else
3094 {
3095 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3096 prod *= compute_power(UINT32_C(10), exp: 8 - digits_in_the_second_part);
3097
3098 if ((remaining_digits & 1) != 0)
3099 {
3100 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
3101 }
3102 else
3103 {
3104 if (remaining_digits == 0)
3105 {
3106 goto second_segment252_second_subsegment_rounding_inside_subsegment;
3107 }
3108
3109 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3110 }
3111 }
3112 digits_in_the_second_part -= remaining_digits;
3113 current_digits = static_cast<std::uint32_t>(prod >> 32);
3114
3115 if (remaining_digits > 2)
3116 {
3117 if ((remaining_digits & 1) != 0)
3118 {
3119 print_1_digit(n: current_digits, buffer);
3120 ++buffer;
3121 }
3122 else
3123 {
3124 print_2_digits(n: current_digits, buffer);
3125 buffer += 2;
3126 }
3127
3128 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3129 {
3130 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3131 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3132 buffer += 2;
3133 }
3134
3135 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3136 current_digits = static_cast<std::uint32_t>(prod >> 32);
3137 remaining_digits = 0;
3138 }
3139
3140 if (digits_in_the_second_part != 0)
3141 {
3142 second_segment252_second_subsegment_rounding_inside_subsegment:
3143 if (check_rounding_condition_inside_subsegment(
3144 current_digits, static_cast<std::uint32_t>(prod),
3145 digits_in_the_second_part, compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3146 {
3147 goto round_up;
3148 }
3149 }
3150 else
3151 {
3152 if (check_rounding_condition_with_next_bit(
3153 current_digits, subsegment_boundary_rounding_bit,
3154 compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3155 {
3156 goto round_up;
3157 }
3158 }
3159 goto print_last_digits;
3160 }
3161 }
3162
3163 // Remaining subsegment pairs do not have overlapping digits.
3164 --remaining_subsegment_pairs;
3165 for (; remaining_subsegment_pairs > 0; --remaining_subsegment_pairs)
3166 {
3167 subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
3168
3169 subsegment_pair += (subsegment_boundary_rounding_bit ? power_of_10[18] : 0);
3170 subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
3171 subsegment_pair >>= 1;
3172
3173 const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
3174 const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
3175
3176 // The first part can be printed without rounding.
3177 if (remaining_digits > 9)
3178 {
3179 print_9_digits(n: first_part, buffer);
3180
3181 // The second part also can be printed without rounding.
3182 if (remaining_digits > 18)
3183 {
3184 print_9_digits(n: second_part, buffer: buffer + 9);
3185 }
3186 // Otherwise, perform rounding and return.
3187 else
3188 {
3189 buffer += 9;
3190 remaining_digits -= 9;
3191
3192 std::uint64_t prod;
3193 int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
3194
3195 if ((remaining_digits & 1) != 0)
3196 {
3197 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3198 current_digits = static_cast<std::uint32_t>(prod >> 32);
3199
3200 if (remaining_digits == 1)
3201 {
3202 goto second_segment252_loop_second_subsegment_rounding;
3203 }
3204
3205 print_1_digit(n: current_digits, buffer);
3206 ++buffer;
3207 }
3208 else
3209 {
3210 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3211 current_digits = static_cast<std::uint32_t>(prod >> 32);
3212
3213 if (remaining_digits == 2)
3214 {
3215 goto second_segment252_loop_second_subsegment_rounding;
3216 }
3217
3218 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3219 buffer += 2;
3220 }
3221
3222 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3223 {
3224 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3225 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3226 buffer += 2;
3227 }
3228
3229 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3230 current_digits = static_cast<std::uint32_t>(prod >> 32);
3231 remaining_digits = 0;
3232
3233 if (remaining_digits_in_the_current_subsegment != 0)
3234 {
3235 second_segment252_loop_second_subsegment_rounding:
3236 if (check_rounding_condition_inside_subsegment(
3237 current_digits, static_cast<std::uint32_t>(prod),
3238 remaining_digits_in_the_current_subsegment,
3239 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3240 {
3241 goto round_up;
3242 }
3243 goto print_last_digits;
3244 }
3245 else
3246 {
3247 if (check_rounding_condition_with_next_bit(
3248 current_digits, subsegment_boundary_rounding_bit,
3249 compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3250 {
3251 goto round_up_two_digits;
3252 }
3253 goto print_last_two_digits;
3254 }
3255 }
3256 }
3257 // Otherwise, perform rounding and return.
3258 else
3259 {
3260 std::uint64_t prod;
3261 int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
3262 if ((remaining_digits & 1) != 0)
3263 {
3264 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
3265 current_digits = static_cast<std::uint32_t>(prod >> 32);
3266
3267 if (remaining_digits == 1)
3268 {
3269 goto second_segment252_loop_first_subsegment_rounding;
3270 }
3271
3272 print_1_digit(n: current_digits, buffer);
3273 ++buffer;
3274 }
3275 else
3276 {
3277 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
3278 current_digits = static_cast<std::uint32_t>(prod >> 32);
3279
3280 if (remaining_digits == 2)
3281 {
3282 goto second_segment252_loop_first_subsegment_rounding;
3283 }
3284
3285 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3286 buffer += 2;
3287 }
3288
3289 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3290 {
3291 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3292 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3293 buffer += 2;
3294 }
3295
3296 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3297 current_digits = static_cast<std::uint32_t>(prod >> 32);
3298 remaining_digits = 0;
3299
3300 if (remaining_digits_in_the_current_subsegment != 0)
3301 {
3302 second_segment252_loop_first_subsegment_rounding:
3303 if (check_rounding_condition_inside_subsegment(
3304 current_digits, static_cast<std::uint32_t>(prod),
3305 remaining_digits_in_the_current_subsegment,
3306 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3307 {
3308 goto round_up;
3309 }
3310 goto print_last_digits;
3311 }
3312 else
3313 {
3314 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3315 current_digits,
3316 uint_with_known_number_of_digits<9>{.value: static_cast<std::uint32_t>(second_part)},
3317 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3318 {
3319 goto round_up_two_digits;
3320 }
3321 goto print_last_two_digits;
3322 }
3323 }
3324
3325 buffer += 18;
3326 remaining_digits -= 18;
3327 }
3328 } // ExtendedCache::segment_length == 252
3329 }
3330
3331 // Print all remaining segments.
3332 while (has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))
3333 {
3334 // Get new segment.
3335 ++multiplier_index;
3336 k += ExtendedCache::segment_length;
3337
3338 cache_block_count = load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(blocks, e, k, multiplier_index);
3339
3340 // Compute nm mod 2^Q.
3341 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
3342
3343 BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
3344 {
3345 // When at least two subsegments left.
3346 if (remaining_digits > 16)
3347 {
3348 std::uint64_t first_second_subsegments = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[16], blocks, cache_block_count);
3349
3350 const auto first_subsegment =
3351 static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(x: first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
3352
3353 const std::uint32_t second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
3354
3355 print_8_digits(n: first_subsegment, buffer);
3356 print_8_digits(n: second_subsegment, buffer: buffer + 8);
3357
3358 // When more segments left.
3359 if (remaining_digits > 22)
3360 {
3361 const auto third_subsegment = static_cast<std::uint32_t>(
3362 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate_and_discard_lower(power_of_10[6], blocks,cache_block_count));
3363
3364 print_6_digits(n: third_subsegment, buffer: buffer + 16);
3365 buffer += 22;
3366 remaining_digits -= 22;
3367 }
3368 // When this is the last segment.
3369 else
3370 {
3371 buffer += 16;
3372 remaining_digits -= 16;
3373
3374 auto third_subsegment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3375 generate_and_discard_lower(power_of_10[6] << 1, blocks, cache_block_count);
3376
3377 bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
3378 third_subsegment >>= 1;
3379
3380 std::uint64_t prod;
3381 if ((remaining_digits & 1) != 0)
3382 {
3383 prod = ((third_subsegment * UINT64_C(687195)) >> 4) + 1;
3384 current_digits = static_cast<std::uint32_t>(prod >> 32);
3385
3386 if (remaining_digits == 1)
3387 {
3388 if (check_rounding_condition_inside_subsegment(
3389 current_digits, static_cast<std::uint32_t>(prod), 5,
3390 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
3391 {
3392 goto round_up_one_digit;
3393 }
3394 goto print_last_one_digit;
3395 }
3396
3397 print_1_digit(n: current_digits, buffer);
3398 ++buffer;
3399 }
3400 else
3401 {
3402 prod = (third_subsegment * UINT64_C(429497)) + 1;
3403 current_digits = static_cast<std::uint32_t>(prod >> 32);
3404
3405 if (remaining_digits == 2)
3406 {
3407 goto segment_loop22_more_than_16_digits_rounding;
3408 }
3409
3410 print_2_digits(n: current_digits, buffer);
3411 buffer += 2;
3412 }
3413
3414 if (remaining_digits > 4)
3415 {
3416 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3417 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3418 buffer += 2;
3419
3420 if (remaining_digits == 6)
3421 {
3422 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3423 current_digits = static_cast<std::uint32_t>(prod >> 32);
3424
3425 if (check_rounding_condition_with_next_bit(
3426 current_digits, segment_boundary_rounding_bit,
3427 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
3428 {
3429 goto round_up_two_digits;
3430 }
3431 goto print_last_two_digits;
3432 }
3433 }
3434
3435 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3436 current_digits = static_cast<std::uint32_t>(prod >> 32);
3437
3438 segment_loop22_more_than_16_digits_rounding:
3439 if (check_rounding_condition_inside_subsegment(
3440 current_digits, static_cast<std::uint32_t>(prod), 6 - remaining_digits,
3441 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
3442 {
3443 goto round_up_two_digits;
3444 }
3445 goto print_last_two_digits;
3446 }
3447 }
3448 // When two subsegments left.
3449 else if (remaining_digits > 8)
3450 {
3451 // Get one more bit for potential rounding conditions check.
3452 auto first_second_subsegments =
3453 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3454 generate_and_discard_lower(power_of_10[16] << 1, blocks, cache_block_count);
3455
3456 bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
3457 first_second_subsegments >>= 1;
3458
3459 // 3022314549036573 = ceil(2^78/10^8) = floor(2^78*(10^8/(10^16 -
3460 // 1))).
3461 const auto first_subsegment =
3462 static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(x: first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
3463
3464 const auto second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
3465
3466 print_8_digits(n: first_subsegment, buffer);
3467 buffer += 8;
3468 remaining_digits -= 8;
3469
3470 // Second subsegment (8 digits).
3471 std::uint64_t prod;
3472 if ((remaining_digits & 1) != 0)
3473 {
3474 prod = ((second_subsegment * UINT64_C(112589991)) >> 18) + 1;
3475 current_digits = static_cast<std::uint32_t>(prod >> 32);
3476
3477 if (remaining_digits == 1)
3478 {
3479 if (check_rounding_condition_inside_subsegment(
3480 current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k,
3481 uconst1, uconst6)))
3482 {
3483 goto round_up_one_digit;
3484 }
3485 goto print_last_one_digit;
3486 }
3487
3488 print_1_digit(n: current_digits, buffer);
3489 ++buffer;
3490 }
3491 else
3492 {
3493 prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
3494 current_digits = static_cast<std::uint32_t>(prod >> 32);
3495
3496 if (remaining_digits == 2)
3497 {
3498 goto segment_loop22_more_than_8_digits_rounding;
3499 }
3500
3501 print_2_digits(n: current_digits, buffer);
3502 buffer += 2;
3503 }
3504
3505 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3506 {
3507 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3508 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3509 buffer += 2;
3510 }
3511
3512 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3513 current_digits = static_cast<std::uint32_t>(prod >> 32);
3514
3515 if (remaining_digits < 8)
3516 {
3517 segment_loop22_more_than_8_digits_rounding:
3518 if (check_rounding_condition_inside_subsegment(
3519 current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
3520 has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k, uconst1, uconst6)))
3521 {
3522 goto round_up_two_digits;
3523 }
3524 }
3525 else {
3526 if (check_rounding_condition_with_next_bit(
3527 current_digits, first_bit_of_third_subsegment,
3528 has_further_digits<0, 6, ExtendedCache>(significand, exp2_base, k, uconst0, uconst6)))
3529 {
3530 goto round_up_two_digits;
3531 }
3532 }
3533 goto print_last_two_digits;
3534 }
3535 // remaining_digits is at most 8.
3536 else
3537 {
3538 // Get one more bit for potential rounding conditions check.
3539 auto first_subsegment =
3540 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3541 generate_and_discard_lower(power_of_10[8] << 1, blocks, cache_block_count);
3542
3543 bool first_bit_of_second_subsegment = ((first_subsegment & 1) != 0);
3544 first_subsegment >>= 1;
3545
3546 std::uint64_t prod;
3547 if ((remaining_digits & 1) != 0)
3548 {
3549 prod = ((first_subsegment * UINT64_C(112589991)) >> 18) + 1;
3550 current_digits = static_cast<std::uint32_t>(prod >> 32);
3551
3552 if (remaining_digits == 1)
3553 {
3554 if (check_rounding_condition_inside_subsegment(
3555 current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k,
3556 uconst1, uconst14)))
3557 {
3558 goto round_up_one_digit;
3559 }
3560 goto print_last_one_digit;
3561 }
3562
3563 print_1_digit(n: current_digits, buffer);
3564 ++buffer;
3565 }
3566 else
3567 {
3568 prod = ((first_subsegment * UINT64_C(140737489)) >> 15) + 1;
3569 current_digits = static_cast<std::uint32_t>(prod >> 32);
3570
3571 if (remaining_digits == 2)
3572 {
3573 goto segment_loop22_at_most_8_digits_rounding;
3574 }
3575
3576 print_2_digits(n: current_digits, buffer);
3577 buffer += 2;
3578 }
3579
3580 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3581 {
3582 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3583 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3584 buffer += 2;
3585 }
3586
3587 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3588 current_digits = static_cast<std::uint32_t>(prod >> 32);
3589
3590 if (remaining_digits < 8)
3591 {
3592 segment_loop22_at_most_8_digits_rounding:
3593 if (check_rounding_condition_inside_subsegment(
3594 current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
3595 has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k, uconst1, uconst14)))
3596 {
3597 goto round_up_two_digits;
3598 }
3599 }
3600 else
3601 {
3602 if (check_rounding_condition_with_next_bit(
3603 current_digits, first_bit_of_second_subsegment,
3604 has_further_digits<0, 14, ExtendedCache>(significand, exp2_base, k, uconst0, uconst14)))
3605 {
3606 goto round_up_two_digits;
3607 }
3608 }
3609 goto print_last_two_digits;
3610 }
3611 } // ExtendedCache::segment_length == 22
3612 else if (ExtendedCache::segment_length == 252)
3613 {
3614 // Print as many 18-digits subsegment pairs as possible.
3615 for (int remaining_subsegment_pairs = 14; remaining_subsegment_pairs > 0;
3616 --remaining_subsegment_pairs)
3617 {
3618 // No rounding, continue.
3619 if (remaining_digits > 18)
3620 {
3621 const auto subsegment_pair =
3622 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
3623
3624 const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
3625 const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
3626
3627 print_9_digits(n: first_part, buffer);
3628 print_9_digits(n: second_part, buffer: buffer + 9);
3629 buffer += 18;
3630 remaining_digits -= 18;
3631 }
3632 // Final subsegment pair.
3633 else
3634 {
3635 auto last_subsegment_pair =
3636 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3637 generate_and_discard_lower(power_of_10[18] << 1, blocks, cache_block_count);
3638
3639 const bool subsegment_boundary_rounding_bit = ((last_subsegment_pair & 1) != 0);
3640 last_subsegment_pair >>= 1;
3641
3642 const auto first_part = static_cast<std::uint32_t>(last_subsegment_pair / power_of_10[9]);
3643 const auto second_part = static_cast<std::uint32_t>(last_subsegment_pair) - power_of_10[9] * first_part;
3644
3645 if (remaining_digits <= 9)
3646 {
3647 std::uint64_t prod;
3648
3649 if ((remaining_digits & 1) != 0)
3650 {
3651 prod = ((first_part * UINT64_C(1441151881)) >> 25) + 1;
3652 current_digits = static_cast<std::uint32_t>(prod >> 32);
3653
3654 if (remaining_digits == 1)
3655 {
3656 if (check_rounding_condition_inside_subsegment(
3657 current_digits, static_cast<std::uint32_t>(prod), 8,
3658 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3659 {
3660 goto round_up_one_digit;
3661 }
3662 goto print_last_one_digit;
3663 }
3664
3665 print_1_digit(n: current_digits, buffer);
3666 ++buffer;
3667 }
3668 else
3669 {
3670 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
3671 current_digits = static_cast<std::uint32_t>(prod >> 32);
3672
3673 if (remaining_digits == 2)
3674 {
3675 goto segment_loop252_final18_first_part_rounding;
3676 }
3677
3678 print_2_digits(n: current_digits, buffer);
3679 buffer += 2;
3680 }
3681
3682 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3683 {
3684 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3685 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3686 buffer += 2;
3687 }
3688
3689 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3690 current_digits = static_cast<std::uint32_t>(prod >> 32);
3691
3692 if (remaining_digits < 9)
3693 {
3694 segment_loop252_final18_first_part_rounding:
3695 if (check_rounding_condition_inside_subsegment(
3696 current_digits, static_cast<std::uint32_t>(prod),
3697 9 - remaining_digits, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3698 {
3699 goto round_up_two_digits;
3700 }
3701 }
3702 else
3703 {
3704 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3705 current_digits,
3706 uint_with_known_number_of_digits<9>{.value: static_cast<std::uint32_t>(second_part)},
3707 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3708 {
3709 goto round_up_two_digits;
3710 }
3711 }
3712 goto print_last_two_digits;
3713 } // remaining_digits <= 9
3714
3715 print_9_digits(n: first_part, buffer);
3716 buffer += 9;
3717 remaining_digits -= 9;
3718
3719 std::uint64_t prod;
3720
3721 if ((remaining_digits & 1) != 0)
3722 {
3723 prod = ((second_part * UINT64_C(1441151881)) >> 25) + 1;
3724 current_digits = static_cast<std::uint32_t>(prod >> 32);
3725
3726 if (remaining_digits == 1)
3727 {
3728 if (check_rounding_condition_inside_subsegment(
3729 current_digits, static_cast<std::uint32_t>(prod), 8,
3730 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3731 {
3732 goto round_up_one_digit;
3733 }
3734 goto print_last_one_digit;
3735 }
3736
3737 print_1_digit(n: current_digits, buffer);
3738 ++buffer;
3739 }
3740 else
3741 {
3742 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3743 current_digits = static_cast<std::uint32_t>(prod >> 32);
3744
3745 if (remaining_digits == 2)
3746 {
3747 goto segment_loop252_final18_second_part_rounding;
3748 }
3749
3750 print_2_digits(n: current_digits, buffer);
3751 buffer += 2;
3752 }
3753
3754 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3755 {
3756 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3757 print_2_digits(n: static_cast<std::uint32_t>(prod >> 32), buffer);
3758 buffer += 2;
3759 }
3760
3761 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3762 current_digits = static_cast<std::uint32_t>(prod >> 32);
3763
3764 if (remaining_digits < 9)
3765 {
3766 segment_loop252_final18_second_part_rounding:
3767 if (check_rounding_condition_inside_subsegment(
3768 current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
3769 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3770 {
3771 goto round_up_two_digits;
3772 }
3773 }
3774 else
3775 {
3776 if (check_rounding_condition_with_next_bit(
3777 current_digits, subsegment_boundary_rounding_bit,
3778 compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3779 {
3780 goto round_up_two_digits;
3781 }
3782 }
3783 goto print_last_two_digits;
3784 }
3785 }
3786 } // if (ExtendedCache::segment_length == 252)
3787 }
3788 }
3789
3790
3791 /////////////////////////////////////////////////////////////////////////////////////////////////
3792 /// Phase 3 - Fill remaining digits with 0's, insert decimal dot, print exponent, and
3793 /// return.
3794 /////////////////////////////////////////////////////////////////////////////////////////////////
3795
3796fill_remaining_digits_with_0s:
3797 // This is probably not needed for the general format, but currently I am not 100% sure.
3798 // (When fixed format is eventually choosed, we do not remove trailing zeros in the integer part.
3799 // I am not sure if those trailing zeros are guaranteed to be already printed or not.)
3800 std::memset(s: buffer, c: '0', n: static_cast<std::size_t>(remaining_digits));
3801 buffer += remaining_digits;
3802
3803insert_decimal_dot:
3804 if (fmt == chars_format::general)
3805 {
3806 // Decide between fixed vs scientific.
3807 if (-4 <= decimal_exponent_normalized && decimal_exponent_normalized < precision)
3808 {
3809 // Fixed.
3810 if (decimal_exponent_normalized >= 0)
3811 {
3812 // Insert decimal dot.
3813 decimal_dot_pos = buffer_starting_pos + decimal_exponent_normalized + 1;
3814 std::memmove(dest: buffer_starting_pos, src: buffer_starting_pos + 1,
3815 n: static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
3816 *decimal_dot_pos = '.';
3817 }
3818 else
3819 {
3820 // Print leading zeros and insert decimal dot.
3821 int number_of_leading_zeros = -decimal_exponent_normalized - 1;
3822 std::memmove(dest: buffer_starting_pos + number_of_leading_zeros + 2, src: buffer_starting_pos + 1,
3823 n: static_cast<std::size_t>(buffer - buffer_starting_pos - 1));
3824 std::memcpy(dest: buffer_starting_pos, src: "0.", n: 2);
3825 std::memset(s: buffer_starting_pos + 2, c: '0', n: static_cast<std::size_t>(number_of_leading_zeros));
3826 buffer += number_of_leading_zeros + 1;
3827 }
3828 // Don't print exponent.
3829 fmt = chars_format::fixed;
3830 }
3831 else
3832 {
3833 // Scientific.
3834 // Insert decimal dot.
3835 *buffer_starting_pos = *(buffer_starting_pos + 1);
3836 *(buffer_starting_pos + 1) = '.';
3837 }
3838
3839 // Remove trailing zeros.
3840 while (true)
3841 {
3842 auto prev = buffer - 1;
3843
3844 // Remove decimal dot as well if there is no fractional digits.
3845 if (*prev == '.')
3846 {
3847 buffer = prev;
3848 break;
3849 }
3850 else if (*prev != '0')
3851 {
3852 break;
3853 }
3854 buffer = prev;
3855 }
3856 }
3857 else if (decimal_dot_pos != buffer_starting_pos)
3858 {
3859 std::memmove(dest: buffer_starting_pos, src: buffer_starting_pos + 1,
3860 n: static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
3861 *decimal_dot_pos = '.';
3862 }
3863
3864 if (fmt != chars_format::fixed)
3865 {
3866 if (decimal_exponent_normalized >= 0)
3867 {
3868 std::memcpy(dest: buffer, src: "e+", n: 2); // NOLINT : Specifically not null-terminating
3869 }
3870 else
3871 {
3872 std::memcpy(dest: buffer, src: "e-", n: 2); // NOLINT : Specifically not null-terminating
3873 decimal_exponent_normalized = -decimal_exponent_normalized;
3874 }
3875
3876 buffer += 2;
3877 if (decimal_exponent_normalized >= 100)
3878 {
3879 // d1 = decimal_exponent / 10; d2 = decimal_exponent % 10;
3880 // 6554 = ceil(2^16 / 10)
3881 auto prod = static_cast<std::uint32_t>(decimal_exponent_normalized) * UINT32_C(6554);
3882 auto d1 = prod >> 16;
3883 prod = static_cast<std::uint16_t>(prod) * UINT16_C(5); // * 10
3884 auto d2 = prod >> 15; // >> 16
3885 print_2_digits(n: d1, buffer);
3886 print_1_digit(n: d2, buffer: buffer + 2);
3887 buffer += 3;
3888 }
3889 else
3890 {
3891 print_2_digits(n: static_cast<std::uint32_t>(decimal_exponent_normalized), buffer);
3892 buffer += 2;
3893 }
3894 }
3895
3896 return {.ptr: buffer, .ec: std::errc()};
3897
3898round_up:
3899 if ((remaining_digits & 1) != 0)
3900 {
3901 round_up_one_digit:
3902 if (++current_digits == 10)
3903 {
3904 goto round_up_all_9s;
3905 }
3906
3907 goto print_last_one_digit;
3908 }
3909 else
3910 {
3911 round_up_two_digits:
3912 if (++current_digits == 100)
3913 {
3914 goto round_up_all_9s;
3915 }
3916
3917 goto print_last_two_digits;
3918 }
3919
3920print_last_digits:
3921 if ((remaining_digits & 1) != 0)
3922 {
3923 print_last_one_digit:
3924 print_1_digit(n: current_digits, buffer);
3925 ++buffer;
3926 }
3927 else
3928 {
3929 print_last_two_digits:
3930 print_2_digits(n: current_digits, buffer);
3931 buffer += 2;
3932 }
3933
3934 goto insert_decimal_dot;
3935
3936round_up_all_9s:
3937 char* first_9_pos = buffer;
3938 buffer += (2 - (remaining_digits & 1));
3939
3940 // Find the starting position of printed digits.
3941 char* digit_starting_pos = [&] {
3942 // For negative exponent & fixed format, we already printed leading zeros.
3943 if (fmt == chars_format::fixed && decimal_exponent_normalized < 0)
3944 {
3945 return buffer_starting_pos - decimal_exponent_normalized + 1;
3946 }
3947 // We reserved one slot for decimal dot, so the starting position of printed digits
3948 // is buffer_starting_pos + 1 if we need to print decimal dot.
3949 return buffer_starting_pos == decimal_dot_pos ? buffer_starting_pos
3950 : buffer_starting_pos + 1;
3951 }();
3952 // Find all preceding 9's.
3953 if ((first_9_pos - digit_starting_pos) % 2 != 0)
3954 {
3955 if (*(first_9_pos - 1) != '9')
3956 {
3957 ++*(first_9_pos - 1);
3958 if ((remaining_digits & 1) != 0)
3959 {
3960 *first_9_pos = '0';
3961 }
3962 else
3963 {
3964 std::memcpy(dest: first_9_pos, src: "00", n: 2);
3965 }
3966 goto insert_decimal_dot;
3967 }
3968 --first_9_pos;
3969 }
3970 while (first_9_pos != digit_starting_pos)
3971 {
3972 if (std::memcmp(s1: first_9_pos - 2, s2: "99", n: 2) != 0)
3973 {
3974 if (*(first_9_pos - 1) != '9')
3975 {
3976 ++*(first_9_pos - 1);
3977 }
3978 else
3979 {
3980 ++*(first_9_pos - 2);
3981 *(first_9_pos - 1) = '0';
3982 }
3983 std::memset(s: first_9_pos, c: '0', n: static_cast<std::size_t>(buffer - first_9_pos));
3984 goto insert_decimal_dot;
3985 }
3986 first_9_pos -= 2;
3987 }
3988
3989 // Every digit we wrote so far are all 9's. In this case, we have to shift the whole thing by 1.
3990 ++decimal_exponent_normalized;
3991
3992 if (fmt == chars_format::fixed)
3993 {
3994 if (decimal_exponent_normalized > 0)
3995 {
3996 // We need to print one more character.
3997 if (buffer == last)
3998 {
3999 return {.ptr: last, .ec: std::errc::value_too_large};
4000 }
4001 ++buffer;
4002 // If we were to print the decimal dot, we have to shift it to right
4003 // since we now have one more digit in the integer part.
4004 if (buffer_starting_pos != decimal_dot_pos)
4005 {
4006 ++decimal_dot_pos;
4007 }
4008 }
4009 else if (decimal_exponent_normalized == 0)
4010 {
4011 // For the case 0.99...9 -> 1.00...0, the rounded digit is one before the first digit written.
4012 // Note: decimal_exponent_normalized was negative before the increment (++decimal_exponent_normalized),
4013 // so we already have printed "00" onto the buffer.
4014 // Hence, --digit_starting_pos doesn't go more than the starting position of the buffer.
4015 --digit_starting_pos;
4016 }
4017 }
4018
4019 // Nolint is applied to the following two calls since we know they are not supposed to be null terminated
4020 *digit_starting_pos = '1';
4021 std::memset(s: digit_starting_pos + 1, c: '0', n: static_cast<std::size_t>(buffer - digit_starting_pos - 1)); // NOLINT
4022
4023 goto insert_decimal_dot;
4024}
4025
4026}}} // Namespaces
4027
4028#ifdef BOOST_MSVC
4029# pragma warning(pop)
4030#endif
4031
4032#endif // BOOST_CHARCONV_DETAIL_FLOFF
4033

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