mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-10-28 18:07:16 +08:00
Gate the subnormal tie test on a compile-time predicate
This commit is contained in:
parent
abb4c8659a
commit
20a9b35333
@ -163,7 +163,8 @@ compute_float(int64_t q, uint64_t w) noexcept {
|
||||
// std::float16_t (e.g., 2^-25 = 298023223876953125e-25), so we apply the
|
||||
// same round-to-even test as in the normal case below.
|
||||
// See script/format_parameters.py.
|
||||
if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) &&
|
||||
if (binary::subnormal_ties_possible() && (product.low <= 1) &&
|
||||
(q >= binary::min_exponent_round_to_even()) &&
|
||||
(q <= binary::max_exponent_round_to_even()) &&
|
||||
((answer.mantissa & 3) == 1)) {
|
||||
if (((answer.mantissa << subnormal_shift) << shift) == product.high) {
|
||||
|
||||
@ -225,12 +225,16 @@ using parse_options = parse_options_t<char>;
|
||||
|
||||
#ifndef FASTFLOAT_ASSERT
|
||||
#define FASTFLOAT_ASSERT(x) \
|
||||
{ static_cast<void>(x); }
|
||||
{ \
|
||||
static_cast<void>(x); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef FASTFLOAT_DEBUG_ASSERT
|
||||
#define FASTFLOAT_DEBUG_ASSERT(x) \
|
||||
{ static_cast<void>(x); }
|
||||
{ \
|
||||
static_cast<void>(x); \
|
||||
}
|
||||
#endif
|
||||
|
||||
// rust style `try!()` macro, or `?` operator
|
||||
@ -662,6 +666,7 @@ template <typename T> struct binary_format : binary_format_lookup_tables<T> {
|
||||
static constexpr uint64_t
|
||||
max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST
|
||||
static constexpr bool fast_path_can_overflow();
|
||||
static constexpr bool subnormal_ties_possible();
|
||||
static constexpr int largest_power_of_ten();
|
||||
static constexpr int smallest_power_of_ten();
|
||||
static constexpr T exact_power_of_ten(int64_t power);
|
||||
@ -1110,6 +1115,15 @@ inline constexpr bool binary_format<T>::fast_path_can_overflow() {
|
||||
double((std::numeric_limits<T>::max)());
|
||||
}
|
||||
|
||||
// A subnormal needs w * 10^q < 2^(minimum_exponent() + 1), so q is at most
|
||||
// (minimum_exponent() + 1) * log10(2), with 1233/4096 < log10(2). Only
|
||||
// std::float16_t has such q in its round-to-even range.
|
||||
template <typename T>
|
||||
inline constexpr bool binary_format<T>::subnormal_ties_possible() {
|
||||
return min_exponent_round_to_even() <=
|
||||
(((minimum_exponent() + 1) * 1233) >> 12);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline constexpr uint64_t
|
||||
binary_format<double>::max_mantissa_fast_path(int64_t power) {
|
||||
|
||||
@ -310,6 +310,11 @@ def check_ties(fmt):
|
||||
check(lo <= min(sub), "and the subnormal ties at q in [%d, %d]" % (min(sub), max(sub)))
|
||||
else:
|
||||
note("no subnormal tie has fewer than 20 digits")
|
||||
# subnormal_ties_possible() in float_common.h: an upper bound on the
|
||||
# largest q that can give a subnormal, compared with the tie range
|
||||
q_sub = ((fmt.minimum_exponent + 1) * 1233) >> 12
|
||||
check(10**q_sub < 2**fmt.emin < 10 ** (q_sub + 2), "q <= %d bounds the subnormal exponents" % q_sub)
|
||||
check((lo <= q_sub) == bool(sub), "subnormal_ties_possible() == %s" % bool(sub))
|
||||
longest = len(str(((1 << (p + 2)) - 1) * 5**fmt.bias))
|
||||
check(fmt.max_digits >= longest, "max_digits=%d >= %d, the longest tie" % (fmt.max_digits, longest))
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user