Make dragonbox::to_decimal available in format.h

This commit is contained in:
Victor Zverovich 2020-09-27 07:17:16 -07:00
parent 2213a7110c
commit 63e0c35412
2 changed files with 79 additions and 71 deletions

View File

@ -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 <class T> struct float_info;
template <> struct float_info<float> {
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<double> {
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 <class T> struct decimal_fp {
using significand_type = typename float_info<T>::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<T> shorter_interval_case(
return ret_value;
}
template <class T> FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
template <typename T>
FMT_SAFEBUFFERS enable_if_t<is_fast_float<T>(), decimal_fp<T>> to_decimal(T x)
FMT_NOEXCEPT {
// Step 1: integer promotion & Schubfach multiplier calculation.
using carrier_uint = typename float_info<T>::carrier_uint;

View File

@ -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 <typename T> constexpr bool use_grisu() {
return FMT_USE_GRISU && std::numeric_limits<double>::is_iec559 &&
sizeof(T) <= sizeof(double);
template <typename T> constexpr bool is_fast_float() {
return std::numeric_limits<T>::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 <typename T> T promote_float(T value) { return value; }
inline double promote_float(float value) { return static_cast<double>(value); }
namespace dragonbox {
// Type-specific information that Dragonbox uses.
template <class T> struct float_info;
template <> struct float_info<float> {
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<double> {
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 <typename T> struct decimal_fp {
using significand_type = typename float_info<T>::carrier_uint;
significand_type significand;
int exponent;
};
template <typename T>
enable_if_t<is_fast_float<T>(), decimal_fp<T>> to_decimal(T x) FMT_NOEXCEPT;
template <typename T>
inline enable_if_t<!is_fast_float<T>(), unformattable> to_decimal(T) {
return {};
}
} // namespace dragonbox
template <typename Handler>
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<Char> specs,
++precision;
}
if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
fspecs.use_grisu = use_grisu<T>();
fspecs.use_grisu = is_fast_float<T>();
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<T, float>())) fspecs.binary32 = true;
fspecs.use_grisu = use_grisu<T>();
fspecs.use_grisu = is_fast_float<T>();
int exp = format_float(promote_float(value), precision, fspecs, buffer);
fspecs.precision = precision;
float_writer<Char> w(buffer.data(), static_cast<int>(buffer.size()), exp,