From 63e0c35412a731a3584fa89093bbedfafdd8fd65 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 27 Sep 2020 07:17:16 -0700 Subject: [PATCH] Make dragonbox::to_decimal available in format.h --- include/fmt/format-inl.h | 65 ++---------------------------- include/fmt/format.h | 85 +++++++++++++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 71 deletions(-) diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index e7ac53e4..d2a0b81a 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -1776,67 +1776,6 @@ inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT { shift_amount; } -// Type-specific information that Dragonbox uses. -template struct float_info; - -template <> struct float_info { - using carrier_uint = uint32_t; - static const int significand_bits = 23; - static const int exponent_bits = 8; - static const int min_exponent = -126; - static const int max_exponent = 127; - static const int exponent_bias = -127; - static const int decimal_digits = 9; - static const int kappa = 1; - static const int big_divisor = 100; - static const int small_divisor = 10; - static const int min_k = -31; - static const int max_k = 46; - static const int cache_bits = 64; - static const int divisibility_check_by_5_threshold = 39; - static const int case_fc_pm_half_lower_threshold = -1; - static const int case_fc_pm_half_upper_threshold = 6; - static const int case_fc_lower_threshold = -2; - static const int case_fc_upper_threshold = 6; - static const int case_shorter_interval_left_endpoint_lower_threshold = 2; - static const int case_shorter_interval_left_endpoint_upper_threshold = 3; - static const int shorter_interval_tie_lower_threshold = -35; - static const int shorter_interval_tie_upper_threshold = -35; - static const int max_trailing_zeros = 7; -}; - -template <> struct float_info { - using carrier_uint = uint64_t; - static const int significand_bits = 52; - static const int exponent_bits = 11; - static const int min_exponent = -1022; - static const int max_exponent = 1023; - static const int exponent_bias = -1023; - static const int decimal_digits = 17; - static const int kappa = 2; - static const int big_divisor = 1000; - static const int small_divisor = 100; - static const int min_k = -292; - static const int max_k = 326; - static const int cache_bits = 128; - static const int divisibility_check_by_5_threshold = 86; - static const int case_fc_pm_half_lower_threshold = -2; - static const int case_fc_pm_half_upper_threshold = 9; - static const int case_fc_lower_threshold = -4; - static const int case_fc_upper_threshold = 9; - static const int case_shorter_interval_left_endpoint_lower_threshold = 2; - static const int case_shorter_interval_left_endpoint_upper_threshold = 3; - static const int shorter_interval_tie_lower_threshold = -77; - static const int shorter_interval_tie_upper_threshold = -77; - static const int max_trailing_zeros = 16; -}; - -template struct decimal_fp { - using significand_type = typename float_info::carrier_uint; - significand_type significand; - int exponent; -}; - // Returns true iff x is divisible by pow(2, exp). inline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT { FMT_ASSERT(exp >= 1, ""); @@ -2291,7 +2230,9 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp shorter_interval_case( return ret_value; } -template FMT_SAFEBUFFERS decimal_fp to_decimal(T x) FMT_NOEXCEPT { +template +FMT_SAFEBUFFERS enable_if_t(), decimal_fp> to_decimal(T x) + FMT_NOEXCEPT { // Step 1: integer promotion & Schubfach multiplier calculation. using carrier_uint = typename float_info::carrier_uint; diff --git a/include/fmt/format.h b/include/fmt/format.h index 5a42d761..e181575a 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -587,13 +587,8 @@ inline counting_iterator copy_str(InputIt begin, InputIt end, return it + (end - begin); } -#ifndef FMT_USE_GRISU -# define FMT_USE_GRISU 1 -#endif - -template constexpr bool use_grisu() { - return FMT_USE_GRISU && std::numeric_limits::is_iec559 && - sizeof(T) <= sizeof(double); +template constexpr bool is_fast_float() { + return std::numeric_limits::is_iec559 && sizeof(T) <= sizeof(double); } #ifndef FMT_USE_FULL_CACHE_DRAGONBOX @@ -1368,6 +1363,78 @@ int snprintf_float(T value, int precision, float_specs specs, template T promote_float(T value) { return value; } inline double promote_float(float value) { return static_cast(value); } +namespace dragonbox { + +// Type-specific information that Dragonbox uses. +template struct float_info; + +template <> struct float_info { + using carrier_uint = uint32_t; + static const int significand_bits = 23; + static const int exponent_bits = 8; + static const int min_exponent = -126; + static const int max_exponent = 127; + static const int exponent_bias = -127; + static const int decimal_digits = 9; + static const int kappa = 1; + static const int big_divisor = 100; + static const int small_divisor = 10; + static const int min_k = -31; + static const int max_k = 46; + static const int cache_bits = 64; + static const int divisibility_check_by_5_threshold = 39; + static const int case_fc_pm_half_lower_threshold = -1; + static const int case_fc_pm_half_upper_threshold = 6; + static const int case_fc_lower_threshold = -2; + static const int case_fc_upper_threshold = 6; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; + static const int max_trailing_zeros = 7; +}; + +template <> struct float_info { + using carrier_uint = uint64_t; + static const int significand_bits = 52; + static const int exponent_bits = 11; + static const int min_exponent = -1022; + static const int max_exponent = 1023; + static const int exponent_bias = -1023; + static const int decimal_digits = 17; + static const int kappa = 2; + static const int big_divisor = 1000; + static const int small_divisor = 100; + static const int min_k = -292; + static const int max_k = 326; + static const int cache_bits = 128; + static const int divisibility_check_by_5_threshold = 86; + static const int case_fc_pm_half_lower_threshold = -2; + static const int case_fc_pm_half_upper_threshold = 9; + static const int case_fc_lower_threshold = -4; + static const int case_fc_upper_threshold = 9; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; + static const int max_trailing_zeros = 16; +}; + +template struct decimal_fp { + using significand_type = typename float_info::carrier_uint; + significand_type significand; + int exponent; +}; + +template +enable_if_t(), decimal_fp> to_decimal(T x) FMT_NOEXCEPT; + +template +inline enable_if_t(), unformattable> to_decimal(T) { + return {}; +} +} // namespace dragonbox + template FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) { switch (spec) { @@ -1810,7 +1877,7 @@ OutputIt write(OutputIt out, T value, basic_format_specs specs, ++precision; } if (const_check(std::is_same())) fspecs.binary32 = true; - fspecs.use_grisu = use_grisu(); + fspecs.use_grisu = is_fast_float(); int exp = format_float(promote_float(value), precision, fspecs, buffer); fspecs.precision = precision; Char point = @@ -1837,7 +1904,7 @@ OutputIt write(OutputIt out, T value) { memory_buffer buffer; int precision = -1; if (const_check(std::is_same())) fspecs.binary32 = true; - fspecs.use_grisu = use_grisu(); + fspecs.use_grisu = is_fast_float(); int exp = format_float(promote_float(value), precision, fspecs, buffer); fspecs.precision = precision; float_writer w(buffer.data(), static_cast(buffer.size()), exp,