File indexing completed on 2025-04-19 08:19:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
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)
0044 # pragma warning(disable: 4554)
0045 #endif
0046
0047 namespace boost { namespace charconv { namespace detail {
0048
0049 #ifdef BOOST_MSVC
0050 # pragma warning(push)
0051 # pragma warning(disable: 4702)
0052
0053
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
0062
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);
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
0116
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
0164
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);
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
0275
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
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
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
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
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
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
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
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
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);
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);
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
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
0495
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; }
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; }
0528 cache_block_count_t& operator=(std::uint8_t) noexcept
0529 {
0530
0531 return *this;
0532 }
0533 };
0534
0535 template <unsigned n>
0536 struct uconst
0537 {
0538 constexpr uconst() {};
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)
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
0686 if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2)
0687 {
0688 return true;
0689 }
0690
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
0708
0709 if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2) {
0710 return true;
0711 }
0712
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 }
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
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
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
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
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
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
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
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
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
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)
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
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
1205
1206
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
1213
1214
1215 else BOOST_IF_CONSTEXPR (min_neg_exp_of_5 + ExtendedCache::segment_length > 23)
1216 {
1217
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
1233
1234
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);
1293 }
1294 #undef BOOST_CHARCONV_252_HAS_FURTHER_DIGITS
1295
1296 BOOST_UNREACHABLE_RETURN(false);
1297 }
1298
1299 #ifdef BOOST_MSVC
1300 # pragma warning(pop)
1301 #endif
1302
1303
1304 inline to_chars_result print_zero_fixed(char* buffer, std::size_t buffer_size, const int precision) noexcept
1305 {
1306
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);
1319 std::memset(buffer + 2, '0', static_cast<std::size_t>(precision));
1320 return {buffer + 2 + precision, std::errc()};
1321 }
1322
1323
1324
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
1337 BOOST_CHARCONV_ASSERT(precision >= 0);
1338 using namespace detail;
1339
1340 std::uint64_t br = default_float_traits<double>::float_to_carrier(x);
1341 bool is_negative = ((br >> 63) != 0);
1342 br <<= 1;
1343 int e = static_cast<int>(br >> (ieee754_binary64::significand_bits + 1));
1344 auto significand = (br & ((UINT64_C(1) << (ieee754_binary64::significand_bits + 1)) - 1));
1345
1346 if (is_negative)
1347 {
1348 *buffer = '-';
1349 ++buffer;
1350 --buffer_size;
1351
1352 if (buffer_size == 0)
1353 {
1354 return {buffer, std::errc::value_too_large};
1355 }
1356 }
1357
1358
1359 if (e == ((UINT32_C(1) << ieee754_binary64::exponent_bits) - 1))
1360 {
1361 if (significand == 0)
1362 {
1363 constexpr std::size_t inf_chars = 3;
1364
1365 if (buffer_size < inf_chars)
1366 {
1367 return {last, std::errc::value_too_large};
1368 }
1369
1370 std::memcpy(buffer, "inf", inf_chars);
1371 return {buffer + inf_chars, std::errc()};
1372 }
1373 else
1374 {
1375
1376
1377
1378
1379 if (significand == UINT64_C(4503599627370496))
1380 {
1381 if (!is_negative)
1382 {
1383 constexpr std::size_t nan_chars = 3;
1384
1385 if (buffer_size < nan_chars)
1386 {
1387 return {last, std::errc::value_too_large};
1388 }
1389
1390 std::memcpy(buffer, "nan", nan_chars);
1391 return {buffer + nan_chars, std::errc()};
1392 }
1393 else
1394 {
1395 constexpr std::size_t neg_nan_chars = 8;
1396
1397 if (buffer_size < neg_nan_chars)
1398 {
1399 return {last, std::errc::value_too_large};
1400 }
1401
1402 std::memcpy(buffer, "nan(ind)", neg_nan_chars);
1403 return {buffer + neg_nan_chars, std::errc()};
1404 }
1405 }
1406 else
1407 {
1408 constexpr std::size_t snan_chars = 9;
1409
1410 if (buffer_size < snan_chars)
1411 {
1412 return {last, std::errc::value_too_large};
1413 }
1414
1415 std::memcpy(buffer, "nan(snan)", snan_chars);
1416 return {buffer + snan_chars, std::errc()};
1417 }
1418 }
1419 }
1420 else
1421 {
1422
1423 if (e != 0)
1424 {
1425 significand |= (decltype(significand)(1) << (ieee754_binary64::significand_bits + 1));
1426 e += (ieee754_binary64::exponent_bias - ieee754_binary64::significand_bits);
1427 }
1428
1429 else
1430 {
1431
1432 if (significand == 0)
1433 {
1434 if (fmt == boost::charconv::chars_format::general)
1435 {
1436
1437 *buffer = '0';
1438 return {buffer + 1, std::errc()};
1439 }
1440 else if (fmt == boost::charconv::chars_format::fixed)
1441 {
1442 return print_zero_fixed(buffer, buffer_size, precision);
1443 }
1444
1445 if (precision == 0)
1446 {
1447 constexpr std::size_t zero_chars = 5;
1448
1449 if (buffer_size < zero_chars)
1450 {
1451 return {last, std::errc::value_too_large};
1452 }
1453
1454 std::memcpy(buffer, "0e+00", zero_chars);
1455 return {buffer + zero_chars, std::errc()};
1456 }
1457 else
1458 {
1459 if (buffer_size < static_cast<std::size_t>(precision) + 6U)
1460 {
1461 return {last, std::errc::value_too_large};
1462 }
1463
1464 std::memcpy(buffer, "0.", 2);
1465 std::memset(buffer + 2, '0', static_cast<std::size_t>(precision));
1466 std::memcpy(buffer + 2 + precision, "e+00", 4);
1467 return {buffer + precision + 6, std::errc()};
1468 }
1469 }
1470
1471 e = ieee754_binary64::min_exponent - ieee754_binary64::significand_bits;
1472 }
1473 }
1474
1475 constexpr int kappa = 2;
1476 int k = kappa - log::floor_log10_pow2(e);
1477 std::uint32_t current_digits {};
1478 char* const buffer_starting_pos = buffer;
1479 char* decimal_dot_pos = buffer;
1480 int decimal_exponent_normalized {};
1481
1482
1483 int remaining_digits {};
1484
1485
1486
1487
1488
1489 {
1490
1491 const auto main_cache = MainCache::template get_cache<ieee754_binary64>(k);
1492 const int beta = e + log::floor_log2_pow10(k);
1493
1494
1495
1496 compute_mul_result segments = [&] {
1497 const auto r = umul192_upper128(significand << beta, main_cache);
1498 return compute_mul_result{r.high, r.low == 0};
1499 }();
1500
1501 auto first_segment = segments.result;
1502 auto has_more_segments = !segments.is_integer;
1503
1504
1505
1506
1507
1508
1509 int first_segment_length = 19;
1510 auto first_segment_aligned = first_segment;
1511 while (first_segment_aligned < UINT64_C(10000000000000000))
1512 {
1513 first_segment_aligned *= 100;
1514 first_segment_length -= 2;
1515 }
1516 if (first_segment_aligned < UINT64_C(1000000000000000000))
1517 {
1518 first_segment_aligned *= 10;
1519 first_segment_length -= 1;
1520 }
1521
1522 decimal_exponent_normalized = first_segment_length - k - 1;
1523
1524
1525 if (fmt == boost::charconv::chars_format::scientific)
1526 {
1527 remaining_digits = precision + 1;
1528 int exponent_print_length =
1529 decimal_exponent_normalized >= 100 ? 5 :
1530 decimal_exponent_normalized <= -100 ? 6 :
1531 decimal_exponent_normalized >= 0 ? 4 : 5;
1532
1533
1534 auto minimum_required_buffer_size =
1535 static_cast<std::size_t>(remaining_digits + exponent_print_length + (precision != 0 ? 1 : 0));
1536 if (buffer_size < minimum_required_buffer_size)
1537 {
1538 return {last, std::errc::value_too_large};
1539 }
1540
1541 if (precision != 0)
1542 {
1543
1544 *buffer = '0';
1545 ++buffer;
1546 ++decimal_dot_pos;
1547 }
1548 }
1549 else if (fmt == boost::charconv::chars_format::fixed)
1550 {
1551 if (decimal_exponent_normalized >= 0)
1552 {
1553 remaining_digits = precision + decimal_exponent_normalized + 1;
1554
1555
1556 auto minimum_required_buffer_size =
1557 static_cast<std::size_t>(remaining_digits + (precision != 0 ? 1 : 0));
1558
1559
1560
1561
1562 if (buffer_size < minimum_required_buffer_size)
1563 {
1564 return {last, std::errc::value_too_large};
1565 }
1566
1567 if (precision != 0)
1568 {
1569
1570 *buffer = '0';
1571 ++buffer;
1572 decimal_dot_pos += decimal_exponent_normalized + 1;
1573 }
1574 }
1575 else
1576 {
1577 int number_of_leading_zeros = -decimal_exponent_normalized - 1;
1578
1579
1580
1581 if (number_of_leading_zeros > precision)
1582 {
1583 return print_zero_fixed(buffer, buffer_size, precision);
1584 }
1585
1586
1587 if (number_of_leading_zeros == precision)
1588 {
1589
1590
1591
1592 bool round_up = (first_segment_aligned + (has_more_segments ? 1 : 0)) > UINT64_C(5000000000000000000);
1593 if (!round_up)
1594 {
1595 return print_zero_fixed(buffer, buffer_size, precision);
1596 }
1597
1598
1599 if (precision == 0)
1600 {
1601 *buffer = '1';
1602 return {buffer + 1, std::errc()};
1603 }
1604
1605 if (buffer_size < static_cast<std::size_t>(precision) + 2U)
1606 {
1607 return {buffer + buffer_size, std::errc::value_too_large};
1608 }
1609
1610 std::memcpy(buffer, "0.", 2);
1611 std::memset(buffer + 2, '0', static_cast<std::size_t>(precision - 1));
1612 buffer[1 + precision] = '1';
1613 return {buffer + 2 + precision, std::errc()};
1614 }
1615
1616 remaining_digits = precision - number_of_leading_zeros;
1617
1618
1619 BOOST_CHARCONV_ASSERT(precision > 0);
1620 auto minimum_required_buffer_size = static_cast<std::size_t>(precision + 2);
1621 if (buffer_size < minimum_required_buffer_size)
1622 {
1623 return {last, std::errc::value_too_large};
1624 }
1625
1626
1627 std::memset(buffer, '0', static_cast<std::size_t>(number_of_leading_zeros + 2));
1628 buffer += number_of_leading_zeros + 2;
1629 ++decimal_dot_pos;
1630 }
1631 }
1632 else
1633 {
1634
1635 if (precision == 0)
1636 {
1637
1638 precision = 1;
1639 }
1640 remaining_digits = precision;
1641
1642
1643
1644
1645
1646
1647
1648
1649 *buffer = '0';
1650 ++buffer;
1651 decimal_dot_pos += (0 < decimal_exponent_normalized && decimal_exponent_normalized < precision)
1652 ? decimal_exponent_normalized + 1 : 1;
1653 }
1654
1655 if (remaining_digits <= 2)
1656 {
1657 uint128 prod;
1658 std::uint64_t fractional_part64;
1659 std::uint64_t fractional_part_rounding_threshold64;
1660
1661
1662
1663 if (remaining_digits == 1)
1664 {
1665 prod = umul128(first_segment_aligned, UINT64_C(1329227995784915873));
1666
1667 fractional_part_rounding_threshold64 = additional_static_data_holder::fractional_part_rounding_thresholds64[17];
1668 }
1669 else
1670 {
1671 prod = umul128(first_segment_aligned, UINT64_C(13292279957849158730));
1672
1673 fractional_part_rounding_threshold64 = additional_static_data_holder::
1674 fractional_part_rounding_thresholds64[16];
1675 }
1676 fractional_part64 = (prod.low >> 56) | (prod.high << 8);
1677 current_digits = static_cast<std::uint32_t>(prod.high >> 56);
1678
1679
1680 if (remaining_digits == 1)
1681 {
1682 if (fractional_part64 >= fractional_part_rounding_threshold64 ||
1683 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1684 {
1685 goto round_up_one_digit;
1686 }
1687
1688 print_1_digit(current_digits, buffer);
1689 ++buffer;
1690 }
1691 else
1692 {
1693 if (fractional_part64 >= fractional_part_rounding_threshold64 ||
1694 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1695 {
1696 goto round_up_two_digits;
1697 }
1698
1699 print_2_digits(current_digits, buffer);
1700 buffer += 2;
1701 }
1702
1703 goto insert_decimal_dot;
1704 }
1705
1706
1707
1708
1709
1710
1711
1712 const auto first_subsegment =
1713 static_cast<std::uint32_t>(umul128_upper64(first_segment, UINT64_C(7922816251426433760)) >> 32);
1714
1715 const auto second_third_subsegments =
1716 first_segment - first_subsegment * UINT64_C(10000000000);
1717
1718 BOOST_CHARCONV_ASSERT(first_subsegment < UINT64_C(1000000000));
1719 BOOST_CHARCONV_ASSERT(second_third_subsegments < UINT64_C(10000000000));
1720
1721 int remaining_digits_in_the_current_subsegment;
1722 std::uint64_t prod;
1723
1724
1725 if (first_subsegment != 0)
1726 {
1727
1728 if (first_subsegment >= 100000000)
1729 {
1730
1731 prod = first_subsegment * UINT64_C(1441151882);
1732 prod >>= 25;
1733 remaining_digits_in_the_current_subsegment = 8;
1734 }
1735
1736 else if (first_subsegment >= 1000000)
1737 {
1738
1739 prod = first_subsegment * UINT64_C(281474978);
1740 prod >>= 16;
1741 remaining_digits_in_the_current_subsegment = 6;
1742 }
1743
1744 else if (first_subsegment >= 10000)
1745 {
1746
1747 prod = first_subsegment * UINT64_C(429497);
1748 remaining_digits_in_the_current_subsegment = 4;
1749 }
1750
1751 else if (first_subsegment >= 100)
1752 {
1753
1754 prod = first_subsegment * UINT64_C(42949673);
1755 remaining_digits_in_the_current_subsegment = 2;
1756 }
1757
1758 else
1759 {
1760 prod = std::uint64_t(first_subsegment) << 32;
1761 remaining_digits_in_the_current_subsegment = 0;
1762 }
1763
1764 const auto initial_digits = static_cast<std::uint32_t>(prod >> 32);
1765
1766 buffer -= (initial_digits < 10 && buffer != first ? 1 : 0);
1767 remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
1768
1769
1770
1771
1772 if (precision == 0 && initial_digits < 10)
1773 {
1774 print_1_digit(initial_digits, buffer);
1775 ++buffer;
1776 }
1777 else
1778 {
1779 print_2_digits(initial_digits, buffer);
1780 buffer += 2;
1781 }
1782
1783 if (remaining_digits > remaining_digits_in_the_current_subsegment)
1784 {
1785 remaining_digits -= remaining_digits_in_the_current_subsegment;
1786
1787 for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2)
1788 {
1789
1790 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1791 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1792 buffer += 2;
1793 }
1794 }
1795 else
1796 {
1797 for (int i = 0; i < (remaining_digits - 1) / 2; ++i)
1798 {
1799
1800 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1801 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1802 buffer += 2;
1803 }
1804
1805
1806 if (remaining_digits_in_the_current_subsegment > remaining_digits)
1807 {
1808 if ((remaining_digits & 1) != 0)
1809 {
1810 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
1811 }
1812 else
1813 {
1814 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1815 }
1816
1817 current_digits = static_cast<std::uint32_t>(prod >> 32);
1818
1819 if (check_rounding_condition_inside_subsegment(
1820 current_digits, static_cast<std::uint32_t>(prod),
1821 remaining_digits_in_the_current_subsegment - remaining_digits,
1822 second_third_subsegments != 0 || has_more_segments))
1823 {
1824 goto round_up;
1825 }
1826
1827 goto print_last_digits;
1828 }
1829 else
1830 {
1831 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1832 current_digits = static_cast<std::uint32_t>(prod >> 32);
1833
1834 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
1835 current_digits,
1836 uint_with_known_number_of_digits<10>{second_third_subsegments},
1837 has_more_segments))
1838 {
1839 goto round_up_two_digits;
1840 }
1841
1842 goto print_last_two_digits;
1843 }
1844 }
1845 }
1846
1847
1848
1849
1850 if (remaining_digits <= 2)
1851 {
1852
1853
1854 if (remaining_digits == 1)
1855 {
1856 const auto prod128 = umul128(second_third_subsegments, UINT64_C(18446744074));
1857
1858 current_digits = static_cast<std::uint32_t>(prod128.high);
1859 const auto fractional_part64 = prod128.low + 1;
1860
1861 BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
1862
1863 if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[8] ||
1864 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1865 {
1866 goto round_up_one_digit;
1867 }
1868
1869 goto print_last_one_digit;
1870 }
1871 else
1872 {
1873 const auto prod128 = umul128(second_third_subsegments, UINT64_C(184467440738));
1874
1875 current_digits = static_cast<std::uint32_t>(prod128.high);
1876 const auto fractional_part64 = prod128.low + 1;
1877
1878 BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
1879
1880 if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[7] ||
1881 ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
1882 {
1883 goto round_up_two_digits;
1884 }
1885
1886 goto print_last_two_digits;
1887 }
1888 }
1889
1890
1891
1892
1893
1894 const auto second_subsegment = static_cast<std::uint32_t>(
1895 umul128_upper64(second_third_subsegments, UINT64_C(184467440737095517)));
1896
1897
1898 const auto third_subsegment =
1899 static_cast<std::uint32_t>(second_third_subsegments) - second_subsegment * 100;
1900
1901 BOOST_CHARCONV_ASSERT(second_subsegment < 100000000);
1902 BOOST_CHARCONV_ASSERT(third_subsegment < 100);
1903
1904 {
1905 std::uint32_t initial_digits;
1906 if (first_subsegment != 0)
1907 {
1908 prod = ((second_subsegment * UINT64_C(281474977)) >> 16) + 1;
1909 remaining_digits_in_the_current_subsegment = 6;
1910
1911 initial_digits = static_cast<std::uint32_t>(prod >> 32);
1912 remaining_digits -= 2;
1913 }
1914 else
1915 {
1916
1917 if (second_subsegment >= 1000000)
1918 {
1919 prod = (second_subsegment * UINT64_C(281474978)) >> 16;
1920 remaining_digits_in_the_current_subsegment = 6;
1921 }
1922
1923 else if (second_subsegment >= 10000)
1924 {
1925 prod = second_subsegment * UINT64_C(429497);
1926 remaining_digits_in_the_current_subsegment = 4;
1927 }
1928
1929 else if (second_subsegment >= 100)
1930 {
1931 prod = second_subsegment * UINT64_C(42949673);
1932 remaining_digits_in_the_current_subsegment = 2;
1933 }
1934
1935 else
1936 {
1937 prod = std::uint64_t(second_subsegment) << 32;
1938 remaining_digits_in_the_current_subsegment = 0;
1939 }
1940
1941 initial_digits = static_cast<std::uint32_t>(prod >> 32);
1942 buffer -= (initial_digits < 10 ? 1 : 0);
1943 remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
1944 }
1945
1946 print_2_digits(initial_digits, buffer);
1947 buffer += 2;
1948
1949 if (remaining_digits > remaining_digits_in_the_current_subsegment)
1950 {
1951 remaining_digits -= remaining_digits_in_the_current_subsegment;
1952 for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2)
1953 {
1954
1955 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1956 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1957 buffer += 2;
1958 }
1959 }
1960 else
1961 {
1962 for (int i = 0; i < (remaining_digits - 1) / 2; ++i)
1963 {
1964
1965 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1966 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
1967 buffer += 2;
1968 }
1969
1970
1971 if (remaining_digits_in_the_current_subsegment > remaining_digits)
1972 {
1973 if ((remaining_digits & 1) != 0)
1974 {
1975 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
1976 }
1977 else
1978 {
1979 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1980 }
1981 current_digits = static_cast<std::uint32_t>(prod >> 32);
1982
1983 if (check_rounding_condition_inside_subsegment(
1984 current_digits, static_cast<std::uint32_t>(prod),
1985 remaining_digits_in_the_current_subsegment - remaining_digits,
1986 third_subsegment != 0 || has_more_segments))
1987 {
1988 goto round_up;
1989 }
1990
1991 goto print_last_digits;
1992 }
1993 else
1994 {
1995 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
1996 current_digits = static_cast<std::uint32_t>(prod >> 32);
1997
1998 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
1999 current_digits,
2000 uint_with_known_number_of_digits<2>{third_subsegment},
2001 has_more_segments))
2002 {
2003 goto round_up_two_digits;
2004 }
2005
2006 goto print_last_two_digits;
2007 }
2008 }
2009 }
2010
2011
2012 {
2013 if (remaining_digits > 2)
2014 {
2015 print_2_digits(third_subsegment, buffer);
2016 buffer += 2;
2017 remaining_digits -= 2;
2018
2019
2020 if (!has_more_segments)
2021 {
2022 goto fill_remaining_digits_with_0s;
2023 }
2024 }
2025 else if (remaining_digits == 1)
2026 {
2027 prod = third_subsegment * UINT64_C(429496730);
2028 current_digits = static_cast<std::uint32_t>(prod >> 32);
2029
2030 if (check_rounding_condition_inside_subsegment(
2031 current_digits, static_cast<std::uint32_t>(prod), 1, has_more_segments))
2032 {
2033 goto round_up_one_digit;
2034 }
2035
2036 goto print_last_one_digit;
2037 }
2038 else
2039 {
2040
2041
2042 if (!has_more_segments)
2043 {
2044 print_2_digits(third_subsegment, buffer);
2045 buffer += 2;
2046 goto insert_decimal_dot;
2047 }
2048
2049
2050
2051
2052 remaining_digits = 0;
2053 current_digits = third_subsegment;
2054 }
2055 }
2056 }
2057
2058
2059
2060
2061
2062 {
2063 auto multiplier_index =
2064 static_cast<std::uint32_t>(k + ExtendedCache::segment_length - ExtendedCache::k_min) /
2065 static_cast<std::uint32_t>(ExtendedCache::segment_length);
2066
2067 int digits_in_the_second_segment;
2068 {
2069 const auto new_k =
2070 ExtendedCache::k_min + static_cast<int>(multiplier_index) * ExtendedCache::segment_length;
2071 digits_in_the_second_segment = new_k - k;
2072 k = new_k;
2073 }
2074
2075 const auto exp2_base = e + boost::core::countr_zero(significand);
2076
2077 using cache_block_type = typename std::decay<decltype(ExtendedCache::cache[0])>::type;
2078
2079 cache_block_type blocks[ExtendedCache::max_cache_blocks];
2080 cache_block_count_t<ExtendedCache::constant_block_count, ExtendedCache::max_cache_blocks> cache_block_count;
2081
2082
2083
2084
2085
2086 {
2087 cache_block_count =
2088 load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(
2089 blocks, e, k, multiplier_index);
2090
2091
2092 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
2093
2094 BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
2095 {
2096
2097 if (remaining_digits > digits_in_the_second_segment)
2098 {
2099 remaining_digits -= digits_in_the_second_segment;
2100
2101 if (digits_in_the_second_segment <= 2)
2102 {
2103 BOOST_CHARCONV_ASSERT(digits_in_the_second_segment != 0);
2104
2105 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2106 power_of_10[19], blocks, cache_block_count);
2107
2108 auto subsegment =
2109 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2110 generate_and_discard_lower(power_of_10[3], blocks,
2111 cache_block_count);
2112
2113 if (digits_in_the_second_segment == 1)
2114 {
2115 auto prod = subsegment * UINT64_C(429496730);
2116 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2117 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2118 ++buffer;
2119 }
2120 else
2121 {
2122 auto prod = subsegment * UINT64_C(42949673);
2123 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2124 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2125 buffer += 2;
2126 }
2127 }
2128 else if (digits_in_the_second_segment <= 16)
2129 {
2130 BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
2131
2132 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2133 compute_power(UINT64_C(10), 22 - digits_in_the_second_segment),
2134 blocks, cache_block_count);
2135
2136
2137 if (digits_in_the_second_segment <= 9)
2138 {
2139
2140 const auto subsegment =
2141 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2142 generate_and_discard_lower(power_of_10[9], blocks,
2143 cache_block_count);
2144
2145 std::uint64_t prod;
2146 if ((digits_in_the_second_segment & 1) != 0)
2147 {
2148 prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
2149 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2150 ++buffer;
2151 }
2152 else
2153 {
2154 prod = ((subsegment * UINT64_C(450359963)) >> 20) + 1;
2155 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2156 buffer += 2;
2157 }
2158
2159 for (; digits_in_the_second_segment > 2; digits_in_the_second_segment -= 2)
2160 {
2161 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2162 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2163 buffer += 2;
2164 }
2165 }
2166 else
2167 {
2168
2169 const auto first_second_subsegments =
2170 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2171 generate_and_discard_lower(power_of_10[16], blocks,
2172 cache_block_count);
2173
2174
2175
2176
2177
2178 const auto first_subsegment =
2179 static_cast<std::uint32_t>(umul128_upper64(first_second_subsegments,
2180 UINT64_C(3022314549036573)) >>
2181 14);
2182 const auto second_subsegment =
2183 static_cast<std::uint32_t>(first_second_subsegments) -
2184 UINT32_C(100000000) * first_subsegment;
2185
2186
2187 print_8_digits(first_subsegment, buffer);
2188 buffer += 8;
2189
2190
2191
2192 auto prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
2193 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2194 buffer += 2;
2195 digits_in_the_second_segment -= 10;
2196
2197 for (; digits_in_the_second_segment > 1; digits_in_the_second_segment -= 2)
2198 {
2199 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2200 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2201 buffer += 2;
2202 }
2203
2204 if (digits_in_the_second_segment != 0)
2205 {
2206 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2207 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2208 ++buffer;
2209 }
2210 }
2211 }
2212 else
2213 {
2214
2215 const auto first_subsegment =
2216 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
2217 power_of_10[6], blocks, cache_block_count);
2218
2219 const auto second_third_subsegments =
2220 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2221 generate_and_discard_lower(power_of_10[16], blocks,
2222 cache_block_count);
2223
2224
2225
2226 const auto second_subsegment =
2227 static_cast<std::uint32_t>(umul128_upper64(second_third_subsegments,
2228 UINT64_C(3022314549036573)) >>
2229 14);
2230 const auto third_subsegment = static_cast<std::uint32_t>(second_third_subsegments) -
2231 UINT32_C(100000000) * second_subsegment;
2232
2233
2234 std::uint64_t prod {};
2235 auto remaining_digits_in_the_current_subsegment =
2236 digits_in_the_second_segment - 16;
2237
2238 switch (remaining_digits_in_the_current_subsegment)
2239 {
2240 case 1:
2241 prod = first_subsegment * UINT64_C(429496730);
2242 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2243
2244 case 2:
2245 prod = first_subsegment * UINT64_C(42949673);
2246 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2247
2248 case 3:
2249 prod = first_subsegment * UINT64_C(4294968);
2250 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2251
2252 case 4:
2253 prod = first_subsegment * UINT64_C(429497);
2254 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2255
2256 case 5:
2257 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2258 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
2259
2260 case 6:
2261 prod = first_subsegment * UINT64_C(429497);
2262 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2263 buffer += 2;
2264 remaining_digits_in_the_current_subsegment = 4;
2265 goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
2266
2267 default:
2268 BOOST_UNREACHABLE_RETURN(prod);
2269 }
2270
2271 second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining
2272 :
2273 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2274 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2275 ++buffer;
2276
2277 second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining
2278 :
2279 for (; remaining_digits_in_the_current_subsegment > 1;
2280 remaining_digits_in_the_current_subsegment -= 2)
2281 {
2282 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2283 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2284 buffer += 2;
2285 }
2286
2287
2288 print_8_digits(second_subsegment, buffer);
2289 print_8_digits(third_subsegment, buffer + 8);
2290 buffer += 16;
2291 }
2292 }
2293
2294
2295 else
2296 {
2297 if (digits_in_the_second_segment <= 2)
2298 {
2299 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2300 power_of_10[19], blocks, cache_block_count);
2301
2302
2303 auto subsegment =
2304 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2305 generate_and_discard_lower(2000, blocks, cache_block_count);
2306
2307 bool segment_boundary_rounding_bit = ((subsegment & 1) != 0);
2308 subsegment >>= 1;
2309
2310 if (digits_in_the_second_segment == 2)
2311 {
2312
2313
2314
2315 auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(42949673);
2316
2317 if (remaining_digits == 1)
2318 {
2319 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2320 current_digits = static_cast<std::uint32_t>(prod >> 32);
2321 const bool has_further_digits_v = has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
2322 if (check_rounding_condition_inside_subsegment(current_digits, static_cast<std::uint32_t>(prod), 1, has_further_digits_v))
2323 {
2324 goto round_up_one_digit;
2325 }
2326 goto print_last_one_digit;
2327 }
2328
2329 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2330 const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2331
2332 if (remaining_digits == 0)
2333 {
2334 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2335 current_digits,
2336 uint_with_known_number_of_digits<2>{next_digits},
2337 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2338 {
2339 goto round_up_two_digits;
2340 }
2341 goto print_last_two_digits;
2342 }
2343
2344 current_digits = next_digits;
2345 BOOST_CHARCONV_ASSERT(remaining_digits == 2);
2346 }
2347 else
2348 {
2349 BOOST_CHARCONV_ASSERT(digits_in_the_second_segment == 1);
2350
2351
2352
2353 auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(429496730);
2354 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2355 const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2356
2357 if (remaining_digits == 0)
2358 {
2359 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2360 current_digits,
2361 uint_with_known_number_of_digits<1>{next_digits},
2362 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2363 {
2364 goto round_up_two_digits;
2365 }
2366 goto print_last_two_digits;
2367 }
2368
2369 current_digits = next_digits;
2370 BOOST_CHARCONV_ASSERT(remaining_digits == 1);
2371 }
2372
2373 if (check_rounding_condition_with_next_bit(
2374 current_digits, segment_boundary_rounding_bit,
2375 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
2376 {
2377 goto round_up;
2378 }
2379
2380 goto print_last_digits;
2381 }
2382
2383
2384 if (digits_in_the_second_segment <= 9)
2385 {
2386
2387 BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
2388
2389 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2390 compute_power(UINT64_C(10), 22 - digits_in_the_second_segment),
2391 blocks, cache_block_count);
2392
2393
2394 auto segment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2395 generate_and_discard_lower(power_of_10[9] << 1, blocks,
2396 cache_block_count);
2397
2398 std::uint64_t prod;
2399 digits_in_the_second_segment -= remaining_digits;
2400
2401 if ((remaining_digits & 1) != 0)
2402 {
2403 prod = ((segment * UINT64_C(1441151881)) >> 26) + 1;
2404 current_digits = static_cast<std::uint32_t>(prod >> 32);
2405
2406 if (remaining_digits == 1)
2407 {
2408 goto second_segment22_at_most_9_digits_rounding;
2409 }
2410
2411 print_1_digit(current_digits, buffer);
2412 ++buffer;
2413 }
2414 else
2415 {
2416 prod = ((segment * UINT64_C(1801439851)) >> 23) + 1;
2417 const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
2418
2419 if (remaining_digits == 0)
2420 {
2421 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2422 current_digits,
2423 uint_with_known_number_of_digits<2>{next_digits}, [&] {
2424 return static_cast<std::uint32_t>(prod) >=
2425 (additional_static_data_holder::
2426 fractional_part_rounding_thresholds32[digits_in_the_second_segment - 3] & UINT32_C(0x7fffffff))
2427 || has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
2428 }))
2429 {
2430 goto round_up_two_digits;
2431 }
2432 goto print_last_two_digits;
2433 }
2434 else if (remaining_digits == 2)
2435 {
2436 current_digits = next_digits;
2437 goto second_segment22_at_most_9_digits_rounding;
2438 }
2439
2440 print_2_digits(next_digits, buffer);
2441 buffer += 2;
2442 }
2443
2444 BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2445
2446 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
2447 {
2448 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2449 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2450 buffer += 2;
2451 }
2452
2453 if (digits_in_the_second_segment != 0)
2454 {
2455 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2456 current_digits = static_cast<std::uint32_t>(prod >> 32);
2457 remaining_digits = 0;
2458
2459 second_segment22_at_most_9_digits_rounding:
2460 if (check_rounding_condition_inside_subsegment(
2461 current_digits, static_cast<std::uint32_t>(prod),
2462 digits_in_the_second_segment, has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1,
2463 uconst0)))
2464 {
2465 goto round_up;
2466 }
2467
2468 goto print_last_digits;
2469 }
2470 else
2471 {
2472 prod = static_cast<std::uint32_t>(prod) * UINT64_C(200);
2473 current_digits = static_cast<std::uint32_t>(prod >> 32);
2474 const auto segment_boundary_rounding_bit = (current_digits & 1) != 0;
2475 current_digits >>= 1;
2476
2477 if (check_rounding_condition_with_next_bit(
2478 current_digits, segment_boundary_rounding_bit,
2479 has_further_digits<0, 1, ExtendedCache>(significand, exp2_base, k, uconst0, uconst1)))
2480 {
2481 goto round_up_two_digits;
2482 }
2483 goto print_last_two_digits;
2484 }
2485 }
2486
2487
2488
2489
2490 auto first_second_subsegments =
2491 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
2492 power_of_10[13] << 1, blocks, cache_block_count);
2493
2494 bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
2495 first_second_subsegments >>= 1;
2496
2497
2498
2499
2500
2501 const auto first_subsegment =
2502 static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(
2503 first_second_subsegments, 1844674407371));
2504
2505 const auto second_subsegment =
2506 static_cast<std::uint32_t>(first_second_subsegments) - 10000000 * first_subsegment;
2507
2508 int digits_in_the_second_subsegment;
2509
2510
2511 if (digits_in_the_second_segment > 16)
2512 {
2513 std::uint64_t prod;
2514 int remaining_digits_in_the_current_subsegment = digits_in_the_second_segment - 16;
2515
2516
2517 if (remaining_digits > remaining_digits_in_the_current_subsegment)
2518 {
2519 remaining_digits -= remaining_digits_in_the_current_subsegment;
2520
2521
2522 digits_in_the_second_subsegment = 7;
2523
2524
2525 if (remaining_digits_in_the_current_subsegment == 6)
2526 {
2527 prod = (first_subsegment * UINT64_C(429497)) + 1;
2528 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2529 buffer += 2;
2530 remaining_digits_in_the_current_subsegment -= 2;
2531 }
2532
2533
2534 else
2535 {
2536 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2537 prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
2538
2539 if ((remaining_digits_in_the_current_subsegment & 1) != 0)
2540 {
2541 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2542 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2543 ++buffer;
2544 }
2545 }
2546
2547 for (; remaining_digits_in_the_current_subsegment > 1; remaining_digits_in_the_current_subsegment -= 2)
2548 {
2549 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2550 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2551 buffer += 2;
2552 }
2553 }
2554
2555 else
2556 {
2557 if ((remaining_digits & 1) != 0)
2558 {
2559 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2560
2561
2562
2563 if (remaining_digits_in_the_current_subsegment < 6)
2564 {
2565 prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
2566 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2567 }
2568 current_digits = static_cast<std::uint32_t>(prod >> 32);
2569 remaining_digits_in_the_current_subsegment -= remaining_digits;
2570
2571 if (remaining_digits == 1)
2572 {
2573 goto second_segment22_more_than_9_digits_first_subsegment_rounding;
2574 }
2575
2576 print_1_digit(current_digits, buffer);
2577 ++buffer;
2578 }
2579 else
2580 {
2581
2582 if (remaining_digits_in_the_current_subsegment == 6)
2583 {
2584 if (remaining_digits == 0)
2585 {
2586 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2587 current_digits,
2588 uint_with_known_number_of_digits<6>{
2589 first_subsegment},
2590 has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
2591 {
2592 goto round_up_two_digits;
2593 }
2594 goto print_last_two_digits;
2595 }
2596
2597 prod = (first_subsegment * UINT64_C(429497)) + 1;
2598 }
2599
2600
2601
2602 else
2603 {
2604 prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
2605 prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
2606
2607 if (remaining_digits == 0)
2608 {
2609 goto second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment;
2610 }
2611
2612 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2613 }
2614 current_digits = static_cast<std::uint32_t>(prod >> 32);
2615 remaining_digits_in_the_current_subsegment -= remaining_digits;
2616
2617 if (remaining_digits == 2)
2618 {
2619 goto second_segment22_more_than_9_digits_first_subsegment_rounding;
2620 }
2621
2622 print_2_digits(current_digits, buffer);
2623 buffer += 2;
2624 }
2625
2626 BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2627
2628 if (remaining_digits > 4)
2629 {
2630 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2631 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2632 buffer += 2;
2633 }
2634
2635 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2636 current_digits = static_cast<std::uint32_t>(prod >> 32);
2637 remaining_digits = 0;
2638
2639 second_segment22_more_than_9_digits_first_subsegment_rounding:
2640 if (remaining_digits_in_the_current_subsegment == 0)
2641 {
2642 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2643 current_digits,
2644 uint_with_known_number_of_digits<7>{second_subsegment},
2645 has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
2646 {
2647 goto round_up;
2648 }
2649 }
2650 else
2651 {
2652 second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment
2653 :
2654 if (check_rounding_condition_inside_subsegment(
2655 current_digits, static_cast<std::uint32_t>(prod),
2656 remaining_digits_in_the_current_subsegment,
2657 has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
2658 {
2659 goto round_up;
2660 }
2661 }
2662 goto print_last_digits;
2663 }
2664 }
2665 else
2666 {
2667 digits_in_the_second_subsegment = digits_in_the_second_segment - 9;
2668 }
2669
2670
2671 {
2672
2673 if (remaining_digits > digits_in_the_second_subsegment)
2674 {
2675 auto prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2676 remaining_digits -= digits_in_the_second_subsegment;
2677
2678
2679 if (digits_in_the_second_subsegment == 7)
2680 {
2681 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2682 ++buffer;
2683 }
2684
2685
2686 else
2687 {
2688 prod *= compute_power(UINT64_C(10),
2689 6 - digits_in_the_second_subsegment);
2690
2691 if ((digits_in_the_second_subsegment & 1) != 0)
2692 {
2693 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2694 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2695 ++buffer;
2696 }
2697 }
2698
2699 for (; digits_in_the_second_subsegment > 1; digits_in_the_second_subsegment -= 2)
2700 {
2701 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2702 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2703 buffer += 2;
2704 }
2705 }
2706
2707 else
2708 {
2709 std::uint64_t prod;
2710
2711 if ((remaining_digits & 1) != 0)
2712 {
2713 prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2714
2715
2716
2717 if (digits_in_the_second_subsegment < 7)
2718 {
2719 prod *= compute_power(UINT64_C(10), 6 - digits_in_the_second_subsegment);
2720 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2721 }
2722 current_digits = static_cast<std::uint32_t>(prod >> 32);
2723 digits_in_the_second_subsegment -= remaining_digits;
2724
2725 if (remaining_digits == 1)
2726 {
2727 goto second_segment22_more_than_9_digits_second_subsegment_rounding;
2728 }
2729
2730 print_1_digit(current_digits, buffer);
2731 ++buffer;
2732 }
2733 else
2734 {
2735
2736 if (digits_in_the_second_subsegment == 7)
2737 {
2738 if (remaining_digits == 0)
2739 {
2740 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2741 current_digits,
2742 uint_with_known_number_of_digits<7>{
2743 second_subsegment},
2744 has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
2745 {
2746 goto round_up_two_digits;
2747 }
2748 goto print_last_two_digits;
2749 }
2750
2751 prod = ((second_subsegment * UINT64_C(10995117)) >> 8) + 1;
2752 }
2753
2754
2755
2756 else
2757 {
2758 prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
2759 prod *= compute_power(UINT64_C(10), 6 - digits_in_the_second_subsegment);
2760
2761 if (remaining_digits == 0)
2762 {
2763 goto second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment;
2764 }
2765
2766 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2767 }
2768 current_digits = static_cast<std::uint32_t>(prod >> 32);
2769 digits_in_the_second_subsegment -= remaining_digits;
2770
2771 if (remaining_digits == 2)
2772 {
2773 goto second_segment22_more_than_9_digits_second_subsegment_rounding;
2774 }
2775
2776 print_2_digits(current_digits, buffer);
2777 buffer += 2;
2778 }
2779
2780 BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
2781
2782 if (remaining_digits > 4)
2783 {
2784 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2785 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2786 buffer += 2;
2787 }
2788
2789 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2790 current_digits = static_cast<std::uint32_t>(prod >> 32);
2791 remaining_digits = 0;
2792
2793 second_segment22_more_than_9_digits_second_subsegment_rounding:
2794 if (digits_in_the_second_subsegment == 0)
2795 {
2796 if (check_rounding_condition_with_next_bit(
2797 current_digits, first_bit_of_third_subsegment,
2798 has_further_digits<0, 9, ExtendedCache>(significand, exp2_base, k, uconst0, uconst9)))
2799 {
2800 goto round_up;
2801 }
2802 }
2803 else
2804 {
2805 second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment
2806 :
2807 if (check_rounding_condition_inside_subsegment(
2808 current_digits, static_cast<std::uint32_t>(prod),
2809 digits_in_the_second_subsegment, has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k,
2810 uconst1, uconst9)))
2811 {
2812 goto round_up;
2813 }
2814 }
2815 goto print_last_digits;
2816 }
2817 }
2818
2819
2820 {
2821
2822
2823
2824
2825 auto third_subsegment =
2826 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
2827 generate_and_discard_lower(power_of_10[9], blocks,
2828 cache_block_count);
2829
2830 bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
2831 third_subsegment >>= 1;
2832 third_subsegment += (first_bit_of_third_subsegment ? 500000000 : 0);
2833
2834 std::uint64_t prod;
2835 if ((remaining_digits & 1) != 0)
2836 {
2837 prod = ((third_subsegment * UINT64_C(720575941)) >> 24) + 1;
2838 current_digits = static_cast<std::uint32_t>(prod >> 32);
2839
2840 if (remaining_digits == 1)
2841 {
2842 if (check_rounding_condition_inside_subsegment(
2843 current_digits, static_cast<std::uint32_t>(prod), 8,
2844 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2845 {
2846 goto round_up_one_digit;
2847 }
2848 goto print_last_one_digit;
2849 }
2850
2851 print_1_digit(current_digits, buffer);
2852 ++buffer;
2853 }
2854 else
2855 {
2856 prod = ((third_subsegment * UINT64_C(450359963)) >> 20) + 1;
2857 current_digits = static_cast<std::uint32_t>(prod >> 32);
2858
2859 if (remaining_digits == 2)
2860 {
2861 goto second_segment22_more_than_9_digits_third_subsegment_rounding;
2862 }
2863
2864 print_2_digits(current_digits, buffer);
2865 buffer += 2;
2866 }
2867
2868 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
2869 {
2870 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2871 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2872 buffer += 2;
2873 }
2874
2875 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2876 current_digits = static_cast<std::uint32_t>(prod >> 32);
2877
2878 if (remaining_digits < 9)
2879 {
2880 second_segment22_more_than_9_digits_third_subsegment_rounding:
2881 if (check_rounding_condition_inside_subsegment(
2882 current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
2883 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
2884 {
2885 goto round_up_two_digits;
2886 }
2887 }
2888 else
2889 {
2890 if (check_rounding_condition_with_next_bit(
2891 current_digits, segment_boundary_rounding_bit,
2892 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
2893 {
2894 goto round_up_two_digits;
2895 }
2896 }
2897 goto print_last_two_digits;
2898 }
2899 }
2900 }
2901
2902 else BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 252)
2903 {
2904 int overlapping_digits = 252 - digits_in_the_second_segment;
2905 int remaining_subsegment_pairs = 14;
2906
2907 while (overlapping_digits >= 18)
2908 {
2909 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
2910 power_of_10[18], blocks, cache_block_count);
2911 --remaining_subsegment_pairs;
2912 overlapping_digits -= 18;
2913 }
2914
2915 auto subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18] << 1, blocks, cache_block_count);
2916 auto subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
2917 subsegment_pair >>= 1;
2918
2919
2920 {
2921
2922 const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
2923 const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
2924
2925 auto print_subsegment = [&](std::uint32_t subsegment, int digits_in_the_subsegment)
2926 {
2927 remaining_digits -= digits_in_the_subsegment;
2928
2929
2930 auto prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
2931 if (digits_in_the_subsegment < 9)
2932 {
2933 prod *= compute_power(UINT32_C(10), 8 - digits_in_the_subsegment);
2934
2935 if ((digits_in_the_subsegment & 1) != 0)
2936 {
2937 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
2938 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2939 ++buffer;
2940 }
2941 }
2942 else
2943 {
2944 print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
2945 ++buffer;
2946 }
2947
2948 for (; digits_in_the_subsegment > 1; digits_in_the_subsegment -= 2)
2949 {
2950 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
2951 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
2952 buffer += 2;
2953 }
2954 };
2955
2956
2957 int digits_in_the_second_part;
2958 if (overlapping_digits < 9)
2959 {
2960 int digits_in_the_first_part = 9 - overlapping_digits;
2961
2962
2963 if (remaining_digits > digits_in_the_first_part)
2964 {
2965 digits_in_the_second_part = 9;
2966 print_subsegment(first_part, digits_in_the_first_part);
2967 }
2968
2969 else
2970 {
2971
2972 std::uint64_t prod;
2973 if (digits_in_the_first_part == 9)
2974 {
2975 if ((remaining_digits & 1) != 0)
2976 {
2977 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
2978 }
2979 else
2980 {
2981 if (remaining_digits == 0)
2982 {
2983 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
2984 current_digits,
2985 uint_with_known_number_of_digits<9>{first_part},
2986 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
2987 {
2988 goto round_up_two_digits;
2989 }
2990 goto print_last_two_digits;
2991 }
2992
2993 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
2994 }
2995 }
2996 else
2997 {
2998 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
2999 prod *= compute_power(UINT32_C(10), 8 - digits_in_the_first_part);
3000
3001 if ((remaining_digits & 1) != 0)
3002 {
3003 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
3004 }
3005 else
3006 {
3007 if (remaining_digits == 0)
3008 {
3009 goto second_segment252_first_subsegment_rounding_inside_subsegment;
3010 }
3011
3012 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3013 }
3014 }
3015 digits_in_the_first_part -= remaining_digits;
3016 current_digits = static_cast<std::uint32_t>(prod >> 32);
3017
3018 if (remaining_digits > 2)
3019 {
3020 if ((remaining_digits & 1) != 0)
3021 {
3022 print_1_digit(current_digits, buffer);
3023 ++buffer;
3024 }
3025 else
3026 {
3027 print_2_digits(current_digits, buffer);
3028 buffer += 2;
3029 }
3030
3031 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3032 {
3033 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3034 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3035 buffer += 2;
3036 }
3037
3038 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3039 current_digits = static_cast<std::uint32_t>(prod >> 32);
3040 remaining_digits = 0;
3041 }
3042
3043 if (digits_in_the_first_part != 0)
3044 {
3045 second_segment252_first_subsegment_rounding_inside_subsegment:
3046 if (check_rounding_condition_inside_subsegment(
3047 current_digits, static_cast<std::uint32_t>(prod),
3048 digits_in_the_first_part, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3049 {
3050 goto round_up;
3051 }
3052 }
3053 else
3054 {
3055 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3056 current_digits,
3057 uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3058 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3059 {
3060 goto round_up;
3061 }
3062 }
3063 goto print_last_digits;
3064 }
3065 }
3066 else
3067 {
3068 digits_in_the_second_part = 18 - overlapping_digits;
3069 }
3070
3071
3072
3073 if (remaining_digits > digits_in_the_second_part)
3074 {
3075 print_subsegment(second_part, digits_in_the_second_part);
3076 }
3077
3078 else
3079 {
3080
3081 std::uint64_t prod;
3082 if (digits_in_the_second_part == 9)
3083 {
3084 if ((remaining_digits & 1) != 0)
3085 {
3086 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3087 }
3088 else
3089 {
3090 if (remaining_digits == 0)
3091 {
3092 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3093 current_digits,
3094 uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3095 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3096 {
3097 goto round_up_two_digits;
3098 }
3099 goto print_last_two_digits;
3100 }
3101
3102 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3103 }
3104 }
3105 else
3106 {
3107 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3108 prod *= compute_power(UINT32_C(10), 8 - digits_in_the_second_part);
3109
3110 if ((remaining_digits & 1) != 0)
3111 {
3112 prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
3113 }
3114 else
3115 {
3116 if (remaining_digits == 0)
3117 {
3118 goto second_segment252_second_subsegment_rounding_inside_subsegment;
3119 }
3120
3121 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3122 }
3123 }
3124 digits_in_the_second_part -= remaining_digits;
3125 current_digits = static_cast<std::uint32_t>(prod >> 32);
3126
3127 if (remaining_digits > 2)
3128 {
3129 if ((remaining_digits & 1) != 0)
3130 {
3131 print_1_digit(current_digits, buffer);
3132 ++buffer;
3133 }
3134 else
3135 {
3136 print_2_digits(current_digits, buffer);
3137 buffer += 2;
3138 }
3139
3140 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3141 {
3142 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3143 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3144 buffer += 2;
3145 }
3146
3147 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3148 current_digits = static_cast<std::uint32_t>(prod >> 32);
3149 remaining_digits = 0;
3150 }
3151
3152 if (digits_in_the_second_part != 0)
3153 {
3154 second_segment252_second_subsegment_rounding_inside_subsegment:
3155 if (check_rounding_condition_inside_subsegment(
3156 current_digits, static_cast<std::uint32_t>(prod),
3157 digits_in_the_second_part, compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3158 {
3159 goto round_up;
3160 }
3161 }
3162 else
3163 {
3164 if (check_rounding_condition_with_next_bit(
3165 current_digits, subsegment_boundary_rounding_bit,
3166 compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3167 {
3168 goto round_up;
3169 }
3170 }
3171 goto print_last_digits;
3172 }
3173 }
3174
3175
3176 --remaining_subsegment_pairs;
3177 for (; remaining_subsegment_pairs > 0; --remaining_subsegment_pairs)
3178 {
3179 subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
3180
3181 subsegment_pair += (subsegment_boundary_rounding_bit ? power_of_10[18] : 0);
3182 subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
3183 subsegment_pair >>= 1;
3184
3185 const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
3186 const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
3187
3188
3189 if (remaining_digits > 9)
3190 {
3191 print_9_digits(first_part, buffer);
3192
3193
3194 if (remaining_digits > 18)
3195 {
3196 print_9_digits(second_part, buffer + 9);
3197 }
3198
3199 else
3200 {
3201 buffer += 9;
3202 remaining_digits -= 9;
3203
3204 std::uint64_t prod;
3205 int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
3206
3207 if ((remaining_digits & 1) != 0)
3208 {
3209 prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
3210 current_digits = static_cast<std::uint32_t>(prod >> 32);
3211
3212 if (remaining_digits == 1)
3213 {
3214 goto second_segment252_loop_second_subsegment_rounding;
3215 }
3216
3217 print_1_digit(current_digits, buffer);
3218 ++buffer;
3219 }
3220 else
3221 {
3222 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3223 current_digits = static_cast<std::uint32_t>(prod >> 32);
3224
3225 if (remaining_digits == 2)
3226 {
3227 goto second_segment252_loop_second_subsegment_rounding;
3228 }
3229
3230 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3231 buffer += 2;
3232 }
3233
3234 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3235 {
3236 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3237 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3238 buffer += 2;
3239 }
3240
3241 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3242 current_digits = static_cast<std::uint32_t>(prod >> 32);
3243 remaining_digits = 0;
3244
3245 if (remaining_digits_in_the_current_subsegment != 0)
3246 {
3247 second_segment252_loop_second_subsegment_rounding:
3248 if (check_rounding_condition_inside_subsegment(
3249 current_digits, static_cast<std::uint32_t>(prod),
3250 remaining_digits_in_the_current_subsegment,
3251 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3252 {
3253 goto round_up;
3254 }
3255 goto print_last_digits;
3256 }
3257 else
3258 {
3259 if (check_rounding_condition_with_next_bit(
3260 current_digits, subsegment_boundary_rounding_bit,
3261 compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3262 {
3263 goto round_up_two_digits;
3264 }
3265 goto print_last_two_digits;
3266 }
3267 }
3268 }
3269
3270 else
3271 {
3272 std::uint64_t prod;
3273 int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
3274 if ((remaining_digits & 1) != 0)
3275 {
3276 prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
3277 current_digits = static_cast<std::uint32_t>(prod >> 32);
3278
3279 if (remaining_digits == 1)
3280 {
3281 goto second_segment252_loop_first_subsegment_rounding;
3282 }
3283
3284 print_1_digit(current_digits, buffer);
3285 ++buffer;
3286 }
3287 else
3288 {
3289 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
3290 current_digits = static_cast<std::uint32_t>(prod >> 32);
3291
3292 if (remaining_digits == 2)
3293 {
3294 goto second_segment252_loop_first_subsegment_rounding;
3295 }
3296
3297 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3298 buffer += 2;
3299 }
3300
3301 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3302 {
3303 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3304 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3305 buffer += 2;
3306 }
3307
3308 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3309 current_digits = static_cast<std::uint32_t>(prod >> 32);
3310 remaining_digits = 0;
3311
3312 if (remaining_digits_in_the_current_subsegment != 0)
3313 {
3314 second_segment252_loop_first_subsegment_rounding:
3315 if (check_rounding_condition_inside_subsegment(
3316 current_digits, static_cast<std::uint32_t>(prod),
3317 remaining_digits_in_the_current_subsegment,
3318 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3319 {
3320 goto round_up;
3321 }
3322 goto print_last_digits;
3323 }
3324 else
3325 {
3326 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3327 current_digits,
3328 uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3329 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3330 {
3331 goto round_up_two_digits;
3332 }
3333 goto print_last_two_digits;
3334 }
3335 }
3336
3337 buffer += 18;
3338 remaining_digits -= 18;
3339 }
3340 }
3341 }
3342
3343
3344 while (has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))
3345 {
3346
3347 ++multiplier_index;
3348 k += ExtendedCache::segment_length;
3349
3350 cache_block_count = load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(blocks, e, k, multiplier_index);
3351
3352
3353 fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
3354
3355 BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
3356 {
3357
3358 if (remaining_digits > 16)
3359 {
3360 std::uint64_t first_second_subsegments = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[16], blocks, cache_block_count);
3361
3362 const auto first_subsegment =
3363 static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
3364
3365 const std::uint32_t second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
3366
3367 print_8_digits(first_subsegment, buffer);
3368 print_8_digits(second_subsegment, buffer + 8);
3369
3370
3371 if (remaining_digits > 22)
3372 {
3373 const auto third_subsegment = static_cast<std::uint32_t>(
3374 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate_and_discard_lower(power_of_10[6], blocks,cache_block_count));
3375
3376 print_6_digits(third_subsegment, buffer + 16);
3377 buffer += 22;
3378 remaining_digits -= 22;
3379 }
3380
3381 else
3382 {
3383 buffer += 16;
3384 remaining_digits -= 16;
3385
3386 auto third_subsegment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3387 generate_and_discard_lower(power_of_10[6] << 1, blocks, cache_block_count);
3388
3389 bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
3390 third_subsegment >>= 1;
3391
3392 std::uint64_t prod;
3393 if ((remaining_digits & 1) != 0)
3394 {
3395 prod = ((third_subsegment * UINT64_C(687195)) >> 4) + 1;
3396 current_digits = static_cast<std::uint32_t>(prod >> 32);
3397
3398 if (remaining_digits == 1)
3399 {
3400 if (check_rounding_condition_inside_subsegment(
3401 current_digits, static_cast<std::uint32_t>(prod), 5,
3402 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
3403 {
3404 goto round_up_one_digit;
3405 }
3406 goto print_last_one_digit;
3407 }
3408
3409 print_1_digit(current_digits, buffer);
3410 ++buffer;
3411 }
3412 else
3413 {
3414 prod = (third_subsegment * UINT64_C(429497)) + 1;
3415 current_digits = static_cast<std::uint32_t>(prod >> 32);
3416
3417 if (remaining_digits == 2)
3418 {
3419 goto segment_loop22_more_than_16_digits_rounding;
3420 }
3421
3422 print_2_digits(current_digits, buffer);
3423 buffer += 2;
3424 }
3425
3426 if (remaining_digits > 4)
3427 {
3428 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3429 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3430 buffer += 2;
3431
3432 if (remaining_digits == 6)
3433 {
3434 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3435 current_digits = static_cast<std::uint32_t>(prod >> 32);
3436
3437 if (check_rounding_condition_with_next_bit(
3438 current_digits, segment_boundary_rounding_bit,
3439 has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
3440 {
3441 goto round_up_two_digits;
3442 }
3443 goto print_last_two_digits;
3444 }
3445 }
3446
3447 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3448 current_digits = static_cast<std::uint32_t>(prod >> 32);
3449
3450 segment_loop22_more_than_16_digits_rounding:
3451 if (check_rounding_condition_inside_subsegment(
3452 current_digits, static_cast<std::uint32_t>(prod), 6 - remaining_digits,
3453 has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
3454 {
3455 goto round_up_two_digits;
3456 }
3457 goto print_last_two_digits;
3458 }
3459 }
3460
3461 else if (remaining_digits > 8)
3462 {
3463
3464 auto first_second_subsegments =
3465 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3466 generate_and_discard_lower(power_of_10[16] << 1, blocks, cache_block_count);
3467
3468 bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
3469 first_second_subsegments >>= 1;
3470
3471
3472
3473 const auto first_subsegment =
3474 static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
3475
3476 const auto second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
3477
3478 print_8_digits(first_subsegment, buffer);
3479 buffer += 8;
3480 remaining_digits -= 8;
3481
3482
3483 std::uint64_t prod;
3484 if ((remaining_digits & 1) != 0)
3485 {
3486 prod = ((second_subsegment * UINT64_C(112589991)) >> 18) + 1;
3487 current_digits = static_cast<std::uint32_t>(prod >> 32);
3488
3489 if (remaining_digits == 1)
3490 {
3491 if (check_rounding_condition_inside_subsegment(
3492 current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k,
3493 uconst1, uconst6)))
3494 {
3495 goto round_up_one_digit;
3496 }
3497 goto print_last_one_digit;
3498 }
3499
3500 print_1_digit(current_digits, buffer);
3501 ++buffer;
3502 }
3503 else
3504 {
3505 prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
3506 current_digits = static_cast<std::uint32_t>(prod >> 32);
3507
3508 if (remaining_digits == 2)
3509 {
3510 goto segment_loop22_more_than_8_digits_rounding;
3511 }
3512
3513 print_2_digits(current_digits, buffer);
3514 buffer += 2;
3515 }
3516
3517 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3518 {
3519 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3520 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3521 buffer += 2;
3522 }
3523
3524 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3525 current_digits = static_cast<std::uint32_t>(prod >> 32);
3526
3527 if (remaining_digits < 8)
3528 {
3529 segment_loop22_more_than_8_digits_rounding:
3530 if (check_rounding_condition_inside_subsegment(
3531 current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
3532 has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k, uconst1, uconst6)))
3533 {
3534 goto round_up_two_digits;
3535 }
3536 }
3537 else {
3538 if (check_rounding_condition_with_next_bit(
3539 current_digits, first_bit_of_third_subsegment,
3540 has_further_digits<0, 6, ExtendedCache>(significand, exp2_base, k, uconst0, uconst6)))
3541 {
3542 goto round_up_two_digits;
3543 }
3544 }
3545 goto print_last_two_digits;
3546 }
3547
3548 else
3549 {
3550
3551 auto first_subsegment =
3552 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3553 generate_and_discard_lower(power_of_10[8] << 1, blocks, cache_block_count);
3554
3555 bool first_bit_of_second_subsegment = ((first_subsegment & 1) != 0);
3556 first_subsegment >>= 1;
3557
3558 std::uint64_t prod;
3559 if ((remaining_digits & 1) != 0)
3560 {
3561 prod = ((first_subsegment * UINT64_C(112589991)) >> 18) + 1;
3562 current_digits = static_cast<std::uint32_t>(prod >> 32);
3563
3564 if (remaining_digits == 1)
3565 {
3566 if (check_rounding_condition_inside_subsegment(
3567 current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k,
3568 uconst1, uconst14)))
3569 {
3570 goto round_up_one_digit;
3571 }
3572 goto print_last_one_digit;
3573 }
3574
3575 print_1_digit(current_digits, buffer);
3576 ++buffer;
3577 }
3578 else
3579 {
3580 prod = ((first_subsegment * UINT64_C(140737489)) >> 15) + 1;
3581 current_digits = static_cast<std::uint32_t>(prod >> 32);
3582
3583 if (remaining_digits == 2)
3584 {
3585 goto segment_loop22_at_most_8_digits_rounding;
3586 }
3587
3588 print_2_digits(current_digits, buffer);
3589 buffer += 2;
3590 }
3591
3592 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3593 {
3594 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3595 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3596 buffer += 2;
3597 }
3598
3599 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3600 current_digits = static_cast<std::uint32_t>(prod >> 32);
3601
3602 if (remaining_digits < 8)
3603 {
3604 segment_loop22_at_most_8_digits_rounding:
3605 if (check_rounding_condition_inside_subsegment(
3606 current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
3607 has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k, uconst1, uconst14)))
3608 {
3609 goto round_up_two_digits;
3610 }
3611 }
3612 else
3613 {
3614 if (check_rounding_condition_with_next_bit(
3615 current_digits, first_bit_of_second_subsegment,
3616 has_further_digits<0, 14, ExtendedCache>(significand, exp2_base, k, uconst0, uconst14)))
3617 {
3618 goto round_up_two_digits;
3619 }
3620 }
3621 goto print_last_two_digits;
3622 }
3623 }
3624 else if (ExtendedCache::segment_length == 252)
3625 {
3626
3627 for (int remaining_subsegment_pairs = 14; remaining_subsegment_pairs > 0;
3628 --remaining_subsegment_pairs)
3629 {
3630
3631 if (remaining_digits > 18)
3632 {
3633 const auto subsegment_pair =
3634 fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
3635
3636 const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
3637 const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
3638
3639 print_9_digits(first_part, buffer);
3640 print_9_digits(second_part, buffer + 9);
3641 buffer += 18;
3642 remaining_digits -= 18;
3643 }
3644
3645 else
3646 {
3647 auto last_subsegment_pair =
3648 fixed_point_calculator<ExtendedCache::max_cache_blocks>::
3649 generate_and_discard_lower(power_of_10[18] << 1, blocks, cache_block_count);
3650
3651 const bool subsegment_boundary_rounding_bit = ((last_subsegment_pair & 1) != 0);
3652 last_subsegment_pair >>= 1;
3653
3654 const auto first_part = static_cast<std::uint32_t>(last_subsegment_pair / power_of_10[9]);
3655 const auto second_part = static_cast<std::uint32_t>(last_subsegment_pair) - power_of_10[9] * first_part;
3656
3657 if (remaining_digits <= 9)
3658 {
3659 std::uint64_t prod;
3660
3661 if ((remaining_digits & 1) != 0)
3662 {
3663 prod = ((first_part * UINT64_C(1441151881)) >> 25) + 1;
3664 current_digits = static_cast<std::uint32_t>(prod >> 32);
3665
3666 if (remaining_digits == 1)
3667 {
3668 if (check_rounding_condition_inside_subsegment(
3669 current_digits, static_cast<std::uint32_t>(prod), 8,
3670 compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3671 {
3672 goto round_up_one_digit;
3673 }
3674 goto print_last_one_digit;
3675 }
3676
3677 print_1_digit(current_digits, buffer);
3678 ++buffer;
3679 }
3680 else
3681 {
3682 prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
3683 current_digits = static_cast<std::uint32_t>(prod >> 32);
3684
3685 if (remaining_digits == 2)
3686 {
3687 goto segment_loop252_final18_first_part_rounding;
3688 }
3689
3690 print_2_digits(current_digits, buffer);
3691 buffer += 2;
3692 }
3693
3694 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3695 {
3696 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3697 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3698 buffer += 2;
3699 }
3700
3701 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3702 current_digits = static_cast<std::uint32_t>(prod >> 32);
3703
3704 if (remaining_digits < 9)
3705 {
3706 segment_loop252_final18_first_part_rounding:
3707 if (check_rounding_condition_inside_subsegment(
3708 current_digits, static_cast<std::uint32_t>(prod),
3709 9 - remaining_digits, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3710 {
3711 goto round_up_two_digits;
3712 }
3713 }
3714 else
3715 {
3716 if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
3717 current_digits,
3718 uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
3719 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3720 {
3721 goto round_up_two_digits;
3722 }
3723 }
3724 goto print_last_two_digits;
3725 }
3726
3727 print_9_digits(first_part, buffer);
3728 buffer += 9;
3729 remaining_digits -= 9;
3730
3731 std::uint64_t prod;
3732
3733 if ((remaining_digits & 1) != 0)
3734 {
3735 prod = ((second_part * UINT64_C(1441151881)) >> 25) + 1;
3736 current_digits = static_cast<std::uint32_t>(prod >> 32);
3737
3738 if (remaining_digits == 1)
3739 {
3740 if (check_rounding_condition_inside_subsegment(
3741 current_digits, static_cast<std::uint32_t>(prod), 8,
3742 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3743 {
3744 goto round_up_one_digit;
3745 }
3746 goto print_last_one_digit;
3747 }
3748
3749 print_1_digit(current_digits, buffer);
3750 ++buffer;
3751 }
3752 else
3753 {
3754 prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
3755 current_digits = static_cast<std::uint32_t>(prod >> 32);
3756
3757 if (remaining_digits == 2)
3758 {
3759 goto segment_loop252_final18_second_part_rounding;
3760 }
3761
3762 print_2_digits(current_digits, buffer);
3763 buffer += 2;
3764 }
3765
3766 for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
3767 {
3768 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3769 print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
3770 buffer += 2;
3771 }
3772
3773 prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
3774 current_digits = static_cast<std::uint32_t>(prod >> 32);
3775
3776 if (remaining_digits < 9)
3777 {
3778 segment_loop252_final18_second_part_rounding:
3779 if (check_rounding_condition_inside_subsegment(
3780 current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
3781 compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3782 {
3783 goto round_up_two_digits;
3784 }
3785 }
3786 else
3787 {
3788 if (check_rounding_condition_with_next_bit(
3789 current_digits, subsegment_boundary_rounding_bit,
3790 compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
3791 {
3792 goto round_up_two_digits;
3793 }
3794 }
3795 goto print_last_two_digits;
3796 }
3797 }
3798 }
3799 }
3800 }
3801
3802
3803
3804
3805
3806
3807
3808 fill_remaining_digits_with_0s:
3809
3810
3811
3812 std::memset(buffer, '0', static_cast<std::size_t>(remaining_digits));
3813 buffer += remaining_digits;
3814
3815 insert_decimal_dot:
3816 if (fmt == chars_format::general)
3817 {
3818
3819 if (-4 <= decimal_exponent_normalized && decimal_exponent_normalized < precision)
3820 {
3821
3822 if (decimal_exponent_normalized >= 0)
3823 {
3824
3825 decimal_dot_pos = buffer_starting_pos + decimal_exponent_normalized + 1;
3826 std::memmove(buffer_starting_pos, buffer_starting_pos + 1,
3827 static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
3828 *decimal_dot_pos = '.';
3829 }
3830 else
3831 {
3832
3833 int number_of_leading_zeros = -decimal_exponent_normalized - 1;
3834 std::memmove(buffer_starting_pos + number_of_leading_zeros + 2, buffer_starting_pos + 1,
3835 static_cast<std::size_t>(buffer - buffer_starting_pos - 1));
3836 std::memcpy(buffer_starting_pos, "0.", 2);
3837 std::memset(buffer_starting_pos + 2, '0', static_cast<std::size_t>(number_of_leading_zeros));
3838 buffer += number_of_leading_zeros + 1;
3839 }
3840
3841 fmt = chars_format::fixed;
3842 }
3843 else
3844 {
3845
3846
3847 *buffer_starting_pos = *(buffer_starting_pos + 1);
3848 *(buffer_starting_pos + 1) = '.';
3849 }
3850
3851
3852 while (true)
3853 {
3854 auto prev = buffer - 1;
3855
3856
3857 if (*prev == '.')
3858 {
3859 buffer = prev;
3860 break;
3861 }
3862 else if (*prev != '0')
3863 {
3864 break;
3865 }
3866 buffer = prev;
3867 }
3868 }
3869 else if (decimal_dot_pos != buffer_starting_pos)
3870 {
3871 std::memmove(buffer_starting_pos, buffer_starting_pos + 1,
3872 static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
3873 *decimal_dot_pos = '.';
3874 }
3875
3876 if (fmt != chars_format::fixed)
3877 {
3878 if (decimal_exponent_normalized >= 0)
3879 {
3880 std::memcpy(buffer, "e+", 2);
3881 }
3882 else
3883 {
3884 std::memcpy(buffer, "e-", 2);
3885 decimal_exponent_normalized = -decimal_exponent_normalized;
3886 }
3887
3888 buffer += 2;
3889 if (decimal_exponent_normalized >= 100)
3890 {
3891
3892
3893 auto prod = static_cast<std::uint32_t>(decimal_exponent_normalized) * UINT32_C(6554);
3894 auto d1 = prod >> 16;
3895 prod = static_cast<std::uint16_t>(prod) * UINT16_C(5);
3896 auto d2 = prod >> 15;
3897 print_2_digits(d1, buffer);
3898 print_1_digit(d2, buffer + 2);
3899 buffer += 3;
3900 }
3901 else
3902 {
3903 print_2_digits(static_cast<std::uint32_t>(decimal_exponent_normalized), buffer);
3904 buffer += 2;
3905 }
3906 }
3907
3908 return {buffer, std::errc()};
3909
3910 round_up:
3911 if ((remaining_digits & 1) != 0)
3912 {
3913 round_up_one_digit:
3914 if (++current_digits == 10)
3915 {
3916 goto round_up_all_9s;
3917 }
3918
3919 goto print_last_one_digit;
3920 }
3921 else
3922 {
3923 round_up_two_digits:
3924 if (++current_digits == 100)
3925 {
3926 goto round_up_all_9s;
3927 }
3928
3929 goto print_last_two_digits;
3930 }
3931
3932 print_last_digits:
3933 if ((remaining_digits & 1) != 0)
3934 {
3935 print_last_one_digit:
3936 print_1_digit(current_digits, buffer);
3937 ++buffer;
3938 }
3939 else
3940 {
3941 print_last_two_digits:
3942 print_2_digits(current_digits, buffer);
3943 buffer += 2;
3944 }
3945
3946 goto insert_decimal_dot;
3947
3948 round_up_all_9s:
3949 char* first_9_pos = buffer;
3950 buffer += (2 - (remaining_digits & 1));
3951
3952
3953 char* digit_starting_pos = [&] {
3954
3955 if (fmt == chars_format::fixed && decimal_exponent_normalized < 0)
3956 {
3957 return buffer_starting_pos - decimal_exponent_normalized + 1;
3958 }
3959
3960
3961 return buffer_starting_pos == decimal_dot_pos ? buffer_starting_pos
3962 : buffer_starting_pos + 1;
3963 }();
3964
3965 if ((first_9_pos - digit_starting_pos) % 2 != 0)
3966 {
3967 if (*(first_9_pos - 1) != '9')
3968 {
3969 ++*(first_9_pos - 1);
3970 if ((remaining_digits & 1) != 0)
3971 {
3972 *first_9_pos = '0';
3973 }
3974 else
3975 {
3976 std::memcpy(first_9_pos, "00", 2);
3977 }
3978 goto insert_decimal_dot;
3979 }
3980 --first_9_pos;
3981 }
3982 while (first_9_pos != digit_starting_pos)
3983 {
3984 if (std::memcmp(first_9_pos - 2, "99", 2) != 0)
3985 {
3986 if (*(first_9_pos - 1) != '9')
3987 {
3988 ++*(first_9_pos - 1);
3989 }
3990 else
3991 {
3992 ++*(first_9_pos - 2);
3993 *(first_9_pos - 1) = '0';
3994 }
3995 std::memset(first_9_pos, '0', static_cast<std::size_t>(buffer - first_9_pos));
3996 goto insert_decimal_dot;
3997 }
3998 first_9_pos -= 2;
3999 }
4000
4001
4002 ++decimal_exponent_normalized;
4003
4004 if (fmt == chars_format::fixed)
4005 {
4006 if (decimal_exponent_normalized > 0)
4007 {
4008
4009 if (buffer == last)
4010 {
4011 return {last, std::errc::value_too_large};
4012 }
4013 ++buffer;
4014
4015
4016 if (buffer_starting_pos != decimal_dot_pos)
4017 {
4018 ++decimal_dot_pos;
4019 }
4020 }
4021 else if (decimal_exponent_normalized == 0)
4022 {
4023
4024
4025
4026
4027 --digit_starting_pos;
4028 }
4029 }
4030
4031
4032 *digit_starting_pos = '1';
4033 std::memset(digit_starting_pos + 1, '0', static_cast<std::size_t>(buffer - digit_starting_pos - 1));
4034
4035 goto insert_decimal_dot;
4036 }
4037
4038 }}}
4039
4040 #ifdef BOOST_MSVC
4041 # pragma warning(pop)
4042 #endif
4043
4044 #endif