Minor tweaks to get_cached_power

This commit is contained in:
Victor Zverovich 2020-09-23 16:04:40 -07:00
parent 6c025520aa
commit 0651e4598b

View File

@ -1934,6 +1934,7 @@ template <class T> struct cache_accessor;
template <> struct cache_accessor<float> { template <> struct cache_accessor<float> {
using carrier_uint = float_info<float>::carrier_uint; using carrier_uint = float_info<float>::carrier_uint;
using cache_entry_type = uint64_t; using cache_entry_type = uint64_t;
static uint64_t get_cached_power(int k) FMT_NOEXCEPT { static uint64_t get_cached_power(int k) FMT_NOEXCEPT {
FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k, FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,
"k is out of range"); "k is out of range");
@ -1986,6 +1987,7 @@ template <> struct cache_accessor<float> {
template <> struct cache_accessor<double> { template <> struct cache_accessor<double> {
using carrier_uint = float_info<double>::carrier_uint; using carrier_uint = float_info<double>::carrier_uint;
using cache_entry_type = uint128_wrapper; using cache_entry_type = uint128_wrapper;
static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT { static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT {
FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k, FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k,
"k is out of range"); "k is out of range");
@ -1996,23 +1998,21 @@ template <> struct cache_accessor<double> {
#else #else
static const int compression_ratio = 27; static const int compression_ratio = 27;
// Compute base index // Compute base index.
int cache_index = (k - float_info<double>::min_k) / compression_ratio; int cache_index = (k - float_info<double>::min_k) / compression_ratio;
int kb = cache_index * compression_ratio + float_info<double>::min_k; int kb = cache_index * compression_ratio + float_info<double>::min_k;
int offset = k - kb; int offset = k - kb;
// Get base cache // Get base cache.
uint128_wrapper base_cache = uint128_wrapper base_cache =
data::dragonbox_pow10_significands_128[cache_index]; data::dragonbox_pow10_significands_128[cache_index];
if (offset == 0) return base_cache;
if (offset == 0) { // Compute the required amount of bit-shift.
return base_cache;
} else {
// Compute the required amount of bit-shift
int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset; int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset;
FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected"); FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected");
// Try to recover the real cache // Try to recover the real cache.
uint64_t pow5 = data::powers_of_5_64[offset]; uint64_t pow5 = data::powers_of_5_64[offset];
uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5); uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5);
uint128_wrapper middle_low = uint128_wrapper middle_low =
@ -2027,22 +2027,17 @@ template <> struct cache_accessor<double> {
uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle, uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle,
((middle_low.low() >> alpha) | middle_to_low)}; ((middle_low.low() >> alpha) | middle_to_low)};
if (kb < 0) { if (kb < 0) recovered_cache += 1;
recovered_cache += 1;
}
// Get error // Get error.
int error_idx = (k - float_info<double>::min_k) / 16; int error_idx = (k - float_info<double>::min_k) / 16;
uint32_t error = (data::dragonbox_pow10_recovery_errors[error_idx] >> uint32_t error = (data::dragonbox_pow10_recovery_errors[error_idx] >>
((k - float_info<double>::min_k) % 16) * 2) & ((k - float_info<double>::min_k) % 16) * 2) &
0x3; 0x3;
// Add the error back // Add the error back.
FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), ""); FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), "");
recovered_cache = {recovered_cache.high(), recovered_cache.low() + error}; return {recovered_cache.high(), recovered_cache.low() + error};
return recovered_cache;
}
#endif #endif
} }