Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-05 08:40:12

0001 // Copyright 2020-2022 Junekey Jeon
0002 //
0003 // The contents of this file may be used under the terms of
0004 // the Apache License v2.0 with LLVM Exceptions.
0005 //
0006 //    (See accompanying file LICENSE-Apache or copy at
0007 //     https://llvm.org/foundation/relicensing/LICENSE.txt)
0008 //
0009 // Alternatively, the contents of this file may be used under the terms of
0010 // the Boost Software License, Version 1.0.
0011 //    (See accompanying file LICENSE-Boost or copy at
0012 //     https://www.boost.org/LICENSE_1_0.txt)
0013 //
0014 // Unless required by applicable law or agreed to in writing, this software
0015 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0016 // KIND, either express or implied.
0017 //
0018 // Some parts are copied from Dragonbox project.
0019 //
0020 // Copyright 2023 Matt Borland
0021 // Distributed under the Boost Software License, Version 1.0.
0022 // https://www.boost.org/LICENSE_1_0.txt
0023 
0024 #ifndef BOOST_CHARCONV_DETAIL_FLOFF
0025 #define BOOST_CHARCONV_DETAIL_FLOFF
0026 
0027 #include <boost/charconv/detail/config.hpp>
0028 #include <boost/charconv/detail/bit_layouts.hpp>
0029 #include <boost/charconv/detail/emulated128.hpp>
0030 #include <boost/charconv/detail/dragonbox/dragonbox_common.hpp>
0031 #include <boost/charconv/detail/to_chars_result.hpp>
0032 #include <boost/charconv/chars_format.hpp>
0033 #include <boost/core/bit.hpp>
0034 #include <type_traits>
0035 #include <limits>
0036 #include <cstdint>
0037 #include <cstring>
0038 #include <cstddef>
0039 #include <climits>
0040 
0041 #ifdef BOOST_MSVC
0042 # pragma warning(push)
0043 # pragma warning(disable: 4127) // Extensive use of BOOST_IF_CONSTEXPR emits warnings under C++11 and 14
0044 # pragma warning(disable: 4554) // parentheses are used be warning is still emitted
0045 #endif
0046 
0047 namespace boost { namespace charconv { namespace detail {
0048 
0049 #ifdef BOOST_MSVC
0050 # pragma warning(push)
0051 # pragma warning(disable: 4702) // use of BOOST_IF_CONSTEXPR can result in unreachable code if max_blocks is 3
0052                                 // Other older compilers will emit warnings if the unreachable code is wrapped
0053                                 // in an else block (e.g. no return statment)
0054 #endif
0055 
0056 template <std::size_t max_blocks>
0057 struct fixed_point_calculator 
0058 {
0059     static_assert(1 < max_blocks, "Max blocks must be greater than 1");
0060 
0061     // Multiply multiplier to the fractional blocks and take the resulting integer part.
0062     // The fractional blocks are updated.
0063     template <typename MultiplierType>
0064     BOOST_FORCEINLINE static MultiplierType generate(MultiplierType multiplier,
0065                                                      std::uint64_t* blocks_ptr,
0066                                                      std::size_t number_of_blocks) noexcept
0067     {
0068         BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
0069 
0070         BOOST_IF_CONSTEXPR (max_blocks == 3)
0071         {
0072             uint128 mul_result;
0073             std::uint64_t carry = 0;
0074 
0075             switch (number_of_blocks) 
0076             {
0077             case 3:
0078                 mul_result = umul128(blocks_ptr[2], multiplier);
0079                 blocks_ptr[2] = mul_result.low;
0080                 carry = mul_result.high;
0081                 BOOST_FALLTHROUGH;
0082 
0083             case 2:
0084                 mul_result = umul128(blocks_ptr[1], multiplier);
0085                 mul_result += carry;
0086                 blocks_ptr[1] = mul_result.low;
0087                 carry = mul_result.high;
0088                 BOOST_FALLTHROUGH;
0089 
0090             case 1:
0091                 mul_result = umul128(blocks_ptr[0], multiplier);
0092                 mul_result += carry;
0093                 blocks_ptr[0] = mul_result.low;
0094                 return mul_result.high;
0095 
0096             default:
0097                 BOOST_UNREACHABLE_RETURN(carry); // NOLINT : Macro for unreachable can expand to be empty
0098             }
0099         }
0100 
0101         auto mul_result = umul128(blocks_ptr[number_of_blocks - 1], multiplier);
0102         blocks_ptr[number_of_blocks - 1] = mul_result.low;
0103         auto carry = mul_result.high;
0104         for (std::size_t i = 1; i < number_of_blocks; ++i) 
0105         {
0106             mul_result = umul128(blocks_ptr[number_of_blocks - i - 1], multiplier);
0107             mul_result += carry;
0108             blocks_ptr[number_of_blocks - i - 1] = mul_result.low;
0109             carry = mul_result.high;
0110         }
0111 
0112         return MultiplierType(carry);
0113     }
0114 
0115     // Multiply multiplier to the fractional blocks and discard the resulting integer part.
0116     // The fractional blocks are updated.
0117     template <typename MultiplierType>
0118     BOOST_FORCEINLINE static void discard_upper(MultiplierType multiplier,
0119                                                 std::uint64_t* blocks_ptr,
0120                                                 std::size_t number_of_blocks) noexcept 
0121     {
0122         BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
0123 
0124         blocks_ptr[0] *= multiplier;
0125         if (number_of_blocks > 1) 
0126         {
0127             BOOST_IF_CONSTEXPR (max_blocks == 3) 
0128             {
0129                 uint128 mul_result;
0130                 std::uint64_t carry = 0;
0131 
0132                 if (number_of_blocks > 2)
0133                 {
0134                     mul_result = umul128(multiplier, blocks_ptr[2]);
0135                     blocks_ptr[2] = mul_result.low;
0136                     carry = mul_result.high;
0137                 }
0138 
0139                 mul_result = umul128(multiplier, blocks_ptr[1]);
0140                 mul_result += carry;
0141                 blocks_ptr[1] = mul_result.low;
0142                 blocks_ptr[0] += mul_result.high;
0143             }
0144             else 
0145             {
0146                 auto mul_result = umul128(multiplier, blocks_ptr[number_of_blocks - 1]);
0147                 blocks_ptr[number_of_blocks - 1] = mul_result.low;
0148                 auto carry = mul_result.high;
0149 
0150                 for (std::size_t i = 2; i < number_of_blocks; ++i)
0151                 {
0152                     mul_result = umul128(multiplier, blocks_ptr[number_of_blocks - i]);
0153                     mul_result += carry;
0154                     blocks_ptr[number_of_blocks - i] = mul_result.low;
0155                     carry = mul_result.high;
0156                 }
0157 
0158                 blocks_ptr[0] += carry;
0159             }
0160         }
0161     }
0162 
0163     // Multiply multiplier to the fractional blocks and take the resulting integer part.
0164     // Don't care about what happens to the fractional blocks.
0165     template <typename MultiplierType>
0166     BOOST_FORCEINLINE static MultiplierType
0167     generate_and_discard_lower(MultiplierType multiplier, std::uint64_t* blocks_ptr,
0168                                 std::size_t number_of_blocks) noexcept 
0169     {
0170         BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
0171 
0172         BOOST_IF_CONSTEXPR (max_blocks == 3) 
0173         {
0174             uint128 mul_result;
0175             std::uint64_t carry = 0;
0176 
0177             switch (number_of_blocks) 
0178             {
0179             case 3:
0180                 mul_result = umul128(blocks_ptr[2], static_cast<std::uint64_t>(multiplier));
0181                 carry = mul_result.high;
0182                 BOOST_FALLTHROUGH;
0183 
0184             case 2:
0185                 mul_result = umul128(blocks_ptr[1], static_cast<std::uint64_t>(multiplier));
0186                 mul_result += carry;
0187                 carry = mul_result.high;
0188                 BOOST_FALLTHROUGH;
0189 
0190             case 1:
0191                 mul_result = umul128(blocks_ptr[0], static_cast<std::uint64_t>(multiplier));
0192                 mul_result += carry;
0193                 return static_cast<MultiplierType>(mul_result.high);
0194 
0195             default:
0196                 BOOST_UNREACHABLE_RETURN(carry); // NOLINT
0197             }
0198         }
0199 
0200         auto mul_result = umul128(blocks_ptr[number_of_blocks - 1], static_cast<std::uint64_t>(multiplier));
0201         auto carry = mul_result.high;
0202         for (std::size_t i = 1; i < number_of_blocks; ++i)
0203         {
0204             mul_result = umul128(blocks_ptr[number_of_blocks - i - 1], static_cast<std::uint64_t>(multiplier));
0205             mul_result += carry;
0206             carry = mul_result.high;
0207         }
0208 
0209         return static_cast<MultiplierType>(carry);
0210     }
0211 };
0212 
0213 #ifdef BOOST_MSVC
0214 # pragma warning(pop)
0215 #endif
0216 
0217 template <bool b>
0218 struct additional_static_data_holder_impl
0219 {
0220     static constexpr char radix_100_table[] = {
0221         '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', //
0222         '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', //
0223         '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', //
0224         '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', //
0225         '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', //
0226         '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', //
0227         '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', //
0228         '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', //
0229         '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', //
0230         '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', //
0231         '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', //
0232         '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', //
0233         '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', //
0234         '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', //
0235         '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', //
0236         '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', //
0237         '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', //
0238         '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', //
0239         '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', //
0240         '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'  //
0241     };
0242 
0243     static constexpr std::uint32_t fractional_part_rounding_thresholds32[] = {
0244         UINT32_C(2576980378), UINT32_C(2190433321), UINT32_C(2151778616), UINT32_C(2147913145),
0245         UINT32_C(2147526598), UINT32_C(2147487943), UINT32_C(2147484078), UINT32_C(2147483691)
0246     };
0247 
0248     static constexpr std::uint64_t fractional_part_rounding_thresholds64[] = {
0249         UINT64_C(11068046444225730970), UINT64_C(9407839477591871325), UINT64_C(9241818780928485360),
0250         UINT64_C(9225216711262146764),  UINT64_C(9223556504295512904), UINT64_C(9223390483598849518),
0251         UINT64_C(9223373881529183179),  UINT64_C(9223372221322216546), UINT64_C(9223372055301519882),
0252         UINT64_C(9223372038699450216),  UINT64_C(9223372037039243249), UINT64_C(9223372036873222553),
0253         UINT64_C(9223372036856620483),  UINT64_C(9223372036854960276), UINT64_C(9223372036854794255),
0254         UINT64_C(9223372036854777653),  UINT64_C(9223372036854775993), UINT64_C(9223372036854775827)
0255     };
0256 };
0257 
0258 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
0259 
0260 template <bool b> constexpr char additional_static_data_holder_impl<b>::radix_100_table[];
0261 template <bool b> constexpr std::uint32_t additional_static_data_holder_impl<b>::fractional_part_rounding_thresholds32[];
0262 template <bool b> constexpr std::uint64_t additional_static_data_holder_impl<b>::fractional_part_rounding_thresholds64[];
0263 
0264 #endif
0265 
0266 using additional_static_data_holder = additional_static_data_holder_impl<true>;
0267 
0268 struct compute_mul_result 
0269 {
0270     std::uint64_t result;
0271     bool is_integer;
0272 };
0273 
0274 // Load the necessary bits into blocks_ptr and then return the number of cache blocks
0275 // loaded. The most significant block is loaded into blocks_ptr[0].
0276 template <typename ExtendedCache, bool zero_out, 
0277           typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type,
0278           typename std::enable_if<(ExtendedCache::constant_block_count), bool>::type = true>
0279 inline std::uint8_t cache_block_count_helper(CacheBlockType*, int, int, std::uint32_t) noexcept 
0280 {
0281     return static_cast<std::uint8_t>(ExtendedCache::max_cache_blocks);
0282 }
0283 
0284 template <typename ExtendedCache, bool zero_out,
0285           typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type,
0286           typename std::enable_if<!(ExtendedCache::constant_block_count), bool>::type = true>
0287 inline std::uint8_t cache_block_count_helper(CacheBlockType*, int e, int, std::uint32_t multiplier_index) noexcept 
0288 {
0289     const auto mul_info = ExtendedCache::multiplier_index_info_table[multiplier_index];
0290 
0291     const auto cache_block_count_index =
0292                 mul_info.cache_block_count_index_offset +
0293                 static_cast<std::uint32_t>(e - ExtendedCache::e_min) / ExtendedCache::collapse_factor -
0294                 ExtendedCache::cache_block_count_offset_base;
0295 
0296     BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks < 3)
0297     {
0298         // 1-bit packing.
0299         return static_cast<std::uint8_t>(
0300                     (ExtendedCache::cache_block_counts[cache_block_count_index /
0301                                                         8] >>
0302                     (cache_block_count_index % 8)) &
0303                     0x1) +
0304                 1;
0305     }
0306     else BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks < 4)
0307     {
0308         // 2-bit packing.
0309         return static_cast<std::uint8_t>(
0310             (ExtendedCache::cache_block_counts[cache_block_count_index / 4] >>
0311                 (2 * (cache_block_count_index % 4))) &
0312             0x3);
0313     }
0314     else 
0315     {
0316         // 4-bit packing.
0317         return std::uint8_t(
0318             (ExtendedCache::cache_block_counts[cache_block_count_index / 2] >>
0319                 (4 * (cache_block_count_index % 2))) &
0320             0xf);
0321     }
0322 }
0323 
0324 template <typename ExtendedCache, bool zero_out,
0325           typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type>
0326 BOOST_FORCEINLINE std::uint8_t load_extended_cache(CacheBlockType* blocks_ptr, int e, int k,
0327                                                    std::uint32_t multiplier_index) noexcept 
0328 {
0329     BOOST_IF_CONSTEXPR (zero_out)
0330     {
0331         std::memset(blocks_ptr, 0, sizeof(CacheBlockType) * ExtendedCache::max_cache_blocks);
0332     }
0333 
0334     const auto mul_info = ExtendedCache::multiplier_index_info_table[multiplier_index];
0335 
0336     std::uint32_t number_of_leading_zero_blocks;
0337     std::uint32_t first_cache_block_index;
0338     std::uint32_t bit_offset;
0339     std::uint32_t excessive_bits_to_left;
0340     std::uint32_t excessive_bits_to_right;
0341     std::uint8_t  cache_block_count = cache_block_count_helper<ExtendedCache, zero_out, CacheBlockType>(blocks_ptr, e, k, multiplier_index);
0342 
0343     // The request window starting/ending positions.
0344     auto start_bit_index = static_cast<int>(mul_info.cache_bit_index_offset) + e - ExtendedCache::cache_bit_index_offset_base;
0345     auto end_bit_index = start_bit_index + cache_block_count * static_cast<int>(ExtendedCache::cache_bits_unit);
0346 
0347     // The source window starting/ending positions.
0348     const auto src_start_bit_index = static_cast<int>(mul_info.first_cache_bit_index);
0349     const auto src_end_bit_index = static_cast<int>(ExtendedCache::multiplier_index_info_table[multiplier_index + 1].first_cache_bit_index);
0350 
0351     // If the request window goes further than the left boundary of the source window,
0352     if (start_bit_index < src_start_bit_index)
0353     {
0354         number_of_leading_zero_blocks =
0355             static_cast<std::uint32_t>(src_start_bit_index - start_bit_index) /
0356             static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
0357         excessive_bits_to_left = static_cast<std::uint32_t>(src_start_bit_index - start_bit_index) %
0358                                     static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
0359 
0360         BOOST_IF_CONSTEXPR (!zero_out)
0361         {
0362             std::memset(blocks_ptr, 0, number_of_leading_zero_blocks * sizeof(CacheBlockType));
0363         }
0364 
0365         start_bit_index += static_cast<int>(number_of_leading_zero_blocks * ExtendedCache::cache_bits_unit);
0366 
0367         const auto src_start_block_index =
0368             static_cast<int>(static_cast<std::uint32_t>(src_start_bit_index) /
0369                 static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit));
0370         
0371         const auto src_start_block_bit_index =
0372             src_start_block_index * static_cast<int>(ExtendedCache::cache_bits_unit);
0373 
0374         first_cache_block_index = static_cast<std::uint32_t>(src_start_block_index);
0375 
0376         if (start_bit_index < src_start_block_bit_index)
0377         {
0378             auto shift_amount = src_start_block_bit_index - start_bit_index;
0379             BOOST_CHARCONV_ASSERT(shift_amount >= 0 && shift_amount < static_cast<int>(ExtendedCache::cache_bits_unit));
0380 
0381             blocks_ptr[number_of_leading_zero_blocks] =
0382                 ((ExtendedCache::cache[src_start_block_index] >> shift_amount) &
0383                     (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) >>
0384                     excessive_bits_to_left));
0385 
0386             ++number_of_leading_zero_blocks;
0387             bit_offset = static_cast<std::uint32_t>(static_cast<int>(ExtendedCache::cache_bits_unit) - shift_amount);
0388             excessive_bits_to_left = 0;
0389         }
0390         else 
0391         {
0392             bit_offset = static_cast<std::uint32_t>(start_bit_index - src_start_block_bit_index);
0393         }
0394     }
0395     else 
0396     {
0397         number_of_leading_zero_blocks = 0;
0398         first_cache_block_index =
0399             static_cast<std::uint32_t>(start_bit_index) / static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
0400         bit_offset =
0401             static_cast<std::uint32_t>(start_bit_index) % static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
0402         excessive_bits_to_left = 0;
0403     }
0404 
0405     // If the request window goes further than the right boundary of the source window,
0406     if (end_bit_index > src_end_bit_index)
0407     {
0408         const std::uint8_t number_of_trailing_zero_blocks =
0409             static_cast<std::uint8_t>(end_bit_index - src_end_bit_index) / ExtendedCache::cache_bits_unit;
0410         excessive_bits_to_right = static_cast<std::uint32_t>(end_bit_index - src_end_bit_index) %
0411                                     static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
0412 
0413         cache_block_count -= number_of_trailing_zero_blocks;
0414     }
0415     else
0416     {
0417         excessive_bits_to_right = 0;
0418     }
0419 
0420     // Load blocks.
0421     const auto number_of_blocks_to_load = cache_block_count - number_of_leading_zero_blocks;
0422     auto* const dst_ptr = blocks_ptr + number_of_leading_zero_blocks;
0423     if (bit_offset == 0)
0424     {
0425         BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks == 3)
0426         {
0427             switch (number_of_blocks_to_load)
0428             {
0429             case 3:
0430                 std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, 3 * sizeof(CacheBlockType));
0431                 break;
0432             case 2:
0433                 std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, 2 * sizeof(CacheBlockType));
0434                 break;
0435             case 1:
0436                 std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, 1 * sizeof(CacheBlockType));
0437                 break;
0438             case 0:
0439                 break;
0440             default:
0441                 BOOST_UNREACHABLE_RETURN(dst_ptr); // NOLINT
0442             }
0443         }
0444         else 
0445         {
0446             std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, number_of_blocks_to_load * sizeof(CacheBlockType));
0447         }
0448     }
0449     else 
0450     {
0451         BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks == 3)
0452         {
0453             switch (number_of_blocks_to_load)
0454             {
0455             case 3:
0456                 *(dst_ptr + 2) =
0457                     (ExtendedCache::cache[first_cache_block_index + 2] << bit_offset) |
0458                     (ExtendedCache::cache[first_cache_block_index + 3] >>
0459                         (ExtendedCache::cache_bits_unit - bit_offset));
0460                 BOOST_FALLTHROUGH;
0461             case 2:
0462                 *(dst_ptr + 1) =
0463                     (ExtendedCache::cache[first_cache_block_index + 1] << bit_offset) |
0464                     (ExtendedCache::cache[first_cache_block_index + 2] >>
0465                         (ExtendedCache::cache_bits_unit - bit_offset));
0466                 BOOST_FALLTHROUGH;
0467             case 1:
0468                 *dst_ptr = (ExtendedCache::cache[first_cache_block_index] << bit_offset) |
0469                             (ExtendedCache::cache[first_cache_block_index + 1] >>
0470                             (ExtendedCache::cache_bits_unit - bit_offset));
0471             case 0:
0472                 break;
0473             default:
0474                 BOOST_UNREACHABLE_RETURN(dst_ptr); // NOLINT
0475             }
0476         }
0477         else 
0478         {
0479             for (std::uint8_t i = 0; i < number_of_blocks_to_load; ++i)
0480             {
0481                 *(dst_ptr + i) =
0482                     (ExtendedCache::cache[first_cache_block_index + i] << bit_offset) |
0483                     (ExtendedCache::cache[first_cache_block_index + i + 1] >>
0484                         (ExtendedCache::cache_bits_unit - bit_offset));
0485             }
0486         }
0487     }
0488     
0489     // Remove possible flooding bits from adjacent entries.
0490     *dst_ptr &= (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) >> excessive_bits_to_left);
0491 
0492     blocks_ptr[cache_block_count - 1] &= (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) << excessive_bits_to_right);
0493 
0494     // To compute ceil(2^Q * x / D), we need to check if
0495     // 2^Q * x / D = 2^(Q + e + k - eta - 1) * 5^(k - eta) is an integer or not.
0496     if (k < ExtendedCache::segment_length ||
0497         e + k + static_cast<int>(cache_block_count * ExtendedCache::cache_bits_unit) -
0498                 static_cast<int>(excessive_bits_to_right) <
0499             ExtendedCache::segment_length + 1) {
0500         blocks_ptr[cache_block_count - 1] += (CacheBlockType(1) << excessive_bits_to_right);
0501         BOOST_CHARCONV_ASSERT(blocks_ptr[cache_block_count - 1] != 0);
0502     }
0503 
0504     return cache_block_count;
0505 }
0506 
0507 template <bool constant_block_count, std::uint8_t max_cache_blocks>
0508 struct cache_block_count_t;
0509 
0510 template <std::uint8_t max_cache_blocks>
0511 struct cache_block_count_t<false, max_cache_blocks>
0512 {
0513     std::uint8_t value;
0514     
0515     operator std::uint8_t() const noexcept { return value; } // NOLINT : implicit conversions are ok for block count
0516     cache_block_count_t& operator=(std::uint8_t new_value) noexcept
0517     {
0518         value = new_value;
0519         return *this;
0520     }
0521 };
0522 
0523 template <std::uint8_t max_cache_blocks>
0524 struct cache_block_count_t<true, max_cache_blocks>
0525 {
0526     static constexpr std::uint8_t value = max_cache_blocks;
0527     operator std::uint8_t() const noexcept { return value; } // NOLINT : implicit conversions are ok for block count
0528     cache_block_count_t& operator=(std::uint8_t) noexcept
0529     {
0530         // Don't do anything.
0531         return *this;
0532     }
0533 };
0534 
0535 template <unsigned n>
0536 struct uconst
0537 {
0538     constexpr uconst() {}; // NOLINT : Clang 3.x does not support = default
0539     static constexpr unsigned value = n;
0540 };
0541 
0542 BOOST_INLINE_VARIABLE constexpr uconst<0>  uconst0;
0543 BOOST_INLINE_VARIABLE constexpr uconst<1>  uconst1;
0544 BOOST_INLINE_VARIABLE constexpr uconst<6>  uconst6;
0545 BOOST_INLINE_VARIABLE constexpr uconst<9>  uconst9;
0546 BOOST_INLINE_VARIABLE constexpr uconst<14> uconst14;
0547 BOOST_INLINE_VARIABLE constexpr uconst<16> uconst16;
0548 
0549 #ifdef __clang__
0550 #  pragma clang diagnostic push
0551 #  pragma clang diagnostic ignored "-Wsign-conversion"
0552 #elif defined(__GNUC__)
0553 #  pragma GCC diagnostic push
0554 #  pragma GCC diagnostic ignored "-Wsign-conversion"
0555 #elif defined(BOOST_MSVC)
0556 #  pragma warning(push)
0557 #  pragma warning(disable: 4365 4267)
0558 #endif
0559 
0560 template <unsigned digits, bool dummy = (digits <= 9)>
0561 struct uint_with_known_number_of_digits;
0562 
0563 template <unsigned digits_>
0564 struct uint_with_known_number_of_digits<digits_, true> 
0565 {
0566     static constexpr auto digits = digits_;
0567     std::uint32_t value;
0568 };
0569 
0570 template <unsigned digits_>
0571 struct uint_with_known_number_of_digits<digits_, false>
0572 {
0573     static constexpr auto digits = digits_;
0574     std::uint64_t value;
0575 };
0576 
0577 template <typename HasFurtherDigits, typename... Args, typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
0578 static BOOST_FORCEINLINE bool check_rounding_condition_inside_subsegment(
0579     std::uint32_t current_digits, std::uint32_t fractional_part,
0580     int remaining_digits_in_the_current_subsegment, HasFurtherDigits has_further_digits,
0581     Args...) noexcept 
0582 {
0583     if (fractional_part >= additional_static_data_holder::fractional_part_rounding_thresholds32[remaining_digits_in_the_current_subsegment - 1])
0584     {
0585         return true;
0586     }
0587 
0588     return ((fractional_part >> 31) & ((current_digits & 1) | has_further_digits)) != 0;
0589 }
0590 
0591 template <typename HasFurtherDigits, typename... Args,
0592           typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
0593 static BOOST_FORCEINLINE bool check_rounding_condition_inside_subsegment(
0594     std::uint32_t current_digits, std::uint32_t fractional_part,
0595     int remaining_digits_in_the_current_subsegment, HasFurtherDigits has_further_digits,
0596     Args... args) noexcept 
0597 {
0598     if (fractional_part >= additional_static_data_holder::fractional_part_rounding_thresholds32[remaining_digits_in_the_current_subsegment - 1]) 
0599     {
0600         return true;
0601     }
0602     
0603     return fractional_part >= 0x80000000 && ((current_digits & 1) != 0 || has_further_digits(args...));
0604 }
0605 
0606 template <typename HasFurtherDigits, typename... Args,
0607           typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
0608 static BOOST_FORCEINLINE bool check_rounding_condition_with_next_bit(std::uint32_t current_digits, bool next_bit,
0609                                                                      HasFurtherDigits has_further_digits, Args...) noexcept 
0610 {
0611     if (!next_bit) 
0612     {
0613         return false;
0614     }
0615 
0616     return ((current_digits & 1) | has_further_digits) != 0;
0617 }
0618 
0619 template <typename HasFurtherDigits, typename... Args,
0620           typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
0621 static BOOST_FORCEINLINE bool check_rounding_condition_with_next_bit(std::uint32_t current_digits, bool next_bit,
0622                                                                      HasFurtherDigits has_further_digits, Args... args) noexcept 
0623 {
0624     if (!next_bit) 
0625     {
0626         return false;
0627     }
0628 
0629     return (current_digits & 1) != 0 || has_further_digits(args...);
0630 }
0631 
0632 template <typename UintWithKnownDigits, typename HasFurtherDigits, typename... Args, 
0633           typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
0634 static BOOST_FORCEINLINE bool check_rounding_condition_subsegment_boundary_with_next_subsegment(
0635     std::uint32_t current_digits, UintWithKnownDigits next_subsegment,
0636     HasFurtherDigits has_further_digits, Args...) noexcept 
0637 {
0638     if (next_subsegment.value > power_of_10[decltype(next_subsegment)::digits] / 2)
0639     {
0640         return true;
0641     }
0642 
0643     return next_subsegment.value == power_of_10[decltype(next_subsegment)::digits] / 2 && 
0644                                     ((current_digits & 1) | has_further_digits) != 0;
0645 }
0646 
0647 template <typename UintWithKnownDigits, typename HasFurtherDigits, typename... Args, 
0648           typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
0649 static BOOST_FORCEINLINE bool check_rounding_condition_subsegment_boundary_with_next_subsegment(
0650     std::uint32_t current_digits, UintWithKnownDigits next_subsegment,
0651     HasFurtherDigits has_further_digits, Args... args) noexcept 
0652 {
0653     if (next_subsegment.value > power_of_10[decltype(next_subsegment)::digits] / 2) 
0654     {
0655         return true;
0656     }
0657 
0658     return next_subsegment.value == power_of_10[decltype(next_subsegment)::digits] / 2 &&
0659                                     ((current_digits & 1) != 0 || has_further_digits(args...));
0660 }
0661 
0662 #ifdef __clang__
0663 #  pragma clang diagnostic pop
0664 #elif defined(__GNUC__)
0665 #  pragma GCC diagnostic pop
0666 #elif defined(BOOST_MSVC)
0667 #  pragma warning(pop)
0668 #endif
0669 
0670 #ifdef BOOST_MSVC
0671 # pragma warning(push)
0672 # pragma warning(disable: 4307) // MSVC 14.1 emits warnings for uint64_t constants
0673 #endif
0674 
0675 namespace has_further_digits_impl {
0676 template <int k_right_threshold, int additional_neg_exp_of_2>
0677 bool no_neg_k_can_be_integer(int k, int exp2_base) noexcept 
0678 {
0679     return k < k_right_threshold || exp2_base + k < additional_neg_exp_of_2;
0680 }
0681 
0682 template <int k_left_threshold, int k_right_threshold, int additional_neg_exp_of_2, int min_neg_exp_of_5, typename SignificandType>
0683 bool only_one_neg_k_can_be_integer(int k, int exp2_base, SignificandType significand) noexcept
0684 {
0685     // Supposed to be k - additional_neg_exp_of_5_v < -min_neg_exp_of_5 || ...
0686     if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2) 
0687     {
0688         return true;
0689     }
0690     // Supposed to be k - additional_neg_exp_of_5_v >= 0.
0691     if (k >= k_right_threshold) 
0692     {
0693         return false;
0694     }
0695 
0696     BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv = compute_power(UINT64_C(0xcccccccccccccccd), static_cast<unsigned>(min_neg_exp_of_5));
0697     BOOST_CXX14_CONSTEXPR std::uint64_t max_quot = UINT64_C(0xffffffffffffffff) / compute_power(UINT64_C(5), static_cast<unsigned>(min_neg_exp_of_5));
0698 
0699     return (significand * mod_inv) > max_quot;
0700 }
0701 
0702 template <int k_left_threshold, int k_middle_threshold, int k_right_threshold,
0703             int additional_neg_exp_of_2, int min_neg_exp_of_5, int segment_length,
0704             typename SignificandType>
0705 bool only_two_neg_k_can_be_integer(int k, int exp2_base,
0706                                     SignificandType significand) noexcept {
0707     // Supposed to be k - additional_neg_exp_of_5_v < -min_neg_exp_of_5 - segment_length
0708     // || ...
0709     if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2) {
0710         return true;
0711     }
0712     // Supposed to be k - additional_neg_exp_of_5_v >= 0.
0713     if (k >= k_right_threshold) {
0714         return false;
0715     }
0716 
0717     if (k >= k_middle_threshold) {
0718         BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv =
0719             compute_power(UINT64_C(0xcccccccccccccccd), static_cast<unsigned>(min_neg_exp_of_5));
0720         BOOST_CXX14_CONSTEXPR std::uint64_t max_quot =
0721             UINT64_C(0xffffffffffffffff) /
0722             compute_power(UINT64_C(5), static_cast<unsigned>(min_neg_exp_of_5));
0723 
0724         return (significand * mod_inv) > max_quot;
0725     }
0726     else {
0727         BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv = compute_power(
0728             UINT64_C(0xcccccccccccccccd), static_cast<unsigned>(min_neg_exp_of_5 + segment_length));
0729         BOOST_CXX14_CONSTEXPR std::uint64_t max_quot =
0730             UINT64_C(0xffffffffffffffff) /
0731             compute_power(UINT64_C(5),
0732                             static_cast<unsigned>(min_neg_exp_of_5 + segment_length));
0733 
0734         return (significand * mod_inv) > max_quot;
0735     }
0736 }
0737 } // Namespace has_further_digits_impl
0738 
0739 #ifdef BOOST_MSVC
0740 #pragma warning(pop)
0741 #endif
0742 
0743 inline void print_1_digit(std::uint32_t n, char* buffer) noexcept 
0744 {
0745     *buffer = char('0' + n);
0746 }
0747 
0748 inline void print_2_digits(std::uint32_t n, char* buffer) noexcept
0749 {
0750     std::memcpy(buffer, additional_static_data_holder::radix_100_table + n * 2, 2);
0751 }
0752 
0753 inline void print_6_digits(std::uint32_t n, char* buffer) noexcept 
0754 {
0755     // 429497 = ceil(2^32/10^4)
0756     auto prod = (n * UINT64_C(429497)) + 1;
0757     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
0758     
0759     for (int i = 0; i < 2; ++i) 
0760     {
0761         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
0762         print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 2 + i * 2);
0763     }
0764 }
0765 
0766 inline void print_7_digits(std::uint32_t n, char* buffer) noexcept 
0767 {
0768     // 17592187 = ceil(2^(32+12)/10^6)
0769     auto prod = ((n * UINT64_C(17592187)) >> 12) + 1;
0770     print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
0771     
0772     for (int i = 0; i < 3; ++i)
0773     {
0774         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
0775         print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 1 + i * 2);
0776     }
0777 }
0778 
0779 inline void print_8_digits(std::uint32_t n, char* buffer) noexcept
0780 {
0781     // 140737489 = ceil(2^(32+15)/10^6)
0782     auto prod = ((n * UINT64_C(140737489)) >> 15) + 1;
0783     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
0784     
0785     for (int i = 0; i < 3; ++i) 
0786     {
0787         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
0788         print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 2 + i * 2);
0789     }
0790 }
0791 
0792 inline void print_9_digits(std::uint32_t n, char* buffer) noexcept
0793 {
0794     // 1441151881 = ceil(2^(32+25)/10^8)
0795     auto prod = ((n * UINT64_C(1441151881)) >> 25) + 1;
0796     print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
0797     
0798     for (int i = 0; i < 4; ++i) 
0799     {
0800         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
0801         print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 1 + i * 2);
0802     }
0803 }
0804 
0805 struct main_cache_full 
0806 {
0807     template <typename FloatFormat>
0808     static constexpr typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
0809     {
0810         return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
0811     }
0812 };
0813 
0814 struct main_cache_compressed 
0815 {
0816     template <typename FloatFormat>
0817     static BOOST_CHARCONV_CXX14_CONSTEXPR typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
0818     {
0819         BOOST_CHARCONV_ASSERT(k >= main_cache_holder::min_k && k <= main_cache_holder::max_k);
0820 
0821         BOOST_IF_CONSTEXPR (std::is_same<FloatFormat, ieee754_binary64>::value) 
0822         {
0823             // Compute the base index.
0824             const auto cache_index =
0825                 static_cast<int>(static_cast<std::uint32_t>(k - main_cache_holder::min_k) /
0826                     compressed_cache_detail::compression_ratio);
0827 
0828             const auto kb = cache_index * compressed_cache_detail::compression_ratio +
0829                             main_cache_holder::min_k;
0830 
0831             const auto offset = k - kb;
0832 
0833             // Get the base cache.
0834             const auto base_cache = compressed_cache_detail::cache_holder_t::table[cache_index];
0835 
0836             if (offset == 0)
0837             {
0838                 return base_cache;
0839             }
0840             else 
0841             {
0842 
0843                 // Compute the required amount of bit-shift.
0844                 const auto alpha = log::floor_log2_pow10(kb + offset) - log::floor_log2_pow10(kb) - offset;
0845                 BOOST_CHARCONV_ASSERT(alpha > 0 && alpha < 64);
0846 
0847                 // Try to recover the real cache.
0848                 const auto pow5 = compressed_cache_detail::pow5_holder_t::table[offset];
0849                 auto recovered_cache = umul128(base_cache.high, pow5);
0850                 const auto middle_low = umul128(base_cache.low, pow5);
0851 
0852                 recovered_cache += middle_low.high;
0853 
0854                 const auto high_to_middle = recovered_cache.high << (64 - alpha);
0855                 const auto middle_to_low = recovered_cache.low << (64 - alpha);
0856 
0857                 recovered_cache = uint128{(recovered_cache.low >> alpha) | high_to_middle, ((middle_low.low >> alpha) | middle_to_low)};
0858 
0859                 BOOST_CHARCONV_ASSERT(recovered_cache.low + 1 != 0);
0860                 recovered_cache = uint128(recovered_cache.high, recovered_cache.low + 1);
0861 
0862                 return recovered_cache;
0863             }
0864         }
0865         else
0866         {
0867             // Just use the full cache for anything other than binary64
0868             return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
0869         }
0870     }
0871 };
0872 
0873 template <bool b>
0874 struct extended_cache_long_impl
0875 {
0876     static constexpr std::size_t max_cache_blocks = 3;
0877     static constexpr std::size_t cache_bits_unit = 64;
0878     static constexpr int segment_length = 22;
0879     static constexpr bool constant_block_count = true;
0880     static constexpr int e_min = -1074;
0881     static constexpr int k_min = -272;
0882     static constexpr int cache_bit_index_offset_base = 977;
0883     static constexpr std::uint64_t cache[] = {
0884         0xa37fce126597973c, 0xe50ff107bab528a0, 0x8f1ba3f17395a391, 0xd56bdc876cdb4648,
0885         0x6ca000bdd9e33bd4, 0x23cf34bbf983f78b, 0x8737d87296e93f5d, 0xa2824ba6d9df301d,
0886         0x8ce3eccf7cfb42ab, 0xe5ecdc0b78109f00, 0xa620c9995c9c5c3a, 0xa0f79c97ac210943,
0887         0x64dfb5636985915f, 0xc12f542e4c7ea6ee, 0x34de81232784ea17, 0xd0cbde7fac4643f2,
0888         0x5d9400de8fef7552, 0x81214f68696d9af2, 0xb7d0e0a2ccaccf20, 0x5c4ed9243f16193d,
0889         0xf71838486e60b926, 0x48892047ec1a8bf4, 0x14ff2faa9c32befa, 0x666fbaa24ddbb8e9,
0890         0x436682c807652a58, 0xed98ddaee19068c7, 0x63badd624dd9b095, 0x72dbb637d5b77493,
0891         0xd01998fb8d9e8861, 0xacb39418dce017b9, 0x8db8f2f13eed81cf, 0xfd699fbb7d0a737a,
0892         0x011cd67160923d91, 0x9a66fd7732c14d98, 0x235857d065a52d18, 0x895288951dab0d8e,
0893         0x59041cb66e4f0e68, 0x5e7c68240249e750, 0x8881a2a6ab00987b, 0x5fc8c32c863aaeac,
0894         0x3bafbe662a7f81a8, 0xd47692705ae76b64, 0xeb1cc7d99143fb53, 0xcf8be24f7b0fc499,
0895         0x6a276e8f0fbf33eb, 0x63b2d61966fa7243, 0x0970327d2cc58011, 0x43ff09410ec24aae,
0896         0x0bdb6f345ea1851d, 0x409c37132c5836ff, 0xf3150f74a6190324, 0x5c358d6c07453d23,
0897         0x7207012ad7846ba7, 0x61ad5d0772604733, 0x19a20a6e21c2018d, 0x5f568fd497ef18b2,
0898         0xeda5815eed00749f, 0x029531461bc483d8, 0xb8789d7784875911, 0x6fc40572236f2ba5,
0899         0x9c2a50a76ace3168, 0xbf4815c2bea56741, 0xf84e8f2fe9b211f5, 0x689033182d2ea7ed,
0900         0x5bcb3a3230a68f47, 0xa848403d116805ef, 0xfaeaa73623b79604, 0x31d76828d2181b64,
0901         0x7c4eabddc7dd634b, 0xc2b13231eeff6fda, 0x8094743db32bf251, 0x2df07391bde052d2,
0902         0xffd9bdbf321ad8ae, 0x06b2c6d1cf6cf742, 0xf32a54ce1598fe8f, 0x1cc2e3082d28897e,
0903         0x0485f2e46b488584, 0xe3f6965b145a49cb, 0x406eaa1217aefe69, 0x0777373638de456b,
0904         0xcde91853b592212b, 0x3faf7b46d7f79c18, 0x558d83afb7127381, 0x5f490259c7957aeb,
0905         0x76e6540e246d73cc, 0x5098a935a866dc75, 0xc50d9c29002d9e73, 0xcc8f8252faac0b7f,
0906         0xb759afb688f8251d, 0x6a2934d3036c85d3, 0x570eb3ce4c86407f, 0x036f2b68794754af,
0907         0x57661a5d6993fe2c, 0x6d07b7fabe546a80, 0x38efe4029259743c, 0x548f417ebaa61c6c,
0908         0xb0c31fa64a3fcc9e, 0x7dab825964fb7100, 0xd0c92ae8207d6f22, 0xf1e38a8a9c541144,
0909         0x2139951c68d0385b, 0x9d9e22c42f139287, 0x4fea4d670876b800, 0x35f293a9a62252d4,
0910         0x4b606b26f1922c5c, 0x8e5660b37505cb11, 0x868138391855da81, 0x6e95f6c9b45c7aa2,
0911         0x425ff75e14fc31a1, 0x258379a94d028d18, 0xdf2ccd1fe00a03b6, 0x398471c1ff970f83,
0912         0x8c36b2214a3db8e7, 0x431dd42c3fe7f4fb, 0xb09bcf0fffb5b849, 0xc47dd13da60fb5a1,
0913         0x8fdad56516fe9d75, 0xc317e1025a7e1c63, 0x9ddcb98cbb384fda, 0x80adccda993bf70e,
0914         0x667f1622e4052ae4, 0xa41598d58f777363, 0x704b93d675808501, 0xaf046d3fd448aaf3,
0915         0x1dc4611873bf3f70, 0x834acdae9f0f4f53, 0x4f5d60585a5f1c1a, 0x3ced1b4be0d415c1,
0916         0x5d57f4de8ec12376, 0x51c0e7e72f799542, 0x46f7604940e6a510, 0x1a546a0f9345ed75,
0917         0x0df4097cab773ca2, 0x72b122774e4029e6, 0xae4a55b99aebd424, 0x04163a291bad2fa3,
0918         0x86ad58be322a49aa, 0x98f051614696e839, 0x64d08f241fc4ec58, 0xae41f23dca90dd5d,
0919         0x68bbd62f5af3107a, 0x7025f39ef241c56c, 0xd2e7c72fa9be33ac, 0x0aece66fd3e29a7d,
0920         0xd91241cebf3bd47c, 0x3ed7bfdee19ba2f6, 0x4bdf483194c7444e, 0xc99d83c931e8ab87,
0921         0x1732f416dbf7381f, 0x2ac88e244de13b96, 0x2cab688bd86c8bf8, 0x9f209787bb47d6b8,
0922         0x4c0678c5dbd23a49, 0xa0612c3c5ce15e55, 0x4dccc6ca29b3e9df, 0x0dc079c918022212,
0923         0x26be55a64c249495, 0x4da2c9789dd268b0, 0xe975528c76435158, 0xa6cb8a4d2356f9cf,
0924         0xdcafd2279c77d987, 0xaa9aff7904228690, 0xfb44d2f05d0842fb, 0x118fc9c217a1d2b2,
0925         0x04b3d9686f55b572, 0xbd9cb3625ef1cfc3, 0x2eba0e25e938e6c3, 0x1f48eaf234ad3a21,
0926         0xf2dc02fad2890f79, 0xace340325d4a7f9b, 0xe9e051f540b239dc, 0x221091f05abb8687,
0927         0x7e08deb014db8afe, 0x4711e1e9d9a094cc, 0x0b2d79bd90a9ef61, 0xb93d19bd45b82515,
0928         0x45e9e31d63c1afe1, 0x2c5f0a596005c216, 0xe687cc2331b14a12, 0x51963a2412b6f60c,
0929         0x91aeb77c8fe68eaa, 0xd6e18e8cc6841d68, 0x9391085cc2c933d9, 0x6e184be07e68df49,
0930         0x4fe4e52edb0dce60, 0x6cda31e8617f0ca2, 0xf8b9374fda7e7c95, 0x8032c603725e774d,
0931         0x222b6aa27e007612, 0xf7b7f47cf096afad, 0xe6a9fbafee77e77a, 0x3776ee406e63fbaa,
0932         0xde147932fcf78be6, 0x2ab9e031ffaa071e, 0x2169ad0e8a9b1256, 0xe33358135938b76a,
0933         0xcaec07e7a5373835, 0xef2863090a97c3ec, 0x6ccfb95f69c3adcc, 0x173e00da427cee4b,
0934         0x20f4ed58fcfb3040, 0x16f6fb326a60c32c, 0x2968fa04270ed545, 0x70673adfac0eabc4,
0935         0x6ff3c9364ff4e873, 0xde09ed35f13325d3, 0x2396e863b18c500f, 0xe22d253cc031e3ff,
0936         0x756d97a61247798d, 0xc9fc8d937e43c880, 0x0759ba59c08e14c7, 0xcd7aad86a4a45810,
0937         0x9f91c21c571dbe84, 0xd52d936f44abe8a3, 0xd5b48c100959d9d0, 0xb6cc856b3adc93b6,
0938         0x7aea8f8e067d2c8d, 0x04bc177f7b4287a6, 0xe3fcda36fa3b3342, 0xeaeb442e15d45095,
0939         0x2f4dd1ca5e89b18b, 0x602368385bb19cb1, 0x4bdfc434d3028181, 0x0b5a92cb80ac8150,
0940         0xb95953a97b1578ab, 0x46e6a18b01781b92, 0xdfd31585f38d7433, 0x0b1084b96009370b,
0941         0x9a81808e52462ba3, 0xff83368ace4af235, 0xb4e5d8a647e05e95, 0xf848cfc90df4b231,
0942         0x9919c68cf3576038, 0x1e89dad8a6790435, 0x7ac9361379139511, 0x7b5f9b6b937a7760,
0943         0x6e42e395fde0c1f7, 0x430cef1679799f8f, 0x0ad21cc1b4828074, 0x8982577d0ea42349,
0944         0xb1aca6185a7d0d0d, 0x4085c6db106c3d74, 0xba6f7a86e728a418, 0x0325a28758a974d2,
0945         0x57ea317f731817ed, 0xbd1e8e00b215a6eb, 0xb39f323742948e87, 0x9f9b0f873784cef4,
0946         0xa8c83d26585c5377, 0x837ba337bfcf893c, 0x0a7eeca62a23b805, 0xba4925a9e7f7346f,
0947         0xa574eebb90c8da6d, 0x5db7ff0e8d0b8d2d, 0x1562834c52c048d8, 0x0b2e577a853bcafc,
0948         0xdecef97a3524ff97, 0xeec053c8fd537066, 0xeaf2b1df83d600e4, 0x5be8b9ab7717eccf,
0949         0x05905b91ecbba038, 0xabacba5b373029ed, 0x22fb2283c0ee1267, 0x9c32b2ec3634c580,
0950         0x5186c586b6e5611c, 0x71eb0de5e91bb0a0, 0x89e969b42975ef08, 0x2ba0958bc44e322f,
0951         0x626d033cb828ba7d, 0xe5fbb65c7776509d, 0xb1403ae51ae9bc82, 0x5d773f0d9753a966,
0952         0x4a06feadd4ec8585, 0xda58a710fccd7b76, 0x6061ba4cd3d80d59, 0xf4824f5cfa2ba71c,
0953         0xfce622bba0ece756, 0x7d9c738486bc6842, 0x5f629d33c99db969, 0x855ff7c9b79362e6,
0954         0x892188a87c7de231, 0x85fea7caf30e2b5e, 0xbefeb221543782c5, 0x769ca33d280842f6,
0955         0x3974ebaf71353e52, 0xed0577283980f0cb, 0x7c37d689ab6b0662, 0x5037aeffcd3db52d,
0956         0x11bb0a5f64fbdcb5, 0xf5fd5aa5f2b7e974, 0xe1aa07ba7074367b, 0x4b5c14aa1c6a0d28,
0957         0xe9fc8c9c36f73953, 0x2609ad2cd0f99b76, 0x8d4f1d6bb589844f, 0xde09f066714fa909,
0958         0xe004c5d7adad3747, 0xd5ac81a94dfdefe3, 0xfd3e0083658a13c2, 0xf5512f25dd6e39a7,
0959         0xeb7204042ffa181d, 0x046d9254242d06e3, 0x91a5ca94f8706fab, 0xf5c58cc57af63c98,
0960         0x04e7ff1e23474908, 0xe4a9bec5c5818324, 0x1edfb105cc3084dd, 0x82431ec76e72a87a,
0961         0xe0b215be32c51083, 0x0d9942e3b5245098, 0xa49f1aad5723fd7e, 0xad45edba25a4bde8,
0962         0x241f0adc0cd56771, 0xf09bf2de59df3274, 0x090db856bbc020f2, 0x6aa4efb2d2ecb9bb,
0963         0xc6be4224ba04c233, 0x557a1760bde90850, 0x23090117938cb921, 0xcbec34da23f3e9c2,
0964         0xdfe2d55daad85c54, 0xa7932be700067f48, 0xfb7874535e2d76a4, 0x5161ba088056e74f,
0965         0xc275a8435be6cdb2, 0x05fcb771cab5aa15, 0x7f18a4382c9565a8, 0x4244c2cb833d6710,
0966         0x884e2b7a4a3db4d0, 0x08ded459d3edf2c2, 0x1616df531fee90cd, 0x9531c65800a97aaa,
0967         0x881ba77ab7e5d63a, 0x606d27428df4edd3, 0x294063ed78e305c7, 0x7de2b12f8a8cceb5,
0968         0xe6b01cc54a494437, 0x0cdecbe5ac90907c, 0xb88496c657d3e644, 0xf3eecf996f9c6b13,
0969         0x24aad7949edcde03, 0x304ca88ebfeaa534, 0x7b68a7bd3ef1916b, 0x3cc307a784d9060c,
0970         0x5dca03f19b213efd, 0xa380539c235f80c3, 0xf39756fc01d75bd7, 0x39ac6c7281739adb,
0971         0x4b606dc4aa036fda, 0x97126cd02a23b97c, 0x98c1e6906230aead, 0xe12d0f696a6bbc36,
0972         0x657a202bb6a89a33, 0x6421a07bda47e13d, 0x8d9d21b3c6b1dbee, 0x1f110f3744f13e0d,
0973         0x04d86fccb6e77ee8, 0x8c92852d9c9c14b3, 0x56be3cef19b19446, 0x57ceef0e2ebcbcf7,
0974         0x230a9328be0144bf, 0x3c1949b98a92aebc, 0x7ed2db80a62003f2, 0x84e609d13c7594f4,
0975         0xf8e81b9a9f35b4e8, 0xc2982fde1a087e4b, 0x84b0713cb3b18147, 0x3582530578d1ff08,
0976         0x0e5b6538cd61fce4, 0x46867abf4b6e72bc, 0x4fe9652832325e89, 0x7d141d065654745f,
0977         0x9bd5c0479188a53d, 0x4ccd47925108c00b, 0xfd3f6c8d961d47e3, 0x9c5c18a96093d2ad,
0978         0xa7d91bf008a358c3, 0x3ea3e5629f977d55, 0x80f0fed6a5f06003, 0x21f390e377ee4d68,
0979         0x73ed055ec082526b, 0x28482600c10f6ce2, 0x2bff1aaf94c11fe9, 0xde29cb7a943801b8,
0980         0x045b0493dd35af0e, 0xaeae25ff7a431c16, 0x78c9d3348f5364b7, 0xf973d1af84bc2476,
0981         0x4d2303e11baf18f3, 0xacebdb3fe5efbc7b, 0xd274a5cf5be50678, 0x2d60c40fdf53ac67,
0982         0x109592b606139855, 0x612f472a9c09925f, 0x701a035ccd4e7ab0, 0xac881f0db121a709,
0983         0xe1ed47438368366d, 0xde2faff8eeb2810a, 0x8eb2188044342ef9, 0x0e3c1aa7b6851548,
0984         0x7ce94a6ba4fd843f, 0x0da503676ee5ebb2, 0xf3bc7bb2cb8669e8, 0xd4b9e44de392fe64,
0985         0x81e470ebf207fdea, 0xdd53b09d49a0e5b5, 0xf78e23167a350d5a, 0x706470fc2d84423b,
0986         0x816ee82b19a29476, 0x35a9d218ba7cd4a1, 0xf590f12fb09b3fe3, 0x5e574140b302f8b7,
0987         0x6cb237a2021f77c3, 0x30a29037231a861e, 0xff4bb07af553a606, 0x831412ee2690d92c,
0988         0xf6d2d725ef14ff67, 0x2f79f810928a40ff, 0x2857d91ea9b04f71, 0xd063066f0ed78f3c,
0989         0xbf4b8dbc8a34017d, 0x6230f319f8b1f9c4, 0x061b0e25d8899834, 0x4071de32ef7ff0bf,
0990         0xbc546a0793fcfcd3, 0xd5881f5d968cf898, 0x0e21c0674cdda190, 0x0000000000000000};
0991 
0992     struct multiplier_index_info 
0993     {
0994         std::uint16_t first_cache_bit_index;
0995         std::uint16_t cache_bit_index_offset;
0996     };
0997 
0998     static constexpr multiplier_index_info multiplier_index_info_table[] = {
0999         {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 
1016 template <bool b> constexpr std::size_t extended_cache_long_impl<b>::max_cache_blocks;
1017 template <bool b> constexpr std::size_t extended_cache_long_impl<b>::cache_bits_unit;
1018 template <bool b> constexpr int extended_cache_long_impl<b>::segment_length;
1019 template <bool b> constexpr bool extended_cache_long_impl<b>::constant_block_count;
1020 template <bool b> constexpr int extended_cache_long_impl<b>::e_min;
1021 template <bool b> constexpr int extended_cache_long_impl<b>::k_min;
1022 template <bool b> constexpr int extended_cache_long_impl<b>::cache_bit_index_offset_base;
1023 template <bool b> constexpr std::uint64_t extended_cache_long_impl<b>::cache[];
1024 template <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 
1028 using extended_cache_long = extended_cache_long_impl<true>;
1029 
1030 struct 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         {0, 0, 0},          {377, 643, 9},      {1020, 1551, 22},  {1924, 2721, 39},
1085         {3046, 4109, 60},   {3114, 4443, 70},   {3368, 4962, 84},  {3807, 5667, 98},
1086         {4432, 6473, 111},  {5158, 7199, 123},  {5804, 7845, 134}, {6370, 8411, 143},
1087         {6856, 8896, 151},  {7261, 9302, 158},  {7587, 9628, 164}, {7833, 9874, 168},
1088         {7999, 10039, 171}, {8084, 10124, 173}, {8089, 0, 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 
1101 constexpr std::size_t extended_cache_compact::max_cache_blocks;
1102 constexpr std::size_t extended_cache_compact::cache_bits_unit;
1103 constexpr int extended_cache_compact::segment_length;
1104 constexpr bool extended_cache_compact::constant_block_count;
1105 constexpr int extended_cache_compact::collapse_factor;
1106 constexpr int extended_cache_compact::e_min;
1107 constexpr int extended_cache_compact::k_min;
1108 constexpr int extended_cache_compact::cache_bit_index_offset_base;
1109 constexpr int extended_cache_compact::cache_block_count_offset_base;
1110 constexpr extended_cache_compact::multiplier_index_info extended_cache_compact::multiplier_index_info_table[];
1111 constexpr std::uint8_t extended_cache_compact::cache_block_counts[];
1112 
1113 #endif
1114 
1115 struct 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         {0, 0, 0},        {860, 1698, 13},  {2506, 4181, 29}, {2941, 5069, 36},
1155         {3577, 5705, 41}, {3961, 6088, 44}, {4092, 0, 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 
1164 constexpr std::size_t extended_cache_super_compact::max_cache_blocks;
1165 constexpr std::size_t extended_cache_super_compact::cache_bits_unit;
1166 constexpr int extended_cache_super_compact::segment_length;
1167 constexpr bool extended_cache_super_compact::constant_block_count;
1168 constexpr int extended_cache_super_compact::collapse_factor;
1169 constexpr int extended_cache_super_compact::e_min;
1170 constexpr int extended_cache_super_compact::k_min;
1171 constexpr int extended_cache_super_compact::cache_bit_index_offset_base;
1172 constexpr int extended_cache_super_compact::cache_block_count_offset_base;
1173 constexpr std::uint64_t extended_cache_super_compact::cache[];
1174 constexpr extended_cache_super_compact::multiplier_index_info extended_cache_super_compact::multiplier_index_info_table[];
1175 constexpr 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 
1184 template <unsigned v1, unsigned v2, typename ExtendedCache>
1185 bool 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 
1260 template <unsigned v1, unsigned v2, typename ExtendedCache>
1261 inline 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 
1269 template <unsigned additional_neg_exp_of_2, unsigned additional_neg_exp_of_10, typename ExtendedCache>
1270 bool 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.
1304 inline 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 {buffer + 1, std::errc()};
1311     }
1312 
1313     if (buffer_size < static_cast<std::size_t>(precision) + 2U)
1314     {
1315         return {buffer + buffer_size, std::errc::value_too_large};
1316     }
1317 
1318     std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
1319     std::memset(buffer + 2, '0', static_cast<std::size_t>(precision)); // NOLINT : Specifically not null-terminating
1320     return {buffer + 2 + precision, std::errc()};
1321 }
1322 
1323 // precision means the number of decimal significand digits minus 1.
1324 // Assumes round-to-nearest, tie-to-even rounding.
1325 template <typename MainCache = main_cache_full, typename ExtendedCache>
1326 BOOST_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 {last, std::errc::value_too_large};
1332     }
1333 
1334     auto buffer_size = static_cast<std::size_t>(last - first);
1335     auto buffer = first;
1336     bool trailing_zeros_removed = false;
1337 
1338     BOOST_CHARCONV_ASSERT(precision >= 0);
1339     using namespace detail;
1340 
1341     std::uint64_t br = default_float_traits<double>::float_to_carrier(x);
1342     bool is_negative = ((br >> 63) != 0);
1343     br <<= 1;
1344     int e = static_cast<int>(br >> (ieee754_binary64::significand_bits + 1));
1345     auto significand = (br & ((UINT64_C(1) << (ieee754_binary64::significand_bits + 1)) - 1)); // shifted by 1-bit.
1346 
1347     if (is_negative)
1348     {
1349         *buffer = '-';
1350         ++buffer;
1351         --buffer_size;
1352 
1353         if (buffer_size == 0)
1354         {
1355             return {buffer, std::errc::value_too_large};
1356         }
1357     }
1358 
1359     // Infinities or NaN
1360     if (e == ((UINT32_C(1) << ieee754_binary64::exponent_bits) - 1)) 
1361     {
1362         if (significand == 0)
1363         {
1364             constexpr std::size_t inf_chars = 3;
1365 
1366             if (buffer_size < inf_chars)
1367             {
1368                 return {last, std::errc::value_too_large};
1369             }
1370 
1371             std::memcpy(buffer, "inf", inf_chars); // NOLINT : Specifically not null-terminating
1372             return {buffer + inf_chars, std::errc()};
1373         }
1374         else 
1375         {
1376             // Significand values for NaN by type
1377             // qNaN = 4503599627370496
1378             // sNaN = 2251799813685248
1379             //
1380             if (significand == UINT64_C(4503599627370496))
1381             {
1382                 if (!is_negative)
1383                 {
1384                     constexpr std::size_t nan_chars = 3;
1385 
1386                     if (buffer_size < nan_chars)
1387                     {
1388                         return {last, std::errc::value_too_large};
1389                     }
1390 
1391                     std::memcpy(buffer, "nan", nan_chars); // NOLINT : Specifically not null-terminating
1392                     return {buffer + nan_chars, std::errc()};
1393                 }
1394                 else
1395                 {
1396                     constexpr std::size_t neg_nan_chars = 8;
1397 
1398                     if (buffer_size < neg_nan_chars)
1399                     {
1400                         return {last, std::errc::value_too_large};
1401                     }
1402 
1403                     std::memcpy(buffer, "nan(ind)", neg_nan_chars); // NOLINT : Specifically not null-terminating
1404                     return {buffer + neg_nan_chars, std::errc()};
1405                 }
1406             }
1407             else
1408             {
1409                 constexpr std::size_t snan_chars = 9;
1410 
1411                 if (buffer_size < snan_chars)
1412                 {
1413                     return {last, std::errc::value_too_large};
1414                 }
1415 
1416                 std::memcpy(buffer, "nan(snan)", snan_chars); // NOLINT : Specifically not null-terminating
1417                 return {buffer + snan_chars, std::errc()};
1418             }
1419         }
1420     }
1421     else
1422     {
1423         // Normal numbers.
1424         if (e != 0)
1425         {
1426             significand |= (decltype(significand)(1) << (ieee754_binary64::significand_bits + 1));
1427             e += (ieee754_binary64::exponent_bias - ieee754_binary64::significand_bits);
1428         }
1429         // Subnormal numbers.
1430         else 
1431         {
1432             // Zero
1433             if (significand == 0) 
1434             {
1435                 if (fmt == boost::charconv::chars_format::general)
1436                 {
1437                     // For the case of chars_format::general, 0 is always printed as 0.
1438                     *buffer = '0';
1439                     return {buffer + 1, std::errc()};
1440                 }
1441                 else if (fmt == boost::charconv::chars_format::fixed)
1442                 {
1443                     return print_zero_fixed(buffer, buffer_size, precision);
1444                 }
1445                 // For the case of chars_format::scientific, print as many 0's as requested after the decimal dot, and then print e+00.
1446                 if (precision == 0) 
1447                 {
1448                     constexpr std::size_t zero_chars = 5;
1449 
1450                     if (buffer_size < zero_chars)
1451                     {
1452                         return {last, std::errc::value_too_large};
1453                     }
1454 
1455                     std::memcpy(buffer, "0e+00", zero_chars);
1456                     return {buffer + zero_chars, std::errc()};
1457                 }
1458                 else 
1459                 {
1460                     if (buffer_size < static_cast<std::size_t>(precision) + 6U)
1461                     {
1462                         return {last, std::errc::value_too_large};
1463                     }
1464 
1465                     std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
1466                     std::memset(buffer + 2, '0', static_cast<std::size_t>(precision)); // NOLINT : Specifically not null-terminating
1467                     std::memcpy(buffer + 2 + precision, "e+00", 4); // NOLINT : Specifically not null-terminating
1468                     return {buffer + precision + 6, std::errc()};
1469                 }
1470             }
1471             // Nonzero
1472             e = ieee754_binary64::min_exponent - ieee754_binary64::significand_bits;
1473         }
1474     }
1475 
1476     constexpr int kappa = 2;
1477     int k = kappa - log::floor_log10_pow2(e);
1478     std::uint32_t current_digits {};
1479     char* const buffer_starting_pos = buffer;
1480     char* decimal_dot_pos = buffer; // decimal_dot_pos == buffer_starting_pos indicates that there should be no decimal dot.
1481     int decimal_exponent_normalized {};
1482 
1483     // Number of digits to be printed.
1484     int remaining_digits {};
1485 
1486     /////////////////////////////////////////////////////////////////////////////////////////////////
1487     /// Phase 1 - Print the first digit segment computed with the Dragonbox table.
1488     /////////////////////////////////////////////////////////////////////////////////////////////////
1489 
1490     {
1491         // Compute the first digit segment.
1492         const auto main_cache = MainCache::template get_cache<ieee754_binary64>(k);
1493         const int beta = e + log::floor_log2_pow10(k);
1494 
1495         // Integer check is okay for binary64.
1496         //auto [first_segment, has_more_segments] 
1497         compute_mul_result segments = [&] {
1498             const auto r = umul192_upper128(significand << beta, main_cache);
1499             return compute_mul_result{r.high, r.low == 0};
1500         }();
1501 
1502         auto first_segment = segments.result;
1503         auto has_more_segments = !segments.is_integer;
1504 
1505         // The first segment can be up to 19 digits. It is in fact always of either 18 or 19
1506         // digits except when the input is a subnormal number. For subnormal numbers, the
1507         // smallest possible value of the first segment is 10^kappa, so it is of at least
1508         // kappa+1 digits (i.e., 3 in this case).
1509 
1510         int first_segment_length = 19;
1511         auto first_segment_aligned = first_segment; // Aligned to have 19 digits.
1512         while (first_segment_aligned < UINT64_C(10000000000000000))
1513         {
1514             first_segment_aligned *= 100;
1515             first_segment_length -= 2;
1516         }
1517         if (first_segment_aligned < UINT64_C(1000000000000000000))
1518         {
1519             first_segment_aligned *= 10;
1520             first_segment_length -= 1;
1521         }
1522         // The decimal exponent when written as X.XXXX.... x 10^XX.
1523         decimal_exponent_normalized = first_segment_length - k - 1;
1524 
1525         // Figure out the correct value of remaining_digits.
1526         if (fmt == boost::charconv::chars_format::scientific)
1527         {
1528             remaining_digits = precision + 1;
1529 
1530             // e+XX or e+XXX since we always print at least two characters e.g. e+02
1531             const int exponent_print_length =
1532                 decimal_exponent_normalized > -100 && decimal_exponent_normalized < 100 ? 4 : 5;
1533 
1534             // No trailing decimal dot.
1535             const auto minimum_required_buffer_size =
1536                 static_cast<std::size_t>(remaining_digits + exponent_print_length + (precision != 0 ? 1 : 0));
1537             if (buffer_size < minimum_required_buffer_size)
1538             {
1539                 return {last, std::errc::value_too_large};
1540             }
1541 
1542             if (precision != 0)
1543             {
1544                 // Reserve a place for the decimal dot.
1545                 *buffer = '0';
1546                 ++buffer;
1547                 ++decimal_dot_pos;
1548             }
1549         }
1550         else if (fmt == boost::charconv::chars_format::fixed)
1551         {
1552             if (decimal_exponent_normalized >= 0)
1553             {
1554                 remaining_digits = precision + decimal_exponent_normalized + 1;
1555                 
1556                 // No trailing decimal dot.
1557                 auto minimum_required_buffer_size =
1558                     static_cast<std::size_t>(remaining_digits + (precision != 0 ? 1 : 0));
1559 
1560                 // We need one more space if the rounding changes the exponent,
1561                 // but since we don't know at this point if that will actually happen, handle such a case later.
1562 
1563                 if (buffer_size < minimum_required_buffer_size)
1564                 {
1565                     return {last, std::errc::value_too_large};
1566                 }
1567 
1568                 if (precision != 0)
1569                 {
1570                     // Reserve a place for the decimal dot.
1571                     *buffer = '0';
1572                     ++buffer;
1573                     decimal_dot_pos += decimal_exponent_normalized + 1;
1574                 }
1575             }
1576             else
1577             {
1578                 int number_of_leading_zeros = -decimal_exponent_normalized - 1;
1579 
1580                 // When there are more than precision number of leading zeros,
1581                 // all the digits we need to print are 0.
1582                 if (number_of_leading_zeros > precision)
1583                 {
1584                     return print_zero_fixed(buffer, buffer_size, precision);
1585                 }
1586                 // When the number of leading zeros is exactly precision,
1587                 // then we might need to print 1 at the last digit due to rounding.
1588                 if (number_of_leading_zeros == precision)
1589                 {
1590                     // Since the last digit before rounding is 0,
1591                     // according to the "round-to-nearest, tie-to-even" rule, we round-up
1592                     // if and only if the input is strictly larger than the midpoint.
1593                     bool round_up = (first_segment_aligned + (has_more_segments ? 1 : 0)) > UINT64_C(5000000000000000000);
1594                     if (!round_up)
1595                     {
1596                         return print_zero_fixed(buffer, buffer_size, precision);
1597                     }
1598 
1599                     // No trailing decimal dot.
1600                     if (precision == 0)
1601                     {
1602                         *buffer = '1';
1603                         return {buffer + 1, std::errc()};
1604                     }
1605 
1606                     if (buffer_size < static_cast<std::size_t>(precision) + 2U)
1607                     {
1608                         return {buffer + buffer_size, std::errc::value_too_large};
1609                     }
1610 
1611                     std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
1612                     std::memset(buffer + 2, '0', static_cast<std::size_t>(precision - 1)); // NOLINT : Specifically not null-terminating
1613                     buffer[1 + precision] = '1';
1614                     return {buffer + 2 + precision, std::errc()};
1615                 }
1616 
1617                 remaining_digits = precision - number_of_leading_zeros;
1618                 
1619                 // Always have decimal dot.
1620                 BOOST_CHARCONV_ASSERT(precision > 0);
1621                 auto minimum_required_buffer_size = static_cast<std::size_t>(precision + 2);
1622                 if (buffer_size < minimum_required_buffer_size)
1623                 {
1624                     return {last, std::errc::value_too_large};
1625                 }
1626 
1627                 // Print leading zeros.
1628                 std::memset(buffer, '0', static_cast<std::size_t>(number_of_leading_zeros + 2));
1629                 buffer += number_of_leading_zeros + 2;
1630                 ++decimal_dot_pos;
1631             }
1632         }
1633         else
1634         {
1635             // fmt == boost::charconv::chars_format::general
1636             if (precision == 0)
1637             {
1638                 // For general format, precision = 0 is interpreted as precision = 1.
1639                 precision = 1;
1640             }
1641             remaining_digits = precision;
1642 
1643             // Use scientific format if decimal_exponent_normalized <= -6 or decimal_exponent_normalized >= precision.
1644             // Use fixed format if -4 <= decimal_exponent_normalized <= precision - 2.
1645             // If decimal_exponent_normalized == -5, use fixed format if and only if the rounding increases the exponent.
1646             // If decimal_exponent_normalized == precision - 1, use scientific format if and only if the rounding increases the exponent.
1647             // Since we cannot reliably decide which format to use, necessary corrections will be made in the last phase.
1648 
1649             // We may end up not printing the decimal dot if fixed format is chosen, but reserve a place anyway.
1650             *buffer = '0';
1651             ++buffer;
1652             decimal_dot_pos += (0 < decimal_exponent_normalized && decimal_exponent_normalized < precision)
1653                                 ? decimal_exponent_normalized + 1 : 1;
1654         }
1655 
1656         if (remaining_digits <= 2) 
1657         {
1658             uint128 prod;
1659             std::uint64_t fractional_part64;
1660             std::uint64_t fractional_part_rounding_threshold64;
1661 
1662             // Convert to fixed-point form with 64/32-bit boundary for the fractional part.
1663 
1664             if (remaining_digits == 1)
1665             {
1666                 prod = umul128(first_segment_aligned, UINT64_C(1329227995784915873));
1667                 // ceil(2^63 + 2^64/10^18)
1668                 fractional_part_rounding_threshold64 = additional_static_data_holder::fractional_part_rounding_thresholds64[17];
1669             }
1670             else
1671             {
1672                 prod = umul128(first_segment_aligned, UINT64_C(13292279957849158730));
1673                 // ceil(2^63 + 2^64/10^17)
1674                 fractional_part_rounding_threshold64 = additional_static_data_holder::
1675                     fractional_part_rounding_thresholds64[16];
1676             }
1677             fractional_part64 = (prod.low >> 56) | (prod.high << 8);
1678             current_digits = static_cast<std::uint32_t>(prod.high >> 56);
1679 
1680             // Perform rounding, print the digit, and return.
1681             if (remaining_digits == 1)
1682             {
1683                 if (fractional_part64 >= fractional_part_rounding_threshold64 ||
1684                     ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0) 
1685                 {
1686                     goto round_up_one_digit;
1687                 }
1688 
1689                 print_1_digit(current_digits, buffer);
1690                 ++buffer;
1691             }
1692             else 
1693             {
1694                 if (fractional_part64 >= fractional_part_rounding_threshold64 ||
1695                     ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1696                 {
1697                     goto round_up_two_digits;
1698                 }
1699 
1700                 print_2_digits(current_digits, buffer);
1701                 buffer += 2;
1702             }
1703 
1704             goto insert_decimal_dot;
1705         } // remaining_digits <= 2
1706 
1707         // At this point, there are at least 3 digits to print.
1708         // We split the segment into three chunks, each consisting of 9 digits, 8 digits,
1709         // and 2 digits.
1710 
1711         // MSVC doesn't know how to do Grandlund-Montgomery for large 64-bit integers.
1712         // 7922816251426433760 = ceil(2^96/10^10) = floor(2^96*(10^9/(10^19 - 1)))
1713         const auto first_subsegment =
1714             static_cast<std::uint32_t>(umul128_upper64(first_segment, UINT64_C(7922816251426433760)) >> 32);
1715 
1716         const auto second_third_subsegments =
1717             first_segment - first_subsegment * UINT64_C(10000000000);
1718 
1719         BOOST_CHARCONV_ASSERT(first_subsegment < UINT64_C(1000000000));
1720         BOOST_CHARCONV_ASSERT(second_third_subsegments < UINT64_C(10000000000));
1721 
1722         int remaining_digits_in_the_current_subsegment;
1723         std::uint64_t prod; // holds intermediate values for digit generation.
1724 
1725         // Print the first subsegment.
1726         if (first_subsegment != 0)
1727         {
1728             // 9 digits (19 digits in total).
1729             if (first_subsegment >= 100000000) 
1730             {
1731                 // 1441151882 = ceil(2^57 / 10^8) + 1
1732                 prod = first_subsegment * UINT64_C(1441151882);
1733                 prod >>= 25;
1734                 remaining_digits_in_the_current_subsegment = 8;
1735             }
1736             // 7 or 8 digits (17 or 18 digits in total).
1737             else if (first_subsegment >= 1000000)
1738             {
1739                 // 281474978 = ceil(2^48 / 10^6) + 1
1740                 prod = first_subsegment * UINT64_C(281474978);
1741                 prod >>= 16;
1742                 remaining_digits_in_the_current_subsegment = 6;
1743             }
1744             // 5 or 6 digits (15 or 16 digits in total).
1745             else if (first_subsegment >= 10000)
1746             {
1747                 // 429497 = ceil(2^32 / 10^4)
1748                 prod = first_subsegment * UINT64_C(429497);
1749                 remaining_digits_in_the_current_subsegment = 4;
1750             }
1751             // 3 or 4 digits (13 or 14 digits in total).
1752             else if (first_subsegment >= 100)
1753             {
1754                 // 42949673 = ceil(2^32 / 10^2)
1755                 prod = first_subsegment * UINT64_C(42949673);
1756                 remaining_digits_in_the_current_subsegment = 2;
1757             }
1758             // 1 or 2 digits (11 or 12 digits in total).
1759             else
1760             {
1761                 prod = std::uint64_t(first_subsegment) << 32;
1762                 remaining_digits_in_the_current_subsegment = 0;
1763             }
1764 
1765             const auto initial_digits = static_cast<std::uint32_t>(prod >> 32);
1766 
1767             buffer -= (initial_digits < 10 && buffer != first ? 1 : 0);
1768             remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
1769 
1770             // Avoid the situation where we have a leading 0 that we don't need
1771             // Typically used to account for inserting a decimal, but we know
1772             // we won't need that in the 0 precision case
1773             if (precision == 0 && initial_digits < 10)
1774             {
1775                 print_1_digit(initial_digits, buffer);
1776                 ++buffer;
1777             }
1778             else
1779             {
1780                 print_2_digits(initial_digits, buffer);
1781                 buffer += 2;
1782             }
1783 
1784             if (remaining_digits > remaining_digits_in_the_current_subsegment) 
1785             {
1786                 remaining_digits -= remaining_digits_in_the_current_subsegment;
1787                 
1788                 for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2) 
1789                 {
1790                     // Write next two digits.
1791                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1792                     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1793                     buffer += 2;
1794                 }
1795             }
1796             else 
1797             {
1798                 for (int i = 0; i < (remaining_digits - 1) / 2; ++i) 
1799                 {
1800                     // Write next two digits.
1801                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1802                     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1803                     buffer += 2;
1804                 }
1805 
1806                 // Distinguish two cases of rounding.
1807                 if (remaining_digits_in_the_current_subsegment > remaining_digits)
1808                 {
1809                     if ((remaining_digits & 1) != 0) 
1810                     {
1811                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
1812                     }
1813                     else 
1814                     {
1815                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1816                     }
1817                     
1818                     current_digits = static_cast<std::uint32_t>(prod >> 32);
1819 
1820                     if (check_rounding_condition_inside_subsegment(
1821                             current_digits, static_cast<std::uint32_t>(prod),
1822                             remaining_digits_in_the_current_subsegment - remaining_digits,
1823                             second_third_subsegments != 0 || has_more_segments)) 
1824                     {
1825                         goto round_up;
1826                     }
1827 
1828                     goto print_last_digits;
1829                 }
1830                 else 
1831                 {
1832                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1833                     current_digits = static_cast<std::uint32_t>(prod >> 32);
1834 
1835                     if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
1836                             current_digits,
1837                             uint_with_known_number_of_digits<10>{second_third_subsegments},
1838                             has_more_segments)) 
1839                     {
1840                         goto round_up_two_digits;
1841                     }
1842 
1843                     goto print_last_two_digits;
1844                 }
1845             }
1846         }
1847 
1848         // Print the second subsegment.
1849         // The second subsegment cannot be zero even for subnormal numbers.
1850 
1851         if (remaining_digits <= 2) 
1852         {
1853             // In this case the first subsegment must be nonzero.
1854 
1855             if (remaining_digits == 1) 
1856             {
1857                 const auto prod128 = umul128(second_third_subsegments, UINT64_C(18446744074));
1858 
1859                 current_digits = static_cast<std::uint32_t>(prod128.high);
1860                 const auto fractional_part64 = prod128.low + 1;
1861                 // 18446744074 is even, so prod.low cannot be equal to 2^64 - 1.
1862                 BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
1863 
1864                 if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[8] ||
1865                     ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0) 
1866                 {
1867                     goto round_up_one_digit;
1868                 }
1869 
1870                 goto print_last_one_digit;
1871             } // remaining_digits == 1
1872             else 
1873             {
1874                 const auto prod128 = umul128(second_third_subsegments, UINT64_C(184467440738));
1875 
1876                 current_digits = static_cast<std::uint32_t>(prod128.high);
1877                 const auto fractional_part64 = prod128.low + 1;
1878                 // 184467440738 is even, so prod.low cannot be equal to 2^64 - 1.
1879                 BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
1880 
1881                 if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[7] ||
1882                     ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0) 
1883                 {
1884                     goto round_up_two_digits;
1885                 }
1886 
1887                 goto print_last_two_digits;
1888             }
1889         } // remaining_digits <= 2
1890 
1891         // Compilers are not aware of how to leverage the maximum value of
1892         // second_third_subsegments to find out a better magic number which allows us to
1893         // eliminate an additional shift.
1894         // 184467440737095517 = ceil(2^64/100) < floor(2^64*(10^8/(10^10 - 1))).
1895         const auto second_subsegment = static_cast<std::uint32_t>(
1896             umul128_upper64(second_third_subsegments, UINT64_C(184467440737095517)));
1897 
1898         // Since the final result is of 2 digits, we can do the computation in 32-bits.
1899         const auto third_subsegment =
1900             static_cast<std::uint32_t>(second_third_subsegments) - second_subsegment * 100;
1901 
1902         BOOST_CHARCONV_ASSERT(second_subsegment < 100000000);
1903         BOOST_CHARCONV_ASSERT(third_subsegment < 100);
1904 
1905         {
1906             std::uint32_t initial_digits;
1907             if (first_subsegment != 0) 
1908             {
1909                 prod = ((second_subsegment * UINT64_C(281474977)) >> 16) + 1;
1910                 remaining_digits_in_the_current_subsegment = 6;
1911 
1912                 initial_digits = static_cast<std::uint32_t>(prod >> 32);
1913                 remaining_digits -= 2;
1914             }
1915             else 
1916             {
1917                 // 7 or 8 digits (9 or 10 digits in total).
1918                 if (second_subsegment >= 1000000) 
1919                 {
1920                     prod = (second_subsegment * UINT64_C(281474978)) >> 16;
1921                     remaining_digits_in_the_current_subsegment = 6;
1922                 }
1923                 // 5 or 6 digits (7 or 8 digits in total).
1924                 else if (second_subsegment >= 10000)
1925                 {
1926                     prod = second_subsegment * UINT64_C(429497);
1927                     remaining_digits_in_the_current_subsegment = 4;
1928                 }
1929                 // 3 or 4 digits (5 or 6 digits in total).
1930                 else if (second_subsegment >= 100)
1931                 {
1932                     prod = second_subsegment * UINT64_C(42949673);
1933                     remaining_digits_in_the_current_subsegment = 2;
1934                 }
1935                 // 1 or 2 digits (3 or 4 digits in total).
1936                 else
1937                 {
1938                     prod = std::uint64_t(second_subsegment) << 32;
1939                     remaining_digits_in_the_current_subsegment = 0;
1940                 }
1941 
1942                 initial_digits = static_cast<std::uint32_t>(prod >> 32);
1943                 buffer -= (initial_digits < 10 ? 1 : 0);
1944                 remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
1945             }
1946 
1947             print_2_digits(initial_digits, buffer);
1948             buffer += 2;
1949 
1950             if (remaining_digits > remaining_digits_in_the_current_subsegment)
1951             {
1952                 remaining_digits -= remaining_digits_in_the_current_subsegment;
1953                 for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2) 
1954                 {
1955                     // Write next two digits.
1956                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1957                     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1958                     buffer += 2;
1959                 }
1960             }
1961             else 
1962             {
1963                 for (int i = 0; i < (remaining_digits - 1) / 2; ++i) 
1964                 {
1965                     // Write next two digits.
1966                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1967                     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1968                     buffer += 2;
1969                 }
1970 
1971                 // Distinguish two cases of rounding.
1972                 if (remaining_digits_in_the_current_subsegment > remaining_digits) 
1973                 {
1974                     if ((remaining_digits & 1) != 0) 
1975                     {
1976                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
1977                     }
1978                     else 
1979                     {
1980                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1981                     }
1982                     current_digits = static_cast<std::uint32_t>(prod >> 32);
1983 
1984                     if (check_rounding_condition_inside_subsegment(
1985                             current_digits, static_cast<std::uint32_t>(prod),
1986                             remaining_digits_in_the_current_subsegment - remaining_digits,
1987                             third_subsegment != 0 || has_more_segments)) 
1988                     {
1989                         goto round_up;
1990                     }
1991 
1992                     goto print_last_digits;
1993                 }
1994                 else 
1995                 {
1996                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1997                     current_digits = static_cast<std::uint32_t>(prod >> 32);
1998 
1999                     if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2000                             current_digits,
2001                             uint_with_known_number_of_digits<2>{third_subsegment},
2002                             has_more_segments)) 
2003                     {
2004                         goto round_up_two_digits;
2005                     }
2006 
2007                     goto print_last_two_digits;
2008                 }
2009             }
2010         }
2011 
2012         // Print the third subsegment.
2013         {
2014             if (remaining_digits > 2) 
2015             {
2016                 print_2_digits(third_subsegment, buffer);
2017                 buffer += 2;
2018                 remaining_digits -= 2;
2019 
2020                 // If there is no more segment, then fill remaining digits with 0's and return.
2021                 if (!has_more_segments) 
2022                 {
2023                     goto fill_remaining_digits_with_0s;
2024                 }
2025             }
2026             else if (remaining_digits == 1) 
2027             {
2028                 prod = third_subsegment * UINT64_C(429496730);
2029                 current_digits = static_cast<std::uint32_t>(prod >> 32);
2030 
2031                 if (check_rounding_condition_inside_subsegment(
2032                         current_digits, static_cast<std::uint32_t>(prod), 1, has_more_segments)) 
2033                 {
2034                     goto round_up_one_digit;
2035                 }
2036 
2037                 goto print_last_one_digit;
2038             }
2039             else 
2040             {
2041                 // remaining_digits == 2.
2042                 // If there is no more segment, then print the current two digits and return.
2043                 if (!has_more_segments)
2044                 {
2045                     print_2_digits(third_subsegment, buffer);
2046                     buffer += 2;
2047                     goto insert_decimal_dot;
2048                 }
2049 
2050                 // Otherwise, for performing the rounding, we have to wait until the next
2051                 // segment becomes available. This state can be detected afterward by
2052                 // inspecting if remaining_digits == 0.
2053                 remaining_digits = 0;
2054                 current_digits = third_subsegment;
2055             }
2056         }
2057     }
2058 
2059     /////////////////////////////////////////////////////////////////////////////////////////////////
2060     /// Phase 2 - Print further digit segments computed with the extended cache table.
2061     /////////////////////////////////////////////////////////////////////////////////////////////////
2062 
2063     {
2064         auto multiplier_index =
2065             static_cast<std::uint32_t>(k + ExtendedCache::segment_length - ExtendedCache::k_min) /
2066             static_cast<std::uint32_t>(ExtendedCache::segment_length);
2067 
2068         int digits_in_the_second_segment;
2069         {
2070             const auto new_k =
2071                 ExtendedCache::k_min + static_cast<int>(multiplier_index) * ExtendedCache::segment_length;
2072             digits_in_the_second_segment = new_k - k;
2073             k = new_k;
2074         }
2075 
2076         const auto exp2_base = e + boost::core::countr_zero(significand);
2077 
2078         using cache_block_type = typename std::decay<decltype(ExtendedCache::cache[0])>::type;
2079         
2080         cache_block_type blocks[ExtendedCache::max_cache_blocks];
2081         cache_block_count_t<ExtendedCache::constant_block_count, ExtendedCache::max_cache_blocks> cache_block_count;
2082 
2083         // Deal with the second segment. The second segment is special because it can have
2084         // overlapping digits with the first segment. Note that we cannot just move the buffer
2085         // pointer backward and print the whole segment from there, because it may contain
2086         // leading zeros.
2087         {
2088             cache_block_count =
2089                 load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(
2090                     blocks, e, k, multiplier_index);
2091 
2092             // Compute nm mod 2^Q.
2093             fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
2094 
2095             BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
2096             {
2097                 // No rounding, continue.
2098                 if (remaining_digits > digits_in_the_second_segment)
2099                 {
2100                     remaining_digits -= digits_in_the_second_segment;
2101 
2102                     if (digits_in_the_second_segment <= 2)
2103                     {
2104                         BOOST_CHARCONV_ASSERT(digits_in_the_second_segment != 0);
2105 
2106                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2107                             power_of_10[19], blocks, cache_block_count);
2108 
2109                         auto subsegment =
2110                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2111                                 generate_and_discard_lower(power_of_10[3], blocks,
2112                                                             cache_block_count);
2113 
2114                         if (digits_in_the_second_segment == 1)
2115                         {
2116                             auto prod = subsegment * UINT64_C(429496730);
2117                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2118                             print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2119                             ++buffer;
2120                         }
2121                         else 
2122                         {
2123                             auto prod = subsegment * UINT64_C(42949673);
2124                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2125                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2126                             buffer += 2;
2127                         }
2128                     } // digits_in_the_second_segment <= 2
2129                     else if (digits_in_the_second_segment <= 16)
2130                     {
2131                         BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
2132                         
2133                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2134                             compute_power(UINT64_C(10), 22 - digits_in_the_second_segment),
2135                             blocks, cache_block_count);
2136 
2137                         // When there are at most 9 digits, we can store them in 32-bits.
2138                         if (digits_in_the_second_segment <= 9) 
2139                         {
2140                             // The number of overlapping digits is in the range 13 ~ 19.
2141                             const auto subsegment =
2142                                 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2143                                     generate_and_discard_lower(power_of_10[9], blocks,
2144                                                                 cache_block_count);
2145 
2146                             std::uint64_t prod;
2147                             if ((digits_in_the_second_segment & 1) != 0)
2148                             {
2149                                 prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
2150                                 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2151                                 ++buffer;
2152                             }
2153                             else
2154                             {
2155                                 prod = ((subsegment * UINT64_C(450359963)) >> 20) + 1;
2156                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2157                                 buffer += 2;
2158                             }
2159 
2160                             for (; digits_in_the_second_segment > 2; digits_in_the_second_segment -= 2)
2161                             {
2162                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2163                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2164                                 buffer += 2;
2165                             }
2166                         } // digits_in_the_second_segment <= 9
2167                         else 
2168                         {
2169                             // The number of digits in the segment is in the range 10 ~ 16.
2170                             const auto first_second_subsegments =
2171                                 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2172                                     generate_and_discard_lower(power_of_10[16], blocks,
2173                                                                 cache_block_count);
2174 
2175                             // The first segment is of 8 digits, and the second segment is of
2176                             // 2 ~ 8 digits.
2177                             // ceil(2^(64+14)/10^8) = 3022314549036573
2178                             // = floor(2^(64+14)*(10^8/(10^16 - 1)))
2179                             const auto first_subsegment =
2180                                 static_cast<std::uint32_t>(umul128_upper64(first_second_subsegments,
2181                                                                         UINT64_C(3022314549036573)) >>
2182                                                 14);
2183                             const auto second_subsegment =
2184                                 static_cast<std::uint32_t>(first_second_subsegments) -
2185                                 UINT32_C(100000000) * first_subsegment;
2186 
2187                             // Print the first subsegment.
2188                             print_8_digits(first_subsegment, buffer);
2189                             buffer += 8;
2190 
2191                             // Print the second subsegment.
2192                             // There are at least 2 digits in the second subsegment.
2193                             auto prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
2194                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2195                             buffer += 2;
2196                             digits_in_the_second_segment -= 10;
2197 
2198                             for (; digits_in_the_second_segment > 1; digits_in_the_second_segment -= 2)
2199                             {
2200                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2201                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2202                                 buffer += 2;
2203                             }
2204 
2205                             if (digits_in_the_second_segment != 0)
2206                             {
2207                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2208                                 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2209                                 ++buffer;
2210                             }
2211                         }
2212                     } // digits_in_the_second_segment <= 16
2213                     else 
2214                     {
2215                         // The number of digits in the segment is in the range 17 ~ 22.
2216                         const auto first_subsegment =
2217                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
2218                                 power_of_10[6], blocks, cache_block_count);
2219 
2220                         const auto second_third_subsegments =
2221                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2222                                 generate_and_discard_lower(power_of_10[16], blocks,
2223                                                             cache_block_count);
2224 
2225                         // ceil(2^(64+14)/10^8) = 3022314549036573
2226                         // = floor(2^(64+14)*(10^8/(10^16 - 1)))
2227                         const auto second_subsegment =
2228                             static_cast<std::uint32_t>(umul128_upper64(second_third_subsegments,
2229                                                                     UINT64_C(3022314549036573)) >>
2230                                             14);
2231                         const auto third_subsegment = static_cast<std::uint32_t>(second_third_subsegments) -
2232                                                         UINT32_C(100000000) * second_subsegment;
2233 
2234                         // Print the first subsegment (1 ~ 6 digits).
2235                         std::uint64_t prod {};
2236                         auto remaining_digits_in_the_current_subsegment =
2237                             digits_in_the_second_segment - 16;
2238 
2239                         switch (remaining_digits_in_the_current_subsegment)
2240                         {
2241                         case 1:
2242                             prod = first_subsegment * UINT64_C(429496730);
2243                             goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2244 
2245                         case 2:
2246                             prod = first_subsegment * UINT64_C(42949673);
2247                             goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2248 
2249                         case 3:
2250                             prod = first_subsegment * UINT64_C(4294968);
2251                             goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2252 
2253                         case 4:
2254                             prod = first_subsegment * UINT64_C(429497);
2255                             goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2256 
2257                         case 5:
2258                             prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2259                             goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2260 
2261                         case 6:
2262                             prod = first_subsegment * UINT64_C(429497);
2263                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2264                             buffer += 2;
2265                             remaining_digits_in_the_current_subsegment = 4;
2266                             goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2267 
2268                         default:
2269                             BOOST_UNREACHABLE_RETURN(prod); // NOLINT
2270                         }
2271 
2272                     second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining
2273                         :
2274                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2275                         print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2276                         ++buffer;
2277 
2278                     second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining
2279                         :
2280                         for (; remaining_digits_in_the_current_subsegment > 1;
2281                                 remaining_digits_in_the_current_subsegment -= 2)
2282                         {
2283                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2284                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2285                             buffer += 2;
2286                         }
2287 
2288                         // Print the second and third subsegments (8 digits each).
2289                         print_8_digits(second_subsegment, buffer);
2290                         print_8_digits(third_subsegment, buffer + 8);
2291                         buffer += 16;
2292                     }
2293                 } // remaining_digits > digits_in_the_second_segment
2294 
2295                 // Perform rounding and return.
2296                 else
2297                 {
2298                     if (digits_in_the_second_segment <= 2)
2299                     {
2300                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2301                             power_of_10[19], blocks, cache_block_count);
2302 
2303                         // Get one more bit for potential rounding on the segment boundary.
2304                         auto subsegment =
2305                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2306                                 generate_and_discard_lower(2000, blocks, cache_block_count);
2307 
2308                         bool segment_boundary_rounding_bit = ((subsegment & 1) != 0);
2309                         subsegment >>= 1;
2310 
2311                         if (digits_in_the_second_segment == 2)
2312                         {
2313                             // Convert subsegment into fixed-point fractional form where the
2314                             // integer part is of one digit. The integer part is ignored.
2315                             // 42949673 = ceil(2^32/10^2)
2316                             auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(42949673);
2317 
2318                             if (remaining_digits == 1)
2319                             {
2320                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2321                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
2322                                 const bool has_further_digits_v = has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
2323                                 if (check_rounding_condition_inside_subsegment(current_digits, static_cast<std::uint32_t>(prod), 1, has_further_digits_v))
2324                                 {
2325                                     goto round_up_one_digit;
2326                                 }
2327                                 goto print_last_one_digit;
2328                             }
2329 
2330                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2331                             const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2332 
2333                             if (remaining_digits == 0)
2334                             {
2335                                 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2336                                         current_digits,
2337                                         uint_with_known_number_of_digits<2>{next_digits},
2338                                         has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))) 
2339                                 {
2340                                     goto round_up_two_digits;
2341                                 }
2342                                 goto print_last_two_digits;
2343                             }
2344 
2345                             current_digits = next_digits;
2346                             BOOST_CHARCONV_ASSERT(remaining_digits == 2);
2347                         }
2348                         else
2349                         {
2350                             BOOST_CHARCONV_ASSERT(digits_in_the_second_segment == 1);
2351                             // Convert subsegment into fixed-point fractional form where the
2352                             // integer part is of two digits. The integer part is ignored.
2353                             // 429496730 = ceil(2^32/10^1)
2354                             auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(429496730);
2355                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2356                             const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2357 
2358                             if (remaining_digits == 0) 
2359                             {
2360                                 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2361                                         current_digits,
2362                                         uint_with_known_number_of_digits<1>{next_digits},
2363                                         has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2364                                 {
2365                                     goto round_up_two_digits;
2366                                 }
2367                                 goto print_last_two_digits;
2368                             }
2369 
2370                             current_digits = next_digits;
2371                             BOOST_CHARCONV_ASSERT(remaining_digits == 1);
2372                         }
2373 
2374                         if (check_rounding_condition_with_next_bit(
2375                                 current_digits, segment_boundary_rounding_bit,
2376                                 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0))) 
2377                         {
2378                             goto round_up;
2379                         }
2380 
2381                         goto print_last_digits;
2382                     } // digits_in_the_second_segment <= 2
2383 
2384                     // When there are at most 9 digits in the segment.
2385                     if (digits_in_the_second_segment <= 9)
2386                     {
2387                         // Throw away all overlapping digits.
2388                         BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
2389 
2390                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2391                             compute_power(UINT64_C(10), 22 - digits_in_the_second_segment),
2392                             blocks, cache_block_count);
2393 
2394                         // Get one more bit for potential rounding on the segment boundary.
2395                         auto segment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2396                             generate_and_discard_lower(power_of_10[9] << 1, blocks,
2397                                                         cache_block_count);
2398 
2399                         std::uint64_t prod;
2400                         digits_in_the_second_segment -= remaining_digits;
2401 
2402                         if ((remaining_digits & 1) != 0)
2403                         {
2404                             prod = ((segment * UINT64_C(1441151881)) >> 26) + 1;
2405                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2406 
2407                             if (remaining_digits == 1)
2408                             {
2409                                 goto second_segment22_at_most_9_digits_rounding;
2410                             }
2411 
2412                             print_1_digit(current_digits, buffer);
2413                             ++buffer;
2414                         }
2415                         else 
2416                         {
2417                             prod = ((segment * UINT64_C(1801439851)) >> 23) + 1;
2418                             const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2419 
2420                             if (remaining_digits == 0)
2421                             {
2422                                 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2423                                         current_digits,
2424                                         uint_with_known_number_of_digits<2>{next_digits}, [&] {
2425                                             return static_cast<std::uint32_t>(prod) >=
2426                                                         (additional_static_data_holder::
2427                                                             fractional_part_rounding_thresholds32[digits_in_the_second_segment - 3] & UINT32_C(0x7fffffff))
2428                                                     || has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
2429                                         })) 
2430                                 {
2431                                     goto round_up_two_digits;
2432                                 }
2433                                 goto print_last_two_digits;
2434                             }
2435                             else if (remaining_digits == 2)
2436                             {
2437                                 current_digits = next_digits;
2438                                 goto second_segment22_at_most_9_digits_rounding;
2439                             }
2440 
2441                             print_2_digits(next_digits, buffer);
2442                             buffer += 2;
2443                         }
2444 
2445                         BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2446 
2447                         for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
2448                         {
2449                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2450                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2451                             buffer += 2;
2452                         }
2453 
2454                         if (digits_in_the_second_segment != 0) 
2455                         {
2456                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2457                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2458                             remaining_digits = 0;
2459 
2460                         second_segment22_at_most_9_digits_rounding:
2461                             if (check_rounding_condition_inside_subsegment(
2462                                     current_digits, static_cast<std::uint32_t>(prod),
2463                                     digits_in_the_second_segment, has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1,
2464                                     uconst0))) 
2465                             {
2466                                 goto round_up;
2467                             }
2468 
2469                             goto print_last_digits;
2470                         }
2471                         else
2472                         {
2473                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(200);
2474                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2475                             const auto segment_boundary_rounding_bit = (current_digits & 1) != 0;
2476                             current_digits >>= 1;
2477 
2478                             if (check_rounding_condition_with_next_bit(
2479                                     current_digits, segment_boundary_rounding_bit,
2480                                     has_further_digits<0, 1, ExtendedCache>(significand, exp2_base, k, uconst0, uconst1)))
2481                             {
2482                                 goto round_up_two_digits;
2483                             }
2484                             goto print_last_two_digits;
2485                         }
2486                     } // digits_in_the_second_segment <= 9
2487 
2488                     // first_second_subsegments is of 1 ~ 13 digits, and third_subsegment is
2489                     // of 9 digits.
2490                     // Get one more bit for potential rounding condition check.
2491                     auto first_second_subsegments =
2492                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
2493                             power_of_10[13] << 1, blocks, cache_block_count);
2494                     
2495                     bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
2496                     first_second_subsegments >>= 1;
2497 
2498                     // Compilers are not aware of how to leverage the maximum value of
2499                     // first_second_subsegments to find out a better magic number which
2500                     // allows us to eliminate an additional shift.
2501                     // 1844674407371 = ceil(2^64/10^7) = floor(2^64*(10^6/(10^13 - 1))).
2502                     const auto first_subsegment =
2503                         static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(
2504                             first_second_subsegments, 1844674407371));
2505 
2506                     const auto second_subsegment =
2507                         static_cast<std::uint32_t>(first_second_subsegments) - 10000000 * first_subsegment;
2508 
2509                     int digits_in_the_second_subsegment;
2510 
2511                     // Print the first subsegment (0 ~ 6 digits) if exists.
2512                     if (digits_in_the_second_segment > 16)
2513                     {
2514                         std::uint64_t prod;
2515                         int remaining_digits_in_the_current_subsegment = digits_in_the_second_segment - 16;
2516 
2517                         // No rounding, continue.
2518                         if (remaining_digits > remaining_digits_in_the_current_subsegment)
2519                         {
2520                             remaining_digits -= remaining_digits_in_the_current_subsegment;
2521 
2522                             // There is no overlap in the second subsegment.
2523                             digits_in_the_second_subsegment = 7;
2524 
2525                             // When there is no overlapping digit.
2526                             if (remaining_digits_in_the_current_subsegment == 6)
2527                             {
2528                                 prod = (first_subsegment * UINT64_C(429497)) + 1;
2529                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2530                                 buffer += 2;
2531                                 remaining_digits_in_the_current_subsegment -= 2;
2532                             }
2533                             // If there are overlapping digits, move all overlapping digits
2534                             // into the integer part.
2535                             else 
2536                             {
2537                                 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2538                                 prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
2539 
2540                                 if ((remaining_digits_in_the_current_subsegment & 1) != 0) 
2541                                 {
2542                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2543                                     print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2544                                     ++buffer;
2545                                 }
2546                             }
2547 
2548                             for (; remaining_digits_in_the_current_subsegment > 1; remaining_digits_in_the_current_subsegment -= 2) 
2549                             {
2550                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2551                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2552                                 buffer += 2;
2553                             }
2554                         }
2555                         // The first subsegment is the last subsegment to print.
2556                         else
2557                         {
2558                             if ((remaining_digits & 1) != 0)
2559                             {
2560                                 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2561 
2562                                 // If there are overlapping digits, move all overlapping digits
2563                                 // into the integer part and then get the next digit.
2564                                 if (remaining_digits_in_the_current_subsegment < 6)
2565                                 {
2566                                     prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
2567                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2568                                 }
2569                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
2570                                 remaining_digits_in_the_current_subsegment -= remaining_digits;
2571 
2572                                 if (remaining_digits == 1) 
2573                                 {
2574                                     goto second_segment22_more_than_9_digits_first_subsegment_rounding;
2575                                 }
2576 
2577                                 print_1_digit(current_digits, buffer);
2578                                 ++buffer;
2579                             }
2580                             else 
2581                             {
2582                                 // When there is no overlapping digit.
2583                                 if (remaining_digits_in_the_current_subsegment == 6) 
2584                                 {
2585                                     if (remaining_digits == 0)
2586                                     {
2587                                         if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2588                                                 current_digits,
2589                                                 uint_with_known_number_of_digits<6>{
2590                                                     first_subsegment},
2591                                                 has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
2592                                         {
2593                                             goto round_up_two_digits;
2594                                         }
2595                                         goto print_last_two_digits;
2596                                     }
2597 
2598                                     prod = (first_subsegment * UINT64_C(429497)) + 1;
2599                                 }
2600                                 // Otherwise, convert the subsegment into a fixed-point
2601                                 // fraction form, move all overlapping digits into the
2602                                 // integer part, and then extract the next two digits.
2603                                 else 
2604                                 {
2605                                     prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2606                                     prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
2607 
2608                                     if (remaining_digits == 0)
2609                                     {
2610                                         goto second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment;
2611                                     }
2612 
2613                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2614                                 }
2615                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
2616                                 remaining_digits_in_the_current_subsegment -= remaining_digits;
2617 
2618                                 if (remaining_digits == 2)
2619                                 {
2620                                     goto second_segment22_more_than_9_digits_first_subsegment_rounding;
2621                                 }
2622 
2623                                 print_2_digits(current_digits, buffer);
2624                                 buffer += 2;
2625                             }
2626 
2627                             BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2628 
2629                             if (remaining_digits > 4)
2630                             {
2631                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2632                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2633                                 buffer += 2;
2634                             }
2635 
2636                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2637                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2638                             remaining_digits = 0;
2639 
2640                         second_segment22_more_than_9_digits_first_subsegment_rounding:
2641                             if (remaining_digits_in_the_current_subsegment == 0) 
2642                             {
2643                                 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2644                                         current_digits,
2645                                         uint_with_known_number_of_digits<7>{second_subsegment},
2646                                         has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9))) 
2647                                 {
2648                                     goto round_up;
2649                                 }
2650                             }
2651                             else 
2652                             {
2653                             second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment
2654                                 :
2655                                 if (check_rounding_condition_inside_subsegment(
2656                                         current_digits, static_cast<std::uint32_t>(prod),
2657                                         remaining_digits_in_the_current_subsegment,
2658                                         has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
2659                                 {
2660                                     goto round_up;
2661                                 }
2662                             }
2663                             goto print_last_digits;
2664                         }
2665                     }
2666                     else
2667                     {
2668                         digits_in_the_second_subsegment = digits_in_the_second_segment - 9;
2669                     }
2670 
2671                     // Print the second subsegment (1 ~ 7 digits).
2672                     {
2673                         // No rounding, continue.
2674                         if (remaining_digits > digits_in_the_second_subsegment) 
2675                         {
2676                             auto prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2677                             remaining_digits -= digits_in_the_second_subsegment;
2678 
2679                             // When there is no overlapping digit.
2680                             if (digits_in_the_second_subsegment == 7)
2681                             {
2682                                 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2683                                 ++buffer;
2684                             }
2685                             // If there are overlapping digits, move all overlapping digits
2686                             // into the integer part.
2687                             else
2688                             {
2689                                 prod *= compute_power(UINT64_C(10),
2690                                                         6 - digits_in_the_second_subsegment);
2691 
2692                                 if ((digits_in_the_second_subsegment & 1) != 0)
2693                                 {
2694                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2695                                     print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2696                                     ++buffer;
2697                                 }
2698                             }
2699 
2700                             for (; digits_in_the_second_subsegment > 1; digits_in_the_second_subsegment -= 2)
2701                             {
2702                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2703                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2704                                 buffer += 2;
2705                             }
2706                         }
2707                         // The second subsegment is the last subsegment to print.
2708                         else
2709                         {
2710                             std::uint64_t prod;
2711 
2712                             if ((remaining_digits & 1) != 0)
2713                             {
2714                                 prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2715 
2716                                 // If there are overlapping digits, move all overlapping digits
2717                                 // into the integer part and then get the next digit.
2718                                 if (digits_in_the_second_subsegment < 7) 
2719                                 {
2720                                     prod *= compute_power(UINT64_C(10), 6 - digits_in_the_second_subsegment);
2721                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2722                                 }
2723                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
2724                                 digits_in_the_second_subsegment -= remaining_digits;
2725 
2726                                 if (remaining_digits == 1)
2727                                 {
2728                                     goto second_segment22_more_than_9_digits_second_subsegment_rounding;
2729                                 }
2730 
2731                                 print_1_digit(current_digits, buffer);
2732                                 ++buffer;
2733                             }
2734                             else
2735                             {
2736                                 // When there is no overlapping digit.
2737                                 if (digits_in_the_second_subsegment == 7)
2738                                 {
2739                                     if (remaining_digits == 0)
2740                                     {
2741                                         if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2742                                                 current_digits,
2743                                                 uint_with_known_number_of_digits<7>{
2744                                                     second_subsegment},
2745                                                 has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
2746                                         {
2747                                             goto round_up_two_digits;
2748                                         }
2749                                         goto print_last_two_digits;
2750                                     }
2751 
2752                                     prod = ((second_subsegment * UINT64_C(10995117)) >> 8) + 1;
2753                                 }
2754                                 // Otherwise, convert the subsegment into a fixed-point
2755                                 // fraction form, move all overlapping digits into the
2756                                 // integer part, and then extract the next two digits.
2757                                 else 
2758                                 {
2759                                     prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2760                                     prod *= compute_power(UINT64_C(10), 6 - digits_in_the_second_subsegment);
2761 
2762                                     if (remaining_digits == 0)
2763                                     {
2764                                         goto second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment;
2765                                     }
2766 
2767                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2768                                 }
2769                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
2770                                 digits_in_the_second_subsegment -= remaining_digits;
2771 
2772                                 if (remaining_digits == 2)
2773                                 {
2774                                     goto second_segment22_more_than_9_digits_second_subsegment_rounding;
2775                                 }
2776 
2777                                 print_2_digits(current_digits, buffer);
2778                                 buffer += 2;
2779                             }
2780 
2781                             BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2782 
2783                             if (remaining_digits > 4)
2784                             {
2785                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2786                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2787                                 buffer += 2;
2788                             }
2789 
2790                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2791                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2792                             remaining_digits = 0;
2793 
2794                         second_segment22_more_than_9_digits_second_subsegment_rounding:
2795                             if (digits_in_the_second_subsegment == 0)
2796                             {
2797                                 if (check_rounding_condition_with_next_bit(
2798                                         current_digits, first_bit_of_third_subsegment,
2799                                         has_further_digits<0, 9, ExtendedCache>(significand, exp2_base, k, uconst0, uconst9)))
2800                                 {
2801                                     goto round_up;
2802                                 }
2803                             }
2804                             else
2805                             {
2806                             second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment
2807                                 :
2808                                 if (check_rounding_condition_inside_subsegment(
2809                                         current_digits, static_cast<std::uint32_t>(prod),
2810                                         digits_in_the_second_subsegment, has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k,
2811                                         uconst1, uconst9)))
2812                                 {
2813                                     goto round_up;
2814                                 }
2815                             }
2816                             goto print_last_digits;
2817                         }
2818                     }
2819 
2820                     // Print the third subsegment (9 digits).
2821                     {
2822                         // Get one more bit if we need to check rounding conditions on
2823                         // the segment boundary. We already have shifted by 1-bit in the
2824                         // computation of first & second subsegments, so here we don't
2825                         // shift the multiplier.
2826                         auto third_subsegment =
2827                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2828                                 generate_and_discard_lower(power_of_10[9], blocks,
2829                                                             cache_block_count);
2830 
2831                         bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
2832                         third_subsegment >>= 1;
2833                         third_subsegment += (first_bit_of_third_subsegment ? 500000000 : 0);
2834 
2835                         std::uint64_t prod;
2836                         if ((remaining_digits & 1) != 0)
2837                         {
2838                             prod = ((third_subsegment * UINT64_C(720575941)) >> 24) + 1;
2839                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2840 
2841                             if (remaining_digits == 1) 
2842                             {
2843                                 if (check_rounding_condition_inside_subsegment(
2844                                         current_digits, static_cast<std::uint32_t>(prod), 8,
2845                                         has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))) 
2846                                 {
2847                                     goto round_up_one_digit;
2848                                 }
2849                                 goto print_last_one_digit;
2850                             }
2851 
2852                             print_1_digit(current_digits, buffer);
2853                             ++buffer;
2854                         }
2855                         else 
2856                         {
2857                             prod = ((third_subsegment * UINT64_C(450359963)) >> 20) + 1;
2858                             current_digits = static_cast<std::uint32_t>(prod >> 32);
2859 
2860                             if (remaining_digits == 2) 
2861                             {
2862                                 goto second_segment22_more_than_9_digits_third_subsegment_rounding;
2863                             }
2864 
2865                             print_2_digits(current_digits, buffer);
2866                             buffer += 2;
2867                         }
2868 
2869                         for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
2870                         {
2871                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2872                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2873                             buffer += 2;
2874                         }
2875 
2876                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2877                         current_digits = static_cast<std::uint32_t>(prod >> 32);
2878 
2879                         if (remaining_digits < 9)
2880                         {
2881                         second_segment22_more_than_9_digits_third_subsegment_rounding:
2882                             if (check_rounding_condition_inside_subsegment(
2883                                     current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
2884                                     has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2885                             {
2886                                 goto round_up_two_digits;
2887                             }
2888                         }
2889                         else 
2890                         {
2891                             if (check_rounding_condition_with_next_bit(
2892                                     current_digits, segment_boundary_rounding_bit,
2893                                     has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0))) 
2894                             {
2895                                 goto round_up_two_digits;
2896                             }
2897                         }
2898                         goto print_last_two_digits;
2899                     }
2900                 }
2901             } // ExtendedCache::segment_length == 22
2902 
2903             else BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 252)
2904             {
2905                 int overlapping_digits = 252 - digits_in_the_second_segment;
2906                 int remaining_subsegment_pairs = 14;
2907 
2908                 while (overlapping_digits >= 18)
2909                 {
2910                     fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2911                         power_of_10[18], blocks, cache_block_count);
2912                     --remaining_subsegment_pairs;
2913                     overlapping_digits -= 18;
2914                 }
2915 
2916                 auto subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18] << 1, blocks, cache_block_count);
2917                 auto subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
2918                 subsegment_pair >>= 1;
2919 
2920                 // Deal with the first subsegment pair.
2921                 {
2922                     // Divide it into two 9-digits subsegments.
2923                     const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
2924                     const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
2925 
2926                     auto print_subsegment = [&](std::uint32_t subsegment, int digits_in_the_subsegment)
2927                     {
2928                         remaining_digits -= digits_in_the_subsegment;
2929 
2930                         // Move all overlapping digits into the integer part.
2931                         auto prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
2932                         if (digits_in_the_subsegment < 9) 
2933                         {
2934                             prod *= compute_power(UINT32_C(10), 8 - digits_in_the_subsegment);
2935 
2936                             if ((digits_in_the_subsegment & 1) != 0) 
2937                             {
2938                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2939                                 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2940                                 ++buffer;
2941                             }
2942                         }
2943                         else 
2944                         {
2945                             print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2946                             ++buffer;
2947                         }
2948 
2949                         for (; digits_in_the_subsegment > 1; digits_in_the_subsegment -= 2) 
2950                         {
2951                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2952                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2953                             buffer += 2;
2954                         }
2955                     };
2956 
2957                     // When the first part is not completely overlapping with the first segment.
2958                     int digits_in_the_second_part;
2959                     if (overlapping_digits < 9) 
2960                     {
2961                         int digits_in_the_first_part = 9 - overlapping_digits;
2962 
2963                         // No rounding, continue.
2964                         if (remaining_digits > digits_in_the_first_part) 
2965                         {
2966                             digits_in_the_second_part = 9;
2967                             print_subsegment(first_part, digits_in_the_first_part);
2968                         }
2969                         // Perform rounding and return.
2970                         else 
2971                         {
2972                             // When there is no overlapping digit.
2973                             std::uint64_t prod;
2974                             if (digits_in_the_first_part == 9)
2975                             {
2976                                 if ((remaining_digits & 1) != 0) 
2977                                 {
2978                                     prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
2979                                 }
2980                                 else 
2981                                 {
2982                                     if (remaining_digits == 0) 
2983                                     {
2984                                         if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2985                                                 current_digits,
2986                                                 uint_with_known_number_of_digits<9>{first_part},
2987                                                 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
2988                                         {
2989                                             goto round_up_two_digits;
2990                                         }
2991                                         goto print_last_two_digits;
2992                                     }
2993 
2994                                     prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
2995                                 }
2996                             }
2997                             else 
2998                             {
2999                                 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
3000                                 prod *= compute_power(UINT32_C(10), 8 - digits_in_the_first_part);
3001 
3002                                 if ((remaining_digits & 1) != 0) 
3003                                 {
3004                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
3005                                 }
3006                                 else 
3007                                 {
3008                                     if (remaining_digits == 0) 
3009                                     {
3010                                         goto second_segment252_first_subsegment_rounding_inside_subsegment;
3011                                     }
3012 
3013                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3014                                 }
3015                             }
3016                             digits_in_the_first_part -= remaining_digits;
3017                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3018 
3019                             if (remaining_digits > 2) 
3020                             {
3021                                 if ((remaining_digits & 1) != 0) 
3022                                 {
3023                                     print_1_digit(current_digits, buffer);
3024                                     ++buffer;
3025                                 }
3026                                 else 
3027                                 {
3028                                     print_2_digits(current_digits, buffer);
3029                                     buffer += 2;
3030                                 }
3031 
3032                                 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3033                                 {
3034                                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3035                                     print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3036                                     buffer += 2;
3037                                 }
3038 
3039                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3040                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
3041                                 remaining_digits = 0;
3042                             }
3043 
3044                             if (digits_in_the_first_part != 0)
3045                             {
3046                             second_segment252_first_subsegment_rounding_inside_subsegment:
3047                                 if (check_rounding_condition_inside_subsegment(
3048                                         current_digits, static_cast<std::uint32_t>(prod),
3049                                         digits_in_the_first_part, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k)) 
3050                                 {
3051                                     goto round_up;
3052                                 }
3053                             }
3054                             else 
3055                             {
3056                                 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3057                                         current_digits,
3058                                         uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3059                                         compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3060                                 {
3061                                     goto round_up;
3062                                 }
3063                             }
3064                             goto print_last_digits;
3065                         }
3066                     }
3067                     else
3068                     {
3069                         digits_in_the_second_part = 18 - overlapping_digits;
3070                     }
3071 
3072                     // Print the second part.
3073                     // No rounding, continue.
3074                     if (remaining_digits > digits_in_the_second_part)
3075                     {
3076                         print_subsegment(second_part, digits_in_the_second_part);
3077                     }
3078                     // Perform rounding and return.
3079                     else
3080                     {
3081                         // When there is no overlapping digit.
3082                         std::uint64_t prod;
3083                         if (digits_in_the_second_part == 9)
3084                         {
3085                             if ((remaining_digits & 1) != 0)
3086                             {
3087                                 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3088                             }
3089                             else 
3090                             {
3091                                 if (remaining_digits == 0)
3092                                 {
3093                                     if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3094                                             current_digits,
3095                                             uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3096                                             compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k)) 
3097                                     {
3098                                         goto round_up_two_digits;
3099                                     }
3100                                     goto print_last_two_digits;
3101                                 }
3102 
3103                                 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3104                             }
3105                         }
3106                         else 
3107                         {
3108                             prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3109                             prod *= compute_power(UINT32_C(10), 8 - digits_in_the_second_part);
3110 
3111                             if ((remaining_digits & 1) != 0)
3112                             {
3113                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
3114                             }
3115                             else 
3116                             {
3117                                 if (remaining_digits == 0) 
3118                                 {
3119                                     goto second_segment252_second_subsegment_rounding_inside_subsegment;
3120                                 }
3121 
3122                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3123                             }
3124                         }
3125                         digits_in_the_second_part -= remaining_digits;
3126                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3127 
3128                         if (remaining_digits > 2)
3129                         {
3130                             if ((remaining_digits & 1) != 0) 
3131                             {
3132                                 print_1_digit(current_digits, buffer);
3133                                 ++buffer;
3134                             }
3135                             else 
3136                             {
3137                                 print_2_digits(current_digits, buffer);
3138                                 buffer += 2;
3139                             }
3140 
3141                             for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3142                             {
3143                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3144                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3145                                 buffer += 2;
3146                             }
3147 
3148                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3149                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3150                             remaining_digits = 0;
3151                         }
3152 
3153                         if (digits_in_the_second_part != 0)
3154                         {
3155                         second_segment252_second_subsegment_rounding_inside_subsegment:
3156                             if (check_rounding_condition_inside_subsegment(
3157                                     current_digits, static_cast<std::uint32_t>(prod),
3158                                     digits_in_the_second_part, compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3159                             {
3160                                 goto round_up;
3161                             }
3162                         }
3163                         else 
3164                         {
3165                             if (check_rounding_condition_with_next_bit(
3166                                     current_digits, subsegment_boundary_rounding_bit,
3167                                     compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3168                             {
3169                                 goto round_up;
3170                             }
3171                         }
3172                         goto print_last_digits;
3173                     }
3174                 }
3175 
3176                 // Remaining subsegment pairs do not have overlapping digits.
3177                 --remaining_subsegment_pairs;
3178                 for (; remaining_subsegment_pairs > 0; --remaining_subsegment_pairs) 
3179                 {
3180                     subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
3181 
3182                     subsegment_pair += (subsegment_boundary_rounding_bit ? power_of_10[18] : 0);
3183                     subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
3184                     subsegment_pair >>= 1;
3185 
3186                     const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
3187                     const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
3188 
3189                     // The first part can be printed without rounding.
3190                     if (remaining_digits > 9)
3191                     {
3192                         print_9_digits(first_part, buffer);
3193 
3194                         // The second part also can be printed without rounding.
3195                         if (remaining_digits > 18) 
3196                         {
3197                             print_9_digits(second_part, buffer + 9);
3198                         }
3199                         // Otherwise, perform rounding and return.
3200                         else
3201                         {
3202                             buffer += 9;
3203                             remaining_digits -= 9;
3204 
3205                             std::uint64_t prod;
3206                             int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
3207 
3208                             if ((remaining_digits & 1) != 0)
3209                             {
3210                                 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3211                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
3212 
3213                                 if (remaining_digits == 1)
3214                                 {
3215                                     goto second_segment252_loop_second_subsegment_rounding;
3216                                 }
3217 
3218                                 print_1_digit(current_digits, buffer);
3219                                 ++buffer;
3220                             }
3221                             else
3222                             {
3223                                 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3224                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
3225 
3226                                 if (remaining_digits == 2)
3227                                 {
3228                                     goto second_segment252_loop_second_subsegment_rounding;
3229                                 }
3230 
3231                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3232                                 buffer += 2;
3233                             }
3234 
3235                             for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3236                             {
3237                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3238                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3239                                 buffer += 2;
3240                             }
3241 
3242                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3243                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3244                             remaining_digits = 0;
3245 
3246                             if (remaining_digits_in_the_current_subsegment != 0) 
3247                             {
3248                             second_segment252_loop_second_subsegment_rounding:
3249                                 if (check_rounding_condition_inside_subsegment(
3250                                         current_digits, static_cast<std::uint32_t>(prod),
3251                                         remaining_digits_in_the_current_subsegment,
3252                                         compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3253                                 {
3254                                     goto round_up;
3255                                 }
3256                                 goto print_last_digits;
3257                             }
3258                             else 
3259                             {
3260                                 if (check_rounding_condition_with_next_bit(
3261                                         current_digits, subsegment_boundary_rounding_bit,
3262                                         compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3263                                 {
3264                                     goto round_up_two_digits;
3265                                 }
3266                                 goto print_last_two_digits;
3267                             }
3268                         }
3269                     }
3270                     // Otherwise, perform rounding and return.
3271                     else
3272                     {
3273                         std::uint64_t prod;
3274                         int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
3275                         if ((remaining_digits & 1) != 0) 
3276                         {
3277                             prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
3278                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3279 
3280                             if (remaining_digits == 1) 
3281                             {
3282                                 goto second_segment252_loop_first_subsegment_rounding;
3283                             }
3284 
3285                             print_1_digit(current_digits, buffer);
3286                             ++buffer;
3287                         }
3288                         else
3289                         {
3290                             prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
3291                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3292 
3293                             if (remaining_digits == 2)
3294                             {
3295                                 goto second_segment252_loop_first_subsegment_rounding;
3296                             }
3297 
3298                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3299                             buffer += 2;
3300                         }
3301 
3302                         for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3303                         {
3304                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3305                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3306                             buffer += 2;
3307                         }
3308 
3309                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3310                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3311                         remaining_digits = 0;
3312 
3313                         if (remaining_digits_in_the_current_subsegment != 0)
3314                         {
3315                         second_segment252_loop_first_subsegment_rounding:
3316                             if (check_rounding_condition_inside_subsegment(
3317                                     current_digits, static_cast<std::uint32_t>(prod),
3318                                     remaining_digits_in_the_current_subsegment,
3319                                     compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3320                             {
3321                                 goto round_up;
3322                             }
3323                             goto print_last_digits;
3324                         }
3325                         else
3326                         {
3327                             if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3328                                     current_digits,
3329                                     uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3330                                     compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3331                             {
3332                                 goto round_up_two_digits;
3333                             }
3334                             goto print_last_two_digits;
3335                         }
3336                     }
3337 
3338                     buffer += 18;
3339                     remaining_digits -= 18;
3340                 }
3341             } // ExtendedCache::segment_length == 252
3342         }
3343 
3344         // Print all remaining segments.
3345         while (has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))
3346         {
3347             // Get new segment.
3348             ++multiplier_index;
3349             k += ExtendedCache::segment_length;
3350 
3351             cache_block_count = load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(blocks, e, k, multiplier_index);
3352 
3353             // Compute nm mod 2^Q.
3354             fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
3355 
3356             BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
3357             {
3358                 // When at least two subsegments left.
3359                 if (remaining_digits > 16) 
3360                 {
3361                     std::uint64_t first_second_subsegments = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[16], blocks, cache_block_count);
3362 
3363                     const auto first_subsegment =
3364                         static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
3365                     
3366                     const std::uint32_t second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
3367 
3368                     print_8_digits(first_subsegment, buffer);
3369                     print_8_digits(second_subsegment, buffer + 8);
3370 
3371                     // When more segments left.
3372                     if (remaining_digits > 22)
3373                     {
3374                         const auto third_subsegment = static_cast<std::uint32_t>(
3375                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate_and_discard_lower(power_of_10[6], blocks,cache_block_count));
3376 
3377                         print_6_digits(third_subsegment, buffer + 16);
3378                         buffer += 22;
3379                         remaining_digits -= 22;
3380                     }
3381                     // When this is the last segment.
3382                     else
3383                     {
3384                         buffer += 16;
3385                         remaining_digits -= 16;
3386 
3387                         auto third_subsegment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3388                             generate_and_discard_lower(power_of_10[6] << 1, blocks, cache_block_count);
3389 
3390                         bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
3391                         third_subsegment >>= 1;
3392 
3393                         std::uint64_t prod;
3394                         if ((remaining_digits & 1) != 0)
3395                         {
3396                             prod = ((third_subsegment * UINT64_C(687195)) >> 4) + 1;
3397                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3398 
3399                             if (remaining_digits == 1)
3400                             {
3401                                 if (check_rounding_condition_inside_subsegment(
3402                                         current_digits, static_cast<std::uint32_t>(prod), 5,
3403                                         has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))) 
3404                                 {
3405                                     goto round_up_one_digit;
3406                                 }
3407                                 goto print_last_one_digit;
3408                             }
3409 
3410                             print_1_digit(current_digits, buffer);
3411                             ++buffer;
3412                         }
3413                         else
3414                         {
3415                             prod = (third_subsegment * UINT64_C(429497)) + 1;
3416                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3417 
3418                             if (remaining_digits == 2)
3419                             {
3420                                 goto segment_loop22_more_than_16_digits_rounding;
3421                             }
3422 
3423                             print_2_digits(current_digits, buffer);
3424                             buffer += 2;
3425                         }
3426 
3427                         if (remaining_digits > 4)
3428                         {
3429                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3430                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3431                             buffer += 2;
3432 
3433                             if (remaining_digits == 6)
3434                             {
3435                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3436                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
3437 
3438                                 if (check_rounding_condition_with_next_bit(
3439                                         current_digits, segment_boundary_rounding_bit,
3440                                         has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
3441                                 {
3442                                     goto round_up_two_digits;
3443                                 }
3444                                 goto print_last_two_digits;
3445                             }
3446                         }
3447 
3448                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3449                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3450 
3451                     segment_loop22_more_than_16_digits_rounding:
3452                         if (check_rounding_condition_inside_subsegment(
3453                                 current_digits, static_cast<std::uint32_t>(prod), 6 - remaining_digits,
3454                                 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
3455                         {
3456                             goto round_up_two_digits;
3457                         }
3458                         goto print_last_two_digits;
3459                     }
3460                 }
3461                 // When two subsegments left.
3462                 else if (remaining_digits > 8)
3463                 {
3464                     // Get one more bit for potential rounding conditions check.
3465                     auto first_second_subsegments =
3466                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3467                             generate_and_discard_lower(power_of_10[16] << 1, blocks, cache_block_count);
3468 
3469                     bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
3470                     first_second_subsegments >>= 1;
3471 
3472                     // 3022314549036573 = ceil(2^78/10^8) = floor(2^78*(10^8/(10^16 -
3473                     // 1))).
3474                     const auto first_subsegment =
3475                         static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
3476 
3477                     const auto second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
3478 
3479                     print_8_digits(first_subsegment, buffer);
3480                     buffer += 8;
3481                     remaining_digits -= 8;
3482 
3483                     // Second subsegment (8 digits).
3484                     std::uint64_t prod;
3485                     if ((remaining_digits & 1) != 0)
3486                     {
3487                         prod = ((second_subsegment * UINT64_C(112589991)) >> 18) + 1;
3488                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3489 
3490                         if (remaining_digits == 1)
3491                         {
3492                             if (check_rounding_condition_inside_subsegment(
3493                                     current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k,
3494                                     uconst1, uconst6)))
3495                             {
3496                                 goto round_up_one_digit;
3497                             }
3498                             goto print_last_one_digit;
3499                         }
3500 
3501                         print_1_digit(current_digits, buffer);
3502                         ++buffer;
3503                     }
3504                     else
3505                     {
3506                         prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
3507                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3508 
3509                         if (remaining_digits == 2)
3510                         {
3511                             goto segment_loop22_more_than_8_digits_rounding;
3512                         }
3513 
3514                         print_2_digits(current_digits, buffer);
3515                         buffer += 2;
3516                     }
3517 
3518                     for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3519                     {
3520                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3521                         print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3522                         buffer += 2;
3523                     }
3524 
3525                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3526                     current_digits = static_cast<std::uint32_t>(prod >> 32);
3527 
3528                     if (remaining_digits < 8)
3529                     {
3530                     segment_loop22_more_than_8_digits_rounding:
3531                         if (check_rounding_condition_inside_subsegment(
3532                                 current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
3533                                 has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k, uconst1, uconst6)))
3534                         {
3535                             goto round_up_two_digits;
3536                         }
3537                     }
3538                     else {
3539                         if (check_rounding_condition_with_next_bit(
3540                                 current_digits, first_bit_of_third_subsegment,
3541                                 has_further_digits<0, 6, ExtendedCache>(significand, exp2_base, k, uconst0, uconst6)))
3542                         {
3543                             goto round_up_two_digits;
3544                         }
3545                     }
3546                     goto print_last_two_digits;
3547                 }
3548                 // remaining_digits is at most 8.
3549                 else
3550                 {
3551                     // Get one more bit for potential rounding conditions check.
3552                     auto first_subsegment =
3553                         fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3554                             generate_and_discard_lower(power_of_10[8] << 1, blocks, cache_block_count);
3555 
3556                     bool first_bit_of_second_subsegment = ((first_subsegment & 1) != 0);
3557                     first_subsegment >>= 1;
3558 
3559                     std::uint64_t prod;
3560                     if ((remaining_digits & 1) != 0)
3561                     {
3562                         prod = ((first_subsegment * UINT64_C(112589991)) >> 18) + 1;
3563                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3564 
3565                         if (remaining_digits == 1)
3566                         {
3567                             if (check_rounding_condition_inside_subsegment(
3568                                     current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k,
3569                                     uconst1, uconst14)))
3570                             {
3571                                 goto round_up_one_digit;
3572                             }
3573                             goto print_last_one_digit;
3574                         }
3575 
3576                         print_1_digit(current_digits, buffer);
3577                         ++buffer;
3578                     }
3579                     else
3580                     {
3581                         prod = ((first_subsegment * UINT64_C(140737489)) >> 15) + 1;
3582                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3583 
3584                         if (remaining_digits == 2)
3585                         {
3586                             goto segment_loop22_at_most_8_digits_rounding;
3587                         }
3588 
3589                         print_2_digits(current_digits, buffer);
3590                         buffer += 2;
3591                     }
3592 
3593                     for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3594                     {
3595                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3596                         print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3597                         buffer += 2;
3598                     }
3599 
3600                     prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3601                     current_digits = static_cast<std::uint32_t>(prod >> 32);
3602 
3603                     if (remaining_digits < 8)
3604                     {
3605                     segment_loop22_at_most_8_digits_rounding:
3606                         if (check_rounding_condition_inside_subsegment(
3607                                 current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
3608                                 has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k, uconst1, uconst14)))
3609                         {
3610                             goto round_up_two_digits;
3611                         }
3612                     }
3613                     else
3614                     {
3615                         if (check_rounding_condition_with_next_bit(
3616                                 current_digits, first_bit_of_second_subsegment,
3617                                 has_further_digits<0, 14, ExtendedCache>(significand, exp2_base, k, uconst0, uconst14)))
3618                         {
3619                             goto round_up_two_digits;
3620                         }
3621                     }
3622                     goto print_last_two_digits;
3623                 }
3624             } // ExtendedCache::segment_length == 22
3625             else if (ExtendedCache::segment_length == 252)
3626             {
3627                 // Print as many 18-digits subsegment pairs as possible.
3628                 for (int remaining_subsegment_pairs = 14; remaining_subsegment_pairs > 0;
3629                         --remaining_subsegment_pairs)
3630                 {
3631                     // No rounding, continue.
3632                     if (remaining_digits > 18)
3633                     {
3634                         const auto subsegment_pair =
3635                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
3636 
3637                         const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
3638                         const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
3639 
3640                         print_9_digits(first_part, buffer);
3641                         print_9_digits(second_part, buffer + 9);
3642                         buffer += 18;
3643                         remaining_digits -= 18;
3644                     }
3645                     // Final subsegment pair.
3646                     else
3647                     {
3648                         auto last_subsegment_pair =
3649                             fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3650                                 generate_and_discard_lower(power_of_10[18] << 1, blocks, cache_block_count);
3651 
3652                         const bool subsegment_boundary_rounding_bit = ((last_subsegment_pair & 1) != 0);
3653                         last_subsegment_pair >>= 1;
3654 
3655                         const auto first_part = static_cast<std::uint32_t>(last_subsegment_pair / power_of_10[9]);
3656                         const auto second_part = static_cast<std::uint32_t>(last_subsegment_pair) - power_of_10[9] * first_part;
3657 
3658                         if (remaining_digits <= 9)
3659                         {
3660                             std::uint64_t prod;
3661 
3662                             if ((remaining_digits & 1) != 0)
3663                             {
3664                                 prod = ((first_part * UINT64_C(1441151881)) >> 25) + 1;
3665                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
3666 
3667                                 if (remaining_digits == 1)
3668                                 {
3669                                     if (check_rounding_condition_inside_subsegment(
3670                                             current_digits, static_cast<std::uint32_t>(prod), 8,
3671                                             compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3672                                     {
3673                                         goto round_up_one_digit;
3674                                     }
3675                                     goto print_last_one_digit;
3676                                 }
3677 
3678                                 print_1_digit(current_digits, buffer);
3679                                 ++buffer;
3680                             }
3681                             else
3682                             {
3683                                 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
3684                                 current_digits = static_cast<std::uint32_t>(prod >> 32);
3685 
3686                                 if (remaining_digits == 2)
3687                                 {
3688                                     goto segment_loop252_final18_first_part_rounding;
3689                                 }
3690 
3691                                 print_2_digits(current_digits, buffer);
3692                                 buffer += 2;
3693                             }
3694 
3695                             for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3696                             {
3697                                 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3698                                 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3699                                 buffer += 2;
3700                             }
3701 
3702                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3703                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3704 
3705                             if (remaining_digits < 9)
3706                             {
3707                             segment_loop252_final18_first_part_rounding:
3708                                 if (check_rounding_condition_inside_subsegment(
3709                                         current_digits, static_cast<std::uint32_t>(prod),
3710                                         9 - remaining_digits, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3711                                 {
3712                                     goto round_up_two_digits;
3713                                 }
3714                             }
3715                             else
3716                             {
3717                                 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3718                                         current_digits,
3719                                         uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3720                                         compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3721                                 {
3722                                     goto round_up_two_digits;
3723                                 }
3724                             }
3725                             goto print_last_two_digits;
3726                         } // remaining_digits <= 9
3727 
3728                         print_9_digits(first_part, buffer);
3729                         buffer += 9;
3730                         remaining_digits -= 9;
3731 
3732                         std::uint64_t prod;
3733 
3734                         if ((remaining_digits & 1) != 0)
3735                         {
3736                             prod = ((second_part * UINT64_C(1441151881)) >> 25) + 1;
3737                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3738 
3739                             if (remaining_digits == 1)
3740                             {
3741                                 if (check_rounding_condition_inside_subsegment(
3742                                         current_digits, static_cast<std::uint32_t>(prod), 8,
3743                                         compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3744                                 {
3745                                     goto round_up_one_digit;
3746                                 }
3747                                 goto print_last_one_digit;
3748                             }
3749 
3750                             print_1_digit(current_digits, buffer);
3751                             ++buffer;
3752                         }
3753                         else
3754                         {
3755                             prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3756                             current_digits = static_cast<std::uint32_t>(prod >> 32);
3757 
3758                             if (remaining_digits == 2)
3759                             {
3760                                 goto segment_loop252_final18_second_part_rounding;
3761                             }
3762 
3763                             print_2_digits(current_digits, buffer);
3764                             buffer += 2;
3765                         }
3766 
3767                         for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3768                         {
3769                             prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3770                             print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3771                             buffer += 2;
3772                         }
3773 
3774                         prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3775                         current_digits = static_cast<std::uint32_t>(prod >> 32);
3776 
3777                         if (remaining_digits < 9)
3778                         {
3779                         segment_loop252_final18_second_part_rounding:
3780                             if (check_rounding_condition_inside_subsegment(
3781                                     current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
3782                                     compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3783                             {
3784                                 goto round_up_two_digits;
3785                             }
3786                         }
3787                         else
3788                         {
3789                             if (check_rounding_condition_with_next_bit(
3790                                     current_digits, subsegment_boundary_rounding_bit,
3791                                     compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3792                             {
3793                                 goto round_up_two_digits;
3794                             }
3795                         }
3796                         goto print_last_two_digits;
3797                     }
3798                 }
3799             } // if (ExtendedCache::segment_length == 252)
3800         }
3801     }
3802 
3803 
3804     /////////////////////////////////////////////////////////////////////////////////////////////////
3805     /// Phase 3 - Fill remaining digits with 0's, insert decimal dot, print exponent, and
3806     /// return.
3807     /////////////////////////////////////////////////////////////////////////////////////////////////
3808 
3809 fill_remaining_digits_with_0s:
3810     // This is probably not needed for the general format, but currently I am not 100% sure.
3811     // (When fixed format is eventually chosen, we do not remove trailing zeros in the integer part.
3812     // I am not sure if those trailing zeros are guaranteed to be already printed or not.)
3813     std::memset(buffer, '0', static_cast<std::size_t>(remaining_digits));
3814     buffer += remaining_digits;
3815 
3816 insert_decimal_dot:
3817     if (fmt == chars_format::general)
3818     {
3819         // Decide between fixed vs scientific.
3820         if (-4 <= decimal_exponent_normalized && decimal_exponent_normalized < precision)
3821         {
3822             // Fixed.
3823             if (decimal_exponent_normalized >= 0)
3824             {
3825                 // Insert decimal dot.
3826                 decimal_dot_pos = buffer_starting_pos + decimal_exponent_normalized + 1;
3827                 std::memmove(buffer_starting_pos, buffer_starting_pos + 1,
3828                              static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
3829                 *decimal_dot_pos = '.';
3830             }
3831             else
3832             {
3833                 // Print leading zeros and insert decimal dot.
3834                 int number_of_leading_zeros = -decimal_exponent_normalized - 1;
3835                 std::memmove(buffer_starting_pos + number_of_leading_zeros + 2, buffer_starting_pos + 1,
3836                              static_cast<std::size_t>(buffer - buffer_starting_pos - 1));
3837                 std::memcpy(buffer_starting_pos, "0.", 2);
3838                 std::memset(buffer_starting_pos + 2, '0', static_cast<std::size_t>(number_of_leading_zeros));
3839                 buffer += number_of_leading_zeros + 1;
3840             }
3841             // Don't print exponent.
3842             fmt = chars_format::fixed;
3843         }
3844         else
3845         {
3846             // Scientific.
3847             // Insert decimal dot.
3848             *buffer_starting_pos = *(buffer_starting_pos + 1);
3849             *(buffer_starting_pos + 1) = '.';
3850         }
3851 
3852         // Remove trailing zeros.
3853         trailing_zeros_removed = true;
3854         while (true)
3855         {
3856             auto prev = buffer - 1;
3857 
3858             // Remove decimal dot as well if there is no fractional digits.
3859             if (*prev == '.')
3860             {
3861                 buffer = prev;
3862                 break;
3863             }
3864             else if (*prev != '0')
3865             {
3866                 break;
3867             }
3868             buffer = prev;
3869         }
3870     }
3871     else if (decimal_dot_pos != buffer_starting_pos)
3872     {
3873         std::memmove(buffer_starting_pos, buffer_starting_pos + 1,
3874                      static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
3875         *decimal_dot_pos = '.';
3876     }
3877 
3878     if (fmt != chars_format::fixed)
3879     {
3880         if (decimal_exponent_normalized >= 0)
3881         {
3882             std::memcpy(buffer, "e+", 2); // NOLINT : Specifically not null-terminating
3883         }
3884         else
3885         {
3886             std::memcpy(buffer, "e-", 2); // NOLINT : Specifically not null-terminating
3887             decimal_exponent_normalized = -decimal_exponent_normalized;
3888         }
3889 
3890         buffer += 2;
3891         if (decimal_exponent_normalized >= 100)
3892         {
3893             // d1 = decimal_exponent / 10; d2 = decimal_exponent % 10;
3894             // 6554 = ceil(2^16 / 10)
3895             auto prod = static_cast<std::uint32_t>(decimal_exponent_normalized) * UINT32_C(6554);
3896             auto d1 = prod >> 16;
3897             prod = static_cast<std::uint16_t>(prod) * UINT16_C(5); // * 10
3898             auto d2 = prod >> 15;                                  // >> 16
3899             print_2_digits(d1, buffer);
3900             print_1_digit(d2, buffer + 2);
3901             buffer += 3;
3902         }
3903         else
3904         {
3905             print_2_digits(static_cast<std::uint32_t>(decimal_exponent_normalized), buffer);
3906             buffer += 2;
3907         }
3908     }
3909     else if (!trailing_zeros_removed && buffer - (decimal_dot_pos + 1) < precision)
3910     {
3911         // If we have fixed precision, and we don't have enough digits after the decimal yet
3912         // insert a sufficient amount of zeros
3913         const auto remaining_zeros = precision - (buffer - (decimal_dot_pos + 1));
3914         BOOST_CHARCONV_ASSERT(remaining_zeros > 0);
3915         std::memset(buffer, '0', static_cast<std::size_t>(remaining_zeros));
3916         buffer += remaining_zeros;
3917     }
3918 
3919     return {buffer, std::errc()};
3920 
3921 round_up:
3922     if ((remaining_digits & 1) != 0)
3923     {
3924     round_up_one_digit:
3925         if (++current_digits == 10)
3926         {
3927             goto round_up_all_9s;
3928         }
3929 
3930         goto print_last_one_digit;
3931     }
3932     else
3933     {
3934     round_up_two_digits:
3935         if (++current_digits == 100)
3936         {
3937             goto round_up_all_9s;
3938         }
3939 
3940         goto print_last_two_digits;
3941     }
3942 
3943 print_last_digits:
3944     if ((remaining_digits & 1) != 0) 
3945     {
3946     print_last_one_digit:
3947         print_1_digit(current_digits, buffer);
3948         ++buffer;
3949     }
3950     else
3951     {
3952     print_last_two_digits:
3953         print_2_digits(current_digits, buffer);
3954         buffer += 2;
3955     }
3956 
3957     goto insert_decimal_dot;
3958 
3959 round_up_all_9s:
3960     char* first_9_pos = buffer;
3961     buffer += (2 - (remaining_digits & 1));
3962     
3963     // Find the starting position of printed digits.
3964     char* digit_starting_pos = [&] {
3965         // For negative exponent & fixed format, we already printed leading zeros.
3966         if (fmt == chars_format::fixed && decimal_exponent_normalized < 0)
3967         {
3968             return buffer_starting_pos - decimal_exponent_normalized + 1;
3969         }
3970         // We reserved one slot for decimal dot, so the starting position of printed digits
3971         // is buffer_starting_pos + 1 if we need to print decimal dot.
3972         return buffer_starting_pos == decimal_dot_pos ? buffer_starting_pos
3973             : buffer_starting_pos + 1;
3974     }();
3975     // Find all preceding 9's.
3976     if ((first_9_pos - digit_starting_pos) % 2 != 0)
3977     {
3978         if (*(first_9_pos - 1) != '9')
3979         {
3980             ++*(first_9_pos - 1);
3981             if ((remaining_digits & 1) != 0)
3982             {
3983                 *first_9_pos = '0';
3984             }
3985             else
3986             {
3987                 std::memcpy(first_9_pos, "00", 2);
3988             }
3989             goto insert_decimal_dot;
3990         }
3991         --first_9_pos;
3992     }
3993     while (first_9_pos != digit_starting_pos)
3994     {
3995         if (std::memcmp(first_9_pos - 2, "99", 2) != 0)
3996         {
3997             if (*(first_9_pos - 1) != '9')
3998             {
3999                 ++*(first_9_pos - 1);
4000             }
4001             else
4002             {
4003                 ++*(first_9_pos - 2);
4004                 *(first_9_pos - 1) = '0';
4005             }
4006             std::memset(first_9_pos, '0', static_cast<std::size_t>(buffer - first_9_pos));
4007             goto insert_decimal_dot;
4008         }
4009         first_9_pos -= 2;
4010     }
4011 
4012     // Every digit we wrote so far are all 9's. In this case, we have to shift the whole thing by 1.
4013     ++decimal_exponent_normalized;
4014 
4015     if (fmt == chars_format::fixed)
4016     {
4017         if (decimal_exponent_normalized > 0)
4018         {
4019             // We need to print one more character.
4020             if (buffer == last)
4021             {
4022                 return {last, std::errc::value_too_large};
4023             }
4024             ++buffer;
4025             // If we were to print the decimal dot, we have to shift it to right
4026             // since we now have one more digit in the integer part.
4027             if (buffer_starting_pos != decimal_dot_pos)
4028             {
4029                 ++decimal_dot_pos;
4030             }
4031         }
4032         else if (decimal_exponent_normalized == 0 || remaining_digits == 1)
4033         {
4034             // For the case 0.99...9 -> 1.00...0, the rounded digit is one before the first digit written.
4035             // This same case applies for 0.099 -> 0.10 in the precision = 2 instance
4036             // Note: decimal_exponent_normalized was negative before the increment (++decimal_exponent_normalized),
4037             //       so we already have printed "00" onto the buffer.
4038             //       Hence, --digit_starting_pos doesn't go more than the starting position of the buffer.
4039             --digit_starting_pos;
4040         }
4041     }
4042 
4043     // Nolint is applied to the following two calls since we know they are not supposed to be null terminated
4044     *digit_starting_pos = '1';
4045     std::memset(digit_starting_pos + 1, '0', static_cast<std::size_t>(buffer - digit_starting_pos - 1)); // NOLINT
4046 
4047     goto insert_decimal_dot;
4048 }
4049 
4050 }}} // Namespaces 
4051 
4052 #ifdef BOOST_MSVC
4053 # pragma warning(pop)
4054 #endif
4055 
4056 #endif // BOOST_CHARCONV_DETAIL_FLOFF