Skip to content

Commit a5edb7c

Browse files
committed
Introduce isnan helper
1 parent 71d4b4a commit a5edb7c

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
@@ -26,6 +26,10 @@ constexpr uint32_t F32AbsMask = 0x7fffffff;
2626
constexpr uint32_t F32SignMask = ~F32AbsMask;
2727
constexpr uint64_t F64AbsMask = 0x7fffffffffffffff;
2828
constexpr 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

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

@@ -399,7 +418,7 @@ template <typename T>
399418
inline 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>
410429
inline 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>
429448
inline 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

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

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

Comments
 (0)