Skip to content

Commit 18fdb1e

Browse files
committed
Introduce isnan helper
1 parent dbaaddd commit 18fdb1e

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

lib/fizzy/execute.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ constexpr uint32_t F32AbsMask = 0x7fffffff;
2525
constexpr uint32_t F32SignMask = ~F32AbsMask;
2626
constexpr uint64_t F64AbsMask = 0x7fffffffffffffff;
2727
constexpr 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

2933
template <typename T>
3034
inline 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+
348367
template <typename T>
349368
T fabs(T value) noexcept = delete;
350369

@@ -398,7 +417,7 @@ template <typename T>
398417
inline 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>
409428
inline 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>
428447
inline 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

468487
template <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

482501
template <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

Comments
 (0)