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