[libc-commits] [libc] Revert "[libc] Remove unnecessary `FPBits` functions and properties" (PR #79118)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Tue Jan 23 02:50:49 PST 2024


https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/79118

Reverts llvm/llvm-project#79113

>From 061ab6a24791b1f35e0ab0343a4ead186d3313be Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <chatelet.guillaume at gmail.com>
Date: Tue, 23 Jan 2024 11:50:37 +0100
Subject: [PATCH] Revert "[libc] Remove unnecessary `FPBits` functions and
 properties"

---
 libc/fuzzing/stdlib/strtofloat_fuzz.cpp       |  2 +-
 .../FPUtil/DivisionAndRemainderOperations.h   |  2 +-
 libc/src/__support/FPUtil/FPBits.h            | 51 +++++++++---
 libc/src/__support/FPUtil/Hypot.h             |  4 +-
 .../__support/FPUtil/ManipulationFunctions.h  | 24 +++---
 libc/src/__support/FPUtil/NormalFloat.h       |  2 +-
 libc/src/__support/FPUtil/dyadic_float.h      |  2 +-
 .../src/__support/FPUtil/except_value_utils.h |  6 +-
 libc/src/__support/FPUtil/generic/FMA.h       | 10 ++-
 libc/src/__support/FPUtil/generic/FMod.h      |  2 +-
 libc/src/__support/FPUtil/generic/sqrt.h      | 18 ++---
 .../FPUtil/generic/sqrt_80_bit_long_double.h  |  8 +-
 .../FPUtil/x86_64/NextAfterLongDouble.h       | 58 ++++++-------
 libc/src/__support/common.h                   |  1 +
 libc/src/__support/str_to_float.h             |  4 +-
 libc/src/math/generic/acosf.cpp               |  2 +-
 libc/src/math/generic/acoshf.cpp              |  2 +-
 libc/src/math/generic/asinf.cpp               |  2 +-
 libc/src/math/generic/atanhf.cpp              |  4 +-
 libc/src/math/generic/cosf.cpp                |  2 +-
 libc/src/math/generic/coshf.cpp               |  6 +-
 libc/src/math/generic/exp.cpp                 |  4 +-
 libc/src/math/generic/exp10.cpp               |  4 +-
 libc/src/math/generic/exp10f_impl.h           |  6 +-
 libc/src/math/generic/exp2.cpp                |  4 +-
 libc/src/math/generic/exp2f_impl.h            |  6 +-
 libc/src/math/generic/expf.cpp                |  4 +-
 libc/src/math/generic/expm1.cpp               |  4 +-
 libc/src/math/generic/expm1f.cpp              |  4 +-
 libc/src/math/generic/log.cpp                 | 11 ++-
 libc/src/math/generic/log10.cpp               | 11 ++-
 libc/src/math/generic/log10f.cpp              |  8 +-
 libc/src/math/generic/log1p.cpp               |  7 +-
 libc/src/math/generic/log1pf.cpp              |  4 +-
 libc/src/math/generic/log2.cpp                | 11 ++-
 libc/src/math/generic/log2f.cpp               |  8 +-
 libc/src/math/generic/logf.cpp                |  9 +--
 libc/src/math/generic/powf.cpp                | 13 ++-
 libc/src/math/generic/sincosf.cpp             |  4 +-
 libc/src/math/generic/sinf.cpp                |  2 +-
 libc/src/math/generic/sinhf.cpp               |  6 +-
 libc/src/math/generic/tanf.cpp                |  2 +-
 libc/test/UnitTest/FPMatcher.h                | 40 ++++-----
 .../test/src/__support/FPUtil/fpbits_test.cpp | 81 +++++++++++--------
 libc/test/src/math/FDimTest.h                 |  2 +-
 libc/test/src/math/FmaTest.h                  | 37 ++++-----
 libc/test/src/math/HypotTest.h                | 43 +++++-----
 libc/test/src/math/ILogbTest.h                | 22 ++---
 libc/test/src/math/LdExpTest.h                |  2 +-
 libc/test/src/math/NextAfterTest.h            | 10 +--
 libc/test/src/math/RIntTest.h                 | 21 +++--
 libc/test/src/math/RemQuoTest.h               | 25 +++---
 libc/test/src/math/RoundToIntegerTest.h       | 22 +++--
 .../BinaryOpSingleOutputDiff.h                | 16 ++--
 .../SingleInputSingleOutputDiff.h             |  7 +-
 libc/test/src/math/smoke/FDimTest.h           |  2 +-
 libc/test/src/math/smoke/FmaTest.h            | 16 ++--
 libc/test/src/math/smoke/HypotTest.h          | 20 ++---
 libc/test/src/math/smoke/ILogbTest.h          | 18 ++---
 libc/test/src/math/smoke/LdExpTest.h          |  2 +-
 libc/test/src/math/smoke/NextAfterTest.h      | 14 ++--
 libc/test/src/math/smoke/NextTowardTest.h     | 22 +++--
 libc/test/src/math/smoke/RIntTest.h           |  2 +-
 libc/test/src/math/smoke/RemQuoTest.h         |  2 +-
 libc/test/src/math/smoke/RoundToIntegerTest.h | 22 +++--
 libc/test/src/stdio/sprintf_test.cpp          | 32 +++-----
 libc/test/src/stdio/sscanf_test.cpp           | 21 ++---
 libc/utils/MPFRWrapper/MPFRUtils.cpp          |  2 +-
 68 files changed, 421 insertions(+), 426 deletions(-)

diff --git a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
index b773043bda67d8a..affef6fcf549e08 100644
--- a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
+++ b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
@@ -28,7 +28,7 @@ using LIBC_NAMESPACE::fputil::FPBits;
 // exponent. Subnormals have a lower effective precision since they don't
 // necessarily use all of the bits of the mantissa.
 template <typename F> inline constexpr int effective_precision(int exponent) {
-  const int full_precision = FPBits<F>::FRACTION_LEN + 1;
+  const int full_precision = FPBits<F>::MANTISSA_PRECISION;
 
   // This is intended to be 0 when the exponent is the lowest normal and
   // increase as the exponent's magnitude increases.
diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
index ef9593a42b00557..1798310c3e31e30 100644
--- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
@@ -31,7 +31,7 @@ LIBC_INLINE T remquo(T x, T y, int &q) {
   if (ybits.is_nan())
     return y;
   if (xbits.is_inf() || ybits.is_zero())
-    return FPBits<T>::build_quiet_nan(fputil::Sign::POS, 1).get_val();
+    return FPBits<T>::build_quiet_nan(1);
 
   if (xbits.is_zero()) {
     q = 0;
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 0a79b505ecbe1c2..2465158bb2cdfc7 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -390,7 +390,7 @@ struct FPRepSem : public FPStorage<fp_type> {
     return exp_bits() == encode(BiasedExp::BITS_ALL_ZEROES());
   }
   LIBC_INLINE constexpr bool is_normal() const {
-    return is_finite() && !is_subnormal();
+    return is_finite() && !UP::is_subnormal();
   }
   // Returns the mantissa with the implicit bit set iff the current
   // value is a valid normal number.
@@ -556,14 +556,6 @@ struct FPRep : public FPRepSem<fp_type, RetT> {
   using UP::FRACTION_MASK;
   using UP::SIGN_MASK;
 
-  // Comparison
-  LIBC_INLINE constexpr friend bool operator==(FPRep a, FPRep b) {
-    return a.uintval() == b.uintval();
-  }
-  LIBC_INLINE constexpr friend bool operator!=(FPRep a, FPRep b) {
-    return a.uintval() != b.uintval();
-  }
-
   // Representation
   LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; }
   LIBC_INLINE constexpr void set_uintval(StorageType value) {
@@ -706,6 +698,16 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
   using UP::bits;
 
   // Constants.
+  LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_PRECISION =
+      UP::FRACTION_LEN + 1;
+  LIBC_INLINE_VAR static constexpr StorageType MIN_NORMAL =
+      UP::min_normal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MAX_NORMAL =
+      UP::max_normal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MIN_SUBNORMAL =
+      UP::min_subnormal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MAX_SUBNORMAL =
+      UP::max_subnormal(Sign::POS).uintval();
   LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
       (1 << UP::EXP_LEN) - 1;
 
@@ -729,6 +731,37 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
 
   LIBC_INLINE constexpr explicit operator T() const { return get_val(); }
 
+  // Methods below this are used by tests.
+  // TODO: inline and remove.
+  LIBC_INLINE static constexpr T one(Sign sign = Sign::POS) {
+    return T(UP::one(sign));
+  }
+  LIBC_INLINE static constexpr T zero(Sign sign = Sign::POS) {
+    return T(UP::zero(sign));
+  }
+  LIBC_INLINE static constexpr T inf(Sign sign = Sign::POS) {
+    return T(UP::inf(sign));
+  }
+  LIBC_INLINE static constexpr T min_normal() {
+    return T(UP::min_normal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T max_normal() {
+    return T(UP::max_normal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T min_denormal() {
+    return T(UP::min_subnormal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T max_denormal() {
+    return T(UP::max_subnormal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T build_nan(StorageType v) {
+    return T(UP::build_nan(Sign::POS, v));
+  }
+  LIBC_INLINE static constexpr T build_quiet_nan(StorageType v,
+                                                 Sign sign = Sign::POS) {
+    return T(UP::build_quiet_nan(sign, v));
+  }
+
   // TODO: Use an uint32_t for 'biased_exp'.
   LIBC_INLINE static constexpr FPBits<T>
   create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 82237dec09e42e3..c38a40dfb08984a 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -197,7 +197,7 @@ LIBC_INLINE T hypot(T x, T y) {
         if (int round_mode = quick_get_round();
             round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
           return T(FPBits_t::inf());
-        return T(FPBits_t::max_normal());
+        return T(FPBits_t(FPBits_t::MAX_NORMAL));
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
@@ -254,7 +254,7 @@ LIBC_INLINE T hypot(T x, T y) {
     if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
       if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
         return T(FPBits_t::inf());
-      return T(FPBits_t::max_normal());
+      return T(FPBits_t(FPBits_t::MAX_NORMAL));
     }
   }
 
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index d7114625a9b3141..81c8281f3c7bbee 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -108,7 +108,7 @@ LIBC_INLINE T logb(T x) {
     return x;
   } else if (bits.is_inf()) {
     // Return positive infinity.
-    return T(FPBits<T>::inf());
+    return T(FPBits<T>::inf(Sign::POS));
   }
 
   NormalFloat<T> normal(bits);
@@ -127,7 +127,7 @@ LIBC_INLINE T ldexp(T x, int exp) {
   // that adding |exp| to it does not lead to integer rollover. But, if |exp|
   // value is larger the exponent range for type T, then we can return infinity
   // early. Because the result of the ldexp operation can be a subnormal number,
-  // we need to accommodate the (mantissaWidth + 1) worth of shift in
+  // we need to accommodate the (mantissaWidht + 1) worth of shift in
   // calculating the limit.
   int exp_limit = FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
   if (exp > exp_limit)
@@ -164,22 +164,26 @@ LIBC_INLINE T nextafter(T from, U to) {
     return static_cast<T>(to);
 
   using StorageType = typename FPBits<T>::StorageType;
-  if (from != T(0)) {
-    if ((static_cast<U>(from) < to) == (from > T(0))) {
-      from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1));
+  StorageType int_val = from_bits.uintval();
+  if (from != FPBits<T>::zero()) {
+    if ((static_cast<U>(from) < to) == (from > FPBits<T>::zero())) {
+      ++int_val;
     } else {
-      from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1));
+      --int_val;
     }
   } else {
-    from_bits = FPBits<T>::min_subnormal(to_bits.sign());
+    int_val = FPBits<T>::MIN_SUBNORMAL;
+    if (to_bits.is_neg())
+      int_val |= FPBits<T>::SIGN_MASK;
   }
 
-  if (from_bits.is_subnormal())
+  StorageType exponent_bits = int_val & FPBits<T>::EXP_MASK;
+  if (exponent_bits == StorageType(0))
     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
-  else if (from_bits.is_inf())
+  else if (exponent_bits == FPBits<T>::EXP_MASK)
     raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
 
-  return from_bits.get_val();
+  return cpp::bit_cast<T>(int_val);
 }
 
 } // namespace fputil
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index fa4da33b5b17fae..cfa9e1417510559 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -215,7 +215,7 @@ template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {
   // Max exponent is of the form 0xFF...E. That is why -2 and not -1.
   constexpr int MAX_EXPONENT_VALUE = (1 << LDBits::EXP_LEN) - 2;
   if (biased_exponent > MAX_EXPONENT_VALUE) {
-    return LDBits::inf(sign).get_val();
+    return LDBits::inf(sign);
   }
 
   FPBits<long double> result(0.0l);
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 888d7ffec241ea4..5449f5561d56968 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -93,7 +93,7 @@ template <size_t Bits> struct DyadicFloat {
       return 0.0;
 
     // Assume that it is normalized, and output is also normal.
-    constexpr uint32_t PRECISION = FPBits<T>::FRACTION_LEN + 1;
+    constexpr uint32_t PRECISION = FPBits<T>::MANTISSA_PRECISION;
     using output_bits_t = typename FPBits<T>::StorageType;
 
     int exp_hi = exponent + static_cast<int>((Bits - 1) + FPBits<T>::EXP_BIAS);
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 1e0381194009d55..89849540315f64d 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -102,13 +102,15 @@ 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;
-  tmp -= 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;
-  tmp += 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/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 5c36463ea50213e..6285cac1983d1e9 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -130,9 +130,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
     return x * y + z;
 
   // Extract mantissa and append hidden leading bits.
-  UInt128 x_mant = x_bits.get_explicit_mantissa();
-  UInt128 y_mant = y_bits.get_explicit_mantissa();
-  UInt128 z_mant = z_bits.get_explicit_mantissa();
+  UInt128 x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL;
 
   // If the exponent of the product x*y > the exponent of z, then no extra
   // precision beside the entire product x*y is needed.  On the other hand, when
@@ -255,7 +255,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
     if ((round_mode == FE_TOWARDZERO) ||
         (round_mode == FE_UPWARD && prod_sign.is_neg()) ||
         (round_mode == FE_DOWNWARD && prod_sign.is_pos())) {
-      return FPBits::max_normal(prod_sign).get_val();
+      result = FPBits::MAX_NORMAL;
+      return prod_sign.is_neg() ? -cpp::bit_cast<double>(result)
+                                : cpp::bit_cast<double>(result);
     }
     return static_cast<double>(FPBits::inf(prod_sign));
   }
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 18355b801dbc7c9..f4000b97751efc4 100644
--- a/libc/src/__support/FPUtil/generic/FMod.h
+++ b/libc/src/__support/FPUtil/generic/FMod.h
@@ -124,7 +124,7 @@ template <typename T> struct FModExceptionalInputHandler {
 
   LIBC_INLINE static bool pre_check(T x, T y, T &out) {
     using FPB = fputil::FPBits<T>;
-    const T quiet_nan = FPB::build_quiet_nan().get_val();
+    const T quiet_nan = FPB::build_quiet_nan(0);
     FPB sx(x), sy(y);
     if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
                     !sx.is_inf_or_nan())) {
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 0a0690ec1463b9d..21ae9d081d3f12e 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -71,19 +71,15 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
     return x86::sqrt(x);
   } else {
     // IEEE floating points formats.
-    using Sign = fputil::Sign;
-    using FPBits_t = typename fputil::FPBits<T>;
-    using StorageType = typename FPBits_t::StorageType;
-    constexpr StorageType ONE = StorageType(1) << FPBits_t::FRACTION_LEN;
-    constexpr auto FLT_NAN =
-        FPBits_t::build_quiet_nan(Sign::POS, ONE >> 1).get_val();
+    using StorageType = typename FPBits<T>::StorageType;
+    constexpr StorageType ONE = StorageType(1) << FPBits<T>::FRACTION_LEN;
 
-    FPBits_t bits(x);
+    FPBits<T> bits(x);
 
     if (bits.is_inf_or_nan()) {
       if (bits.is_neg() && (bits.get_mantissa() == 0)) {
         // sqrt(-Inf) = NaN
-        return FLT_NAN;
+        return FPBits<T>::build_quiet_nan(ONE >> 1);
       } else {
         // sqrt(NaN) = NaN
         // sqrt(+Inf) = +Inf
@@ -95,7 +91,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
       return x;
     } else if (bits.is_neg()) {
       // sqrt( negative numbers ) = NaN
-      return FLT_NAN;
+      return FPBits<T>::build_quiet_nan(ONE >> 1);
     } else {
       int x_exp = bits.get_exponent();
       StorageType x_mant = bits.get_mantissa();
@@ -149,10 +145,10 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
       }
 
       // Remove hidden bit and append the exponent field.
-      x_exp = ((x_exp >> 1) + FPBits_t::EXP_BIAS);
+      x_exp = ((x_exp >> 1) + FPBits<T>::EXP_BIAS);
 
       y = (y - ONE) |
-          (static_cast<StorageType>(x_exp) << FPBits_t::FRACTION_LEN);
+          (static_cast<StorageType>(x_exp) << FPBits<T>::FRACTION_LEN);
 
       switch (quick_get_round()) {
       case FE_TONEAREST:
diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index b0a3776029ca78a..4f8d136938f56e7 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -38,16 +38,14 @@ LIBC_INLINE long double sqrt(long double x);
 LIBC_INLINE long double sqrt(long double x) {
   using LDBits = FPBits<long double>;
   using StorageType = typename LDBits::StorageType;
-  using Sign = fputil::Sign;
   constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN);
-  constexpr auto LDNAN = LDBits::build_quiet_nan(Sign::POS, ONE >> 1).get_val();
 
-  LDBits bits(x);
+  FPBits<long double> bits(x);
 
   if (bits.is_inf_or_nan()) {
     if (bits.is_neg() && (bits.get_mantissa() == 0)) {
       // sqrt(-Inf) = NaN
-      return LDNAN;
+      return LDBits::build_quiet_nan(ONE >> 1);
     } else {
       // sqrt(NaN) = NaN
       // sqrt(+Inf) = +Inf
@@ -59,7 +57,7 @@ LIBC_INLINE long double sqrt(long double x) {
     return x;
   } else if (bits.is_neg()) {
     // sqrt( negative numbers ) = NaN
-    return LDNAN;
+    return LDBits::build_quiet_nan(ONE >> 1);
   } else {
     int x_exp = bits.get_explicit_exponent();
     StorageType x_mant = bits.get_mantissa();
diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
index d1c76ba954b9304..512f5de4e7931ac 100644
--- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
@@ -43,18 +43,16 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
   }
 
   using StorageType = FPBits::StorageType;
-
+  constexpr StorageType SIGN_VAL = (StorageType(1) << 79);
   constexpr StorageType FRACTION_MASK = FPBits::FRACTION_MASK;
-  // StorageType int_val = from_bits.uintval();
-  if (from == 0.0l) { // +0.0 / -0.0
-    from_bits = FPBits::min_subnormal(from > to ? Sign::NEG : Sign::POS);
-  } else if (from < 0.0l) {
-    if (to < from) { // toward -inf
-      if (from_bits == FPBits::max_subnormal(Sign::NEG)) {
+  StorageType int_val = from_bits.uintval();
+  if (from < 0.0l) {
+    if (from > to) {
+      if (int_val == (SIGN_VAL + FPBits::MAX_SUBNORMAL)) {
         // We deal with normal/subnormal boundary separately to avoid
         // dealing with the implicit bit.
-        from_bits = FPBits::min_normal(Sign::NEG);
-      } else if (from_bits.get_mantissa() == FRACTION_MASK) {
+        int_val = SIGN_VAL + FPBits::MIN_NORMAL;
+      } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) {
         from_bits.set_mantissa(0);
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
@@ -64,40 +62,45 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() + 1));
+        ++int_val;
       }
-    } else { // toward +inf
-      if (from_bits == FPBits::min_normal(Sign::NEG)) {
+    } else {
+      if (int_val == (SIGN_VAL + FPBits::MIN_NORMAL)) {
         // We deal with normal/subnormal boundary separately to avoid
         // dealing with the implicit bit.
-        from_bits = FPBits::max_subnormal(Sign::NEG);
-      } else if (from_bits.get_mantissa() == 0) {
+        int_val = SIGN_VAL + FPBits::MAX_SUBNORMAL;
+      } else if ((int_val & FRACTION_MASK) == 0) {
         from_bits.set_mantissa(FRACTION_MASK);
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() - 1));
+        --int_val;
       }
     }
+  } else if (from == 0.0l) {
+    if (from > to)
+      int_val = SIGN_VAL + 1;
+    else
+      int_val = 1;
   } else {
-    if (to < from) { // toward -inf
-      if (from_bits == FPBits::min_normal(Sign::POS)) {
-        from_bits = FPBits::max_subnormal(Sign::POS);
-      } else if (from_bits.get_mantissa() == 0) {
+    if (from > to) {
+      if (int_val == FPBits::MIN_NORMAL) {
+        int_val = FPBits::MAX_SUBNORMAL;
+      } else if ((int_val & FRACTION_MASK) == 0) {
         from_bits.set_mantissa(FRACTION_MASK);
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() - 1));
+        --int_val;
       }
-    } else { // toward +inf
-      if (from_bits == FPBits::max_subnormal(Sign::POS)) {
-        from_bits = FPBits::min_normal(Sign::POS);
-      } else if (from_bits.get_mantissa() == FRACTION_MASK) {
+    } else {
+      if (int_val == FPBits::MAX_SUBNORMAL) {
+        int_val = FPBits::MIN_NORMAL;
+      } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) {
         from_bits.set_mantissa(0);
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
@@ -107,15 +110,16 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() + 1));
+        ++int_val;
       }
     }
   }
 
-  if (!from_bits.get_implicit_bit())
+  StorageType implicit_bit = int_val & (StorageType(1) << FPBits::FRACTION_LEN);
+  if (implicit_bit == StorageType(0))
     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-  return from_bits.get_val();
+  return cpp::bit_cast<long double>(int_val);
 }
 
 } // namespace fputil
diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h
index a153dfc363d7374..53951dc131c28b6 100644
--- a/libc/src/__support/common.h
+++ b/libc/src/__support/common.h
@@ -25,6 +25,7 @@
 #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)                           \
   LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name)                       \
       __##name##_impl__ __asm__(#name);                                        \
+  decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]];                   \
   type __##name##_impl__ arglist
 #else
 #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 9655c993bee28f4..8aeb3d2cea03ddf 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1167,7 +1167,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
           index = left_paren;
         }
       }
-      result = FPBits(result.build_quiet_nan(result.sign(), nan_mantissa));
+      result = FPBits(result.build_quiet_nan(nan_mantissa, result.sign()));
     }
   } else if (tolower(src[index]) == 'i') { // INF
     if (tolower(src[index + 1]) == inf_string[1] &&
@@ -1215,7 +1215,7 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
     nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
   }
 
-  result = FPBits::build_quiet_nan(fputil::Sign::POS, nan_mantissa);
+  result = FPBits(result.build_quiet_nan(nan_mantissa));
   return {T(result), 0, error};
 }
 
diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp
index 7b2a09101182e14..67832596a67fba8 100644
--- a/libc/src/math/generic/acosf.cpp
+++ b/libc/src/math/generic/acosf.cpp
@@ -85,7 +85,7 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
     }
-    return x + FPBits::build_quiet_nan().get_val();
+    return x + FPBits::build_quiet_nan(0);
   }
 
   // When 0.5 < |x| < 1, we perform range reduction as follow:
diff --git a/libc/src/math/generic/acoshf.cpp b/libc/src/math/generic/acoshf.cpp
index a546cc2268b049d..b0b87095fbb07a2 100644
--- a/libc/src/math/generic/acoshf.cpp
+++ b/libc/src/math/generic/acoshf.cpp
@@ -29,7 +29,7 @@ LLVM_LIBC_FUNCTION(float, acoshf, (float x)) {
     // x < 1.
     fputil::set_errno_if_required(EDOM);
     fputil::raise_except_if_required(FE_INVALID);
-    return FPBits_t::build_quiet_nan().get_val();
+    return FPBits_t::build_quiet_nan(0);
   }
 
   if (LIBC_UNLIKELY(x_u >= 0x4f8ffb03)) {
diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp
index ee8e853063644ee..bc0d27c1eebc5d1 100644
--- a/libc/src/math/generic/asinf.cpp
+++ b/libc/src/math/generic/asinf.cpp
@@ -109,7 +109,7 @@ LLVM_LIBC_FUNCTION(float, asinf, (float x)) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
     }
-    return x + FPBits::build_nan(Sign::POS, FPBits::FRACTION_MASK).get_val();
+    return x + FPBits::build_nan(FPBits::FRACTION_MASK);
   }
 
   // Check for exceptional values
diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp
index cd0acbf24e928c7..fd6f5c96b6b4e6a 100644
--- a/libc/src/math/generic/atanhf.cpp
+++ b/libc/src/math/generic/atanhf.cpp
@@ -29,11 +29,11 @@ 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);
-      return FPBits::build_quiet_nan().get_val();
+      return FPBits::build_quiet_nan(0);
     }
   }
 
diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp
index 132e72c0f65dad3..89333ab19e89f9c 100644
--- a/libc/src/math/generic/cosf.cpp
+++ b/libc/src/math/generic/cosf.cpp
@@ -118,7 +118,7 @@ LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
     }
-    return x + FPBits::build_quiet_nan().get_val();
+    return x + FPBits::build_quiet_nan(0);
   }
 
   // Combine the results with the sine of sum formula:
diff --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp
index a618056a64dc8a3..3b01852e9f544a5 100644
--- a/libc/src/math/generic/coshf.cpp
+++ b/libc/src/math/generic/coshf.cpp
@@ -32,16 +32,16 @@ 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))
-      return FPBits::max_normal().get_val();
+      return FPBits::max_normal();
 
     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/exp.cpp b/libc/src/math/generic/exp.cpp
index 49ea1699bb20934..a1b4d9a64f96906 100644
--- a/libc/src/math/generic/exp.cpp
+++ b/libc/src/math/generic/exp.cpp
@@ -205,7 +205,7 @@ double set_exceptional(double x) {
       return x;
 
     if (fputil::quick_get_round() == FE_UPWARD)
-      return FPBits::min_subnormal().get_val();
+      return FPBits::min_denormal();
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW);
     return 0.0;
@@ -216,7 +216,7 @@ double set_exceptional(double x) {
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-      return FPBits::max_normal().get_val();
+      return FPBits::max_normal();
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/math/generic/exp10.cpp b/libc/src/math/generic/exp10.cpp
index f1da03cba0b30bb..e441f2c0edc7dd7 100644
--- a/libc/src/math/generic/exp10.cpp
+++ b/libc/src/math/generic/exp10.cpp
@@ -248,7 +248,7 @@ double set_exceptional(double x) {
         return x;
 
       if (fputil::quick_get_round() == FE_UPWARD)
-        return FPBits::min_subnormal().get_val();
+        return FPBits::min_denormal();
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0;
@@ -262,7 +262,7 @@ double set_exceptional(double x) {
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-      return FPBits::max_normal().get_val();
+      return FPBits::max_normal();
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/math/generic/exp10f_impl.h b/libc/src/math/generic/exp10f_impl.h
index ff4c1c3aec67ced..2861659a6e57e07 100644
--- a/libc/src/math/generic/exp10f_impl.h
+++ b/libc/src/math/generic/exp10f_impl.h
@@ -42,7 +42,7 @@ LIBC_INLINE float exp10f(float x) {
       if (xbits.is_nan())
         return x;
       if (fputil::fenv_is_round_up())
-        return FPBits::min_subnormal().get_val();
+        return FPBits::min_denormal();
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0f;
@@ -53,13 +53,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 FPBits::max_normal().get_val();
+          return FPBits::max_normal();
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
       }
       // x is +inf or nan
-      return x + FPBits::inf().get_val();
+      return x + FPBits::inf();
     }
   }
 
diff --git a/libc/src/math/generic/exp2.cpp b/libc/src/math/generic/exp2.cpp
index 508bff9bd9fc9cf..70bc4870806a9cc 100644
--- a/libc/src/math/generic/exp2.cpp
+++ b/libc/src/math/generic/exp2.cpp
@@ -223,7 +223,7 @@ double set_exceptional(double x) {
         return x;
 
       if (fputil::quick_get_round() == FE_UPWARD)
-        return FPBits::min_subnormal().get_val();
+        return FPBits::min_denormal();
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0;
@@ -237,7 +237,7 @@ double set_exceptional(double x) {
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-      return FPBits::max_normal().get_val();
+      return FPBits::max_normal();
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/math/generic/exp2f_impl.h b/libc/src/math/generic/exp2f_impl.h
index d2342e289fcba03..86360840b96e6f0 100644
--- a/libc/src/math/generic/exp2f_impl.h
+++ b/libc/src/math/generic/exp2f_impl.h
@@ -76,13 +76,13 @@ LIBC_INLINE float exp2f(float x) {
       if (x_u < 0x7f80'0000U) {
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-          return FPBits::max_normal().get_val();
+          return FPBits::max_normal();
 
         fputil::set_errno_if_required(ERANGE);
         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) {
@@ -93,7 +93,7 @@ LIBC_INLINE float exp2f(float x) {
       if (xbits.is_nan())
         return x;
       if (fputil::fenv_is_round_up())
-        return FPBits::min_subnormal().get_val();
+        return FPBits::min_denormal();
       if (x != 0.0f) {
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_UNDERFLOW);
diff --git a/libc/src/math/generic/expf.cpp b/libc/src/math/generic/expf.cpp
index f3ce8400d0a41e9..88d408994fe427a 100644
--- a/libc/src/math/generic/expf.cpp
+++ b/libc/src/math/generic/expf.cpp
@@ -50,7 +50,7 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) {
       if (xbits.is_nan())
         return x;
       if (fputil::fenv_is_round_up())
-        return FPBits::min_subnormal().get_val();
+        return FPBits::min_denormal();
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0f;
@@ -61,7 +61,7 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) {
       if (xbits.uintval() < 0x7f80'0000U) {
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-          return FPBits::max_normal().get_val();
+          return FPBits::max_normal();
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/math/generic/expm1.cpp b/libc/src/math/generic/expm1.cpp
index c1fb80309d7b466..d9fccf98e8caac5 100644
--- a/libc/src/math/generic/expm1.cpp
+++ b/libc/src/math/generic/expm1.cpp
@@ -267,13 +267,13 @@ double set_exceptional(double x) {
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-      return FPBits::max_normal().get_val();
+      return FPBits::max_normal();
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
   }
   // x is +inf or nan
-  return x + FPBits::inf().get_val();
+  return x + static_cast<double>(FPBits::inf());
 }
 
 } // namespace
diff --git a/libc/src/math/generic/expm1f.cpp b/libc/src/math/generic/expm1f.cpp
index 037e60021b2961d..c6e0663ec46c3f2 100644
--- a/libc/src/math/generic/expm1f.cpp
+++ b/libc/src/math/generic/expm1f.cpp
@@ -68,12 +68,12 @@ LLVM_LIBC_FUNCTION(float, expm1f, (float x)) {
         if (xbits.uintval() < 0x7f80'0000U) {
           int rounding = fputil::quick_get_round();
           if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
-            return FPBits::max_normal().get_val();
+            return FPBits::max_normal();
 
           fputil::set_errno_if_required(ERANGE);
           fputil::raise_except_if_required(FE_OVERFLOW);
         }
-        return x + FPBits::inf().get_val();
+        return x + static_cast<float>(FPBits::inf());
       }
     }
   }
diff --git a/libc/src/math/generic/log.cpp b/libc/src/math/generic/log.cpp
index b0f7e8c9afa544b..2db6b7f48fd09fc 100644
--- a/libc/src/math/generic/log.cpp
+++ b/libc/src/math/generic/log.cpp
@@ -732,29 +732,28 @@ double log_accurate(int e_x, int index, double m_x) {
 
 LLVM_LIBC_FUNCTION(double, log, (double x)) {
   using FPBits_t = typename fputil::FPBits<double>;
-  using Sign = fputil::Sign;
   FPBits_t xbits(x);
   uint64_t x_u = xbits.uintval();
 
   int x_e = -FPBits_t::EXP_BIAS;
 
-  if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
+  if (LIBC_UNLIKELY(x_u == 0x3FF0'0000'0000'0000ULL)) {
     // log(1.0) = +0.0
     return 0.0;
   }
 
-  if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
-                    xbits.uintval() > FPBits_t::max_normal().uintval())) {
+  if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::MIN_NORMAL ||
+                    xbits.uintval() > FPBits_t::MAX_NORMAL)) {
     if (xbits.is_zero()) {
       // return -Inf and raise FE_DIVBYZERO.
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits_t::inf(Sign::NEG).get_val();
+      return static_cast<double>(FPBits_t::inf(fputil::Sign::NEG));
     }
     if (xbits.is_neg() && !xbits.is_nan()) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
-      return FPBits_t::build_quiet_nan().get_val();
+      return FPBits_t::build_quiet_nan(0);
     }
     if (xbits.is_inf_or_nan()) {
       return x;
diff --git a/libc/src/math/generic/log10.cpp b/libc/src/math/generic/log10.cpp
index 55a3fc5c061e5c2..3a4d321fdb18c5b 100644
--- a/libc/src/math/generic/log10.cpp
+++ b/libc/src/math/generic/log10.cpp
@@ -733,29 +733,28 @@ double log10_accurate(int e_x, int index, double m_x) {
 
 LLVM_LIBC_FUNCTION(double, log10, (double x)) {
   using FPBits_t = typename fputil::FPBits<double>;
-  using Sign = fputil::Sign;
   FPBits_t xbits(x);
   uint64_t x_u = xbits.uintval();
 
   int x_e = -FPBits_t::EXP_BIAS;
 
-  if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
+  if (LIBC_UNLIKELY(x_u == 0x3FF0'0000'0000'0000ULL)) {
     // log10(1.0) = +0.0
     return 0.0;
   }
 
-  if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
-                    xbits.uintval() > FPBits_t::max_normal().uintval())) {
+  if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::MIN_NORMAL ||
+                    xbits.uintval() > FPBits_t::MAX_NORMAL)) {
     if (xbits.is_zero()) {
       // return -Inf and raise FE_DIVBYZERO.
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits_t::inf(Sign::NEG).get_val();
+      return static_cast<double>(FPBits_t::inf(fputil::Sign::NEG));
     }
     if (xbits.is_neg() && !xbits.is_nan()) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
-      return FPBits_t::build_quiet_nan().get_val();
+      return FPBits_t::build_quiet_nan(0);
     }
     if (xbits.is_inf_or_nan()) {
       return x;
diff --git a/libc/src/math/generic/log10f.cpp b/libc/src/math/generic/log10f.cpp
index f87e34ec5fb385f..46505f4e07e6766 100644
--- a/libc/src/math/generic/log10f.cpp
+++ b/libc/src/math/generic/log10f.cpp
@@ -106,7 +106,6 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) {
   constexpr double LOG10_2 = 0x1.34413509f79ffp-2;
 
   using FPBits = typename fputil::FPBits<float>;
-  using Sign = fputil::Sign;
   FPBits xbits(x);
   uint32_t x_u = xbits.uintval();
 
@@ -161,19 +160,18 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) {
 
   int m = -FPBits::EXP_BIAS;
 
-  if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval() ||
-                    x_u > FPBits::max_normal().uintval())) {
+  if (LIBC_UNLIKELY(x_u < FPBits::MIN_NORMAL || x_u > FPBits::MAX_NORMAL)) {
     if (xbits.is_zero()) {
       // Return -inf and raise FE_DIVBYZERO
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits::inf(Sign::NEG).get_val();
+      return static_cast<float>(FPBits::inf(fputil::Sign::NEG));
     }
     if (xbits.is_neg() && !xbits.is_nan()) {
       // Return NaN and raise FE_INVALID
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
-      return FPBits::build_quiet_nan().get_val();
+      return FPBits::build_quiet_nan(0);
     }
     if (xbits.is_inf_or_nan()) {
       return x;
diff --git a/libc/src/math/generic/log1p.cpp b/libc/src/math/generic/log1p.cpp
index ae432620ba32894..731fecae6f1b5c9 100644
--- a/libc/src/math/generic/log1p.cpp
+++ b/libc/src/math/generic/log1p.cpp
@@ -873,7 +873,6 @@ LIBC_INLINE double log1p_accurate(int e_x, int index,
 
 LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
   using FPBits_t = typename fputil::FPBits<double>;
-  using Sign = fputil::Sign;
   constexpr int EXP_BIAS = FPBits_t::EXP_BIAS;
   constexpr int FRACTION_LEN = FPBits_t::FRACTION_LEN;
   constexpr uint64_t FRACTION_MASK = FPBits_t::FRACTION_MASK;
@@ -888,19 +887,19 @@ LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
     // |x| >= 1
     if (LIBC_UNLIKELY(x_u >= 0x4650'0000'0000'0000ULL)) {
       // x >= 2^102 or x is negative, inf, or NaN
-      if (LIBC_UNLIKELY(x_u > FPBits_t::max_normal().uintval())) {
+      if (LIBC_UNLIKELY(x_u > FPBits_t::MAX_NORMAL)) {
         // x <= -1.0 or x is Inf or NaN
         if (x_u == 0xbff0'0000'0000'0000ULL) {
           // x = -1.0
           fputil::set_errno_if_required(ERANGE);
           fputil::raise_except_if_required(FE_DIVBYZERO);
-          return FPBits_t::inf(Sign::NEG).get_val();
+          return static_cast<double>(FPBits_t::inf(fputil::Sign::NEG));
         }
         if (xbits.is_neg() && !xbits.is_nan()) {
           // x < -1.0
           fputil::set_errno_if_required(EDOM);
           fputil::raise_except_if_required(FE_INVALID);
-          return FPBits_t::build_quiet_nan().get_val();
+          return FPBits_t::build_quiet_nan(0);
         }
         // x is +Inf or NaN
         return x;
diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp
index bc472caf54f89c6..0812569c624b854 100644
--- a/libc/src/math/generic/log1pf.cpp
+++ b/libc/src/math/generic/log1pf.cpp
@@ -43,11 +43,11 @@ LIBC_INLINE float log(double x) {
 
   uint64_t x_u = xbits.uintval();
 
-  if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
+  if (LIBC_UNLIKELY(x_u > FPBits::MAX_NORMAL)) {
     if (xbits.is_neg() && !xbits.is_nan()) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
-      return fputil::FPBits<float>::build_quiet_nan().get_val();
+      return fputil::FPBits<float>::build_quiet_nan(0);
     }
     return static_cast<float>(x);
   }
diff --git a/libc/src/math/generic/log2.cpp b/libc/src/math/generic/log2.cpp
index 480c690a650378d..5b7fb65d7738518 100644
--- a/libc/src/math/generic/log2.cpp
+++ b/libc/src/math/generic/log2.cpp
@@ -854,29 +854,28 @@ double log2_accurate(int e_x, int index, double m_x) {
 
 LLVM_LIBC_FUNCTION(double, log2, (double x)) {
   using FPBits_t = typename fputil::FPBits<double>;
-  using Sign = fputil::Sign;
   FPBits_t xbits(x);
   uint64_t x_u = xbits.uintval();
 
   int x_e = -FPBits_t::EXP_BIAS;
 
-  if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
+  if (LIBC_UNLIKELY(x_u == 0x3FF0'0000'0000'0000ULL)) {
     // log2(1.0) = +0.0
     return 0.0;
   }
 
-  if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
-                    xbits.uintval() > FPBits_t::max_normal().uintval())) {
+  if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::MIN_NORMAL ||
+                    xbits.uintval() > FPBits_t::MAX_NORMAL)) {
     if (xbits.is_zero()) {
       // return -Inf and raise FE_DIVBYZERO.
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits_t::inf(Sign::NEG).get_val();
+      return static_cast<double>(FPBits_t::inf(fputil::Sign::NEG));
     }
     if (xbits.is_neg() && !xbits.is_nan()) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
-      return FPBits_t::build_quiet_nan().get_val();
+      return FPBits_t::build_quiet_nan(0);
     }
     if (xbits.is_inf_or_nan()) {
       return x;
diff --git a/libc/src/math/generic/log2f.cpp b/libc/src/math/generic/log2f.cpp
index 7eaa5d53ccedd33..9cddbb9e8ea4866 100644
--- a/libc/src/math/generic/log2f.cpp
+++ b/libc/src/math/generic/log2f.cpp
@@ -55,7 +55,6 @@ namespace LIBC_NAMESPACE {
 
 LLVM_LIBC_FUNCTION(float, log2f, (float x)) {
   using FPBits = typename fputil::FPBits<float>;
-  using Sign = fputil::Sign;
   FPBits xbits(x);
   uint32_t x_u = xbits.uintval();
 
@@ -69,17 +68,16 @@ LLVM_LIBC_FUNCTION(float, log2f, (float x)) {
     return 0.0f;
 
   // Exceptional inputs.
-  if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval() ||
-                    x_u > FPBits::max_normal().uintval())) {
+  if (LIBC_UNLIKELY(x_u < FPBits::MIN_NORMAL || x_u > FPBits::MAX_NORMAL)) {
     if (xbits.is_zero()) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits::inf(Sign::NEG).get_val();
+      return static_cast<float>(FPBits::inf(fputil::Sign::NEG));
     }
     if (xbits.is_neg() && !xbits.is_nan()) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except(FE_INVALID);
-      return FPBits::build_quiet_nan().get_val();
+      return FPBits::build_quiet_nan(0);
     }
     if (xbits.is_inf_or_nan()) {
       return x;
diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index 88f7ea01b2f19a5..8ccb55dcc9e3365 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -54,7 +54,6 @@ namespace LIBC_NAMESPACE {
 LLVM_LIBC_FUNCTION(float, logf, (float x)) {
   constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
   using FPBits = typename fputil::FPBits<float>;
-  using Sign = fputil::Sign;
   FPBits xbits(x);
   uint32_t x_u = xbits.uintval();
 
@@ -80,7 +79,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
 #endif // LIBC_TARGET_CPU_HAS_FMA
     }
     // Subnormal inputs.
-    if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
+    if (LIBC_UNLIKELY(x_u < FPBits::MIN_NORMAL)) {
       if (x_u == 0) {
         // Return -inf and raise FE_DIVBYZERO
         fputil::set_errno_if_required(ERANGE);
@@ -113,18 +112,18 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
 #endif // LIBC_TARGET_CPU_HAS_FMA
     }
     // Exceptional inputs.
-    if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
+    if (LIBC_UNLIKELY(x_u > FPBits::MAX_NORMAL)) {
       if (x_u == 0x8000'0000U) {
         // Return -inf and raise FE_DIVBYZERO
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_DIVBYZERO);
-        return FPBits::inf(Sign::NEG).get_val();
+        return static_cast<float>(FPBits::inf(fputil::Sign::NEG));
       }
       if (xbits.is_neg() && !xbits.is_nan()) {
         // Return NaN and raise FE_INVALID
         fputil::set_errno_if_required(EDOM);
         fputil::raise_except_if_required(FE_INVALID);
-        return FPBits::build_quiet_nan().get_val();
+        return FPBits::build_quiet_nan(0);
       }
       // x is +inf or nan
       return x;
diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp
index 0e164ab8b422537..932f1d70c33e8ec 100644
--- a/libc/src/math/generic/powf.cpp
+++ b/libc/src/math/generic/powf.cpp
@@ -547,15 +547,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
@@ -618,7 +617,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_is_neg ? Sign::NEG : Sign::POS).get_val();
+        return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS);
       }
       // pow(0, positive number) = 0
       return out_is_neg ? -0.0f : 0.0f;
@@ -629,7 +628,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
       if (y_u >= FloatBits::SIGN_MASK) {
         return out_is_neg ? -0.0f : 0.0f;
       }
-      return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS).get_val();
+      return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS);
     }
     }
 
@@ -657,7 +656,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
         // pow( negative, non-integer ) = NaN
         fputil::set_errno_if_required(EDOM);
         fputil::raise_except_if_required(FE_INVALID);
-        return FloatBits::build_quiet_nan().get_val();
+        return FloatBits::build_quiet_nan(0);
       }
     }
   }
diff --git a/libc/src/math/generic/sincosf.cpp b/libc/src/math/generic/sincosf.cpp
index f12b93a0e69653b..44371db710871ac 100644
--- a/libc/src/math/generic/sincosf.cpp
+++ b/libc/src/math/generic/sincosf.cpp
@@ -148,9 +148,7 @@ LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
     }
-    *sinp =
-        x +
-        FPBits::build_nan(fputil::Sign::POS, FPBits::FRACTION_MASK).get_val();
+    *sinp = x + FPBits::build_nan(FPBits::FRACTION_MASK);
     *cosp = *sinp;
     return;
   }
diff --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp
index 7ba479f0a45980a..9e574d4e5724029 100644
--- a/libc/src/math/generic/sinf.cpp
+++ b/libc/src/math/generic/sinf.cpp
@@ -139,7 +139,7 @@ LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
     }
-    return x + FPBits::build_quiet_nan().get_val();
+    return x + FPBits::build_quiet_nan(0);
   }
 
   // Combine the results with the sine of sum formula:
diff --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp
index 780c9a1f8d6ac35..b3850c674270665 100644
--- a/libc/src/math/generic/sinhf.cpp
+++ b/libc/src/math/generic/sinhf.cpp
@@ -56,16 +56,16 @@ LLVM_LIBC_FUNCTION(float, sinhf, (float x)) {
     int rounding = fputil::quick_get_round();
     if (xbits.is_neg()) {
       if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
-        return -FPBits::max_normal().get_val();
+        return -FPBits::max_normal();
     } else {
       if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
-        return FPBits::max_normal().get_val();
+        return FPBits::max_normal();
     }
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
 
-    return x + FPBits::inf(xbits.sign()).get_val();
+    return x + FPBits::inf(xbits.sign());
   }
 
   // sinh(x) = (e^x - e^(-x)) / 2.
diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp
index 09dd62eae03f808..7909e9e5d5568a3 100644
--- a/libc/src/math/generic/tanf.cpp
+++ b/libc/src/math/generic/tanf.cpp
@@ -114,7 +114,7 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
         fputil::set_errno_if_required(EDOM);
         fputil::raise_except_if_required(FE_INVALID);
       }
-      return x + FPBits::build_quiet_nan().get_val();
+      return x + FPBits::build_quiet_nan(0);
     }
     // Other large exceptional values
     if (auto r = TANF_EXCEPTS.lookup_odd(x_abs, x_sign);
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 9880fa51c54811a..26b8e3e60bdfd61 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -66,16 +66,16 @@ template <typename T> struct FPTest : public Test {
   using Sign = LIBC_NAMESPACE::fputil::Sign;
   static constexpr StorageType STORAGE_MAX =
       LIBC_NAMESPACE::cpp::numeric_limits<StorageType>::max();
-  static constexpr T zero = T(FPBits::zero(Sign::POS));
-  static constexpr T neg_zero = T(FPBits::zero(Sign::NEG));
-  static constexpr T aNaN = T(FPBits::build_quiet_nan(Sign::POS, 1));
-  static constexpr T sNaN = T(FPBits::build_nan(Sign::POS, 1));
-  static constexpr T inf = T(FPBits::inf(Sign::POS));
-  static constexpr T neg_inf = T(FPBits::inf(Sign::NEG));
-  static constexpr T min_normal = T(FPBits::min_normal());
-  static constexpr T max_normal = T(FPBits::max_normal());
-  static constexpr T min_denormal = T(FPBits::min_subnormal());
-  static constexpr T max_denormal = T(FPBits::max_subnormal());
+  static constexpr T zero = FPBits::zero(Sign::POS);
+  static constexpr T neg_zero = FPBits::zero(Sign::NEG);
+  static constexpr T aNaN = FPBits::build_quiet_nan(1);
+  static constexpr T sNaN = FPBits::build_nan(1);
+  static constexpr T inf = FPBits::inf(Sign::POS);
+  static constexpr T neg_inf = FPBits::inf(Sign::NEG);
+  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();
 
   static constexpr int N_ROUNDING_MODES = 4;
   static constexpr fputil::testing::RoundingMode ROUNDING_MODES[4] = {
@@ -95,16 +95,16 @@ template <typename T> struct FPTest : public Test {
   using Sign = LIBC_NAMESPACE::fputil::Sign;                                   \
   static constexpr StorageType STORAGE_MAX =                                   \
       LIBC_NAMESPACE::cpp::numeric_limits<StorageType>::max();                 \
-  const T zero = T(FPBits::zero(Sign::POS));                                   \
-  const T neg_zero = T(FPBits::zero(Sign::NEG));                               \
-  const T aNaN = T(FPBits::build_quiet_nan(Sign::POS, 1));                     \
-  const T sNaN = T(FPBits::build_nan(Sign::POS, 1));                           \
-  const T inf = T(FPBits::inf(Sign::POS));                                     \
-  const T neg_inf = T(FPBits::inf(Sign::NEG));                                 \
-  const T min_normal = T(FPBits::min_normal());                                \
-  const T max_normal = T(FPBits::max_normal());                                \
-  const T min_denormal = T(FPBits::min_subnormal());                           \
-  const T max_denormal = T(FPBits::max_subnormal());
+  const T zero = FPBits::zero(Sign::POS);                                      \
+  const T neg_zero = FPBits::zero(Sign::NEG);                                  \
+  const T aNaN = FPBits::build_quiet_nan(1);                                   \
+  const T sNaN = FPBits::build_nan(1);                                         \
+  const T inf = FPBits::inf(Sign::POS);                                        \
+  const T neg_inf = FPBits::inf(Sign::NEG);                                    \
+  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 db9f6750bedef12..e6b6d7d9ec78090 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -232,11 +232,13 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) {
 TEST(LlvmLibcFPBitsTest, FloatType) {
   using FloatBits = FPBits<float>;
 
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::inf(Sign::POS)).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::inf(Sign::NEG)).c_str(),
-               "(-Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::build_nan(Sign::POS, 1)).c_str(),
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(FloatBits(FloatBits::inf(Sign::POS))).c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(FloatBits(FloatBits::inf(Sign::NEG))).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits(FloatBits::build_nan(1))).c_str(),
                "(NaN)");
 
   FloatBits zero(0.0f);
@@ -287,19 +289,22 @@ TEST(LlvmLibcFPBitsTest, FloatType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
                "0xBF900000 = (S: 1, E: 0x007F, M: 0x00100000)");
 
-  FloatBits quiet_nan = FloatBits::build_quiet_nan(Sign::POS, 1);
+  FloatBits quiet_nan = FloatBits(FloatBits::build_quiet_nan(1));
   EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
 }
 
 TEST(LlvmLibcFPBitsTest, DoubleType) {
   using DoubleBits = FPBits<double>;
 
-  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::inf(Sign::POS)).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::inf(Sign::NEG)).c_str(),
-               "(-Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::build_nan(Sign::POS, 1)).c_str(),
-               "(NaN)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(DoubleBits(DoubleBits::inf(Sign::POS))).c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(DoubleBits(DoubleBits::inf(Sign::NEG))).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(DoubleBits(DoubleBits::build_nan(1))).c_str(),
+      "(NaN)");
 
   DoubleBits zero(0.0);
   EXPECT_TRUE(zero.is_pos());
@@ -349,7 +354,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
   EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
                "0xBFF2000000000000 = (S: 1, E: 0x03FF, M: 0x0002000000000000)");
 
-  DoubleBits quiet_nan = DoubleBits::build_quiet_nan(Sign::POS, 1);
+  DoubleBits quiet_nan = DoubleBits(DoubleBits::build_quiet_nan(1));
   EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
 }
 
@@ -360,12 +365,16 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
   if constexpr (sizeof(long double) == sizeof(double))
     return; // The tests for the "double" type cover for this case.
 
-  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(),
-               "(-Infinity)");
   EXPECT_STREQ(
-      LIBC_NAMESPACE::str(LongDoubleBits::build_nan(Sign::POS, 1)).c_str(),
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::POS)))
+          .c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::NEG)))
+          .c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::build_nan(1))).c_str(),
       "(NaN)");
 
   LongDoubleBits zero(0.0l);
@@ -431,7 +440,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
       "0x000000000000BFFF9000000000000000 = "
       "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)");
 
-  LongDoubleBits quiet_nan = LongDoubleBits::build_quiet_nan(Sign::POS, 1);
+  LongDoubleBits quiet_nan = LongDoubleBits(LongDoubleBits::build_quiet_nan(1));
   EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
 }
 #else
@@ -441,12 +450,16 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
 #else
   using LongDoubleBits = FPBits<long double>;
 
-  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(),
-               "(-Infinity)");
   EXPECT_STREQ(
-      LIBC_NAMESPACE::str(LongDoubleBits::build_nan(Sign::POS, 1)).c_str(),
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::POS)))
+          .c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::NEG)))
+          .c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::build_nan(1))).c_str(),
       "(NaN)");
 
   LongDoubleBits zero(0.0l);
@@ -506,7 +519,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
                "0xBFFF2000000000000000000000000000 = "
                "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
 
-  LongDoubleBits quiet_nan = LongDoubleBits::build_quiet_nan(1);
+  LongDoubleBits quiet_nan = LongDoubleBits(LongDoubleBits::build_quiet_nan(1));
   EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
 #endif
 }
@@ -516,15 +529,17 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
 TEST(LlvmLibcFPBitsTest, Float128Type) {
   using Float128Bits = FPBits<float128>;
 
-  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::inf(Sign::POS)).c_str(),
-               "(+Infinity)");
-  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::inf(Sign::NEG)).c_str(),
-               "(-Infinity)");
   EXPECT_STREQ(
-      LIBC_NAMESPACE::str(Float128Bits::build_nan(Sign::POS, 1)).c_str(),
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::inf(Sign::POS))).c_str(),
+      "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::inf(Sign::NEG))).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::build_nan(1))).c_str(),
       "(NaN)");
 
-  Float128Bits zero = Float128Bits::zero(Sign::POS);
+  Float128Bits zero(Float128Bits::zero());
   EXPECT_TRUE(zero.is_pos());
   EXPECT_EQ(zero.get_biased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -534,7 +549,7 @@ TEST(LlvmLibcFPBitsTest, Float128Type) {
                "0x00000000000000000000000000000000 = "
                "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");
 
-  Float128Bits negzero = Float128Bits::zero(Sign::NEG);
+  Float128Bits negzero(Float128Bits::zero(Sign::NEG));
   EXPECT_TRUE(negzero.is_neg());
   EXPECT_EQ(negzero.get_biased_exponent(), static_cast<uint16_t>(0x0000));
   EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
@@ -581,7 +596,7 @@ TEST(LlvmLibcFPBitsTest, Float128Type) {
                "0xBFFF2000000000000000000000000000 = "
                "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
 
-  Float128Bits quiet_nan = Float128Bits::build_quiet_nan(Sign::POS, 1);
+  Float128Bits quiet_nan = Float128Bits(Float128Bits::build_quiet_nan(1));
   EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
 }
 #endif // LIBC_COMPILER_HAS_FLOAT128
diff --git a/libc/test/src/math/FDimTest.h b/libc/test/src/math/FDimTest.h
index c3d9cb1801cd440..0744e6ea8fd8fe8 100644
--- a/libc/test/src/math/FDimTest.h
+++ b/libc/test/src/math/FDimTest.h
@@ -24,7 +24,7 @@ class FDimTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
   void test_na_n_arg(FuncPtr func) {
     EXPECT_FP_EQ(nan, func(nan, inf));
diff --git a/libc/test/src/math/FmaTest.h b/libc/test/src/math/FmaTest.h
index 4343b38053dc47e..032a79821d59013 100644
--- a/libc/test/src/math/FmaTest.h
+++ b/libc/test/src/math/FmaTest.h
@@ -25,21 +25,11 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
   using StorageType = typename FPBits::StorageType;
   using Sign = LIBC_NAMESPACE::fputil::Sign;
 
-  const T min_subnormal = T(FPBits::min_subnormal(Sign::POS));
-  const T min_normal = T(FPBits::min_normal(Sign::POS));
-  const T max_normal = T(FPBits::max_normal(Sign::POS));
   const T inf = T(FPBits::inf(Sign::POS));
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
-  static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-  static constexpr StorageType MAX_SUBNORMAL =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType MIN_SUBNORMAL =
-      FPBits::min_subnormal().uintval();
+  const T nan = T(FPBits::build_quiet_nan(1));
 
   StorageType get_random_bit_pattern() {
     StorageType bits{0};
@@ -62,13 +52,14 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
     EXPECT_FP_EQ(func(inf, neg_inf, nan), nan);
 
     // Test underflow rounding up.
-    EXPECT_FP_EQ(func(T(0.5), min_subnormal, min_subnormal),
+    EXPECT_FP_EQ(func(T(0.5), FPBits::min_denormal(), FPBits::min_denormal()),
                  T(FPBits(StorageType(2))));
     // Test underflow rounding down.
-    T v = T(FPBits(MIN_NORMAL + StorageType(1)));
-    EXPECT_FP_EQ(func(T(1) / T(MIN_NORMAL << 1), v, min_normal), v);
+    T v = T(FPBits(FPBits::MIN_NORMAL + StorageType(1)));
+    EXPECT_FP_EQ(
+        func(T(1) / T(FPBits::MIN_NORMAL << 1), v, FPBits::min_normal()), v);
     // Test overflow.
-    T z = max_normal;
+    T z = FPBits::max_normal();
     EXPECT_FP_EQ(func(T(1.75), z, -z), T(0.75) * z);
     // Exact cancellation.
     EXPECT_FP_EQ(func(T(3.0), T(5.0), -T(15.0)), T(0.0));
@@ -77,9 +68,11 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void test_subnormal_range(Func func) {
     constexpr StorageType COUNT = 100'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType v = MIN_SUBNORMAL, w = MAX_SUBNORMAL;
-         v <= MAX_SUBNORMAL && w >= MIN_SUBNORMAL; v += STEP, w -= STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_SUBNORMAL, w = FPBits::MAX_SUBNORMAL;
+         v <= FPBits::MAX_SUBNORMAL && w >= FPBits::MIN_SUBNORMAL;
+         v += STEP, w -= STEP) {
       T x = T(FPBits(get_random_bit_pattern())), y = T(FPBits(v)),
         z = T(FPBits(w));
       mpfr::TernaryInput<T> input{x, y, z};
@@ -90,9 +83,11 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void test_normal_range(Func func) {
     constexpr StorageType COUNT = 100'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
-    for (StorageType v = MIN_NORMAL, w = MAX_NORMAL;
-         v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL;
+         v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL;
+         v += STEP, w -= STEP) {
       T x = T(FPBits(v)), y = T(FPBits(w)),
         z = T(FPBits(get_random_bit_pattern()));
       mpfr::TernaryInput<T> input{x, y, z};
diff --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h
index 0b85f68fda82aec..b7eb63c192c70ca 100644
--- a/libc/test/src/math/HypotTest.h
+++ b/libc/test/src/math/HypotTest.h
@@ -25,22 +25,15 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
   using Sign = LIBC_NAMESPACE::fputil::Sign;
   using StorageType = typename FPBits::StorageType;
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-  const T inf = T(FPBits::inf());
-  const T neg_inf = T(FPBits::inf(Sign::NEG));
-  const T zero = T(FPBits::zero());
-  const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T max_normal = T(FPBits::max_normal());
-  const T min_normal = T(FPBits::min_normal());
-  const T max_subnormal = T(FPBits::max_subnormal());
-  const T min_subnormal = T(FPBits::min_subnormal());
-
-  static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
-  static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-  static constexpr StorageType MAX_SUBNORMAL =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType MIN_SUBNORMAL =
-      FPBits::min_subnormal().uintval();
+  const T nan = FPBits::build_quiet_nan(1);
+  const T inf = FPBits::inf();
+  const T neg_inf = FPBits::inf(Sign::NEG);
+  const T zero = FPBits::zero();
+  const T neg_zero = FPBits::zero(Sign::NEG);
+  const T max_normal = FPBits::max_normal();
+  const T min_normal = FPBits::min_normal();
+  const T max_subnormal = FPBits::max_denormal();
+  const T min_subnormal = FPBits::min_denormal();
 
 public:
   void test_special_numbers(Func func) {
@@ -69,11 +62,12 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test {
   void test_subnormal_range(Func func) {
     constexpr StorageType COUNT = 10'001;
     for (unsigned scale = 0; scale < 4; ++scale) {
-      StorageType max_value = MAX_SUBNORMAL << scale;
-      StorageType step = (max_value - MIN_SUBNORMAL) / COUNT;
+      StorageType max_value = FPBits::MAX_SUBNORMAL << scale;
+      StorageType step = (max_value - FPBits::MIN_SUBNORMAL) / COUNT;
       for (int signs = 0; signs < 4; ++signs) {
-        for (StorageType v = MIN_SUBNORMAL, w = max_value;
-             v <= max_value && w >= MIN_SUBNORMAL; v += step, w -= step) {
+        for (StorageType v = FPBits::MIN_SUBNORMAL, w = max_value;
+             v <= max_value && w >= FPBits::MIN_SUBNORMAL;
+             v += step, w -= step) {
           T x = T(FPBits(v)), y = T(FPBits(w));
           if (signs % 2 == 1) {
             x = -x;
@@ -92,10 +86,13 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void test_normal_range(Func func) {
     constexpr StorageType COUNT = 10'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
+    constexpr StorageType STEP =
+        (StorageType(FPBits::MAX_NORMAL) - StorageType(FPBits::MIN_NORMAL)) /
+        COUNT;
     for (int signs = 0; signs < 4; ++signs) {
-      for (StorageType v = MIN_NORMAL, w = MAX_NORMAL;
-           v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) {
+      for (StorageType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL;
+           v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL;
+           v += STEP, w -= STEP) {
         T x = T(FPBits(v)), y = T(FPBits(w));
         if (signs % 2 == 1) {
           x = -x;
diff --git a/libc/test/src/math/ILogbTest.h b/libc/test/src/math/ILogbTest.h
index 223de789999afea..9fa25c9ff986148 100644
--- a/libc/test/src/math/ILogbTest.h
+++ b/libc/test/src/math/ILogbTest.h
@@ -26,10 +26,10 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
   void test_special_numbers(typename ILogbFunc<T>::Func func) {
     using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
     using Sign = LIBC_NAMESPACE::fputil::Sign;
-    EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::POS))));
+    EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero())));
     EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::NEG))));
-    EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(Sign::POS, 1))));
-    EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::POS))));
+    EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(1))));
+    EXPECT_EQ(INT_MAX, func(T(FPBits::inf())));
     EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::NEG))));
   }
 
@@ -76,11 +76,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
   void test_subnormal_range(typename ILogbFunc<T>::Func func) {
     using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
     using StorageType = typename FPBits::StorageType;
-    constexpr StorageType MIN_SUBNORMAL = FPBits::min_subnormal().uintval();
-    constexpr StorageType MAX_SUBNORMAL = FPBits::max_subnormal().uintval();
     constexpr StorageType COUNT = 10'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType v = MIN_SUBNORMAL; v <= MAX_SUBNORMAL; v += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_SUBNORMAL; v <= FPBits::MAX_SUBNORMAL;
+         v += STEP) {
       T x = T(FPBits(v));
       if (isnan(x) || isinf(x) || x == 0.0)
         continue;
@@ -95,11 +95,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
   void test_normal_range(typename ILogbFunc<T>::Func func) {
     using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
     using StorageType = typename FPBits::StorageType;
-    constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-    constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
     constexpr StorageType COUNT = 10'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
-    for (StorageType v = MIN_NORMAL; v <= MAX_NORMAL; v += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_NORMAL; v <= FPBits::MAX_NORMAL;
+         v += STEP) {
       T x = T(FPBits(v));
       if (isnan(x) || isinf(x) || x == 0.0)
         continue;
diff --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h
index 3a4baabbf10e663..25120ba3646fda0 100644
--- a/libc/test/src/math/LdExpTest.h
+++ b/libc/test/src/math/LdExpTest.h
@@ -29,7 +29,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
   // A normalized mantissa to be used with tests.
   static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x1234;
diff --git a/libc/test/src/math/NextAfterTest.h b/libc/test/src/math/NextAfterTest.h
index 9ff3bf73d2ede17..aa9646fd921f811 100644
--- a/libc/test/src/math/NextAfterTest.h
+++ b/libc/test/src/math/NextAfterTest.h
@@ -27,12 +27,12 @@ class NextAfterTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
-  const StorageType min_subnormal = FPBits::min_subnormal().uintval();
-  const StorageType max_subnormal = FPBits::max_subnormal().uintval();
-  const StorageType min_normal = FPBits::min_normal().uintval();
-  const StorageType max_normal = FPBits::max_normal().uintval();
+  const StorageType min_subnormal = FPBits::MIN_SUBNORMAL;
+  const StorageType max_subnormal = FPBits::MAX_SUBNORMAL;
+  const StorageType min_normal = FPBits::MIN_NORMAL;
+  const StorageType max_normal = FPBits::MAX_NORMAL;
 
 public:
   typedef T (*NextAfterFunc)(T, T);
diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h
index b478e3f65dbc8ea..6816e94d389f4e3 100644
--- a/libc/test/src/math/RIntTest.h
+++ b/libc/test/src/math/RIntTest.h
@@ -38,14 +38,7 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  static constexpr StorageType MIN_SUBNORMAL =
-      FPBits::min_subnormal().uintval();
-  static constexpr StorageType MAX_SUBNORMAL =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-  static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
+  const T nan = T(FPBits::build_quiet_nan(1));
 
   static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) {
     switch (mode) {
@@ -102,8 +95,10 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void testSubnormalRange(RIntFunc func) {
     constexpr StorageType COUNT = 100'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL;
+         i += STEP) {
       T x = T(FPBits(i));
       for (int mode : ROUNDING_MODES) {
         LIBC_NAMESPACE::fputil::set_round(mode);
@@ -115,8 +110,10 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void testNormalRange(RIntFunc func) {
     constexpr StorageType COUNT = 100'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
-    for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
+    for (StorageType i = FPBits::MIN_NORMAL; i <= FPBits::MAX_NORMAL;
+         i += STEP) {
       T x = T(FPBits(i));
       // In normal range on x86 platforms, the long double implicit 1 bit can be
       // zero making the numbers NaN. We will skip them.
diff --git a/libc/test/src/math/RemQuoTest.h b/libc/test/src/math/RemQuoTest.h
index 0ee41f4bf9acf9d..9ed952566245217 100644
--- a/libc/test/src/math/RemQuoTest.h
+++ b/libc/test/src/math/RemQuoTest.h
@@ -28,14 +28,7 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  static constexpr StorageType MIN_SUBNORMAL =
-      FPBits::min_subnormal().uintval();
-  static constexpr StorageType MAX_SUBNORMAL =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-  static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
+  const T nan = T(FPBits::build_quiet_nan(1));
 
 public:
   typedef T (*RemQuoFunc)(T, T, int *);
@@ -104,9 +97,11 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void testSubnormalRange(RemQuoFunc func) {
     constexpr StorageType COUNT = 100'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType v = MIN_SUBNORMAL, w = MAX_SUBNORMAL;
-         v <= MAX_SUBNORMAL && w >= MIN_SUBNORMAL; v += STEP, w -= STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_SUBNORMAL, w = FPBits::MAX_SUBNORMAL;
+         v <= FPBits::MAX_SUBNORMAL && w >= FPBits::MIN_SUBNORMAL;
+         v += STEP, w -= STEP) {
       T x = T(FPBits(v)), y = T(FPBits(w));
       mpfr::BinaryOutput<T> result;
       mpfr::BinaryInput<T> input{x, y};
@@ -117,9 +112,11 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void testNormalRange(RemQuoFunc func) {
     constexpr StorageType COUNT = 1'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
-    for (StorageType v = MIN_NORMAL, w = MAX_NORMAL;
-         v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL;
+         v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL;
+         v += STEP, w -= STEP) {
       T x = T(FPBits(v)), y = T(FPBits(w));
       mpfr::BinaryOutput<T> result;
       mpfr::BinaryInput<T> input{x, y};
diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h
index 6866c23cb99ca32..e8ada1b4c36c504 100644
--- a/libc/test/src/math/RoundToIntegerTest.h
+++ b/libc/test/src/math/RoundToIntegerTest.h
@@ -37,15 +37,7 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const F neg_zero = F(FPBits::zero(Sign::NEG));
   const F inf = F(FPBits::inf());
   const F neg_inf = F(FPBits::inf(Sign::NEG));
-  const F nan = F(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
-  static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-  static constexpr StorageType MAX_SUBNORMAL =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType MIN_SUBNORMAL =
-      FPBits::min_subnormal().uintval();
-
+  const F nan = F(FPBits::build_quiet_nan(1));
   static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1);
   static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1);
 
@@ -223,8 +215,10 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void testSubnormalRange(RoundToIntegerFunc func) {
     constexpr StorageType COUNT = 1'000'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL;
+         i += STEP) {
       F x = F(FPBits(i));
       if (x == F(0.0))
         continue;
@@ -265,8 +259,10 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test {
       return;
 
     constexpr StorageType COUNT = 1'000'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
-    for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
+    for (StorageType i = FPBits::MIN_NORMAL; i <= FPBits::MAX_NORMAL;
+         i += STEP) {
       F x = F(FPBits(i));
       // In normal range on x86 platforms, the long double implicit 1 bit can be
       // zero making the numbers NaN. We will skip them.
diff --git a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h b/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h
index 48572e78e5153e0..ada7c9e4954265d 100644
--- a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h
+++ b/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h
@@ -109,13 +109,10 @@ template <typename T> class BinaryOpSingleOutputDiff {
     std::ofstream log(logFile);
     log << " Performance tests with inputs in denormal range:\n";
     run_perf_in_range(myFunc, otherFunc, /* startingBit= */ StorageType(0),
-                      /* endingBit= */ FPBits::max_subnormal().uintval(),
-                      1'000'001, log);
+                      /* endingBit= */ FPBits::MAX_SUBNORMAL, 1'000'001, log);
     log << "\n Performance tests with inputs in normal range:\n";
-    run_perf_in_range(myFunc, otherFunc,
-                      /* startingBit= */ FPBits::min_normal().uintval(),
-                      /* endingBit= */ FPBits::max_normal().uintval(),
-                      100'000'001, log);
+    run_perf_in_range(myFunc, otherFunc, /* startingBit= */ FPBits::MIN_NORMAL,
+                      /* endingBit= */ FPBits::MAX_NORMAL, 100'000'001, log);
     log << "\n Performance tests with inputs in normal range with exponents "
            "close to each other:\n";
     run_perf_in_range(
@@ -129,12 +126,11 @@ template <typename T> class BinaryOpSingleOutputDiff {
     log << " Diff tests with inputs in denormal range:\n";
     diffCount += run_diff_in_range(
         myFunc, otherFunc, /* startingBit= */ StorageType(0),
-        /* endingBit= */ FPBits::max_subnormal().uintval(), 1'000'001, log);
+        /* endingBit= */ FPBits::MAX_SUBNORMAL, 1'000'001, log);
     log << "\n Diff tests with inputs in normal range:\n";
     diffCount += run_diff_in_range(
-        myFunc, otherFunc,
-        /* startingBit= */ FPBits::min_normal().uintval(),
-        /* endingBit= */ FPBits::max_normal().uintval(), 100'000'001, log);
+        myFunc, otherFunc, /* startingBit= */ FPBits::MIN_NORMAL,
+        /* endingBit= */ FPBits::MAX_NORMAL, 100'000'001, log);
     log << "\n Diff tests with inputs in normal range with exponents "
            "close to each other:\n";
     diffCount += run_diff_in_range(
diff --git a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h b/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h
index 5e8310e889dc670..e4cd06eb22b7162 100644
--- a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h
+++ b/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h
@@ -93,11 +93,10 @@ template <typename T> class SingleInputSingleOutputDiff {
     std::ofstream log(logFile);
     log << " Performance tests with inputs in denormal range:\n";
     runPerfInRange(myFunc, otherFunc, /* startingBit= */ StorageType(0),
-                   /* endingBit= */ FPBits::max_subnormal().uintval(), log);
+                   /* endingBit= */ FPBits::MAX_SUBNORMAL, log);
     log << "\n Performance tests with inputs in normal range:\n";
-    runPerfInRange(myFunc, otherFunc,
-                   /* startingBit= */ FPBits::min_normal().uintval(),
-                   /* endingBit= */ FPBits::max_normal().uintval(), log);
+    runPerfInRange(myFunc, otherFunc, /* startingBit= */ FPBits::MIN_NORMAL,
+                   /* endingBit= */ FPBits::MAX_NORMAL, log);
   }
 };
 
diff --git a/libc/test/src/math/smoke/FDimTest.h b/libc/test/src/math/smoke/FDimTest.h
index c3d9cb1801cd440..0744e6ea8fd8fe8 100644
--- a/libc/test/src/math/smoke/FDimTest.h
+++ b/libc/test/src/math/smoke/FDimTest.h
@@ -24,7 +24,7 @@ class FDimTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
   void test_na_n_arg(FuncPtr func) {
     EXPECT_FP_EQ(nan, func(nan, inf));
diff --git a/libc/test/src/math/smoke/FmaTest.h b/libc/test/src/math/smoke/FmaTest.h
index 337ce659a23e176..dc624d871b9901b 100644
--- a/libc/test/src/math/smoke/FmaTest.h
+++ b/libc/test/src/math/smoke/FmaTest.h
@@ -25,7 +25,7 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
 public:
   void test_special_numbers(Func func) {
@@ -39,16 +39,14 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
     EXPECT_FP_EQ(func(inf, neg_inf, nan), nan);
 
     // Test underflow rounding up.
-    EXPECT_FP_EQ(
-        func(T(0.5), T(FPBits::min_subnormal()), T(FPBits::min_subnormal())),
-        T(FPBits(StorageType(2))));
+    EXPECT_FP_EQ(func(T(0.5), FPBits::min_denormal(), FPBits::min_denormal()),
+                 T(FPBits(StorageType(2))));
     // Test underflow rounding down.
-    StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-    T v = T(FPBits(MIN_NORMAL + StorageType(1)));
-    EXPECT_FP_EQ(func(T(1) / T(MIN_NORMAL << 1), v, T(FPBits::min_normal())),
-                 v);
+    T v = T(FPBits(FPBits::MIN_NORMAL + StorageType(1)));
+    EXPECT_FP_EQ(
+        func(T(1) / T(FPBits::MIN_NORMAL << 1), v, FPBits::min_normal()), v);
     // Test overflow.
-    T z = T(FPBits::max_normal());
+    T z = FPBits::max_normal();
     EXPECT_FP_EQ(func(T(1.75), z, -z), T(0.75) * z);
     // Exact cancellation.
     EXPECT_FP_EQ(func(T(3.0), T(5.0), -T(15.0)), T(0.0));
diff --git a/libc/test/src/math/smoke/HypotTest.h b/libc/test/src/math/smoke/HypotTest.h
index 67110536b962389..77454c19a6538c6 100644
--- a/libc/test/src/math/smoke/HypotTest.h
+++ b/libc/test/src/math/smoke/HypotTest.h
@@ -22,16 +22,16 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
   using StorageType = typename FPBits::StorageType;
   using Sign = LIBC_NAMESPACE::fputil::Sign;
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-  const T inf = T(FPBits::inf(Sign::POS));
-  const T neg_inf = T(FPBits::inf(Sign::NEG));
-  const T zero = T(FPBits::zero(Sign::POS));
-  const T neg_zero = T(FPBits::zero(Sign::NEG));
-
-  const T max_normal = T(FPBits::max_normal());
-  const T min_normal = T(FPBits::min_normal());
-  const T max_subnormal = T(FPBits::max_subnormal());
-  const T min_subnormal = T(FPBits::min_subnormal());
+  const T nan = FPBits::build_quiet_nan(1);
+  const T inf = FPBits::inf(Sign::POS);
+  const T neg_inf = FPBits::inf(Sign::NEG);
+  const T zero = FPBits::zero(Sign::POS);
+  const T neg_zero = FPBits::zero(Sign::NEG);
+
+  const T max_normal = FPBits::max_normal();
+  const T min_normal = FPBits::min_normal();
+  const T max_subnormal = FPBits::max_denormal();
+  const T min_subnormal = FPBits::min_denormal();
 
 public:
   void test_special_numbers(Func func) {
diff --git a/libc/test/src/math/smoke/ILogbTest.h b/libc/test/src/math/smoke/ILogbTest.h
index 223de789999afea..0a50abc04f727f1 100644
--- a/libc/test/src/math/smoke/ILogbTest.h
+++ b/libc/test/src/math/smoke/ILogbTest.h
@@ -28,7 +28,7 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
     using Sign = LIBC_NAMESPACE::fputil::Sign;
     EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::POS))));
     EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::NEG))));
-    EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(Sign::POS, 1))));
+    EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(1))));
     EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::POS))));
     EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::NEG))));
   }
@@ -76,11 +76,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
   void test_subnormal_range(typename ILogbFunc<T>::Func func) {
     using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
     using StorageType = typename FPBits::StorageType;
-    constexpr StorageType MIN_SUBNORMAL = FPBits::min_subnormal().uintval();
-    constexpr StorageType MAX_SUBNORMAL = FPBits::max_subnormal().uintval();
     constexpr StorageType COUNT = 10'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType v = MIN_SUBNORMAL; v <= MAX_SUBNORMAL; v += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_SUBNORMAL; v <= FPBits::MAX_SUBNORMAL;
+         v += STEP) {
       T x = T(FPBits(v));
       if (isnan(x) || isinf(x) || x == 0.0)
         continue;
@@ -95,11 +95,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
   void test_normal_range(typename ILogbFunc<T>::Func func) {
     using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
     using StorageType = typename FPBits::StorageType;
-    constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-    constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
     constexpr StorageType COUNT = 10'001;
-    constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
-    for (StorageType v = MIN_NORMAL; v <= MAX_NORMAL; v += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
+    for (StorageType v = FPBits::MIN_NORMAL; v <= FPBits::MAX_NORMAL;
+         v += STEP) {
       T x = T(FPBits(v));
       if (isnan(x) || isinf(x) || x == 0.0)
         continue;
diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h
index 3a4baabbf10e663..25120ba3646fda0 100644
--- a/libc/test/src/math/smoke/LdExpTest.h
+++ b/libc/test/src/math/smoke/LdExpTest.h
@@ -29,7 +29,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
   // A normalized mantissa to be used with tests.
   static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x1234;
diff --git a/libc/test/src/math/smoke/NextAfterTest.h b/libc/test/src/math/smoke/NextAfterTest.h
index 1dd07b3d2f93dc0..bdf3da627180aa4 100644
--- a/libc/test/src/math/smoke/NextAfterTest.h
+++ b/libc/test/src/math/smoke/NextAfterTest.h
@@ -38,14 +38,12 @@ class NextAfterTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  static constexpr StorageType min_subnormal =
-      FPBits::min_subnormal().uintval();
-  static constexpr StorageType max_subnormal =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType min_normal = FPBits::min_normal().uintval();
-  static constexpr StorageType max_normal = FPBits::max_normal().uintval();
+  const T nan = T(FPBits::build_quiet_nan(1));
+
+  const StorageType min_subnormal = FPBits::MIN_SUBNORMAL;
+  const StorageType max_subnormal = FPBits::MAX_SUBNORMAL;
+  const StorageType min_normal = FPBits::MIN_NORMAL;
+  const StorageType max_normal = FPBits::MAX_NORMAL;
 
 public:
   typedef T (*NextAfterFunc)(T, T);
diff --git a/libc/test/src/math/smoke/NextTowardTest.h b/libc/test/src/math/smoke/NextTowardTest.h
index d65cc5d84d35a58..af4e0ab14531c16 100644
--- a/libc/test/src/math/smoke/NextTowardTest.h
+++ b/libc/test/src/math/smoke/NextTowardTest.h
@@ -40,18 +40,16 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  const long double to_zero = ToFPBits::zero().get_val();
-  const long double to_neg_zero = ToFPBits::zero(Sign::NEG).get_val();
-  const long double to_nan = ToFPBits::build_quiet_nan(Sign::POS, 1).get_val();
-
-  static constexpr StorageType min_subnormal =
-      FPBits::min_subnormal().uintval();
-  static constexpr StorageType max_subnormal =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType min_normal = FPBits::min_normal().uintval();
-  static constexpr StorageType max_normal = FPBits::max_normal().uintval();
+  const T nan = T(FPBits::build_quiet_nan(1));
+
+  const long double to_zero = ToFPBits::zero();
+  const long double to_neg_zero = ToFPBits::zero(Sign::NEG);
+  const long double to_nan = ToFPBits::build_quiet_nan(1);
+
+  const StorageType min_subnormal = FPBits::MIN_SUBNORMAL;
+  const StorageType max_subnormal = FPBits::MAX_SUBNORMAL;
+  const StorageType min_normal = FPBits::MIN_NORMAL;
+  const StorageType max_normal = FPBits::MAX_NORMAL;
 
 public:
   typedef T (*NextTowardFunc)(T, long double);
diff --git a/libc/test/src/math/smoke/RIntTest.h b/libc/test/src/math/smoke/RIntTest.h
index 7bbbe5430157038..b242c7e441b69f0 100644
--- a/libc/test/src/math/smoke/RIntTest.h
+++ b/libc/test/src/math/smoke/RIntTest.h
@@ -35,7 +35,7 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
 public:
   void testSpecialNumbers(RIntFunc func) {
diff --git a/libc/test/src/math/smoke/RemQuoTest.h b/libc/test/src/math/smoke/RemQuoTest.h
index 5f5cbd4964a62fa..93e20747e52638c 100644
--- a/libc/test/src/math/smoke/RemQuoTest.h
+++ b/libc/test/src/math/smoke/RemQuoTest.h
@@ -25,7 +25,7 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test {
   const T neg_inf = T(FPBits::inf(Sign::NEG));
   const T zero = T(FPBits::zero(Sign::POS));
   const T neg_zero = T(FPBits::zero(Sign::NEG));
-  const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1));
+  const T nan = T(FPBits::build_quiet_nan(1));
 
 public:
   typedef T (*RemQuoFunc)(T, T, int *);
diff --git a/libc/test/src/math/smoke/RoundToIntegerTest.h b/libc/test/src/math/smoke/RoundToIntegerTest.h
index 77c65aa492e22de..2703b78f00e0f1f 100644
--- a/libc/test/src/math/smoke/RoundToIntegerTest.h
+++ b/libc/test/src/math/smoke/RoundToIntegerTest.h
@@ -30,17 +30,11 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test {
   using StorageType = typename FPBits::StorageType;
   using Sign = LIBC_NAMESPACE::fputil::Sign;
 
-  const F zero = F(FPBits::zero(Sign::POS));
-  const F neg_zero = F(FPBits::zero(Sign::NEG));
-  const F inf = F(FPBits::inf(Sign::POS));
-  const F neg_inf = F(FPBits::inf(Sign::NEG));
-  const F nan = F(FPBits::build_quiet_nan(Sign::POS, 1));
-
-  static constexpr StorageType MAX_SUBNORMAL =
-      FPBits::max_subnormal().uintval();
-  static constexpr StorageType MIN_SUBNORMAL =
-      FPBits::min_subnormal().uintval();
-
+  const F zero = F(LIBC_NAMESPACE::fputil::FPBits<F>::zero(Sign::POS));
+  const F neg_zero = F(LIBC_NAMESPACE::fputil::FPBits<F>::zero(Sign::NEG));
+  const F inf = F(LIBC_NAMESPACE::fputil::FPBits<F>::inf(Sign::POS));
+  const F neg_inf = F(LIBC_NAMESPACE::fputil::FPBits<F>::inf(Sign::NEG));
+  const F nan = F(LIBC_NAMESPACE::fputil::FPBits<F>::build_quiet_nan(1));
   static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1);
   static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1);
 
@@ -117,8 +111,10 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
   void testSubnormalRange(RoundToIntegerFunc func) {
     constexpr StorageType COUNT = 1'000'001;
-    constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
-    for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) {
+    constexpr StorageType STEP =
+        (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT;
+    for (StorageType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL;
+         i += STEP) {
       F x = F(FPBits(i));
       if (x == F(0.0))
         continue;
diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp
index b22378b22ab12c6..344853beaf9fa7b 100644
--- a/libc/test/src/stdio/sprintf_test.cpp
+++ b/libc/test/src/stdio/sprintf_test.cpp
@@ -585,10 +585,8 @@ TEST(LlvmLibcSPrintfTest, OctConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
-  double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(
-                   LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                   .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");
 
@@ -951,15 +949,11 @@ TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
-  double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(
-                   LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                   .get_val();
-  long double ld_inf =
-      LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
-  long double ld_nan = LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(
-                           LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                           .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();
+  long double ld_nan =
+      LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(1);
 
   char big_buff[10000]; // Used for long doubles and other extremely wide
                         // numbers.
@@ -1796,10 +1790,8 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
-  double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(
-                   LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                   .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);
   ASSERT_STREQ_LEN(written, buff, "1.000000e+00");
@@ -2430,10 +2422,8 @@ TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) {
 
 TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
   ForceRoundingMode r(RoundingMode::Nearest);
-  double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
-  double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(
-                   LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                   .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);
   ASSERT_STREQ_LEN(written, buff, "1");
diff --git a/libc/test/src/stdio/sscanf_test.cpp b/libc/test/src/stdio/sscanf_test.cpp
index db67c25029133c1..db3c48cdbf7a2d5 100644
--- a/libc/test/src/stdio/sscanf_test.cpp
+++ b/libc/test/src/stdio/sscanf_test.cpp
@@ -230,10 +230,8 @@ TEST(LlvmLibcSScanfTest, FloatConvSimple) {
   int ret_val;
   float result = 0;
 
-  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf().get_val();
-  float nan = LIBC_NAMESPACE::fputil::FPBits<float>::build_nan(
-                  LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                  .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);
   EXPECT_EQ(ret_val, 1);
@@ -296,10 +294,9 @@ TEST(LlvmLibcSScanfTest, FloatConvLengthModifier) {
   double d_result = 0;
   long double ld_result = 0;
 
-  double d_inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
-  long double ld_nan = LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(
-                           LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                           .get_val();
+  double d_inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf();
+  long double ld_nan =
+      LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(1);
 
   ret_val = LIBC_NAMESPACE::sscanf("123", "%lf", &d_result);
   EXPECT_EQ(ret_val, 1);
@@ -394,10 +391,8 @@ TEST(LlvmLibcSScanfTest, FloatConvComplexParsing) {
   int ret_val;
   float result = 0;
 
-  float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf().get_val();
-  float nan = LIBC_NAMESPACE::fputil::FPBits<float>::build_nan(
-                  LIBC_NAMESPACE::fputil::Sign::POS, 1)
-                  .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);
   EXPECT_EQ(ret_val, 1);
@@ -468,7 +463,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);
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 06a231c7d94d059..b6ca525db6cf742 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -49,7 +49,7 @@ template <> struct ExtraPrecision<long double> {
 template <typename T>
 static inline unsigned int get_precision(double ulp_tolerance) {
   if (ulp_tolerance <= 0.5) {
-    return LIBC_NAMESPACE::fputil::FPBits<T>::FRACTION_LEN + 1;
+    return LIBC_NAMESPACE::fputil::FPBits<T>::MANTISSA_PRECISION;
   } else {
     return ExtraPrecision<T>::VALUE;
   }



More information about the libc-commits mailing list