diff --git a/include/fast_float/decimal_to_binary.h b/include/fast_float/decimal_to_binary.h index b9b96f4..a7ee289 100644 --- a/include/fast_float/decimal_to_binary.h +++ b/include/fast_float/decimal_to_binary.h @@ -98,7 +98,9 @@ compute_error(int64_t q, uint64_t w) noexcept { // packed. However, in some very rare cases, the computation will fail. In such // cases, we return an adjusted_mantissa with a negative power of 2: the caller // should recompute in such cases. -template +// known_in_range: the caller knows that q is within the range of powers of +// ten, so only w == 0 is checked. +template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { adjusted_mantissa answer; @@ -107,7 +109,7 @@ compute_float(int64_t q, uint64_t w) noexcept { bool const q_out_of_range = uint64_t(q - binary::smallest_power_of_ten()) > uint64_t(binary::largest_power_of_ten() - binary::smallest_power_of_ten()); - if ((w == 0) || q_out_of_range) { + if ((w == 0) || (!known_in_range && q_out_of_range)) { bool const underflow = (w == 0) | (q < binary::smallest_power_of_ten()); answer.power2 = int32_t(!underflow) * binary::infinite_power(); answer.mantissa = 0; diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index d3856cb..0db46ec 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -445,8 +445,20 @@ from_chars_float_advanced(UC const *first, UC const *last, T &value, return answer; } +#ifdef __clang__ + // If the exponent passed Clinger's range test, it is well within range. GCC + // carries this into compute_float by itself; clang needs the instantiation + // without the range check. The mantissa can still be zero when the rounding + // mode is not to nearest. + adjusted_mantissa am = + (binary_format::min_exponent_fast_path() <= pns.exponent && + pns.exponent <= binary_format::max_exponent_fast_path()) + ? compute_float, true>(pns.exponent, pns.mantissa) + : compute_float>(pns.exponent, pns.mantissa); +#else adjusted_mantissa am = compute_float>(pns.exponent, pns.mantissa); +#endif // Slow path B (rare): Eisel-Lemire could not resolve; digit_comp needs the // integer/fraction spans. Route to the cold helper (clinger there is a // dead-effect since it already failed here; the cold re-parse + digit_comp