Improve dragonbox integration

This commit is contained in:
Victor Zverovich 2020-09-27 18:30:43 -07:00
parent 79694d424c
commit 6417952574
2 changed files with 25 additions and 34 deletions

View File

@ -2231,8 +2231,7 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp<T> shorter_interval_case(
} }
template <typename T> template <typename T>
FMT_SAFEBUFFERS enable_if_t<is_fast_float<T>(), decimal_fp<T>> to_decimal(T x) FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
FMT_NOEXCEPT {
// Step 1: integer promotion & Schubfach multiplier calculation. // Step 1: integer promotion & Schubfach multiplier calculation.
using carrier_uint = typename float_info<T>::carrier_uint; using carrier_uint = typename float_info<T>::carrier_uint;

View File

@ -587,9 +587,9 @@ inline counting_iterator copy_str(InputIt begin, InputIt end,
return it + (end - begin); return it + (end - begin);
} }
template <typename T> constexpr bool is_fast_float() { template <typename T>
return std::numeric_limits<T>::is_iec559 && sizeof(T) <= sizeof(double); using is_fast_float = bool_constant<std::numeric_limits<T>::is_iec559 &&
} sizeof(T) <= sizeof(double)>;
#ifndef FMT_USE_FULL_CACHE_DRAGONBOX #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
# define FMT_USE_FULL_CACHE_DRAGONBOX 0 # define FMT_USE_FULL_CACHE_DRAGONBOX 0
@ -1291,12 +1291,8 @@ template <typename Char> class float_writer {
// 1234e-2 -> 12.34[0+] // 1234e-2 -> 12.34[0+]
it = copy_str<Char>(digits_, digits_ + full_exp, it); it = copy_str<Char>(digits_, digits_ + full_exp, it);
if (!specs_.showpoint) { if (!specs_.showpoint) {
// Remove trailing zeros. if (num_digits_ != full_exp) *it++ = decimal_point_;
int num_digits = num_digits_; return copy_str<Char>(digits_ + full_exp, digits_ + num_digits_, it);
while (num_digits > full_exp && digits_[num_digits - 1] == '0')
--num_digits;
if (num_digits != full_exp) *it++ = decimal_point_;
return copy_str<Char>(digits_ + full_exp, digits_ + num_digits, it);
} }
*it++ = decimal_point_; *it++ = decimal_point_;
it = copy_str<Char>(digits_ + full_exp, digits_ + num_digits_, it); it = copy_str<Char>(digits_ + full_exp, digits_ + num_digits_, it);
@ -1309,18 +1305,14 @@ template <typename Char> class float_writer {
// 1234e-6 -> 0.001234 // 1234e-6 -> 0.001234
*it++ = static_cast<Char>('0'); *it++ = static_cast<Char>('0');
int num_zeros = -full_exp; int num_zeros = -full_exp;
int num_digits = num_digits_; if (num_digits_ == 0 && specs_.precision >= 0 &&
if (num_digits == 0 && specs_.precision >= 0 &&
specs_.precision < num_zeros) { specs_.precision < num_zeros) {
num_zeros = specs_.precision; num_zeros = specs_.precision;
} }
// Remove trailing zeros. if (num_zeros != 0 || num_digits_ != 0 || specs_.showpoint) {
if (!specs_.showpoint)
while (num_digits > 0 && digits_[num_digits - 1] == '0') --num_digits;
if (num_zeros != 0 || num_digits != 0 || specs_.showpoint) {
*it++ = decimal_point_; *it++ = decimal_point_;
it = std::fill_n(it, num_zeros, static_cast<Char>('0')); it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
it = copy_str<Char>(digits_, digits_ + num_digits, it); it = copy_str<Char>(digits_, digits_ + num_digits_, it);
} }
} }
return it; return it;
@ -1426,13 +1418,7 @@ template <typename T> struct decimal_fp {
int exponent; int exponent;
}; };
template <typename T> template <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT;
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 } // namespace dragonbox
template <typename Handler> template <typename Handler>
@ -1887,8 +1873,9 @@ OutputIt write(OutputIt out, T value, basic_format_specs<Char> specs,
return write_padded<align::right>(out, specs, w.size(), w); return write_padded<align::right>(out, specs, w.size(), w);
} }
template <typename Char, typename OutputIt, typename T, template <
FMT_ENABLE_IF(std::is_floating_point<T>::value)> typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(std::is_floating_point<T>::value&& is_fast_float<T>::value)>
OutputIt write(OutputIt out, T value) { OutputIt write(OutputIt out, T value) {
if (const_check(!is_supported_floating_point(value))) return out; if (const_check(!is_supported_floating_point(value))) return out;
auto fspecs = float_specs(); auto fspecs = float_specs();
@ -1901,17 +1888,22 @@ OutputIt write(OutputIt out, T value) {
if (!std::isfinite(value)) if (!std::isfinite(value))
return write_nonfinite(out, std::isinf(value), specs, fspecs); return write_nonfinite(out, std::isinf(value), specs, fspecs);
memory_buffer buffer; using type = conditional_t<std::is_same<T, long double>::value, double, T>;
int precision = -1; auto dec = dragonbox::to_decimal(static_cast<type>(value));
if (const_check(std::is_same<T, float>())) fspecs.binary32 = true; memory_buffer buf;
fspecs.use_grisu = is_fast_float<T>(); write<char>(buffer_appender<char>(buf), dec.significand);
int exp = format_float(promote_float(value), precision, fspecs, buffer); float_writer<Char> w(buf.data(), static_cast<int>(buf.size()), dec.exponent,
fspecs.precision = precision;
float_writer<Char> w(buffer.data(), static_cast<int>(buffer.size()), exp,
fspecs, static_cast<Char>('.')); fspecs, static_cast<Char>('.'));
return base_iterator(out, w(reserve(out, w.size()))); return base_iterator(out, w(reserve(out, w.size())));
} }
template <typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(std::is_floating_point<T>::value &&
!is_fast_float<T>::value)>
inline OutputIt write(OutputIt out, T value) {
return write(out, value, basic_format_specs<Char>());
}
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt>
OutputIt write_char(OutputIt out, Char value, OutputIt write_char(OutputIt out, Char value,
const basic_format_specs<Char>& specs) { const basic_format_specs<Char>& specs) {