Change namespaces

[ci skip]
This commit is contained in:
Matt Borland
2023-04-12 16:15:21 +02:00
parent 96bb503485
commit 5e43fee74f
4 changed files with 65 additions and 76 deletions

View File

@@ -30,15 +30,16 @@
#include <boost/charconv/detail/bit_layouts.hpp>
#include <boost/charconv/detail/dragonbox_common.hpp>
namespace jkj { namespace dragonbox {
namespace boost { namespace charconv { namespace detail {
// A floating-point traits class defines ways to interpret a bit pattern of given size as an
// encoding of floating-point number. This is a default implementation of such a traits class,
// supporting ways to interpret 32-bits into a binary32-encoded floating-point number and to
// interpret 64-bits into a binary64-encoded floating-point number. Users might specialize this
// class to change the default behavior for certain types.
template <class T>
struct default_float_traits {
struct dragonbox_float_traits {
// I don't know if there is a truly reliable way of detecting
// IEEE-754 binary32/binary64 formats; I just did my best here.
static_assert(std::numeric_limits<T>::is_iec559 && std::numeric_limits<T>::radix == 2 &&
@@ -166,23 +167,23 @@ namespace jkj { namespace dragonbox {
// possible (e.g., no inheritance, no private non-static data member, etc.; this is an
// unfortunate fact about common ABI convention).
template <class T, class Traits = default_float_traits<T>>
struct float_bits;
template <class T, class Traits = dragonbox_float_traits<T>>
struct dragonbox_float_bits;
template <class T, class Traits = default_float_traits<T>>
struct signed_significand_bits;
template <class T, class Traits = dragonbox_float_traits<T>>
struct dragonbox_signed_significand_bits;
template <class T, class Traits>
struct float_bits {
struct dragonbox_float_bits {
using type = T;
using traits_type = Traits;
using carrier_uint = typename traits_type::carrier_uint;
carrier_uint u;
float_bits() = default;
constexpr explicit float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
constexpr explicit float_bits(T float_value) noexcept
dragonbox_float_bits() = default;
constexpr explicit dragonbox_float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
constexpr explicit dragonbox_float_bits(T float_value) noexcept
: u{traits_type::float_to_carrier(float_value)} {}
constexpr T to_float() const noexcept { return traits_type::carrier_to_float(u); }
@@ -203,7 +204,7 @@ namespace jkj { namespace dragonbox {
// Remove the exponent bits and extract significand bits together with the sign bit.
constexpr auto remove_exponent_bits(unsigned int exponent_bits) const noexcept {
return signed_significand_bits<type, traits_type>(
return dragonbox_signed_significand_bits<type, traits_type>(
traits_type::remove_exponent_bits(u, exponent_bits));
}
@@ -240,15 +241,15 @@ namespace jkj { namespace dragonbox {
};
template <class T, class Traits>
struct signed_significand_bits {
struct dragonbox_signed_significand_bits {
using type = T;
using traits_type = Traits;
using carrier_uint = typename traits_type::carrier_uint;
carrier_uint u;
signed_significand_bits() = default;
constexpr explicit signed_significand_bits(carrier_uint bit_pattern) noexcept
dragonbox_signed_significand_bits() = default;
constexpr explicit dragonbox_signed_significand_bits(carrier_uint bit_pattern) noexcept
: u{bit_pattern} {}
// Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
@@ -266,7 +267,6 @@ namespace jkj { namespace dragonbox {
}
};
namespace detail {
////////////////////////////////////////////////////////////////////////////////////////
// Utilities for fast divisibility tests.
////////////////////////////////////////////////////////////////////////////////////////
@@ -344,7 +344,6 @@ namespace jkj { namespace dragonbox {
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////
// Return types for the main interface function.
@@ -400,7 +399,6 @@ namespace jkj { namespace dragonbox {
// Computed cache entries.
////////////////////////////////////////////////////////////////////////////////////////
namespace detail {
template <class FloatFormat>
struct cache_holder;
@@ -751,16 +749,14 @@ namespace jkj { namespace dragonbox {
{0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, {0xc5a05277621be293, 0xc7098b7305241886},
{0xf70867153aa2db38, 0xb8cbee4fc66d1ea8}};
};
}
////////////////////////////////////////////////////////////////////////////////////////
// Policies.
////////////////////////////////////////////////////////////////////////////////////////
namespace detail {
// Forward declare the implementation class.
template <class Float, class FloatTraits = default_float_traits<Float>>
template <class Float, class FloatTraits = dragonbox_float_traits<Float>>
struct impl;
namespace policy_impl {
@@ -1011,7 +1007,6 @@ namespace jkj { namespace dragonbox {
}
};
namespace detail {
struct nearest_always_closed {
static constexpr auto tag = tag_t::to_nearest;
using normal_interval_type = interval_type::closed;
@@ -1044,7 +1039,6 @@ namespace jkj { namespace dragonbox {
return f();
}
};
}
struct nearest_to_even_static_boundary : base {
using decimal_to_binary_rounding_policy = nearest_to_even_static_boundary;
@@ -1052,10 +1046,10 @@ namespace jkj { namespace dragonbox {
BOOST_FORCEINLINE static auto delegate(SignedSignificandBits s,
Func&& f) noexcept {
if (s.has_even_significand_bits()) {
return f(detail::nearest_always_closed{});
return f(nearest_always_closed{});
}
else {
return f(detail::nearest_always_open{});
return f(nearest_always_open{});
}
}
};
@@ -1065,10 +1059,10 @@ namespace jkj { namespace dragonbox {
BOOST_FORCEINLINE static auto delegate(SignedSignificandBits s,
Func&& f) noexcept {
if (s.has_even_significand_bits()) {
return f(detail::nearest_always_open{});
return f(nearest_always_open{});
}
else {
return f(detail::nearest_always_closed{});
return f(nearest_always_closed{});
}
}
};
@@ -1101,14 +1095,12 @@ namespace jkj { namespace dragonbox {
}
};
namespace detail {
struct left_closed_directed {
static constexpr auto tag = tag_t::left_closed_directed;
};
struct right_closed_directed {
static constexpr auto tag = tag_t::right_closed_directed;
};
}
struct toward_plus_infinity : base {
using decimal_to_binary_rounding_policy = toward_plus_infinity;
@@ -1116,10 +1108,10 @@ namespace jkj { namespace dragonbox {
BOOST_FORCEINLINE static auto delegate(SignedSignificandBits s,
Func&& f) noexcept {
if (s.is_negative()) {
return f(detail::left_closed_directed{});
return f(left_closed_directed{});
}
else {
return f(detail::right_closed_directed{});
return f(right_closed_directed{});
}
}
};
@@ -1129,10 +1121,10 @@ namespace jkj { namespace dragonbox {
BOOST_FORCEINLINE static auto delegate(SignedSignificandBits s,
Func&& f) noexcept {
if (s.is_negative()) {
return f(detail::right_closed_directed{});
return f(right_closed_directed{});
}
else {
return f(detail::left_closed_directed{});
return f(left_closed_directed{});
}
}
};
@@ -1140,14 +1132,14 @@ namespace jkj { namespace dragonbox {
using decimal_to_binary_rounding_policy = toward_zero;
template <class SignedSignificandBits, class Func>
BOOST_FORCEINLINE static auto delegate(SignedSignificandBits, Func&& f) noexcept {
return f(detail::left_closed_directed{});
return f(left_closed_directed{});
}
};
struct away_from_zero : base {
using decimal_to_binary_rounding_policy = away_from_zero;
template <class SignedSignificandBits, class Func>
BOOST_FORCEINLINE static auto delegate(SignedSignificandBits, Func&& f) noexcept {
return f(detail::right_closed_directed{});
return f(right_closed_directed{});
}
};
}
@@ -1227,7 +1219,6 @@ namespace jkj { namespace dragonbox {
};
}
}
}
namespace policy {
namespace sign {
@@ -1293,8 +1284,6 @@ namespace jkj { namespace dragonbox {
BOOST_INLINE_VARIABLE constexpr auto full = detail::policy_impl::cache::full{};
}
}
namespace detail {
////////////////////////////////////////////////////////////////////////////////////////
// The main algorithm.
////////////////////////////////////////////////////////////////////////////////////////
@@ -2090,19 +2079,18 @@ namespace jkj { namespace dragonbox {
return convert_to_policy_holder(policy_pair_list{});
}
}
}
////////////////////////////////////////////////////////////////////////////////////////
// The interface function.
////////////////////////////////////////////////////////////////////////////////////////
template <class Float, class FloatTraits = default_float_traits<Float>, class... Policies>
template <class Float, class FloatTraits = dragonbox_float_traits<Float>, class... Policies>
BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto
to_decimal(signed_significand_bits<Float, FloatTraits> signed_significand_bits,
to_decimal(dragonbox_signed_significand_bits<Float, FloatTraits> dragonbox_signed_significand_bits,
unsigned int exponent_bits, Policies... policies) noexcept {
// Build policy holder type.
using namespace detail::policy_impl;
using namespace policy_impl;
using policy_holder = decltype(make_policy_holder(
base_default_pair_list<base_default_pair<sign::base, sign::return_sign>,
base_default_pair<trailing_zero::base, trailing_zero::remove>,
@@ -2118,12 +2106,12 @@ namespace jkj { namespace dragonbox {
policy_holder::report_trailing_zeros>;
return_type ret = policy_holder::delegate(
signed_significand_bits,
[exponent_bits, signed_significand_bits](auto interval_type_provider) {
dragonbox_signed_significand_bits,
[exponent_bits, dragonbox_signed_significand_bits](auto interval_type_provider) {
using format = typename FloatTraits::format;
constexpr auto tag = decltype(interval_type_provider)::tag;
auto two_fc = signed_significand_bits.remove_sign_bit_and_shift();
auto two_fc = dragonbox_signed_significand_bits.remove_sign_bit_and_shift();
auto exponent = int(exponent_bits);
BOOST_IF_CONSTEXPR (tag == decimal_to_binary_rounding::tag_t::to_nearest) {
@@ -2162,7 +2150,7 @@ namespace jkj { namespace dragonbox {
if (two_fc == 0) {
return decltype(interval_type_provider)::invoke_shorter_interval_case(
signed_significand_bits, [exponent](auto... additional_args) {
dragonbox_signed_significand_bits, [exponent](auto... additional_args) {
return detail::impl<Float, FloatTraits>::
template compute_nearest_shorter<
return_type,
@@ -2184,7 +2172,7 @@ namespace jkj { namespace dragonbox {
}
return decltype(interval_type_provider)::invoke_normal_interval_case(
signed_significand_bits, [two_fc, exponent](auto... additional_args) {
dragonbox_signed_significand_bits, [two_fc, exponent](auto... additional_args) {
return detail::impl<Float, FloatTraits>::
template compute_nearest_normal<
return_type,
@@ -2234,13 +2222,13 @@ namespace jkj { namespace dragonbox {
}
});
policy_holder::handle_sign(signed_significand_bits, ret);
policy_holder::handle_sign(dragonbox_signed_significand_bits, ret);
return ret;
}
template <class Float, class FloatTraits = default_float_traits<Float>, class... Policies>
template <class Float, class FloatTraits = dragonbox_float_traits<Float>, class... Policies>
BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto to_decimal(Float x, Policies... policies) noexcept {
auto const br = float_bits<Float, FloatTraits>(x);
auto const br = dragonbox_float_bits<Float, FloatTraits>(x);
auto const exponent_bits = br.extract_exponent_bits();
auto const s = br.remove_exponent_bits(exponent_bits);
assert(br.is_finite());
@@ -2255,7 +2243,7 @@ namespace jkj { namespace dragonbox {
// Avoid needless ABI overhead incurred by tag dispatch.
template <class PolicyHolder, class Float, class FloatTraits>
char* to_chars_n_impl(float_bits<Float, FloatTraits> br, char* buffer) noexcept {
char* to_chars_n_impl(dragonbox_float_bits<Float, FloatTraits> br, char* buffer) noexcept {
auto const exponent_bits = br.extract_exponent_bits();
auto const s = br.remove_exponent_bits(exponent_bits);
@@ -2296,9 +2284,9 @@ namespace jkj { namespace dragonbox {
}
// Returns the next-to-end position
template <class Float, class FloatTraits = default_float_traits<Float>, class... Policies>
template <class Float, class FloatTraits = dragonbox_float_traits<Float>, class... Policies>
char* to_chars_n(Float x, char* buffer, Policies... policies) noexcept {
using namespace jkj::dragonbox::detail::policy_impl;
using namespace policy_impl;
using policy_holder = decltype(make_policy_holder(
base_default_pair_list<base_default_pair<decimal_to_binary_rounding::base,
decimal_to_binary_rounding::nearest_to_even>,
@@ -2307,12 +2295,12 @@ namespace jkj { namespace dragonbox {
base_default_pair<cache::base, cache::full>>{},
policies...));
return to_chars_detail::to_chars_n_impl<policy_holder>(float_bits<Float, FloatTraits>(x),
return to_chars_detail::to_chars_n_impl<policy_holder>(dragonbox_float_bits<Float, FloatTraits>(x),
buffer);
}
// Null-terminate and bypass the return value of fp_to_chars_n
template <class Float, class FloatTraits = default_float_traits<Float>, class... Policies>
template <class Float, class FloatTraits = dragonbox_float_traits<Float>, class... Policies>
char* to_chars(Float x, char* buffer, Policies... policies) noexcept {
auto ptr = to_chars_n<Float, FloatTraits>(x, buffer, policies...);
*ptr = '\0';
@@ -2591,7 +2579,7 @@ namespace jkj { namespace dragonbox {
}
template <>
char* to_chars<float, default_float_traits<float>>(std::uint32_t s32, int exponent,
char* to_chars<float, dragonbox_float_traits<float>>(std::uint32_t s32, int exponent,
char* buffer) noexcept {
// Print significand.
print_9_digits(s32, exponent, buffer);
@@ -2620,7 +2608,7 @@ namespace jkj { namespace dragonbox {
}
template <>
char* to_chars<double, default_float_traits<double>>(std::uint64_t const significand,
char* to_chars<double, dragonbox_float_traits<double>>(std::uint64_t const significand,
int exponent, char* buffer) noexcept {
// Print significand by decomposing it into a 9-digit block and a 8-digit block.
std::uint32_t first_block, second_block;
@@ -2825,6 +2813,6 @@ namespace jkj { namespace dragonbox {
return buffer;
}
}
}} // Namespaces
}}} // Namespaces
#endif

View File

@@ -801,33 +801,33 @@ inline void print_9_digits(std::uint32_t n, char* buffer) noexcept
struct main_cache_full
{
template <typename FloatFormat>
static constexpr typename detail::main_cache_holder::cache_entry_type get_cache(int k) noexcept
static constexpr typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
{
return detail::main_cache_holder::cache[std::size_t(k - detail::main_cache_holder::min_k)];
return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
}
};
struct main_cache_compressed
{
template <typename FloatFormat>
static BOOST_CHARCONV_CXX14_CONSTEXPR typename detail::main_cache_holder::cache_entry_type get_cache(int k) noexcept
static BOOST_CHARCONV_CXX14_CONSTEXPR typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
{
BOOST_CHARCONV_ASSERT(k >= detail::main_cache_holder::min_k && k <= detail::main_cache_holder::max_k);
BOOST_CHARCONV_ASSERT(k >= main_cache_holder::min_k && k <= main_cache_holder::max_k);
BOOST_IF_CONSTEXPR (std::is_same<FloatFormat, ieee754_binary64>::value)
{
// Compute the base index.
const auto cache_index =
static_cast<int>(static_cast<std::uint32_t>(k - detail::main_cache_holder::min_k) /
detail::compressed_cache_detail::compression_ratio);
static_cast<int>(static_cast<std::uint32_t>(k - main_cache_holder::min_k) /
compressed_cache_detail::compression_ratio);
const auto kb = cache_index * detail::compressed_cache_detail::compression_ratio +
detail::main_cache_holder::min_k;
const auto kb = cache_index * compressed_cache_detail::compression_ratio +
main_cache_holder::min_k;
const auto offset = k - kb;
// Get the base cache.
const auto base_cache = detail::compressed_cache_detail::cache_holder_t::table[cache_index];
const auto base_cache = compressed_cache_detail::cache_holder_t::table[cache_index];
if (offset == 0)
{
@@ -835,14 +835,13 @@ struct main_cache_compressed
}
else
{
namespace log = detail::log;
// Compute the required amount of bit-shift.
const auto alpha = log::floor_log2_pow10(kb + offset) - log::floor_log2_pow10(kb) - offset;
BOOST_CHARCONV_ASSERT(alpha > 0 && alpha < 64);
// Try to recover the real cache.
const auto pow5 = detail::compressed_cache_detail::pow5_holder_t::table[offset];
const auto pow5 = compressed_cache_detail::pow5_holder_t::table[offset];
auto recovered_cache = umul128(base_cache.high, pow5);
const auto middle_low = umul128(base_cache.low, pow5);
@@ -862,7 +861,7 @@ struct main_cache_compressed
else
{
// Just use the full cache for anything other than binary64
return detail::main_cache_holder::cache[std::size_t(k - detail::main_cache_holder::min_k)];
return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
}
}
};
@@ -1370,7 +1369,7 @@ BOOST_CHARCONV_SAFEBUFFERS char* floff(const double x, const int precision, char
}
constexpr int kappa = 2;
int k = kappa - detail::log::floor_log10_pow2(e);
int k = kappa - log::floor_log10_pow2(e);
std::uint32_t current_digits {};
char* const buffer_starting_pos = buffer;
int decimal_exponent = -k;

View File

@@ -436,10 +436,10 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integ
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
if (base == 10)
{
return detail::to_chars_integer_impl(first, last, value);
return to_chars_integer_impl(first, last, value);
}
return detail::to_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
return to_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
}
#ifdef BOOST_CHARCONV_HAS_INT128

View File

@@ -327,6 +327,8 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, double value, boost::charconv::chars_format fmt, int precision) noexcept
{
const std::ptrdiff_t buffer_size = last - first;
// Unspecified precision so we always go with shortest representation
if (precision == -1)
{
@@ -335,7 +337,7 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la
const auto abs_value = std::abs(value);
if (abs_value >= 1 && abs_value < 1e18) // 1 x 10^(max_digits10 + 1)
{
auto value_struct = jkj::dragonbox::to_decimal(value);
auto value_struct = boost::charconv::detail::to_decimal(value);
if (value_struct.is_negative)
{
*first++ = '-';
@@ -348,7 +350,7 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la
}
// Bounds check
if (value_struct.exponent < 0)
if (value_struct.exponent < 0 && -value_struct.exponent < buffer_size)
{
std::memmove(r.ptr + value_struct.exponent + 1, r.ptr + value_struct.exponent, -value_struct.exponent);
std::memset(r.ptr + value_struct.exponent, '.', 1);
@@ -358,13 +360,13 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la
}
else
{
auto* ptr = jkj::dragonbox::to_chars(value, first);
auto* ptr = boost::charconv::detail::to_chars(value, first);
return { ptr, 0 };
}
}
else if (fmt == boost::charconv::chars_format::scientific)
{
auto* ptr = jkj::dragonbox::to_chars(value, first);
auto* ptr = boost::charconv::detail::to_chars(value, first);
return { ptr, 0 };
}
}