@@ -25,6 +25,10 @@ constexpr uint32_t F32AbsMask = 0x7fffffff;
2525constexpr uint32_t F32SignMask = ~F32AbsMask;
2626constexpr uint64_t F64AbsMask = 0x7fffffffffffffff ;
2727constexpr uint64_t F64SignMask = ~F64AbsMask;
28+ constexpr uint32_t F32ExpMask = 0x7f800000 ;
29+ constexpr uint32_t F32FracMask = 0x007fffff ;
30+ constexpr uint64_t F64ExpMask = 0x7ff0000000000000 ;
31+ constexpr uint64_t F64FracMask = 0x000fffffffffffff ;
2832
2933template <typename T>
3034inline T read (const uint8_t *& input) noexcept
@@ -345,6 +349,21 @@ inline bit_cast_constexpr bool signbit(double value) noexcept
345349 return (bit_cast<uint64_t >(value) & F64SignMask) != 0 ;
346350}
347351
352+ template <typename T>
353+ T isnan (T value) noexcept = delete;
354+
355+ inline bit_cast_constexpr bool isnan (float value) noexcept
356+ {
357+ const auto v = bit_cast<uint32_t >(value);
358+ return ((v & F32ExpMask) == F32ExpMask) && ((v & F32FracMask) != 0 );
359+ }
360+
361+ inline bit_cast_constexpr bool isnan (double value) noexcept
362+ {
363+ const auto v = bit_cast<uint64_t >(value);
364+ return ((v & F64ExpMask) == F64ExpMask) && ((v & F64FracMask) != 0 );
365+ }
366+
348367template <typename T>
349368T fabs (T value) noexcept = delete;
350369
@@ -398,7 +417,7 @@ template <typename T>
398417inline T fceil (T value) noexcept
399418{
400419 static_assert (std::is_floating_point_v<T>);
401- if (std:: isnan (value))
420+ if (isnan (value))
402421 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
403422
404423 // The FE_INEXACT error is ignored (whenever the implementation reports it at all).
@@ -409,7 +428,7 @@ template <typename T>
409428inline T ffloor (T value) noexcept
410429{
411430 static_assert (std::is_floating_point_v<T>);
412- if (std:: isnan (value))
431+ if (isnan (value))
413432 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
414433
415434 // The FE_INEXACT error is ignored (whenever the implementation reports it at all).
@@ -428,7 +447,7 @@ template <typename T>
428447inline T ftrunc (T value) noexcept
429448{
430449 static_assert (std::is_floating_point_v<T>);
431- if (std:: isnan (value))
450+ if (isnan (value))
432451 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
433452
434453 // The FE_INEXACT error is ignored (whenever the implementation reports it at all).
@@ -440,7 +459,7 @@ T fnearest(T value) noexcept
440459{
441460 static_assert (std::is_floating_point_v<T>);
442461
443- if (std:: isnan (value))
462+ if (isnan (value))
444463 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
445464
446465 // Check if the input integer (as floating-point type) is even.
@@ -466,11 +485,11 @@ __attribute__((no_sanitize("float-divide-by-zero"))) inline constexpr T fdiv(T a
466485}
467486
468487template <typename T>
469- inline T fmin (T a, T b) noexcept
488+ inline bit_cast_constexpr T fmin (T a, T b) noexcept
470489{
471490 static_assert (std::is_floating_point_v<T>);
472491
473- if (std:: isnan (a) || std:: isnan (b))
492+ if (isnan (a) || isnan (b))
474493 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
475494
476495 if (a == 0 && b == 0 && (signbit (a) || signbit (b)))
@@ -480,11 +499,11 @@ inline T fmin(T a, T b) noexcept
480499}
481500
482501template <typename T>
483- inline T fmax (T a, T b) noexcept
502+ inline bit_cast_constexpr T fmax (T a, T b) noexcept
484503{
485504 static_assert (std::is_floating_point_v<T>);
486505
487- if (std:: isnan (a) || std:: isnan (b))
506+ if (isnan (a) || isnan (b))
488507 return std::numeric_limits<T>::quiet_NaN (); // Positive canonical NaN.
489508
490509 if (a == 0 && b == 0 && (!signbit (a) || !signbit (b)))
0 commit comments