[clang] [libcxx] [libcxxabi] [llvm] [compiler-rt] [lld] [clang-tools-extra] [libc] [flang] [libc][math] Add min/max/min_denorm/max_denorm constants to FPBits and clean up its constants return types. (PR #71298)

via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 6 15:11:17 PST 2023


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/71298

>From e2142963eccd2ff4d3a0869445064f798fba1ff7 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Sat, 4 Nov 2023 21:29:04 +0000
Subject: [PATCH 1/2] [libc][math] Add min/max/min_denorm/max_denorm constants
 to FPBits and clean up its constants return types.

---
 libc/src/__support/FPUtil/FPBits.h            |  38 +-
 .../src/__support/FPUtil/except_value_utils.h |   4 +-
 libc/src/__support/FPUtil/generic/FMod.h      |   6 +-
 .../__support/FPUtil/x86_64/LongDoubleBits.h  |  91 ++---
 libc/src/__support/str_to_float.h             |   4 +-
 libc/src/math/generic/atanhf.cpp              |   2 +-
 libc/src/math/generic/coshf.cpp               |   4 +-
 libc/src/math/generic/exp2f.cpp               |   2 +-
 libc/src/math/generic/sinhf.cpp               |   2 +-
 libc/test/UnitTest/FPMatcher.h                |  30 +-
 .../test/src/__support/FPUtil/fpbits_test.cpp | 105 +++---
 libc/test/src/math/CMakeLists.txt             |   4 -
 libc/test/src/math/FModTest.h                 | 327 ++++++++----------
 libc/test/src/math/smoke/CMakeLists.txt       |   4 -
 libc/test/src/math/smoke/FModTest.h           | 327 ++++++++----------
 libc/test/src/stdio/sprintf_test.cpp          |  11 +-
 libc/test/src/stdio/sscanf_test.cpp           |   8 +-
 17 files changed, 474 insertions(+), 495 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index b423ba41f11c4be..37e9bc9cfc84c3a 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -114,7 +114,7 @@ template <typename T> struct FPBits {
             cpp::enable_if_t<cpp::is_same_v<XType, UIntType>, int> = 0>
   constexpr explicit FPBits(XType x) : bits(x) {}
 
-  FPBits() : bits(0) {}
+  constexpr FPBits() : bits(0) {}
 
   LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(bits); }
 
@@ -169,30 +169,38 @@ template <typename T> struct FPBits {
     return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK;
   }
 
-  LIBC_INLINE static constexpr FPBits<T> zero(bool sign = false) {
-    return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0));
+  LIBC_INLINE static constexpr T zero(bool sign = false) {
+    return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0)).get_val();
   }
 
-  LIBC_INLINE static constexpr FPBits<T> neg_zero() { return zero(true); }
+  LIBC_INLINE static constexpr T neg_zero() { return zero(true); }
 
-  LIBC_INLINE static constexpr FPBits<T> inf(bool sign = false) {
-    FPBits<T> bits(sign ? FloatProp::SIGN_MASK : UIntType(0));
-    bits.set_unbiased_exponent(MAX_EXPONENT);
-    return bits;
+  LIBC_INLINE static constexpr T inf(bool sign = false) {
+    return FPBits((sign ? FloatProp::SIGN_MASK : UIntType(0)) |
+                  FloatProp::EXPONENT_MASK)
+        .get_val();
   }
 
-  LIBC_INLINE static constexpr FPBits<T> neg_inf() {
-    FPBits<T> bits = inf();
-    bits.set_sign(1);
-    return bits;
+  LIBC_INLINE static constexpr T neg_inf() { return inf(true); }
+
+  LIBC_INLINE static constexpr T min_normal() {
+    return FPBits(MIN_NORMAL).get_val();
+  }
+
+  LIBC_INLINE static constexpr T max_normal() {
+    return FPBits(MAX_NORMAL).get_val();
+  }
+
+  LIBC_INLINE static constexpr T min_denormal() {
+    return FPBits(MIN_SUBNORMAL).get_val();
   }
 
-  LIBC_INLINE static constexpr FPBits<T> min_normal() {
-    return FPBits<T>(MIN_NORMAL);
+  LIBC_INLINE static constexpr T max_denormal() {
+    return FPBits(MAX_SUBNORMAL).get_val();
   }
 
   LIBC_INLINE static constexpr T build_nan(UIntType v) {
-    FPBits<T> bits = inf();
+    FPBits<T> bits(inf());
     bits.set_mantissa(v);
     return T(bits);
   }
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 58c3545afe0dab2..7560e59792e46ee 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -102,14 +102,14 @@ template <typename T, size_t N> struct ExceptValues {
 // Helper functions to set results for exceptional cases.
 template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
   volatile T tmp = value_rn;
-  const T MIN_NORMAL = FPBits<T>::min_normal().get_val();
+  const T MIN_NORMAL = FPBits<T>::min_normal();
   tmp = tmp - MIN_NORMAL;
   return tmp;
 }
 
 template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
   volatile T tmp = value_rn;
-  const T MIN_NORMAL = FPBits<T>::min_normal().get_val();
+  const T MIN_NORMAL = FPBits<T>::min_normal();
   tmp = tmp + MIN_NORMAL;
   return tmp;
 }
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 48906e545a89ba3..ff320f36ee2277b 100644
--- a/libc/src/__support/FPUtil/generic/FMod.h
+++ b/libc/src/__support/FPUtil/generic/FMod.h
@@ -230,7 +230,7 @@ class FMod {
     if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) {
       if (sx.uintval() < sy.uintval())
         return sx;        // |x|<|y| return x
-      return FPB::zero(); // |x|=|y| return 0.0
+      return FPB(FPB::zero()); // |x|=|y| return 0.0
     }
 
     int e_x = sx.get_unbiased_exponent();
@@ -243,7 +243,7 @@ class FMod {
       intU_t m_y = sy.get_explicit_mantissa();
       intU_t d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
       if (d == 0)
-        return FPB::zero();
+        return FPB(FPB::zero());
       // iy - 1 because of "zero power" for number with power 1
       return FPB::make_value(d, e_y - 1);
     }
@@ -291,7 +291,7 @@ class FMod {
 
     m_x %= m_y;
     if (LIBC_UNLIKELY(m_x == 0))
-      return FPB::zero();
+      return FPB(FPB::zero());
 
     if (exp_diff == 0)
       return FPB::make_value(m_x, e_y);
diff --git a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
index 085c19638122b55..f2ac1b3f22933e2 100644
--- a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
+++ b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
@@ -56,21 +56,21 @@ template <> struct FPBits<long double> {
 
   UIntType bits;
 
-  LIBC_INLINE void set_mantissa(UIntType mantVal) {
+  LIBC_INLINE constexpr void set_mantissa(UIntType mantVal) {
     mantVal &= (FloatProp::MANTISSA_MASK);
     bits &= ~(FloatProp::MANTISSA_MASK);
     bits |= mantVal;
   }
 
-  LIBC_INLINE UIntType get_mantissa() const {
+  LIBC_INLINE constexpr UIntType get_mantissa() const {
     return bits & FloatProp::MANTISSA_MASK;
   }
 
-  LIBC_INLINE UIntType get_explicit_mantissa() const {
+  LIBC_INLINE constexpr UIntType get_explicit_mantissa() const {
     return bits & (FloatProp::MANTISSA_MASK | FloatProp::EXPLICIT_BIT_MASK);
   }
 
-  LIBC_INLINE void set_unbiased_exponent(UIntType expVal) {
+  LIBC_INLINE constexpr void set_unbiased_exponent(UIntType expVal) {
     expVal =
         (expVal << (FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH)) &
         FloatProp::EXPONENT_MASK;
@@ -78,36 +78,36 @@ template <> struct FPBits<long double> {
     bits |= expVal;
   }
 
-  LIBC_INLINE uint16_t get_unbiased_exponent() const {
+  LIBC_INLINE constexpr uint16_t get_unbiased_exponent() const {
     return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
                     (FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH));
   }
 
-  LIBC_INLINE void set_implicit_bit(bool implicitVal) {
+  LIBC_INLINE constexpr void set_implicit_bit(bool implicitVal) {
     bits &= ~(UIntType(1) << FloatProp::MANTISSA_WIDTH);
     bits |= (UIntType(implicitVal) << FloatProp::MANTISSA_WIDTH);
   }
 
-  LIBC_INLINE bool get_implicit_bit() const {
+  LIBC_INLINE constexpr bool get_implicit_bit() const {
     return bool((bits & (UIntType(1) << FloatProp::MANTISSA_WIDTH)) >>
                 FloatProp::MANTISSA_WIDTH);
   }
 
-  LIBC_INLINE void set_sign(bool signVal) {
+  LIBC_INLINE constexpr void set_sign(bool signVal) {
     bits &= ~(FloatProp::SIGN_MASK);
     UIntType sign1 = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1);
     bits |= sign1;
   }
 
-  LIBC_INLINE bool get_sign() const {
+  LIBC_INLINE constexpr bool get_sign() const {
     return bool((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1));
   }
 
-  FPBits() : bits(0) {}
+  constexpr FPBits() : bits(0) {}
 
   template <typename XType,
             cpp::enable_if_t<cpp::is_same_v<long double, XType>, int> = 0>
-  explicit FPBits(XType x) : bits(cpp::bit_cast<UIntType>(x)) {
+  constexpr explicit FPBits(XType x) : bits(cpp::bit_cast<UIntType>(x)) {
     // bits starts uninitialized, and setting it to a long double only
     // overwrites the first 80 bits. This clears those upper bits.
     bits = bits & ((UIntType(1) << 80) - 1);
@@ -115,26 +115,26 @@ template <> struct FPBits<long double> {
 
   template <typename XType,
             cpp::enable_if_t<cpp::is_same_v<XType, UIntType>, int> = 0>
-  explicit FPBits(XType x) : bits(x) {}
+  constexpr explicit FPBits(XType x) : bits(x) {}
 
-  LIBC_INLINE operator long double() {
+  LIBC_INLINE constexpr operator long double() {
     return cpp::bit_cast<long double>(bits);
   }
 
-  LIBC_INLINE UIntType uintval() {
+  LIBC_INLINE constexpr UIntType uintval() {
     // We zero the padding bits as they can contain garbage.
-    static constexpr UIntType MASK =
+    constexpr UIntType MASK =
         (UIntType(1) << (sizeof(long double) * 8 -
                          Padding<sizeof(uintptr_t)>::VALUE)) -
         1;
     return bits & MASK;
   }
 
-  LIBC_INLINE long double get_val() const {
+  LIBC_INLINE constexpr long double get_val() const {
     return cpp::bit_cast<long double>(bits);
   }
 
-  LIBC_INLINE int get_exponent() const {
+  LIBC_INLINE constexpr int get_exponent() const {
     return int(get_unbiased_exponent()) - EXPONENT_BIAS;
   }
 
@@ -144,7 +144,7 @@ template <> struct FPBits<long double> {
   // values are calculated from the exponent, since just subtracting the bias
   // will give a slightly incorrect result. Additionally, zero has an exponent
   // of zero, and that should actually be treated as zero.
-  LIBC_INLINE int get_explicit_exponent() const {
+  LIBC_INLINE constexpr int get_explicit_exponent() const {
     const int unbiased_exp = int(get_unbiased_exponent());
     if (is_zero()) {
       return 0;
@@ -155,17 +155,17 @@ template <> struct FPBits<long double> {
     }
   }
 
-  LIBC_INLINE bool is_zero() const {
+  LIBC_INLINE constexpr bool is_zero() const {
     return get_unbiased_exponent() == 0 && get_mantissa() == 0 &&
            get_implicit_bit() == 0;
   }
 
-  LIBC_INLINE bool is_inf() const {
+  LIBC_INLINE constexpr bool is_inf() const {
     return get_unbiased_exponent() == MAX_EXPONENT && get_mantissa() == 0 &&
            get_implicit_bit() == 1;
   }
 
-  LIBC_INLINE bool is_nan() const {
+  LIBC_INLINE constexpr bool is_nan() const {
     if (get_unbiased_exponent() == MAX_EXPONENT) {
       return (get_implicit_bit() == 0) || get_mantissa() != 0;
     } else if (get_unbiased_exponent() != 0) {
@@ -174,39 +174,30 @@ template <> struct FPBits<long double> {
     return false;
   }
 
-  LIBC_INLINE bool is_inf_or_nan() const {
+  LIBC_INLINE constexpr bool is_inf_or_nan() const {
     return (get_unbiased_exponent() == MAX_EXPONENT) ||
            (get_unbiased_exponent() != 0 && get_implicit_bit() == 0);
   }
 
   // Methods below this are used by tests.
 
-  LIBC_INLINE static FPBits<long double> zero() {
-    return FPBits<long double>(0.0l);
-  }
+  LIBC_INLINE static constexpr long double zero() { return 0.0l; }
 
-  LIBC_INLINE static FPBits<long double> neg_zero() {
-    FPBits<long double> bits(0.0l);
-    bits.set_sign(1);
-    return bits;
-  }
+  LIBC_INLINE static constexpr long double neg_zero() { return -0.0l; }
 
-  LIBC_INLINE static FPBits<long double> inf() {
+  LIBC_INLINE static constexpr long double inf(bool sign = false) {
     FPBits<long double> bits(0.0l);
     bits.set_unbiased_exponent(MAX_EXPONENT);
     bits.set_implicit_bit(1);
-    return bits;
+    if (sign) {
+      bits.set_sign(true);
+    }
+    return bits.get_val();
   }
 
-  LIBC_INLINE static FPBits<long double> neg_inf() {
-    FPBits<long double> bits(0.0l);
-    bits.set_unbiased_exponent(MAX_EXPONENT);
-    bits.set_implicit_bit(1);
-    bits.set_sign(1);
-    return bits;
-  }
+  LIBC_INLINE static constexpr long double neg_inf() { return inf(true); }
 
-  LIBC_INLINE static long double build_nan(UIntType v) {
+  LIBC_INLINE static constexpr long double build_nan(UIntType v) {
     FPBits<long double> bits(0.0l);
     bits.set_unbiased_exponent(MAX_EXPONENT);
     bits.set_implicit_bit(1);
@@ -214,11 +205,27 @@ template <> struct FPBits<long double> {
     return bits;
   }
 
-  LIBC_INLINE static long double build_quiet_nan(UIntType v) {
+  LIBC_INLINE static constexpr long double build_quiet_nan(UIntType v) {
     return build_nan(FloatProp::QUIET_NAN_MASK | v);
   }
 
-  LIBC_INLINE static FPBits<long double>
+  LIBC_INLINE static constexpr long double min_normal() {
+    return FPBits(MIN_NORMAL).get_val();
+  }
+
+  LIBC_INLINE static constexpr long double max_normal() {
+    return FPBits(MAX_NORMAL).get_val();
+  }
+
+  LIBC_INLINE static constexpr long double min_denormal() {
+    return FPBits(MIN_SUBNORMAL).get_val();
+  }
+
+  LIBC_INLINE static constexpr long double max_denormal() {
+    return FPBits(MAX_SUBNORMAL).get_val();
+  }
+
+  LIBC_INLINE static constexpr FPBits<long double>
   create_value(bool sign, UIntType unbiased_exp, UIntType mantissa) {
     FPBits<long double> result;
     result.set_sign(sign);
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index db50090ec4e1296..e827e3322fac11f 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1220,9 +1220,9 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
         tolower(src[index + 2]) == inf_string[2]) {
       seen_digit = true;
       if (result.get_sign())
-        result = result.neg_inf();
+        result = fputil::FPBits<T>(result.neg_inf());
       else
-        result = result.inf();
+        result = fputil::FPBits<T>(result.inf());
       if (tolower(src[index + 3]) == inf_string[3] &&
           tolower(src[index + 4]) == inf_string[4] &&
           tolower(src[index + 5]) == inf_string[5] &&
diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp
index 58e7f234b2c55b7..839ef5b076ac355 100644
--- a/libc/src/math/generic/atanhf.cpp
+++ b/libc/src/math/generic/atanhf.cpp
@@ -28,7 +28,7 @@ LLVM_LIBC_FUNCTION(float, atanhf, (float x)) {
     if (x_abs == 0x3F80'0000U) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits::inf(sign).get_val();
+      return FPBits::inf(sign);
     } else {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp
index 62d77867f26f19c..8bfcfa82e972bc3 100644
--- a/libc/src/math/generic/coshf.cpp
+++ b/libc/src/math/generic/coshf.cpp
@@ -31,7 +31,7 @@ LLVM_LIBC_FUNCTION(float, coshf, (float x)) {
     }
 
     if (xbits.is_inf_or_nan())
-      return x + FPBits::inf().get_val();
+      return x + FPBits::inf();
 
     int rounding = fputil::quick_get_round();
     if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
@@ -40,7 +40,7 @@ LLVM_LIBC_FUNCTION(float, coshf, (float x)) {
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
 
-    return x + FPBits::inf().get_val();
+    return x + FPBits::inf();
   }
 
   // TODO: We should be able to reduce the latency and reciprocal throughput
diff --git a/libc/src/math/generic/exp2f.cpp b/libc/src/math/generic/exp2f.cpp
index fc91dfdfe95afa0..122cea0f6e837da 100644
--- a/libc/src/math/generic/exp2f.cpp
+++ b/libc/src/math/generic/exp2f.cpp
@@ -80,7 +80,7 @@ LLVM_LIBC_FUNCTION(float, exp2f, (float x)) {
         fputil::raise_except_if_required(FE_OVERFLOW);
       }
       // x is +inf or nan
-      return x + FPBits::inf().get_val();
+      return x + FPBits::inf();
     }
     // x <= -150
     if (x_u >= 0xc316'0000U) {
diff --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp
index 4917b9980bc6618..2f48ddbc0f88d3c 100644
--- a/libc/src/math/generic/sinhf.cpp
+++ b/libc/src/math/generic/sinhf.cpp
@@ -67,7 +67,7 @@ LLVM_LIBC_FUNCTION(float, sinhf, (float x)) {
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
 
-    return x + FPBits::inf(sign).get_val();
+    return x + FPBits::inf(sign);
   }
 
   // sinh(x) = (e^x - e^(-x)) / 2.
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 14c8a85ba7ad480..321fc18f51b277c 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -62,11 +62,16 @@ template <TestCond C, typename T> FPMatcher<T, C> getMatcher(T expectedValue) {
 template <typename T> struct FPTest : public Test {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
   using UIntType = typename FPBits::UIntType;
-  static constexpr T zero = T(FPBits::zero());
-  static constexpr T neg_zero = T(FPBits::neg_zero());
-  static constexpr T aNaN = T(FPBits::build_quiet_nan(1));
-  static constexpr T inf = T(FPBits::inf());
-  static constexpr T neg_inf = T(FPBits::neg_inf());
+  static constexpr T zero = FPBits::zero();
+  static constexpr T neg_zero = FPBits::neg_zero();
+  static constexpr T aNaN = FPBits::build_quiet_nan(1);
+  static constexpr T sNaN = FPBits::build_nan(1);
+  static constexpr T inf = FPBits::inf();
+  static constexpr T neg_inf = FPBits::neg_inf();
+  static constexpr T min_normal = FPBits::min_normal();
+  static constexpr T max_normal = FPBits::max_normal();
+  static constexpr T min_denormal = FPBits::min_denormal();
+  static constexpr T max_denormal = FPBits::max_denormal();
 };
 
 } // namespace testing
@@ -75,11 +80,16 @@ template <typename T> struct FPTest : public Test {
 #define DECLARE_SPECIAL_CONSTANTS(T)                                           \
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;                            \
   using UIntType = typename FPBits::UIntType;                                  \
-  const T zero = T(FPBits::zero());                                            \
-  const T neg_zero = T(FPBits::neg_zero());                                    \
-  const T aNaN = T(FPBits::build_quiet_nan(1));                                \
-  const T inf = T(FPBits::inf());                                              \
-  const T neg_inf = T(FPBits::neg_inf());
+  const T zero = FPBits::zero();                                               \
+  const T neg_zero = FPBits::neg_zero();                                       \
+  const T aNaN = FPBits::build_quiet_nan(1);                                   \
+  const T sNaN = FPBits::build_nan(1);                                         \
+  const T inf = FPBits::inf();                                                 \
+  const T neg_inf = FPBits::neg_inf();                                         \
+  const T min_normal = FPBits::min_normal();                                   \
+  const T max_normal = FPBits::max_normal();                                   \
+  const T min_denormal = FPBits::min_denormal();                               \
+  const T max_denormal = FPBits::max_denormal();
 
 #define EXPECT_FP_EQ(expected, actual)                                         \
   EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcher<                     \
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index 916523e28266935..5c97ba3a70ca795 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -13,15 +13,16 @@
 using LIBC_NAMESPACE::fputil::FPBits;
 
 TEST(LlvmLibcFPBitsTest, FloatType) {
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<float>::inf()).c_str(),
+  using FloatBits = FPBits<float>;
+
+  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits(FloatBits::inf())).c_str(),
                "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<float>::neg_inf()).c_str(),
+  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits(FloatBits::neg_inf())).c_str(),
                "(-Infinity)");
-  EXPECT_STREQ(
-      LIBC_NAMESPACE::str(FPBits<float>(FPBits<float>::build_nan(1))).c_str(),
-      "(NaN)");
+  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits(FloatBits::build_nan(1))).c_str(),
+               "(NaN)");
 
-  FPBits<float> zero(0.0f);
+  FloatBits zero(0.0f);
   EXPECT_EQ(zero.get_sign(), false);
   EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0));
   EXPECT_EQ(zero.get_mantissa(), static_cast<uint32_t>(0));
@@ -29,7 +30,7 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
                "0x00000000 = (S: 0, E: 0x0000, M: 0x00000000)");
 
-  FPBits<float> negzero(-0.0f);
+  FloatBits negzero(-0.0f);
   EXPECT_EQ(negzero.get_sign(), true);
   EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0));
   EXPECT_EQ(negzero.get_mantissa(), static_cast<uint32_t>(0));
@@ -37,7 +38,7 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
                "0x80000000 = (S: 1, E: 0x0000, M: 0x00000000)");
 
-  FPBits<float> one(1.0f);
+  FloatBits one(1.0f);
   EXPECT_EQ(one.get_sign(), false);
   EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
   EXPECT_EQ(one.get_mantissa(), static_cast<uint32_t>(0));
@@ -45,7 +46,7 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
                "0x3F800000 = (S: 0, E: 0x007F, M: 0x00000000)");
 
-  FPBits<float> negone(-1.0f);
+  FloatBits negone(-1.0f);
   EXPECT_EQ(negone.get_sign(), true);
   EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
   EXPECT_EQ(negone.get_mantissa(), static_cast<uint32_t>(0));
@@ -53,7 +54,7 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
                "0xBF800000 = (S: 1, E: 0x007F, M: 0x00000000)");
 
-  FPBits<float> num(1.125f);
+  FloatBits num(1.125f);
   EXPECT_EQ(num.get_sign(), false);
   EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
   EXPECT_EQ(num.get_mantissa(), static_cast<uint32_t>(0x00100000));
@@ -61,7 +62,7 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
                "0x3F900000 = (S: 0, E: 0x007F, M: 0x00100000)");
 
-  FPBits<float> negnum(-1.125f);
+  FloatBits negnum(-1.125f);
   EXPECT_EQ(negnum.get_sign(), true);
   EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
   EXPECT_EQ(negnum.get_mantissa(), static_cast<uint32_t>(0x00100000));
@@ -71,15 +72,17 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
 }
 
 TEST(LlvmLibcFPBitsTest, DoubleType) {
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<double>::inf()).c_str(),
+  using DoubleBits = FPBits<double>;
+
+  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits(DoubleBits::inf())).c_str(),
                "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<double>::neg_inf()).c_str(),
+  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits(DoubleBits::neg_inf())).c_str(),
                "(-Infinity)");
   EXPECT_STREQ(
-      LIBC_NAMESPACE::str(FPBits<double>(FPBits<double>::build_nan(1))).c_str(),
+      LIBC_NAMESPACE::str(DoubleBits(DoubleBits::build_nan(1))).c_str(),
       "(NaN)");
 
-  FPBits<double> zero(0.0);
+  DoubleBits zero(0.0);
   EXPECT_EQ(zero.get_sign(), false);
   EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(zero.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
@@ -87,7 +90,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
                "0x0000000000000000 = (S: 0, E: 0x0000, M: 0x0000000000000000)");
 
-  FPBits<double> negzero(-0.0);
+  DoubleBits negzero(-0.0);
   EXPECT_EQ(negzero.get_sign(), true);
   EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(negzero.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
@@ -95,7 +98,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
                "0x8000000000000000 = (S: 1, E: 0x0000, M: 0x0000000000000000)");
 
-  FPBits<double> one(1.0);
+  DoubleBits one(1.0);
   EXPECT_EQ(one.get_sign(), false);
   EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
   EXPECT_EQ(one.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
@@ -103,7 +106,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
                "0x3FF0000000000000 = (S: 0, E: 0x03FF, M: 0x0000000000000000)");
 
-  FPBits<double> negone(-1.0);
+  DoubleBits negone(-1.0);
   EXPECT_EQ(negone.get_sign(), true);
   EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
   EXPECT_EQ(negone.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
@@ -111,7 +114,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
                "0xBFF0000000000000 = (S: 1, E: 0x03FF, M: 0x0000000000000000)");
 
-  FPBits<double> num(1.125);
+  DoubleBits num(1.125);
   EXPECT_EQ(num.get_sign(), false);
   EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
   EXPECT_EQ(num.get_mantissa(), static_cast<uint64_t>(0x0002000000000000));
@@ -119,7 +122,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
                "0x3FF2000000000000 = (S: 0, E: 0x03FF, M: 0x0002000000000000)");
 
-  FPBits<double> negnum(-1.125);
+  DoubleBits negnum(-1.125);
   EXPECT_EQ(negnum.get_sign(), true);
   EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
   EXPECT_EQ(negnum.get_mantissa(), static_cast<uint64_t>(0x0002000000000000));
@@ -130,19 +133,22 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
 
 #ifdef LIBC_TARGET_ARCH_IS_X86
 TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
+  using LongDoubleBits = FPBits<long double>;
+
   if constexpr (sizeof(long double) == sizeof(double))
     return; // The tests for the "double" type cover for this case.
 
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<long double>::inf()).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<long double>::neg_inf()).c_str(),
-               "(-Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(
-                   FPBits<long double>(FPBits<long double>::build_nan(1)))
-                   .c_str(),
-               "(NaN)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf())).c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::neg_inf())).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::build_nan(1))).c_str(),
+      "(NaN)");
 
-  FPBits<long double> zero(0.0l);
+  LongDoubleBits zero(0.0l);
   EXPECT_EQ(zero.get_sign(), false);
   EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -153,7 +159,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
       "0x00000000000000000000000000000000 = "
       "(S: 0, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> negzero(-0.0l);
+  LongDoubleBits negzero(-0.0l);
   EXPECT_EQ(negzero.get_sign(), true);
   EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -164,7 +170,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
       "0x00000000000080000000000000000000 = "
       "(S: 1, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> one(1.0l);
+  LongDoubleBits one(1.0l);
   EXPECT_EQ(one.get_sign(), false);
   EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(one.get_mantissa(), static_cast<UInt128>(0x0000000000000000) << 64);
@@ -174,7 +180,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
       "0x0000000000003FFF8000000000000000 = "
       "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> negone(-1.0l);
+  LongDoubleBits negone(-1.0l);
   EXPECT_EQ(negone.get_sign(), true);
   EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(negone.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -185,7 +191,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
       "0x000000000000BFFF8000000000000000 = "
       "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> num(1.125l);
+  LongDoubleBits num(1.125l);
   EXPECT_EQ(num.get_sign(), false);
   EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(num.get_mantissa(), static_cast<UInt128>(0x1) << 60);
@@ -195,7 +201,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
       "0x0000000000003FFF9000000000000000 = "
       "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)");
 
-  FPBits<long double> negnum(-1.125l);
+  LongDoubleBits negnum(-1.125l);
   EXPECT_EQ(negnum.get_sign(), true);
   EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(negnum.get_mantissa(), static_cast<UInt128>(0x1) << 60);
@@ -210,16 +216,19 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
 #if defined(LONG_DOUBLE_IS_DOUBLE)
   return; // The tests for the "double" type cover for this case.
 #else
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<long double>::inf()).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FPBits<long double>::neg_inf()).c_str(),
-               "(-Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(
-                   FPBits<long double>(FPBits<long double>::build_nan(1)))
-                   .c_str(),
-               "(NaN)");
+  using LongDoubleBits = FPBits<long double>;
+
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf())).c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::neg_inf())).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::build_nan(1))).c_str(),
+      "(NaN)");
 
-  FPBits<long double> zero(0.0l);
+  LongDoubleBits zero(0.0l);
   EXPECT_EQ(zero.get_sign(), false);
   EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -229,7 +238,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
                "0x00000000000000000000000000000000 = "
                "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> negzero(-0.0l);
+  LongDoubleBits negzero(-0.0l);
   EXPECT_EQ(negzero.get_sign(), true);
   EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -239,7 +248,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
                "0x80000000000000000000000000000000 = "
                "(S: 1, E: 0x0000, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> one(1.0l);
+  LongDoubleBits one(1.0l);
   EXPECT_EQ(one.get_sign(), false);
   EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(one.get_mantissa(), static_cast<UInt128>(0x0000000000000000) << 64);
@@ -248,7 +257,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
                "0x3FFF0000000000000000000000000000 = "
                "(S: 0, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> negone(-1.0l);
+  LongDoubleBits negone(-1.0l);
   EXPECT_EQ(negone.get_sign(), true);
   EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(negone.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -258,7 +267,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
                "0xBFFF0000000000000000000000000000 = "
                "(S: 1, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
 
-  FPBits<long double> num(1.125l);
+  LongDoubleBits num(1.125l);
   EXPECT_EQ(num.get_sign(), false);
   EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(num.get_mantissa(), static_cast<UInt128>(0x2) << 108);
@@ -267,7 +276,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
                "0x3FFF2000000000000000000000000000 = "
                "(S: 0, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
 
-  FPBits<long double> negnum(-1.125l);
+  LongDoubleBits negnum(-1.125l);
   EXPECT_EQ(negnum.get_sign(), true);
   EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
   EXPECT_EQ(negnum.get_mantissa(), static_cast<UInt128>(0x2) << 108);
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 2ba03676a633fff..fa3cecba7d0d989 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1462,8 +1462,6 @@ add_fp_unittest(
     libc.src.math.fmodf
     libc.src.__support.FPUtil.basic_operations
     libc.src.__support.FPUtil.nearest_integer_operations
-  # Requires C++ limits.
-  UNIT_TEST_ONLY
 )
 
 add_fp_unittest(
@@ -1480,8 +1478,6 @@ add_fp_unittest(
     libc.src.math.fmod
     libc.src.__support.FPUtil.basic_operations
     libc.src.__support.FPUtil.nearest_integer_operations
-  # Requires C++ limits.
-  UNIT_TEST_ONLY
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/FModTest.h b/libc/test/src/math/FModTest.h
index 5fc0ebf6d33e407..2b1442923268d9c 100644
--- a/libc/test/src/math/FModTest.h
+++ b/libc/test/src/math/FModTest.h
@@ -14,7 +14,6 @@
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits>
 #include <math.h>
 
 #define TEST_SPECIAL(x, y, expected, dom_err, expected_exception)              \
@@ -33,201 +32,179 @@ template <typename T> class FmodTest : public LIBC_NAMESPACE::testing::Test {
   typedef T (*FModFunc)(T, T);
 
   void testSpecialNumbers(FModFunc f) {
-    using nl = std::numeric_limits<T>;
-
     // fmod (+0, y) == +0 for y != 0.
     TEST_SPECIAL(0.0, 3.0, 0.0, false, 0);
-    TEST_SPECIAL(0.0, nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, -nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, nl::max(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, -nl::max(), 0.0, false, 0);
+    TEST_SPECIAL(0.0, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, min_normal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, -min_normal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, max_normal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, -max_normal, 0.0, false, 0);
 
     // fmod (-0, y) == -0 for y != 0.
     TEST_SPECIAL(neg_zero, 3.0, neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, -nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, -nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, nl::max(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, -nl::max(), neg_zero, false, 0);
-
-    // fmod (+inf, y) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(inf, 3.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, -1.1L, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, nl::denorm_min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, nl::min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, nl::max(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, inf, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, neg_inf, nl::quiet_NaN(), true, FE_INVALID);
-
-    // fmod (-inf, y) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(neg_inf, 3.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, -1.1L, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::denorm_min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::max(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, inf, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, neg_inf, nl::quiet_NaN(), true, FE_INVALID);
-
-    // fmod (x, +0) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(3.0, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(-1.1L, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(0.0, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_zero, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::denorm_min(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::min(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::max(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
-
-    // fmod (x, -0) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(3.0, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(-1.1L, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(0.0, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_zero, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::denorm_min(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::min(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::max(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
+    TEST_SPECIAL(neg_zero, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, -min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, -min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, max_normal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, -max_normal, neg_zero, false, 0);
+
+    // fmod (+inf, y) == aNaN plus invalid exception.
+    TEST_SPECIAL(inf, 3.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, -1.1L, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, min_denormal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, min_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, max_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, inf, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, neg_inf, aNaN, true, FE_INVALID);
+
+    // fmod (-inf, y) == aNaN plus invalid exception.
+    TEST_SPECIAL(neg_inf, 3.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, -1.1L, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, min_denormal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, min_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, max_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, inf, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, neg_inf, aNaN, true, FE_INVALID);
+
+    // fmod (x, +0) == aNaN plus invalid exception.
+    TEST_SPECIAL(3.0, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(-1.1L, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(0.0, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_zero, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_denormal, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_normal, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(max_normal, 0.0, aNaN, true, FE_INVALID);
+
+    // fmod (x, -0) == aNaN plus invalid exception.
+    TEST_SPECIAL(3.0, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(-1.1L, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(0.0, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_zero, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_denormal, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_normal, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(max_normal, neg_zero, aNaN, true, FE_INVALID);
 
     // fmod (x, +inf) == x for x not infinite.
     TEST_SPECIAL(0.0, inf, 0.0, false, 0);
     TEST_SPECIAL(neg_zero, inf, neg_zero, false, 0);
-    TEST_SPECIAL(nl::denorm_min(), inf, nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::min(), inf, nl::min(), false, 0);
-    TEST_SPECIAL(nl::max(), inf, nl::max(), false, 0);
+    TEST_SPECIAL(min_denormal, inf, min_denormal, false, 0);
+    TEST_SPECIAL(min_normal, inf, min_normal, false, 0);
+    TEST_SPECIAL(max_normal, inf, max_normal, false, 0);
     TEST_SPECIAL(3.0, inf, 3.0, false, 0);
     // fmod (x, -inf) == x for x not infinite.
     TEST_SPECIAL(0.0, neg_inf, 0.0, false, 0);
     TEST_SPECIAL(neg_zero, neg_inf, neg_zero, false, 0);
-    TEST_SPECIAL(nl::denorm_min(), neg_inf, nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::min(), neg_inf, nl::min(), false, 0);
-    TEST_SPECIAL(nl::max(), neg_inf, nl::max(), false, 0);
+    TEST_SPECIAL(min_denormal, neg_inf, min_denormal, false, 0);
+    TEST_SPECIAL(min_normal, neg_inf, min_normal, false, 0);
+    TEST_SPECIAL(max_normal, neg_inf, max_normal, false, 0);
     TEST_SPECIAL(3.0, neg_inf, 3.0, false, 0);
 
-    TEST_SPECIAL(0.0, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(0.0, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_zero, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_zero, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(1.0, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(1.0, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(inf, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(inf, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_inf, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_inf, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(0.0, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(0.0, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(neg_zero, nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(neg_zero, -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(1.0, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(1.0, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(inf, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(inf, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(neg_inf, -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::quiet_NaN(), 0.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), 0.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), neg_zero, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), neg_zero, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), 1.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), 1.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), neg_inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), neg_inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::signaling_NaN(), 0.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), 0.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), neg_zero, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), neg_zero, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), 1.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), 1.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), inf, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), inf, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), neg_inf, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), neg_inf, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::quiet_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::quiet_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::quiet_NaN(), nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::quiet_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
+    TEST_SPECIAL(0.0, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(0.0, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_zero, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_zero, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(1.0, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(1.0, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(inf, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(inf, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_inf, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_inf, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(0.0, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(0.0, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_zero, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_zero, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(1.0, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(1.0, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(inf, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(inf, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_inf, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_inf, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(aNaN, 0.0, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, 0.0, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, neg_zero, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, neg_zero, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, 1.0, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, 1.0, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, inf, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, inf, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, neg_inf, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, neg_inf, aNaN, false, 0);
+    TEST_SPECIAL(sNaN, 0.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, 0.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, neg_zero, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, neg_zero, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, 1.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, 1.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, neg_inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, neg_inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(aNaN, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(aNaN, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-aNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-aNaN, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, -aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, -aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, -sNaN, aNaN, false, FE_INVALID);
 
     TEST_SPECIAL(6.5, 2.25L, 2.0L, false, 0);
     TEST_SPECIAL(-6.5, 2.25L, -2.0L, false, 0);
     TEST_SPECIAL(6.5, -2.25L, 2.0L, false, 0);
     TEST_SPECIAL(-6.5, -2.25L, -2.0L, false, 0);
 
-    TEST_SPECIAL(nl::max(), nl::max(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), -nl::max(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), -nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(-nl::max(), nl::max(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), -nl::max(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), -nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), -nl::denorm_min(), neg_zero, false, 0);
-
-    TEST_SPECIAL(nl::min(), nl::max(), nl::min(), false, 0);
-    TEST_SPECIAL(nl::min(), -nl::max(), nl::min(), false, 0);
-    TEST_SPECIAL(nl::min(), nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::min(), -nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::min(), nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::min(), -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(-nl::min(), nl::max(), -nl::min(), false, 0);
-    TEST_SPECIAL(-nl::min(), -nl::max(), -nl::min(), false, 0);
-    TEST_SPECIAL(-nl::min(), nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::min(), -nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::min(), nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::min(), -nl::denorm_min(), neg_zero, false, 0);
-
-    TEST_SPECIAL(nl::denorm_min(), nl::max(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), -nl::max(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), nl::min(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), -nl::min(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::denorm_min(), -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), nl::max(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), -nl::max(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), nl::min(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), -nl::min(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), -nl::denorm_min(), neg_zero, false, 0);
+    TEST_SPECIAL(max_normal, max_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, -max_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, min_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, -min_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(-max_normal, max_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, -max_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, -min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, -min_denormal, neg_zero, false, 0);
+
+    TEST_SPECIAL(min_normal, max_normal, min_normal, false, 0);
+    TEST_SPECIAL(min_normal, -max_normal, min_normal, false, 0);
+    TEST_SPECIAL(min_normal, min_normal, 0.0, false, 0);
+    TEST_SPECIAL(min_normal, -min_normal, 0.0, false, 0);
+    TEST_SPECIAL(min_normal, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(min_normal, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(-min_normal, max_normal, -min_normal, false, 0);
+    TEST_SPECIAL(-min_normal, -max_normal, -min_normal, false, 0);
+    TEST_SPECIAL(-min_normal, min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_normal, -min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_normal, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_normal, -min_denormal, neg_zero, false, 0);
+
+    TEST_SPECIAL(min_denormal, max_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, -max_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, min_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, -min_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(min_denormal, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(-min_denormal, max_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, -max_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, min_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, -min_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_denormal, -min_denormal, neg_zero, false, 0);
   }
 
   void testRegularExtreme(FModFunc f) {
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index a9b31eaf6a4944c..b190cdd8515e36a 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1347,8 +1347,6 @@ add_fp_unittest(
     libc.src.math.fmodf
     libc.src.__support.FPUtil.basic_operations
     libc.src.__support.FPUtil.nearest_integer_operations
-  # Requires C++ limits.
-  UNIT_TEST_ONLY
 )
 
 add_fp_unittest(
@@ -1365,8 +1363,6 @@ add_fp_unittest(
     libc.src.math.fmod
     libc.src.__support.FPUtil.basic_operations
     libc.src.__support.FPUtil.nearest_integer_operations
-  # Requires C++ limits.
-  UNIT_TEST_ONLY
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/smoke/FModTest.h b/libc/test/src/math/smoke/FModTest.h
index 5fc0ebf6d33e407..2b1442923268d9c 100644
--- a/libc/test/src/math/smoke/FModTest.h
+++ b/libc/test/src/math/smoke/FModTest.h
@@ -14,7 +14,6 @@
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits>
 #include <math.h>
 
 #define TEST_SPECIAL(x, y, expected, dom_err, expected_exception)              \
@@ -33,201 +32,179 @@ template <typename T> class FmodTest : public LIBC_NAMESPACE::testing::Test {
   typedef T (*FModFunc)(T, T);
 
   void testSpecialNumbers(FModFunc f) {
-    using nl = std::numeric_limits<T>;
-
     // fmod (+0, y) == +0 for y != 0.
     TEST_SPECIAL(0.0, 3.0, 0.0, false, 0);
-    TEST_SPECIAL(0.0, nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, -nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, nl::max(), 0.0, false, 0);
-    TEST_SPECIAL(0.0, -nl::max(), 0.0, false, 0);
+    TEST_SPECIAL(0.0, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, min_normal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, -min_normal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, max_normal, 0.0, false, 0);
+    TEST_SPECIAL(0.0, -max_normal, 0.0, false, 0);
 
     // fmod (-0, y) == -0 for y != 0.
     TEST_SPECIAL(neg_zero, 3.0, neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, -nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, -nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, nl::max(), neg_zero, false, 0);
-    TEST_SPECIAL(neg_zero, -nl::max(), neg_zero, false, 0);
-
-    // fmod (+inf, y) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(inf, 3.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, -1.1L, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, nl::denorm_min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, nl::min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, nl::max(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, inf, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(inf, neg_inf, nl::quiet_NaN(), true, FE_INVALID);
-
-    // fmod (-inf, y) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(neg_inf, 3.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, -1.1L, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::denorm_min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::min(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::max(), nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, inf, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_inf, neg_inf, nl::quiet_NaN(), true, FE_INVALID);
-
-    // fmod (x, +0) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(3.0, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(-1.1L, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(0.0, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_zero, 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::denorm_min(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::min(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::max(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
-
-    // fmod (x, -0) == nl::quiet_NaN() plus invalid exception.
-    TEST_SPECIAL(3.0, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(-1.1L, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(0.0, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(neg_zero, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::denorm_min(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::min(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
-    TEST_SPECIAL(nl::max(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
+    TEST_SPECIAL(neg_zero, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, -min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, -min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, max_normal, neg_zero, false, 0);
+    TEST_SPECIAL(neg_zero, -max_normal, neg_zero, false, 0);
+
+    // fmod (+inf, y) == aNaN plus invalid exception.
+    TEST_SPECIAL(inf, 3.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, -1.1L, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, min_denormal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, min_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, max_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, inf, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(inf, neg_inf, aNaN, true, FE_INVALID);
+
+    // fmod (-inf, y) == aNaN plus invalid exception.
+    TEST_SPECIAL(neg_inf, 3.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, -1.1L, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, min_denormal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, min_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, max_normal, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, inf, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_inf, neg_inf, aNaN, true, FE_INVALID);
+
+    // fmod (x, +0) == aNaN plus invalid exception.
+    TEST_SPECIAL(3.0, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(-1.1L, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(0.0, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_zero, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_denormal, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_normal, 0.0, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(max_normal, 0.0, aNaN, true, FE_INVALID);
+
+    // fmod (x, -0) == aNaN plus invalid exception.
+    TEST_SPECIAL(3.0, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(-1.1L, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(0.0, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(neg_zero, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_denormal, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(min_normal, neg_zero, aNaN, true, FE_INVALID);
+    TEST_SPECIAL(max_normal, neg_zero, aNaN, true, FE_INVALID);
 
     // fmod (x, +inf) == x for x not infinite.
     TEST_SPECIAL(0.0, inf, 0.0, false, 0);
     TEST_SPECIAL(neg_zero, inf, neg_zero, false, 0);
-    TEST_SPECIAL(nl::denorm_min(), inf, nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::min(), inf, nl::min(), false, 0);
-    TEST_SPECIAL(nl::max(), inf, nl::max(), false, 0);
+    TEST_SPECIAL(min_denormal, inf, min_denormal, false, 0);
+    TEST_SPECIAL(min_normal, inf, min_normal, false, 0);
+    TEST_SPECIAL(max_normal, inf, max_normal, false, 0);
     TEST_SPECIAL(3.0, inf, 3.0, false, 0);
     // fmod (x, -inf) == x for x not infinite.
     TEST_SPECIAL(0.0, neg_inf, 0.0, false, 0);
     TEST_SPECIAL(neg_zero, neg_inf, neg_zero, false, 0);
-    TEST_SPECIAL(nl::denorm_min(), neg_inf, nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::min(), neg_inf, nl::min(), false, 0);
-    TEST_SPECIAL(nl::max(), neg_inf, nl::max(), false, 0);
+    TEST_SPECIAL(min_denormal, neg_inf, min_denormal, false, 0);
+    TEST_SPECIAL(min_normal, neg_inf, min_normal, false, 0);
+    TEST_SPECIAL(max_normal, neg_inf, max_normal, false, 0);
     TEST_SPECIAL(3.0, neg_inf, 3.0, false, 0);
 
-    TEST_SPECIAL(0.0, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(0.0, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_zero, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_zero, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(1.0, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(1.0, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(inf, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(inf, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_inf, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(neg_inf, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(0.0, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(0.0, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(neg_zero, nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(neg_zero, -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(1.0, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(1.0, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(inf, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(inf, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(neg_inf, nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(neg_inf, -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::quiet_NaN(), 0.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), 0.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), neg_zero, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), neg_zero, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), 1.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), 1.0, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), neg_inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), neg_inf, nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::signaling_NaN(), 0.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), 0.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), neg_zero, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), neg_zero, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), 1.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), 1.0, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), inf, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), inf, nl::quiet_NaN(), false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), neg_inf, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), neg_inf, nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::quiet_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(-nl::quiet_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
-    TEST_SPECIAL(nl::quiet_NaN(), nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::quiet_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::quiet_NaN(), nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::quiet_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false,
-                 FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
-    TEST_SPECIAL(nl::signaling_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
-    TEST_SPECIAL(-nl::signaling_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(),
-                 false, FE_INVALID);
+    TEST_SPECIAL(0.0, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(0.0, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_zero, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_zero, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(1.0, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(1.0, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(inf, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(inf, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_inf, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(neg_inf, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(0.0, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(0.0, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_zero, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_zero, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(1.0, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(1.0, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(inf, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(inf, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_inf, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(neg_inf, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(aNaN, 0.0, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, 0.0, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, neg_zero, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, neg_zero, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, 1.0, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, 1.0, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, inf, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, inf, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, neg_inf, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, neg_inf, aNaN, false, 0);
+    TEST_SPECIAL(sNaN, 0.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, 0.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, neg_zero, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, neg_zero, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, 1.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, 1.0, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, neg_inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, neg_inf, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(aNaN, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, aNaN, aNaN, false, 0);
+    TEST_SPECIAL(-aNaN, -aNaN, aNaN, false, 0);
+    TEST_SPECIAL(aNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(aNaN, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-aNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-aNaN, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, -aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, -aNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(sNaN, -sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, sNaN, aNaN, false, FE_INVALID);
+    TEST_SPECIAL(-sNaN, -sNaN, aNaN, false, FE_INVALID);
 
     TEST_SPECIAL(6.5, 2.25L, 2.0L, false, 0);
     TEST_SPECIAL(-6.5, 2.25L, -2.0L, false, 0);
     TEST_SPECIAL(6.5, -2.25L, 2.0L, false, 0);
     TEST_SPECIAL(-6.5, -2.25L, -2.0L, false, 0);
 
-    TEST_SPECIAL(nl::max(), nl::max(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), -nl::max(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), -nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::max(), -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(-nl::max(), nl::max(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), -nl::max(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), -nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::max(), -nl::denorm_min(), neg_zero, false, 0);
-
-    TEST_SPECIAL(nl::min(), nl::max(), nl::min(), false, 0);
-    TEST_SPECIAL(nl::min(), -nl::max(), nl::min(), false, 0);
-    TEST_SPECIAL(nl::min(), nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::min(), -nl::min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::min(), nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::min(), -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(-nl::min(), nl::max(), -nl::min(), false, 0);
-    TEST_SPECIAL(-nl::min(), -nl::max(), -nl::min(), false, 0);
-    TEST_SPECIAL(-nl::min(), nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::min(), -nl::min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::min(), nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::min(), -nl::denorm_min(), neg_zero, false, 0);
-
-    TEST_SPECIAL(nl::denorm_min(), nl::max(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), -nl::max(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), nl::min(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), -nl::min(), nl::denorm_min(), false, 0);
-    TEST_SPECIAL(nl::denorm_min(), nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(nl::denorm_min(), -nl::denorm_min(), 0.0, false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), nl::max(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), -nl::max(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), nl::min(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), -nl::min(), -nl::denorm_min(), false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), nl::denorm_min(), neg_zero, false, 0);
-    TEST_SPECIAL(-nl::denorm_min(), -nl::denorm_min(), neg_zero, false, 0);
+    TEST_SPECIAL(max_normal, max_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, -max_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, min_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, -min_normal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(max_normal, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(-max_normal, max_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, -max_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, -min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(-max_normal, -min_denormal, neg_zero, false, 0);
+
+    TEST_SPECIAL(min_normal, max_normal, min_normal, false, 0);
+    TEST_SPECIAL(min_normal, -max_normal, min_normal, false, 0);
+    TEST_SPECIAL(min_normal, min_normal, 0.0, false, 0);
+    TEST_SPECIAL(min_normal, -min_normal, 0.0, false, 0);
+    TEST_SPECIAL(min_normal, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(min_normal, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(-min_normal, max_normal, -min_normal, false, 0);
+    TEST_SPECIAL(-min_normal, -max_normal, -min_normal, false, 0);
+    TEST_SPECIAL(-min_normal, min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_normal, -min_normal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_normal, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_normal, -min_denormal, neg_zero, false, 0);
+
+    TEST_SPECIAL(min_denormal, max_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, -max_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, min_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, -min_normal, min_denormal, false, 0);
+    TEST_SPECIAL(min_denormal, min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(min_denormal, -min_denormal, 0.0, false, 0);
+    TEST_SPECIAL(-min_denormal, max_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, -max_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, min_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, -min_normal, -min_denormal, false, 0);
+    TEST_SPECIAL(-min_denormal, min_denormal, neg_zero, false, 0);
+    TEST_SPECIAL(-min_denormal, -min_denormal, neg_zero, false, 0);
   }
 
   void testRegularExtreme(FModFunc f) {
diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp
index a8fe8f2557c8ef9..b3497b8a0b29a9e 100644
--- a/libc/test/src/stdio/sprintf_test.cpp
+++ b/libc/test/src/stdio/sprintf_test.cpp
@@ -586,7 +586,7 @@ TEST(LlvmLibcSPrintfTest, OctConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
+  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf();
   double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(1);
   written = LIBC_NAMESPACE::sprintf(buff, "%a", 1.0);
   ASSERT_STREQ_LEN(written, buff, "0x1p+0");
@@ -950,10 +950,9 @@ TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
+  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf();
   double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(1);
-  long double ld_inf =
-      LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
+  long double ld_inf = LIBC_NAMESPACE::fputil::FPBits<long double>::inf();
   long double ld_nan =
       LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(1);
 
@@ -1791,7 +1790,7 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
+  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf();
   double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(1);
 
   written = LIBC_NAMESPACE::sprintf(buff, "%e", 1.0);
@@ -2423,7 +2422,7 @@ TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
+  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf();
   double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(1);
 
   written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.0);
diff --git a/libc/test/src/stdio/sscanf_test.cpp b/libc/test/src/stdio/sscanf_test.cpp
index 8e0ad7de4f2ea2f..7efc10dfba69dd3 100644
--- a/libc/test/src/stdio/sscanf_test.cpp
+++ b/libc/test/src/stdio/sscanf_test.cpp
@@ -231,7 +231,7 @@ TEST(LlvmLibcSScanfTest, FloatConvSimple) {
   int ret_val;
   float result = 0;
 
-  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf().get_val();
+  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf();
   float nan = LIBC_NAMESPACE::fputil::FPBits<float>::build_nan(1);
 
   ret_val = LIBC_NAMESPACE::sscanf("123", "%f", &result);
@@ -295,7 +295,7 @@ TEST(LlvmLibcSScanfTest, FloatConvLengthModifier) {
   double d_result = 0;
   long double ld_result = 0;
 
-  double d_inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
+  double d_inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf();
   long double ld_nan =
       LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(1);
 
@@ -392,7 +392,7 @@ TEST(LlvmLibcSScanfTest, FloatConvComplexParsing) {
   int ret_val;
   float result = 0;
 
-  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf().get_val();
+  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf();
   float nan = LIBC_NAMESPACE::fputil::FPBits<float>::build_nan(1);
 
   ret_val = LIBC_NAMESPACE::sscanf("0x1.0e3", "%f", &result);
@@ -464,7 +464,7 @@ TEST(LlvmLibcSScanfTest, FloatConvMaxWidth) {
   int ret_val;
   float result = 0;
 
-  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf().get_val();
+  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf();
 
   ret_val = LIBC_NAMESPACE::sscanf("123", "%3f", &result);
   EXPECT_EQ(ret_val, 1);

>From 814e3413336b3b9ff99531e12d63d3072f7e7597 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Mon, 6 Nov 2023 23:10:40 +0000
Subject: [PATCH 2/2] Fix merging issue.

---
 libc/src/math/generic/exp10f_impl.h |  4 ++--
 libc/src/math/generic/powf.cpp      | 11 +++++------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/libc/src/math/generic/exp10f_impl.h b/libc/src/math/generic/exp10f_impl.h
index 1d632b160265e3f..6fe542649400276 100644
--- a/libc/src/math/generic/exp10f_impl.h
+++ b/libc/src/math/generic/exp10f_impl.h
@@ -54,13 +54,13 @@ LIBC_INLINE float exp10f(float x) {
       if (x_u < 0x7f80'0000U) {
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-          return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
+          return FPBits::max_normal();
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
       }
       // x is +inf or nan
-      return x + static_cast<float>(FPBits::inf());
+      return x + FPBits::inf();
     }
   }
 
diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp
index 70a293fbe3fb762..891b09c69baed6d 100644
--- a/libc/src/math/generic/powf.cpp
+++ b/libc/src/math/generic/powf.cpp
@@ -548,15 +548,14 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
         // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO
         fputil::set_errno_if_required(EDOM);
         fputil::raise_except_if_required(FE_DIVBYZERO);
-        return FloatBits::inf().get_val();
+        return FloatBits::inf();
       }
       // pow (|x| < 1, -inf) = +inf
       // pow (|x| < 1, +inf) = 0.0f
       // pow (|x| > 1, -inf) = 0.0f
       // pow (|x| > 1, +inf) = +inf
-      return ((x_abs < 0x3f80'0000) == (y_u == 0xff80'0000))
-                 ? FloatBits::inf().get_val()
-                 : 0.0f;
+      return ((x_abs < 0x3f80'0000) == (y_u == 0xff80'0000)) ? FloatBits::inf()
+                                                             : 0.0f;
     }
     default:
       // Speed up for common exponents
@@ -619,7 +618,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
         // pow(0, negative number) = inf
         fputil::set_errno_if_required(EDOM);
         fputil::raise_except_if_required(FE_DIVBYZERO);
-        return FloatBits::inf(out_sign).get_val();
+        return FloatBits::inf(out_sign);
       }
       // pow(0, positive number) = 0
       return out_sign ? -0.0f : 0.0f;
@@ -630,7 +629,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
       if (y_u >= FloatProp::SIGN_MASK) {
         return out_sign ? -0.0f : 0.0f;
       }
-      return FloatBits::inf(out_sign).get_val();
+      return FloatBits::inf(out_sign);
     }
     }
 



More information about the cfe-commits mailing list