Simplify format_decimal

This commit is contained in:
Victor Zverovich 2024-07-22 16:52:55 -07:00
parent ba36a04811
commit 4239dfe081
2 changed files with 29 additions and 30 deletions

View File

@ -1147,7 +1147,7 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) {
std::chrono::seconds::period>::value) { std::chrono::seconds::period>::value) {
*out++ = '.'; *out++ = '.';
out = detail::fill_n(out, leading_zeroes, '0'); out = detail::fill_n(out, leading_zeroes, '0');
out = format_decimal<Char>(out, n, num_digits).end; out = format_decimal<Char>(out, n, num_digits);
} }
} else if (precision > 0) { } else if (precision > 0) {
*out++ = '.'; *out++ = '.';
@ -1158,12 +1158,12 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) {
int num_truncated_digits = num_digits - remaining; int num_truncated_digits = num_digits - remaining;
n /= to_unsigned(detail::pow10(to_unsigned(num_truncated_digits))); n /= to_unsigned(detail::pow10(to_unsigned(num_truncated_digits)));
if (n) { if (n) {
out = format_decimal<Char>(out, n, remaining).end; out = format_decimal<Char>(out, n, remaining);
} }
return; return;
} }
if (n) { if (n) {
out = format_decimal<Char>(out, n, num_digits).end; out = format_decimal<Char>(out, n, num_digits);
remaining -= num_digits; remaining -= num_digits;
} }
out = detail::fill_n(out, remaining, '0'); out = detail::fill_n(out, remaining, '0');
@ -1319,7 +1319,7 @@ class tm_writer {
const int num_digits = count_digits(n); const int num_digits = count_digits(n);
if (width > num_digits) if (width > num_digits)
out_ = detail::fill_n(out_, width - num_digits, '0'); out_ = detail::fill_n(out_, width - num_digits, '0');
out_ = format_decimal<Char>(out_, n, num_digits).end; out_ = format_decimal<Char>(out_, n, num_digits);
} }
void write_year(long long year) { void write_year(long long year) {
if (year >= 0 && year < 10000) { if (year >= 0 && year < 10000) {
@ -1881,7 +1881,7 @@ struct chrono_formatter {
if (width > num_digits) { if (width > num_digits) {
out = detail::write_padding(out, pad, width - num_digits); out = detail::write_padding(out, pad, width - num_digits);
} }
out = format_decimal<char_type>(out, n, num_digits).end; out = format_decimal<char_type>(out, n, num_digits);
} }
void write_nan() { std::copy_n("nan", 3, out); } void write_nan() { std::copy_n("nan", 3, out); }

View File

@ -1283,45 +1283,45 @@ FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) {
*dst = static_cast<Char>(*src); *dst = static_cast<Char>(*src);
} }
template <typename Iterator> struct format_decimal_result { // Formats a decimal unsigned integer value writing to out pointing to a buffer
Iterator begin; // of specified size. The caller must ensure that the buffer is large enough.
Iterator end;
};
// Formats a decimal unsigned integer value writing into out pointing to a
// buffer of specified size. The caller must ensure that the buffer is large
// enough.
template <typename Char, typename UInt> template <typename Char, typename UInt>
FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) FMT_CONSTEXPR20 auto do_format_decimal(Char* out, UInt value, int size)
-> format_decimal_result<Char*> { -> Char* {
FMT_ASSERT(size >= count_digits(value), "invalid digit count"); FMT_ASSERT(size >= count_digits(value), "invalid digit count");
auto begin = out, end = out + size;
unsigned n = to_unsigned(size); unsigned n = to_unsigned(size);
while (value >= 100) { while (value >= 100) {
// Integer division is slow so do it for a group of two digits instead // Integer division is slow so do it for a group of two digits instead
// of for every digit. The idea comes from the talk by Alexandrescu // of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison. // "Three Optimization Tips for C++". See speed-test for a comparison.
n -= 2; n -= 2;
copy2(begin + n, digits2(static_cast<unsigned>(value % 100))); copy2(out + n, digits2(static_cast<unsigned>(value % 100)));
value /= 100; value /= 100;
} }
if (value >= 10) { if (value >= 10) {
n -= 2; n -= 2;
copy2(begin + n, digits2(static_cast<unsigned>(value))); copy2(out + n, digits2(static_cast<unsigned>(value)));
} else { } else {
begin[--n] = static_cast<Char>('0' + value); out[--n] = static_cast<Char>('0' + value);
} }
return {begin + n, end}; return out + n;
}
template <typename Char, typename UInt>
FMT_CONSTEXPR FMT_INLINE auto format_decimal(Char* out, UInt value, int size)
-> Char* {
do_format_decimal(out, value, size);
return out + size;
} }
template <typename Char, typename UInt, typename OutputIt, template <typename Char, typename UInt, typename OutputIt,
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)> FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)>
FMT_CONSTEXPR inline auto format_decimal(OutputIt out, UInt value, int size) FMT_CONSTEXPR inline auto format_decimal(OutputIt out, UInt value, int size)
-> format_decimal_result<OutputIt> { -> OutputIt {
// Buffer is large enough to hold all digits (digits10 + 1). // Buffer is large enough to hold all digits (digits10 + 1).
Char buffer[digits10<UInt>() + 1] = {}; char buffer[digits10<UInt>() + 1] = {};
auto end = format_decimal(buffer, value, size).end; do_format_decimal(buffer, value, size);
return {out, detail::copy_noinline<Char>(buffer, end, out)}; return detail::copy_noinline<Char>(buffer, buffer + size, out);
} }
template <unsigned BASE_BITS, typename Char, typename UInt> template <unsigned BASE_BITS, typename Char, typename UInt>
@ -2167,7 +2167,7 @@ FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg,
int num_digits = count_digits(abs_value); int num_digits = count_digits(abs_value);
return write_int<Char>( return write_int<Char>(
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
return format_decimal<Char>(it, abs_value, num_digits).end; return format_decimal<Char>(it, abs_value, num_digits);
}); });
} }
case presentation_type::hex: { case presentation_type::hex: {
@ -2295,7 +2295,7 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
return out; return out;
} }
if (negative) *out++ = static_cast<Char>('-'); if (negative) *out++ = static_cast<Char>('-');
return format_decimal<Char>(out, abs_value, num_digits).end; return format_decimal<Char>(out, abs_value, num_digits);
} }
// DEPRECATED! // DEPRECATED!
@ -2426,7 +2426,7 @@ constexpr auto write_significand(OutputIt out, const char* significand,
template <typename Char, typename OutputIt, typename UInt> template <typename Char, typename OutputIt, typename UInt>
inline auto write_significand(OutputIt out, UInt significand, inline auto write_significand(OutputIt out, UInt significand,
int significand_size) -> OutputIt { int significand_size) -> OutputIt {
return format_decimal<Char>(out, significand, significand_size).end; return format_decimal<Char>(out, significand, significand_size);
} }
template <typename Char, typename OutputIt, typename T, typename Grouping> template <typename Char, typename OutputIt, typename T, typename Grouping>
FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
@ -2446,8 +2446,7 @@ template <typename Char, typename UInt,
FMT_ENABLE_IF(std::is_integral<UInt>::value)> FMT_ENABLE_IF(std::is_integral<UInt>::value)>
inline auto write_significand(Char* out, UInt significand, int significand_size, inline auto write_significand(Char* out, UInt significand, int significand_size,
int integral_size, Char decimal_point) -> Char* { int integral_size, Char decimal_point) -> Char* {
if (!decimal_point) if (!decimal_point) return format_decimal(out, significand, significand_size);
return format_decimal(out, significand, significand_size).end;
out += significand_size + 1; out += significand_size + 1;
Char* end = out; Char* end = out;
int floating_size = significand_size - integral_size; int floating_size = significand_size - integral_size;
@ -3889,7 +3888,7 @@ class format_int {
template <typename UInt> template <typename UInt>
FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* { FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* {
auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value); auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
return detail::format_decimal(buffer_, n, buffer_size - 1).begin; return detail::do_format_decimal(buffer_, n, buffer_size - 1);
} }
template <typename Int> template <typename Int>