mirror of
https://github.com/fmtlib/fmt.git
synced 2025-08-01 03:34:45 +02:00
Implement isnan
This commit is contained in:
@@ -1388,15 +1388,6 @@ struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
|
|||||||
FMT_CONSTEXPR void on_duration_unit() {}
|
FMT_CONSTEXPR void on_duration_unit() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
|
||||||
inline bool isnan(T) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
|
||||||
inline bool isnan(T value) {
|
|
||||||
return std::isnan(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
inline bool isfinite(T) {
|
inline bool isfinite(T) {
|
||||||
return true;
|
return true;
|
||||||
|
@@ -1905,11 +1905,11 @@ FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
template <typename Char, typename OutputIt>
|
||||||
FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf,
|
FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan,
|
||||||
basic_format_specs<Char> specs,
|
basic_format_specs<Char> specs,
|
||||||
const float_specs& fspecs) -> OutputIt {
|
const float_specs& fspecs) -> OutputIt {
|
||||||
auto str =
|
auto str =
|
||||||
isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
|
isnan ? (fspecs.upper ? "NAN" : "nan") : (fspecs.upper ? "INF" : "inf");
|
||||||
constexpr size_t str_size = 3;
|
constexpr size_t str_size = 3;
|
||||||
auto sign = fspecs.sign;
|
auto sign = fspecs.sign;
|
||||||
auto size = str_size + (sign ? 1 : 0);
|
auto size = str_size + (sign ? 1 : 0);
|
||||||
@@ -2182,16 +2182,8 @@ constexpr bool isfinite(T value) {
|
|||||||
return value - value == 0; // std::isfinite doesn't support __float128.
|
return value - value == 0; // std::isfinite doesn't support __float128.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value &&
|
template <typename T> constexpr bool isnan(T value) {
|
||||||
!is_float128<T>::value)>
|
return value != value; // std::isnan doesn't support __float128.
|
||||||
FMT_CONSTEXPR20 bool isinf(T value) {
|
|
||||||
if (is_constant_evaluated()) return !isfinite(value) && value == value;
|
|
||||||
return std::isinf(value);
|
|
||||||
}
|
|
||||||
template <typename T, FMT_ENABLE_IF(is_float128<T>::value)>
|
|
||||||
constexpr bool isinf(T value) {
|
|
||||||
// std::isinf doesn't support __float128.
|
|
||||||
return !isfinite(value) && value == value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||||
@@ -2200,7 +2192,7 @@ FMT_INLINE FMT_CONSTEXPR bool signbit(T value) {
|
|||||||
#ifdef __cpp_if_constexpr
|
#ifdef __cpp_if_constexpr
|
||||||
if constexpr (std::numeric_limits<double>::is_iec559) {
|
if constexpr (std::numeric_limits<double>::is_iec559) {
|
||||||
auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
|
auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
|
||||||
return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0;
|
return (bits >> (num_bits<uint64_t>() - 1)) != 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -2223,7 +2215,7 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!detail::isfinite(value))
|
if (!detail::isfinite(value))
|
||||||
return write_nonfinite(out, detail::isinf(value), specs, fspecs);
|
return write_nonfinite(out, detail::isnan(value), specs, fspecs);
|
||||||
|
|
||||||
if (specs.align == align::numeric && fspecs.sign) {
|
if (specs.align == align::numeric && fspecs.sign) {
|
||||||
auto it = reserve(out, 1);
|
auto it = reserve(out, 1);
|
||||||
@@ -2279,7 +2271,7 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
|
|||||||
constexpr auto specs = basic_format_specs<Char>();
|
constexpr auto specs = basic_format_specs<Char>();
|
||||||
uint mask = exponent_mask<floaty>();
|
uint mask = exponent_mask<floaty>();
|
||||||
if ((bits & mask) == mask)
|
if ((bits & mask) == mask)
|
||||||
return write_nonfinite(out, std::isinf(value), specs, fspecs);
|
return write_nonfinite(out, std::isnan(value), specs, fspecs);
|
||||||
|
|
||||||
auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
|
auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
|
||||||
return write_float(out, dec, specs, fspecs, {});
|
return write_float(out, dec, specs, fspecs, {});
|
||||||
|
@@ -87,6 +87,27 @@ TEST(float_test, isfinite) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Float> void check_isnan() {
|
||||||
|
using fmt::detail::isnan;
|
||||||
|
EXPECT_FALSE(isnan(Float(0.0)));
|
||||||
|
EXPECT_FALSE(isnan(Float(42.0)));
|
||||||
|
EXPECT_FALSE(isnan(Float(-42.0)));
|
||||||
|
EXPECT_FALSE(isnan(Float(fmt::detail::max_value<double>())));
|
||||||
|
// Use double because std::numeric_limits is broken for __float128.
|
||||||
|
using limits = std::numeric_limits<double>;
|
||||||
|
EXPECT_FALSE(isnan(Float(limits::infinity())));
|
||||||
|
EXPECT_FALSE(isnan(Float(-limits::infinity())));
|
||||||
|
EXPECT_TRUE(isnan(Float(limits::quiet_NaN())));
|
||||||
|
EXPECT_TRUE(isnan(Float(-limits::quiet_NaN())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(float_test, isnan) {
|
||||||
|
check_isnan<double>();
|
||||||
|
#ifdef __SIZEOF_FLOAT128__
|
||||||
|
check_isnan<fmt::detail::float128>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
struct uint32_pair {
|
struct uint32_pair {
|
||||||
uint32_t u[2];
|
uint32_t u[2];
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user