mirror of
https://github.com/fmtlib/fmt.git
synced 2025-08-09 15:44:43 +02:00
Optimize the default FP formatting
This commit is contained in:
@@ -519,6 +519,11 @@ template <typename T, typename OutputIt>
|
|||||||
constexpr auto to_pointer(OutputIt, size_t) -> T* {
|
constexpr auto to_pointer(OutputIt, size_t) -> T* {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
template <typename T> FMT_CONSTEXPR auto to_pointer(T*& ptr, size_t n) -> T* {
|
||||||
|
T* begin = ptr;
|
||||||
|
ptr += n;
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FMT_CONSTEXPR20 auto to_pointer(basic_appender<T> it, size_t n) -> T* {
|
FMT_CONSTEXPR20 auto to_pointer(basic_appender<T> it, size_t n) -> T* {
|
||||||
buffer<T>& buf = get_container(it);
|
buffer<T>& buf = get_container(it);
|
||||||
@@ -1615,6 +1620,15 @@ constexpr auto convert_float(T value) -> convert_float_result<T> {
|
|||||||
return static_cast<convert_float_result<T>>(value);
|
return static_cast<convert_float_result<T>>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool C, typename T, typename F, FMT_ENABLE_IF(C)>
|
||||||
|
auto select(T true_value, F) -> T {
|
||||||
|
return true_value;
|
||||||
|
}
|
||||||
|
template <bool C, typename T, typename F, FMT_ENABLE_IF(!C)>
|
||||||
|
auto select(T, F false_value) -> F {
|
||||||
|
return false_value;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
template <typename Char, typename OutputIt>
|
||||||
FMT_CONSTEXPR FMT_NOINLINE auto fill(OutputIt it, size_t n,
|
FMT_CONSTEXPR FMT_NOINLINE auto fill(OutputIt it, size_t n,
|
||||||
const basic_specs& specs) -> OutputIt {
|
const basic_specs& specs) -> OutputIt {
|
||||||
@@ -3455,25 +3469,53 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
|
|||||||
return write_nonfinite<Char>(out, std::isnan(value), {}, s);
|
return write_nonfinite<Char>(out, std::isnan(value), {}, s);
|
||||||
|
|
||||||
auto dec = dragonbox::to_decimal(static_cast<fast_float_t<T>>(value));
|
auto dec = dragonbox::to_decimal(static_cast<fast_float_t<T>>(value));
|
||||||
int significand_size = count_digits(dec.significand);
|
auto significand = dec.significand;
|
||||||
int exp = dec.exponent + significand_size - 1;
|
int significand_size = count_digits(significand);
|
||||||
if (use_fixed(exp, detail::exp_upper<T>())) {
|
int exponent = dec.exponent + significand_size - 1;
|
||||||
|
if (use_fixed(exponent, detail::exp_upper<T>())) {
|
||||||
return write_fixed<Char, fallback_digit_grouping<Char>>(
|
return write_fixed<Char, fallback_digit_grouping<Char>>(
|
||||||
out, dec, significand_size, Char('.'), {}, s);
|
out, dec, significand_size, Char('.'), {}, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write value in the exponential format.
|
// Write value in the exponential format.
|
||||||
|
const char* prefix = "e+";
|
||||||
|
int abs_exponent = exponent;
|
||||||
|
if (exponent < 0) {
|
||||||
|
abs_exponent = -exponent;
|
||||||
|
prefix = "e-";
|
||||||
|
}
|
||||||
auto has_decimal_point = significand_size != 1;
|
auto has_decimal_point = significand_size != 1;
|
||||||
size_t size =
|
size_t size = std::is_pointer<OutputIt>::value
|
||||||
to_unsigned((s != sign::none ? 1 : 0) + significand_size +
|
? 0u
|
||||||
(has_decimal_point ? 1 : 0) + compute_exp_size(exp));
|
: to_unsigned((s != sign::none ? 1 : 0) + significand_size +
|
||||||
|
(has_decimal_point ? 1 : 0) +
|
||||||
|
(abs_exponent >= 100 ? 5 : 4));
|
||||||
|
if (auto ptr = to_pointer<Char>(out, size)) {
|
||||||
|
if (s != sign::none) *ptr++ = Char('-');
|
||||||
|
if (has_decimal_point) {
|
||||||
|
auto begin = ptr;
|
||||||
|
ptr = format_decimal<Char>(ptr, significand, significand_size + 1);
|
||||||
|
*begin = begin[1];
|
||||||
|
begin[1] = '.';
|
||||||
|
} else {
|
||||||
|
*ptr++ = static_cast<Char>('0' + significand);
|
||||||
|
}
|
||||||
|
memcpy(ptr, prefix, 2);
|
||||||
|
ptr += 2;
|
||||||
|
if (abs_exponent >= 100) {
|
||||||
|
*ptr++ = static_cast<Char>('0' + abs_exponent / 100);
|
||||||
|
abs_exponent %= 100;
|
||||||
|
}
|
||||||
|
write2digits(ptr, static_cast<unsigned>(abs_exponent));
|
||||||
|
return select<std::is_pointer<OutputIt>::value>(ptr + 2, out);
|
||||||
|
}
|
||||||
auto it = reserve(out, size);
|
auto it = reserve(out, size);
|
||||||
if (s != sign::none) *it++ = Char('-');
|
if (s != sign::none) *it++ = Char('-');
|
||||||
// Insert a decimal point after the first digit and add an exponent.
|
// Insert a decimal point after the first digit and add an exponent.
|
||||||
it = write_significand(it, dec.significand, significand_size, 1,
|
it = write_significand(it, significand, significand_size, 1,
|
||||||
has_decimal_point ? Char('.') : Char());
|
has_decimal_point ? Char('.') : Char());
|
||||||
*it++ = Char('e');
|
*it++ = Char('e');
|
||||||
it = write_exponent<Char>(exp, it);
|
it = write_exponent<Char>(exponent, it);
|
||||||
return base_iterator(out, it);
|
return base_iterator(out, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user