@@ -26,6 +26,10 @@ constexpr uint32_t F32AbsMask = 0x7fffffff;
2626constexpr uint32_t F32SignMask = ~F32AbsMask;
2727constexpr uint64_t F64AbsMask = 0x7fffffffffffffff ;
2828constexpr uint64_t F64SignMask = ~F64AbsMask;
29+ constexpr uint32_t F32ExpMask = 0x7f800000 ;
30+ constexpr uint32_t F32FracMask = 0x007fffff ;
31+ constexpr uint64_t F64ExpMask = 0x7ff0000000000000 ;
32+ constexpr uint64_t F64FracMask = 0x000fffffffffffff ;
2933
3034template <typename T>
3135inline T read (const uint8_t *& input) noexcept
@@ -346,6 +350,21 @@ inline bit_cast_constexpr bool signbit(double value) noexcept
346350 return (bit_cast<uint64_t >(value) & F64SignMask) != 0 ;
347351}
348352
353+ template <typename T>
354+ T isnan (T value) noexcept = delete;
355+
356+ inline bit_cast_constexpr bool isnan (float value) noexcept
357+ {
358+ const auto v = bit_cast<uint32_t >(value);
359+ return ((v & F32ExpMask) == F32ExpMask) && ((v & F32FracMask) != 0 );
360+ }
361+
362+ inline bit_cast_constexpr bool isnan (double value) noexcept
363+ {
364+ const auto v = bit_cast<uint64_t >(value);
365+ return ((v & F64ExpMask) == F64ExpMask) && ((v & F64FracMask) != 0 );
366+ }
367+
349368template <typename T>
350369T fabs (T value) noexcept = delete;
351370
@@ -399,7 +418,7 @@ template <typename T>
399418inline T fceil (T value) noexcept
400419{
401420 static_assert (std::is_floating_point_v<T>);
402- if (std:: isnan (value))
421+ if (isnan (value))
403422 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
404423
405424 // The FE_INEXACT error is ignored (whenever the implementation reports it at all).
@@ -410,7 +429,7 @@ template <typename T>
410429inline T ffloor (T value) noexcept
411430{
412431 static_assert (std::is_floating_point_v<T>);
413- if (std:: isnan (value))
432+ if (isnan (value))
414433 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
415434
416435 // The FE_INEXACT error is ignored (whenever the implementation reports it at all).
@@ -429,7 +448,7 @@ template <typename T>
429448inline T ftrunc (T value) noexcept
430449{
431450 static_assert (std::is_floating_point_v<T>);
432- if (std:: isnan (value))
451+ if (isnan (value))
433452 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
434453
435454 // The FE_INEXACT error is ignored (whenever the implementation reports it at all).
@@ -441,7 +460,7 @@ T fnearest(T value) noexcept
441460{
442461 static_assert (std::is_floating_point_v<T>);
443462
444- if (std:: isnan (value))
463+ if (isnan (value))
445464 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
446465
447466 // Check if the input integer (as floating-point type) is even.
@@ -467,11 +486,11 @@ __attribute__((no_sanitize("float-divide-by-zero"))) inline constexpr T fdiv(T a
467486}
468487
469488template <typename T>
470- inline T fmin (T a, T b) noexcept
489+ inline bit_cast_constexpr T fmin (T a, T b) noexcept
471490{
472491 static_assert (std::is_floating_point_v<T>);
473492
474- if (std:: isnan (a) || std:: isnan (b))
493+ if (isnan (a) || isnan (b))
475494 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
476495
477496 if (a == 0 && b == 0 && (signbit (a) || signbit (b)))
@@ -481,11 +500,11 @@ inline T fmin(T a, T b) noexcept
481500}
482501
483502template <typename T>
484- inline T fmax (T a, T b) noexcept
503+ inline bit_cast_constexpr T fmax (T a, T b) noexcept
485504{
486505 static_assert (std::is_floating_point_v<T>);
487506
488- if (std:: isnan (a) || std:: isnan (b))
507+ if (isnan (a) || isnan (b))
489508 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
490509
491510 if (a == 0 && b == 0 && (!signbit (a) || !signbit (b)))
0 commit comments