mirror of
https://github.com/shadps4-emu/ext-fmt.git
synced 2024-12-04 00:01:06 +00:00
Reuse num_significand_bits
This commit is contained in:
parent
9a1beab574
commit
f91f61cd13
@ -215,18 +215,6 @@ template <typename T> struct bits {
|
||||
static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);
|
||||
};
|
||||
|
||||
template <typename Float> constexpr bool has_implicit_bit() {
|
||||
return std::numeric_limits<Float>::digits != 64;
|
||||
}
|
||||
|
||||
// Returns the number of significand bits in Float excluding the implicit bit.
|
||||
template <typename Float> constexpr int num_significand_bits() {
|
||||
// Subtract 1 to account for an implicit most significant bit in the
|
||||
// normalized form.
|
||||
return std::numeric_limits<Float>::digits -
|
||||
(has_implicit_bit<Float>() ? 1 : 0);
|
||||
}
|
||||
|
||||
// A floating-point number f * pow(2, e).
|
||||
template <typename F> struct basic_fp {
|
||||
F f;
|
||||
@ -259,9 +247,8 @@ template <typename F> struct basic_fp {
|
||||
const carrier_uint significand_mask = implicit_bit - 1;
|
||||
auto u = bit_cast<carrier_uint>(n);
|
||||
f = static_cast<uint64_t>(u & significand_mask);
|
||||
int biased_e =
|
||||
static_cast<int>((u & exponent_mask<Float>()) >>
|
||||
dragonbox::float_info<Float>::significand_bits);
|
||||
int biased_e = static_cast<int>((u & exponent_mask<Float>()) >>
|
||||
detail::num_significand_bits<Float>());
|
||||
// The predecessor is closer if n is a normalized power of 2 (f == 0) other
|
||||
// than the smallest normalized number (biased_e > 1).
|
||||
bool is_predecessor_closer = f == 0 && biased_e > 1;
|
||||
@ -1021,22 +1008,21 @@ template <> struct cache_accessor<float> {
|
||||
static carrier_uint compute_left_endpoint_for_shorter_interval_case(
|
||||
const cache_entry_type& cache, int beta) noexcept {
|
||||
return static_cast<carrier_uint>(
|
||||
(cache - (cache >> (float_info<float>::significand_bits + 2))) >>
|
||||
(64 - float_info<float>::significand_bits - 1 - beta));
|
||||
(cache - (cache >> (num_significand_bits<float>() + 2))) >>
|
||||
(64 - num_significand_bits<float>() - 1 - beta));
|
||||
}
|
||||
|
||||
static carrier_uint compute_right_endpoint_for_shorter_interval_case(
|
||||
const cache_entry_type& cache, int beta) noexcept {
|
||||
return static_cast<carrier_uint>(
|
||||
(cache + (cache >> (float_info<float>::significand_bits + 1))) >>
|
||||
(64 - float_info<float>::significand_bits - 1 - beta));
|
||||
(cache + (cache >> (num_significand_bits<float>() + 1))) >>
|
||||
(64 - num_significand_bits<float>() - 1 - beta));
|
||||
}
|
||||
|
||||
static carrier_uint compute_round_up_for_shorter_interval_case(
|
||||
const cache_entry_type& cache, int beta) noexcept {
|
||||
return (static_cast<carrier_uint>(
|
||||
cache >>
|
||||
(64 - float_info<float>::significand_bits - 2 - beta)) +
|
||||
cache >> (64 - num_significand_bits<float>() - 2 - beta)) +
|
||||
1) /
|
||||
2;
|
||||
}
|
||||
@ -1780,21 +1766,20 @@ template <> struct cache_accessor<double> {
|
||||
static carrier_uint compute_left_endpoint_for_shorter_interval_case(
|
||||
const cache_entry_type& cache, int beta) noexcept {
|
||||
return (cache.high() -
|
||||
(cache.high() >> (float_info<double>::significand_bits + 2))) >>
|
||||
(64 - float_info<double>::significand_bits - 1 - beta);
|
||||
(cache.high() >> (num_significand_bits<double>() + 2))) >>
|
||||
(64 - num_significand_bits<double>() - 1 - beta);
|
||||
}
|
||||
|
||||
static carrier_uint compute_right_endpoint_for_shorter_interval_case(
|
||||
const cache_entry_type& cache, int beta) noexcept {
|
||||
return (cache.high() +
|
||||
(cache.high() >> (float_info<double>::significand_bits + 1))) >>
|
||||
(64 - float_info<double>::significand_bits - 1 - beta);
|
||||
(cache.high() >> (num_significand_bits<double>() + 1))) >>
|
||||
(64 - num_significand_bits<double>() - 1 - beta);
|
||||
}
|
||||
|
||||
static carrier_uint compute_round_up_for_shorter_interval_case(
|
||||
const cache_entry_type& cache, int beta) noexcept {
|
||||
return ((cache.high() >>
|
||||
(64 - float_info<double>::significand_bits - 2 - beta)) +
|
||||
return ((cache.high() >> (64 - num_significand_bits<double>() - 2 - beta)) +
|
||||
1) /
|
||||
2;
|
||||
}
|
||||
@ -1942,25 +1927,24 @@ template <typename T> decimal_fp<T> to_decimal(T x) noexcept {
|
||||
|
||||
// Extract significand bits and exponent bits.
|
||||
const carrier_uint significand_mask =
|
||||
(static_cast<carrier_uint>(1) << float_info<T>::significand_bits) - 1;
|
||||
(static_cast<carrier_uint>(1) << num_significand_bits<T>()) - 1;
|
||||
carrier_uint significand = (br & significand_mask);
|
||||
int exponent = static_cast<int>((br & exponent_mask<T>()) >>
|
||||
float_info<T>::significand_bits);
|
||||
int exponent =
|
||||
static_cast<int>((br & exponent_mask<T>()) >> num_significand_bits<T>());
|
||||
|
||||
if (exponent != 0) { // Check if normal.
|
||||
exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits;
|
||||
exponent += float_info<T>::exponent_bias - num_significand_bits<T>();
|
||||
|
||||
// Shorter interval case; proceed like Schubfach.
|
||||
// In fact, when exponent == 1 and significand == 0, the interval is
|
||||
// regular. However, it can be shown that the end-results are anyway same.
|
||||
if (significand == 0) return shorter_interval_case<T>(exponent);
|
||||
|
||||
significand |=
|
||||
(static_cast<carrier_uint>(1) << float_info<T>::significand_bits);
|
||||
significand |= (static_cast<carrier_uint>(1) << num_significand_bits<T>());
|
||||
} else {
|
||||
// Subnormal case; the interval is always regular.
|
||||
if (significand == 0) return {0, 0};
|
||||
exponent = float_info<T>::min_exponent - float_info<T>::significand_bits;
|
||||
exponent = float_info<T>::min_exponent - num_significand_bits<T>();
|
||||
}
|
||||
|
||||
const bool include_left_endpoint = (significand % 2 == 0);
|
||||
|
@ -1226,7 +1226,6 @@ template <typename T, typename Enable = void> struct float_info;
|
||||
|
||||
template <> struct float_info<float> {
|
||||
using carrier_uint = uint32_t;
|
||||
static const int significand_bits = 23;
|
||||
static const int exponent_bits = 8;
|
||||
static const int min_exponent = -126;
|
||||
static const int max_exponent = 127;
|
||||
@ -1249,7 +1248,6 @@ template <> struct float_info<float> {
|
||||
|
||||
template <> struct float_info<double> {
|
||||
using carrier_uint = uint64_t;
|
||||
static const int significand_bits = 52;
|
||||
static const int exponent_bits = 11;
|
||||
static const int min_exponent = -1022;
|
||||
static const int max_exponent = 1023;
|
||||
@ -1275,7 +1273,6 @@ template <typename T>
|
||||
struct float_info<T, enable_if_t<std::is_same<T, long double>::value &&
|
||||
std::numeric_limits<T>::digits == 64>> {
|
||||
using carrier_uint = detail::uint128_t;
|
||||
static const int significand_bits = 64;
|
||||
static const int exponent_bits = 15;
|
||||
};
|
||||
|
||||
@ -1288,12 +1285,22 @@ template <typename T> struct decimal_fp {
|
||||
template <typename T> FMT_API auto to_decimal(T x) noexcept -> decimal_fp<T>;
|
||||
} // namespace dragonbox
|
||||
|
||||
template <typename T>
|
||||
template <typename Float> constexpr bool has_implicit_bit() {
|
||||
return std::numeric_limits<Float>::digits != 64;
|
||||
}
|
||||
|
||||
// Returns the number of significand bits in Float excluding the implicit bit.
|
||||
template <typename Float> constexpr int num_significand_bits() {
|
||||
return std::numeric_limits<Float>::digits -
|
||||
(has_implicit_bit<Float>() ? 1 : 0);
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
constexpr auto exponent_mask() ->
|
||||
typename dragonbox::float_info<T>::carrier_uint {
|
||||
using uint = typename dragonbox::float_info<T>::carrier_uint;
|
||||
return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)
|
||||
<< dragonbox::float_info<T>::significand_bits;
|
||||
typename dragonbox::float_info<Float>::carrier_uint {
|
||||
using uint = typename dragonbox::float_info<Float>::carrier_uint;
|
||||
return ((uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1)
|
||||
<< num_significand_bits<Float>();
|
||||
}
|
||||
|
||||
// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
|
||||
@ -2178,11 +2185,9 @@ FMT_CONSTEXPR20 bool isinf(T value) {
|
||||
if (is_constant_evaluated()) {
|
||||
#if defined(__cpp_if_constexpr)
|
||||
if constexpr (std::numeric_limits<double>::is_iec559) {
|
||||
auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
|
||||
constexpr auto significand_bits =
|
||||
dragonbox::float_info<double>::significand_bits;
|
||||
auto bits = bit_cast<uint64_t>(static_cast<double>(value));
|
||||
return (bits & exponent_mask<double>()) &&
|
||||
!(bits & ((uint64_t(1) << significand_bits) - 1));
|
||||
!(bits & ((uint64_t(1) << num_significand_bits<double>()) - 1));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -227,13 +227,14 @@ TEST(fp_test, dragonbox_max_k) {
|
||||
using fmt::detail::dragonbox::floor_log10_pow2;
|
||||
using float_info = fmt::detail::dragonbox::float_info<float>;
|
||||
EXPECT_EQ(fmt::detail::const_check(float_info::max_k),
|
||||
float_info::kappa - floor_log10_pow2(float_info::min_exponent -
|
||||
float_info::significand_bits));
|
||||
float_info::kappa -
|
||||
floor_log10_pow2(float_info::min_exponent -
|
||||
fmt::detail::num_significand_bits<float>()));
|
||||
using double_info = fmt::detail::dragonbox::float_info<double>;
|
||||
EXPECT_EQ(
|
||||
fmt::detail::const_check(double_info::max_k),
|
||||
double_info::kappa - floor_log10_pow2(double_info::min_exponent -
|
||||
double_info::significand_bits));
|
||||
EXPECT_EQ(fmt::detail::const_check(double_info::max_k),
|
||||
double_info::kappa -
|
||||
floor_log10_pow2(double_info::min_exponent -
|
||||
fmt::detail::num_significand_bits<double>()));
|
||||
}
|
||||
|
||||
TEST(fp_test, get_round_direction) {
|
||||
|
Loading…
Reference in New Issue
Block a user