From 599febf90a7e52c827ce6be1df8acf5d771d4bc2 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 14 Apr 2023 14:39:03 +0200 Subject: [PATCH] Remove cruft --- include/boost/charconv/detail/dragonbox.hpp | 29 ++- include/boost/charconv/to_chars.hpp | 83 ------ src/to_chars.cpp | 271 -------------------- 3 files changed, 16 insertions(+), 367 deletions(-) diff --git a/include/boost/charconv/detail/dragonbox.hpp b/include/boost/charconv/detail/dragonbox.hpp index c5be16a..7640904 100644 --- a/include/boost/charconv/detail/dragonbox.hpp +++ b/include/boost/charconv/detail/dragonbox.hpp @@ -14,21 +14,23 @@ // Unless required by applicable law or agreed to in writing, this software // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. +// +// Copyright 2023 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +#ifndef BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP +#define BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP -#ifndef JKJ_HEADER_DRAGONBOX -#define JKJ_HEADER_DRAGONBOX - -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include namespace boost { namespace charconv { namespace detail { @@ -2496,7 +2498,7 @@ BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto to_decimal(Float x, Policies.. const auto br = dragonbox_float_bits(x); const auto exponent_bits = br.extract_exponent_bits(); const auto s = br.remove_exponent_bits(exponent_bits); - assert(br.is_finite()); + BOOST_CHARCONV_ASSERT(br.is_finite()); return to_decimal(s, exponent_bits, policies...); } @@ -3077,6 +3079,7 @@ namespace to_chars_detail { return buffer; } } + }}} // Namespaces -#endif +#endif // BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index 6dc0641..bea78d6 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -606,89 +606,6 @@ to_chars_result to_chars_hex(char* first, char* last, Real value, int precision) return to_chars(first, last, abs_unbiased_exponent); } -/* -template -extern char* to_chars(typename FloatTraits::carrier_uint significand, int exponent, char* buffer) noexcept; - -// Avoid needless ABI overhead incurred by tag dispatch. -template -char* to_chars_n_impl(float_bits br, char* buffer) noexcept -{ - const static auto exponent_bits = br.extract_exponent_bits(); - const auto s = br.remove_exponent_bits(exponent_bits); - - if (br.is_finite(exponent_bits)) - { - if (s.is_negative()) - { - *buffer = '-'; - ++buffer; - } - if (br.is_nonzero()) - { - auto result = to_decimal( - s, exponent_bits, policy::sign::ignore, policy::trailing_zero::ignore, - typename PolicyHolder::decimal_to_binary_rounding_policy{}, - typename PolicyHolder::binary_to_decimal_rounding_policy{}, - typename PolicyHolder::cache_policy{}); - - return to_chars(result.significand, result.exponent, buffer); - } - else - { - std::memcpy(buffer, "0E0", 3); - return buffer + 3; - } - } - else - { - if (s.has_all_zero_significand_bits()) - { - if (s.is_negative()) - { - *buffer = '-'; - ++buffer; - } - - std::memcpy(buffer, "Infinity", 8); - return buffer + 8; - } - else - { - std::memcpy(buffer, "NaN", 3); - return buffer + 3; - } - } -} - -// Returns the next-to-end position -template , typename... Policies> -char* to_chars_n(Float x, char* buffer, Policies... policies) noexcept -{ - using namespace boost::charconv::detail::policy_impl; - using policy_holder = decltype(make_policy_holder( - base_default_pair_list, - base_default_pair, - base_default_pair>{}, policies...)); - - return to_chars_n_impl(float_bits(x), buffer); -} - -// Null-terminate and bypass the return value of fp_to_chars_n -template , typename... Policies> -char* to_chars(Float x, char* buffer, Policies... policies) noexcept -{ - auto ptr = to_chars_n(x, buffer, policies...); - *ptr = '\0'; - return ptr; -} - -void print_1_digit(std::uint32_t n, char* buffer) noexcept; - -void print_2_digits(std::uint32_t n, char* buffer) noexcept; - -void print_9_digits(std::uint32_t s32, int& exponent, char* buffer) noexcept; -*/ } // Namespace detail // integer overloads diff --git a/src/to_chars.cpp b/src/to_chars.cpp index 043b1ec..5a6682d 100644 --- a/src/to_chars.cpp +++ b/src/to_chars.cpp @@ -13,277 +13,6 @@ #include #include -namespace boost { namespace charconv { namespace detail { - -// These "//"'s are to prevent clang-format to ruin this nice alignment. -// Thanks to reddit user u/mcmcc: -// https://www.reddit.com/r/cpp/comments/so3wx9/dragonbox_110_is_released_a_fast_floattostring/hw8z26r/?context=3 - -/* -static constexpr char radix_100_table[] = { - '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', // - '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', // - '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', // - '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', // - '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', // - '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', // - '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', // - '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', // - '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', // - '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', // - '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', // - '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', // - '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', // - '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', // - '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', // - '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', // - '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', // - '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', // - '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', // - '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' // -}; - -static constexpr char radix_100_head_table[] = { - '0', '.', '1', '.', '2', '.', '3', '.', '4', '.', // - '5', '.', '6', '.', '7', '.', '8', '.', '9', '.', // - '1', '.', '1', '.', '1', '.', '1', '.', '1', '.', // - '1', '.', '1', '.', '1', '.', '1', '.', '1', '.', // - '2', '.', '2', '.', '2', '.', '2', '.', '2', '.', // - '2', '.', '2', '.', '2', '.', '2', '.', '2', '.', // - '3', '.', '3', '.', '3', '.', '3', '.', '3', '.', // - '3', '.', '3', '.', '3', '.', '3', '.', '3', '.', // - '4', '.', '4', '.', '4', '.', '4', '.', '4', '.', // - '4', '.', '4', '.', '4', '.', '4', '.', '4', '.', // - '5', '.', '5', '.', '5', '.', '5', '.', '5', '.', // - '5', '.', '5', '.', '5', '.', '5', '.', '5', '.', // - '6', '.', '6', '.', '6', '.', '6', '.', '6', '.', // - '6', '.', '6', '.', '6', '.', '6', '.', '6', '.', // - '7', '.', '7', '.', '7', '.', '7', '.', '7', '.', // - '7', '.', '7', '.', '7', '.', '7', '.', '7', '.', // - '8', '.', '8', '.', '8', '.', '8', '.', '8', '.', // - '8', '.', '8', '.', '8', '.', '8', '.', '8', '.', // - '9', '.', '9', '.', '9', '.', '9', '.', '9', '.', // - '9', '.', '9', '.', '9', '.', '9', '.', '9', '.' // -}; - -void print_1_digit(std::uint32_t n, char* buffer) noexcept -{ - *buffer = char('0' | n); -} - -void print_2_digits(std::uint32_t n, char* buffer) noexcept -{ - std::memcpy(buffer, radix_100_table + n * 2, 2); -} - -// These digit generation routines are inspired by James Anhalt's itoa algorithm: -// https://github.com/jeaiii/itoa -// The main idea is for given n, find y such that floor(10^k * y / 2^32) = n holds, -// where k is an appropriate integer depending on the length of n. -// For example, if n = 1234567, we set k = 6. In this case, we have -// floor(y / 2^32) = 1, -// floor(10^2 * ((10^0 * y) mod 2^32) / 2^32) = 23, -// floor(10^2 * ((10^2 * y) mod 2^32) / 2^32) = 45, and -// floor(10^2 * ((10^4 * y) mod 2^32) / 2^32) = 67. -// See https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/ for more explanation. -void print_9_digits(std::uint32_t s32, int& exponent, char* buffer) noexcept -{ - // -- IEEE-754 binary32 - // Since we do not cut trailing zeros in advance, s32 must be of 6~9 digits - // unless the original input was subnormal. - // In particular, when it is of 9 digits it shouldn't have any trailing zeros. - // -- IEEE-754 binary64 - // In this case, s32 must be of 7~9 digits unless the input is subnormal, - // and it shouldn't have any trailing zeros if it is of 9 digits. - if (s32 >= 100000000) - { - // 9 digits. - // 1441151882 = ceil(2^57 / 1'0000'0000) + 1 - auto prod = s32 * UINT64_C(1441151882); - prod >>= 25; - std::memcpy(buffer, radix_100_head_table + UINT32_C(prod >> 32) * 2, 2); - - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 2); - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 4); - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 6); - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 8); - - exponent += 8; - buffer += 10; - } - else if (s32 >= 1000000) - { - // 7 or 8 digits. - // 281474978 = ceil(2^48 / 100'0000) + 1 - auto prod = s32 * UINT64_C(281474978); - prod >>= 16; - auto const head_digits = static_cast(prod >> 32); - // If s32 is of 8 digits, increase the exponent by 7. - // Otherwise, increase it by 6. - exponent += (6 + unsigned(head_digits >= 10)); - - // Write the first digit and the decimal point. - std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2); - // This third character may be overwritten later but we don't care. - buffer[2] = radix_100_table[head_digits * 2 + 1]; - - // Remaining 6 digits are all zero? - if (static_cast(prod) <= static_cast((UINT64_C(1) << 32) / 1000000)) - { - // The number of characters actually need to be written is: - // 1, if only the first digit is nonzero, which means that either s32 is of 7 - // digits or it is of 8 digits but the second digit is zero, or - // 3, otherwise. - // Note that buffer[2] is never '0' if s32 is of 7 digits, because the input is - // never zero. - buffer += (1 + (unsigned(head_digits >= 10) & unsigned(buffer[2] > '0')) * 2); - } - else - { - // At least one of the remaining 6 digits are nonzero. - // After this adjustment, now the first destination becomes buffer + 2. - buffer += unsigned(head_digits >= 10); - - // Obtain the next two digits. - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 2); - - // Remaining 4 digits are all zero? - if (static_cast(prod) <= static_cast((UINT64_C(1) << 32) / 10000)) - { - buffer += (3 + unsigned(buffer[3] > '0')); - } - else - { - // At least one of the remaining 4 digits are nonzero. - - // Obtain the next two digits. - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 4); - - // Remaining 2 digits are all zero? - if (static_cast(prod) <= static_cast((UINT64_C(1) << 32) / 100)) - { - buffer += (5 + unsigned(buffer[5] > '0')); - } - else - { - // Obtain the last two digits. - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 6); - - buffer += (7 + unsigned(buffer[7] > '0')); - } - } - } - } - else if (s32 >= 10000) - { - // 5 or 6 digits. - // 429497 = ceil(2^32 / 1'0000) - auto prod = s32 * UINT64_C(429497); - auto const head_digits = static_cast(prod >> 32); - - // If s32 is of 6 digits, increase the exponent by 5. - // Otherwise, increase it by 4. - exponent += (4 + static_cast(head_digits >= 10)); - - // Write the first digit and the decimal point. - std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2); - // This third character may be overwritten later but we don't care. - buffer[2] = radix_100_table[head_digits * 2 + 1]; - - // Remaining 4 digits are all zero? - if (static_cast(prod) <= static_cast((UINT64_C(1) << 32) / 10000)) - { - // The number of characters actually written is 1 or 3, similarly to the case of - // 7 or 8 digits. - buffer += (1 + (unsigned(head_digits >= 10) & unsigned(buffer[2] > '0')) * 2); - } - else - { - // At least one of the remaining 4 digits are nonzero. - // After this adjustment, now the first destination becomes buffer + 2. - buffer += unsigned(head_digits >= 10); - - // Obtain the next two digits. - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 2); - - // Remaining 2 digits are all zero? - if (static_cast(prod) <= static_cast((UINT64_C(1) << 32) / 100)) - { - buffer += (3 + unsigned(buffer[3] > '0')); - } - else - { - // Obtain the last two digits. - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 4); - - buffer += (5 + unsigned(buffer[5] > '0')); - } - } - } - else if (s32 >= 100) - { - // 3 or 4 digits. - // 42949673 = ceil(2^32 / 100) - auto prod = s32 * UINT64_C(42949673); - auto const head_digits = static_cast(prod >> 32); - - // If s32 is of 4 digits, increase the exponent by 3. - // Otherwise, increase it by 2. - exponent += (2 + int(head_digits >= 10)); - - // Write the first digit and the decimal point. - std::memcpy(buffer, radix_100_head_table + head_digits * 2, 2); - // This third character may be overwritten later but we don't care. - buffer[2] = radix_100_table[head_digits * 2 + 1]; - - // Remaining 2 digits are all zero? - if (static_cast(prod) <= static_cast((UINT64_C(1) << 32) / 100)) - { - // The number of characters actually written is 1 or 3, similarly to the case of - // 7 or 8 digits. - buffer += (1 + (unsigned(head_digits >= 10) & unsigned(buffer[2] > '0')) * 2); - } - else - { - // At least one of the remaining 2 digits are nonzero. - // After this adjustment, now the first destination becomes buffer + 2. - buffer += unsigned(head_digits >= 10); - - // Obtain the last two digits. - prod = static_cast(prod) * UINT64_C(100); - print_2_digits(static_cast(prod >> 32), buffer + 2); - - buffer += (3 + unsigned(buffer[3] > '0')); - } - } - else - { - // 1 or 2 digits. - // If s32 is of 2 digits, increase the exponent by 1. - exponent += int(s32 >= 10); - - // Write the first digit and the decimal point. - std::memcpy(buffer, radix_100_head_table + s32 * 2, 2); - // This third character may be overwritten later but we don't care. - buffer[2] = radix_100_table[s32 * 2 + 1]; - - // The number of characters actually written is 1 or 3, similarly to the case of - // 7 or 8 digits. - buffer += (1 + (unsigned(s32 >= 10) & unsigned(buffer[2] > '0')) * 2); - } -} -*/ -}}} // Namespaces - boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, float value, boost::charconv::chars_format fmt, int precision) noexcept { if (fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::fixed)