mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-31 03:07:36 +02:00
Reuse log10_2_significand constant
This commit is contained in:
@ -1197,11 +1197,11 @@ inline fp operator*(fp x, fp y) { return {multiply(x.f, y.f), x.e + y.e + 64}; }
|
|||||||
// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
|
// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
|
||||||
// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
|
// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
|
||||||
inline fp get_cached_power(int min_exponent, int& pow10_exponent) {
|
inline fp get_cached_power(int min_exponent, int& pow10_exponent) {
|
||||||
const int64_t one_over_log2_10 = 0x4d104d42; // round(pow(2, 32) / log2(10))
|
const int shift = 32;
|
||||||
int index = static_cast<int>(
|
int index = static_cast<int>(((min_exponent + fp::significand_size - 1) *
|
||||||
((min_exponent + fp::significand_size - 1) * one_over_log2_10 +
|
(data::log10_2_significand >> shift) +
|
||||||
((int64_t(1) << 32) - 1)) // ceil
|
((int64_t(1) << shift) - 1)) // ceil
|
||||||
>> 32 // arithmetic shift
|
>> 32 // arithmetic shift
|
||||||
);
|
);
|
||||||
// Decimal exponent of the first (smallest) cached power of 10.
|
// Decimal exponent of the first (smallest) cached power of 10.
|
||||||
const int first_dec_exp = -348;
|
const int first_dec_exp = -348;
|
||||||
@ -1752,15 +1752,16 @@ inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT {
|
|||||||
return x * y;
|
return x * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Various fast log computations.
|
// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from
|
||||||
|
// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4.
|
||||||
inline int floor_log10_pow2(int e) FMT_NOEXCEPT {
|
inline int floor_log10_pow2(int e) FMT_NOEXCEPT {
|
||||||
FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
|
FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
|
||||||
const uint64_t log10_2_fractional_digits = 0x4d104d427de7fbcc;
|
const int shift = 22;
|
||||||
const int shift_amount = 22;
|
return (e * static_cast<int>(data::log10_2_significand >> (64 - shift))) >>
|
||||||
return (e *
|
shift;
|
||||||
static_cast<int>(log10_2_fractional_digits >> (64 - shift_amount))) >>
|
|
||||||
shift_amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Various fast log computations.
|
||||||
inline int floor_log2_pow10(int e) FMT_NOEXCEPT {
|
inline int floor_log2_pow10(int e) FMT_NOEXCEPT {
|
||||||
FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
|
FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
|
||||||
const uint64_t log2_10_integer_part = 3;
|
const uint64_t log2_10_integer_part = 3;
|
||||||
@ -1773,10 +1774,9 @@ inline int floor_log2_pow10(int e) FMT_NOEXCEPT {
|
|||||||
}
|
}
|
||||||
inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT {
|
inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT {
|
||||||
FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
|
FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
|
||||||
const uint64_t log10_2_fractional_digits = 0x4d104d427de7fbcc;
|
|
||||||
const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375;
|
const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375;
|
||||||
const int shift_amount = 22;
|
const int shift_amount = 22;
|
||||||
return (e * static_cast<int>(log10_2_fractional_digits >>
|
return (e * static_cast<int>(data::log10_2_significand >>
|
||||||
(64 - shift_amount)) -
|
(64 - shift_amount)) -
|
||||||
static_cast<int>(log10_4_over_3_fractional_digits >>
|
static_cast<int>(log10_4_over_3_fractional_digits >>
|
||||||
(64 - shift_amount))) >>
|
(64 - shift_amount))) >>
|
||||||
@ -2324,8 +2324,7 @@ template <class T> FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
|
|||||||
exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits;
|
exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits;
|
||||||
|
|
||||||
// Shorter interval case; proceed like Schubfach.
|
// Shorter interval case; proceed like Schubfach.
|
||||||
if (significand == 0)
|
if (significand == 0) return shorter_interval_case<T>(exponent);
|
||||||
return shorter_interval_case<T>(exponent);
|
|
||||||
|
|
||||||
significand |=
|
significand |=
|
||||||
(static_cast<carrier_uint>(1) << float_info<T>::significand_bits);
|
(static_cast<carrier_uint>(1) << float_info<T>::significand_bits);
|
||||||
|
@ -879,6 +879,8 @@ template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
|
|||||||
static const divtest_table_entry<uint64_t> divtest_table_for_pow5_64[];
|
static const divtest_table_entry<uint64_t> divtest_table_for_pow5_64[];
|
||||||
static const uint64_t dragonbox_pow10_significands_64[];
|
static const uint64_t dragonbox_pow10_significands_64[];
|
||||||
static const uint128_wrapper dragonbox_pow10_significands_128[];
|
static const uint128_wrapper dragonbox_pow10_significands_128[];
|
||||||
|
// log10(2) = 0x0.4d104d427de7fbcc...
|
||||||
|
static const uint64_t log10_2_significand = 0x4d104d427de7fbcc;
|
||||||
#if !FMT_USE_FULL_CACHE_DRAGONBOX
|
#if !FMT_USE_FULL_CACHE_DRAGONBOX
|
||||||
static const uint64_t powers_of_5_64[];
|
static const uint64_t powers_of_5_64[];
|
||||||
static const uint32_t dragonbox_pow10_recovery_errors[];
|
static const uint32_t dragonbox_pow10_recovery_errors[];
|
||||||
|
Reference in New Issue
Block a user