diff --git a/include/fmt/format.h b/include/fmt/format.h index 51d830a2..eefc727d 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2164,31 +2164,34 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp, } } -template ::value)> -FMT_CONSTEXPR20 bool isinf(T value) { - if (is_constant_evaluated()) { -#if defined(__cpp_if_constexpr) - if constexpr (std::numeric_limits::is_iec559) { - auto bits = bit_cast(static_cast(value)); - return (bits & exponent_mask()) && - !(bits & ((uint64_t(1) << num_significand_bits()) - 1)); - } +#ifdef __SIZEOF_FLOAT128__ +using float128 = __float128; +#else +using float128 = void; #endif - } - return std::isinf(value); +template using is_float128 = std::is_same; + +template ::value && + !is_float128::value)> +FMT_CONSTEXPR20 bool isfinite(T value) { + if (is_constant_evaluated()) return value - value == 0; + return std::isfinite(value); +} +template ::value)> +constexpr bool isfinite(T value) { + return value - value == 0; // std::isfinite doesn't support __float128. } -template ::value)> -FMT_CONSTEXPR20 bool isfinite(T value) { - if (is_constant_evaluated()) { -#if defined(__cpp_if_constexpr) - if constexpr (std::numeric_limits::is_iec559) { - auto bits = detail::bit_cast(static_cast(value)); - return (bits & exponent_mask()) != exponent_mask(); - } -#endif - } - return std::isfinite(value); +template ::value && + !is_float128::value)> +FMT_CONSTEXPR20 bool isinf(T value) { + if (is_constant_evaluated()) return !isfinite(value) && value == value; + return std::isinf(value); +} +template ::value)> +constexpr bool isinf(T value) { + // std::isinf doesn't support __float128. + return !isfinite(value) && value == value; } template ::value)> @@ -2201,7 +2204,7 @@ FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { } #endif } - return std::signbit(value); + return std::signbit(static_cast(value)); } template void check_isfinite() { + using fmt::detail::isfinite; + EXPECT_TRUE(isfinite(Float(0.0))); + EXPECT_TRUE(isfinite(Float(42.0))); + EXPECT_TRUE(isfinite(Float(-42.0))); + EXPECT_TRUE(isfinite(Float(fmt::detail::max_value()))); + // Use double because std::numeric_limits is broken for __float128. + using limits = std::numeric_limits; + EXPECT_FALSE(isfinite(Float(limits::infinity()))); + EXPECT_FALSE(isfinite(Float(-limits::infinity()))); + EXPECT_FALSE(isfinite(Float(limits::quiet_NaN()))); + EXPECT_FALSE(isfinite(Float(-limits::quiet_NaN()))); +} + +TEST(float_test, isfinite) { + check_isfinite(); +#ifdef __SIZEOF_FLOAT128__ + check_isfinite(); +#endif +} + struct uint32_pair { uint32_t u[2]; };