[libc-commits] [libc] [libc][math] Adding LIBC_MATH_ALWAYS_ROUND_NEAREST option (PR #201154)

Hoàng Minh Thiên via libc-commits libc-commits at lists.llvm.org
Wed Jun 10 07:05:13 PDT 2026


https://github.com/hmthien050209 updated https://github.com/llvm/llvm-project/pull/201154

>From 63c713c8cac7088a652402b366bb741fd67fb1d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Tue, 2 Jun 2026 21:40:23 +0700
Subject: [PATCH 1/9] feat: declared the macro and updated Hypot.h

---
 libc/src/__support/FPUtil/Hypot.h         | 16 ++++++++++++++++
 libc/src/__support/FPUtil/rounding_mode.h |  6 ++++++
 libc/src/__support/macros/optimization.h  |  5 +++++
 3 files changed, 27 insertions(+)

diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 292140065c754..480dbb3be195e 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -199,10 +199,14 @@ LIBC_INLINE T hypot(T x, T y) {
       sum >>= 2;
       ++out_exp;
       if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         if (int round_mode = quick_get_round();
             round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
           return FPBits_t::inf().get_val();
         return FPBits_t::max_normal().get_val();
+#else
+        return FPBits_t::inf().get_val();
+#endif // LIBC_HAS_ALWAYS_ROUND_NEAREST
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
@@ -241,6 +245,17 @@ LIBC_INLINE T hypot(T x, T y) {
 
   y_new >>= 1;
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  // Round to the nearest, tie to even.
+  if (round_bit && (lsb || sticky_bits || (r != 0)))
+    ++y_new;
+  if (y_new >= (ONE >> 1)) {
+    y_new -= ONE >> 1;
+    ++out_exp;
+    if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT)
+      return FPBits_t::inf().get_val();
+  }
+#else
   // Round to the nearest, tie to even.
   int round_mode = quick_get_round();
   switch (round_mode) {
@@ -264,6 +279,7 @@ LIBC_INLINE T hypot(T x, T y) {
       return FPBits_t::max_normal().get_val();
     }
   }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
   y_new |= static_cast<StorageType>(out_exp) << FPBits_t::FRACTION_LEN;
 
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 6ce693d41da50..3a4a41d8beacc 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -67,6 +67,7 @@ LIBC_INLINE bool fenv_is_round_to_zero() {
 
 // Quick free standing get rounding mode based on the above observations.
 LIBC_INLINE int quick_get_round() {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   static volatile float x = 0x1.0p-24f;
   float y = x;
   float z = (0x1.000002p0f + y) + (-1.0f - y);
@@ -76,6 +77,11 @@ LIBC_INLINE int quick_get_round() {
   if (z == 0x1.0p-23f)
     return FE_TOWARDZERO;
   return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+#else
+  // the optimization should've happened in each user of this function,
+  // but just in case
+  return FE_TONEAREST;
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 } // namespace generic
diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h
index 411653439c88c..ecfadc8a86ca0 100644
--- a/libc/src/__support/macros/optimization.h
+++ b/libc/src/__support/macros/optimization.h
@@ -56,6 +56,7 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
   (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES |                     \
    LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)
 #define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
+#define LIBC_MATH_ALWAYS_ROUND_NEAREST 0x20
 
 #ifndef LIBC_MATH
 #define LIBC_MATH 0
@@ -81,4 +82,8 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
 #define LIBC_MATH_HAS_NO_EXCEPT
 #endif
 
+#if ((LIBC_MATH) & LIBC_MATH_ALWAYS_ROUND_NEAREST)
+#define LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif
+
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H

>From c7b584795707ece6812b4e30a970cd08a68a4537 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Tue, 2 Jun 2026 21:54:45 +0700
Subject: [PATCH 2/9] implemented on all all dependant of
 `fputil::quick_get_round()`

---
 .../__support/FPUtil/ManipulationFunctions.h  |  3 +++
 .../FPUtil/NearestIntegerOperations.h         |  4 ++++
 libc/src/__support/FPUtil/dyadic_float.h      | 21 +++++++++++++++++++
 .../src/__support/FPUtil/except_value_utils.h |  8 +++++++
 libc/src/__support/FPUtil/generic/FMA.h       |  6 +++++-
 libc/src/__support/FPUtil/generic/add_sub.h   |  8 +++++++
 .../FPUtil/generic/sqrt_80_bit_long_double.h  |  7 ++++++-
 libc/src/__support/FPUtil/rounding_mode.h     |  9 +++-----
 libc/src/__support/math/asinbf16.h            |  2 ++
 libc/src/__support/math/asinf16.h             |  2 ++
 libc/src/__support/math/asinhf16.h            |  2 ++
 libc/src/__support/math/asinpi.h              |  5 +++++
 libc/src/__support/math/coshf.h               |  2 ++
 libc/src/__support/math/coshf16.h             |  6 ++++++
 libc/src/__support/math/exp.h                 |  4 ++++
 libc/src/__support/math/exp10.h               |  4 ++++
 libc/src/__support/math/exp10f.h              |  6 ++++++
 libc/src/__support/math/exp10f16.h            |  6 ++++++
 libc/src/__support/math/exp10m1f.h            | 13 ++++++++++++
 libc/src/__support/math/exp10m1f16.h          | 14 +++++++++++--
 libc/src/__support/math/exp2.h                |  4 ++++
 libc/src/__support/math/exp2f.h               |  2 ++
 libc/src/__support/math/exp2f16.h             |  6 ++++++
 libc/src/__support/math/exp2m1f.h             |  4 ++++
 libc/src/__support/math/exp2m1f16.h           | 10 +++++++++
 libc/src/__support/math/expf.h                |  2 ++
 libc/src/__support/math/expf16.h              | 10 +++++++++
 libc/src/__support/math/expm1.h               |  2 ++
 libc/src/__support/math/expm1f.h              |  8 +++++++
 libc/src/__support/math/expm1f16.h            |  6 ++++++
 libc/src/__support/math/sin.h                 |  2 ++
 libc/src/__support/math/sincos.h              |  2 ++
 libc/src/__support/math/sincosf.h             |  5 +++++
 libc/src/__support/math/sinf.h                |  2 ++
 libc/src/__support/math/sinf16.h              |  7 +++++++
 libc/src/__support/math/sinhf.h               |  2 ++
 libc/src/__support/math/sinhf16.h             |  6 ++++++
 libc/src/__support/math/tan.h                 |  3 +++
 libc/src/__support/math/tanf16.h              |  2 ++
 libc/src/__support/math/tanhf16.h             | 10 +++++++++
 libc/src/__support/str_to_float.h             |  4 ++++
 .../stdio/printf_core/float_dec_converter.h   |  8 +++++++
 .../stdio/printf_core/float_hex_converter.h   |  8 +++++++
 43 files changed, 237 insertions(+), 10 deletions(-)

diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index 16dc094deda47..a8c034cfaa118 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -170,6 +170,8 @@ ldexp(T x, U exp) {
       FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
   // Make sure that we can safely cast exp to int when not returning early.
   static_assert(EXP_LIMIT <= INT_MAX && -EXP_LIMIT >= INT_MIN);
+
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   if (LIBC_UNLIKELY(exp > EXP_LIMIT)) {
     int rounding_mode = quick_get_round();
     Sign sign = bits.sign();
@@ -197,6 +199,7 @@ ldexp(T x, U exp) {
     raise_except_if_required(FE_UNDERFLOW);
     return FPBits<T>::zero(sign).get_val();
   }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
   // For all other values, NormalFloat to T conversion handles it the right way.
   DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val());
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 4637b46bc9473..9329d2985ac6e 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -246,6 +246,10 @@ round_using_specific_rounding_mode(T x, int rnd) {
 template <typename T>
 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
 round_using_current_rounding_mode(T x) {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+
   int rounding_mode = quick_get_round();
 
   switch (rounding_mode) {
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 7e4ea2f1a81be..4f436a71d2876 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -46,6 +46,18 @@ rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
       (rshift >= Bits && value == 0))
     return 0; // exact
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  if (rshift > 0 && rshift <= Bits && value.get_bit(rshift - 1)) {
+    // We round up, unless the value is an exact halfway case and
+    // the bit that will end up in the units place is 0, in which
+    // case tie-break-to-even says round down.
+    bool round_bit = rshift < Bits ? value.get_bit(rshift) : 0;
+    return round_bit != 0 || (value << (Bits - rshift + 1)) != 0 ? +1 : -1;
+  } else {
+    return -1;
+  }
+#endif
+
   switch (quick_get_round()) {
   case FE_TONEAREST:
     if (rshift > 0 && rshift <= Bits && value.get_bit(rshift - 1)) {
@@ -190,6 +202,10 @@ template <size_t Bits> struct DyadicFloat {
         raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       }
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return FPBits::inf(sign).get_val();
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+
       switch (quick_get_round()) {
       case FE_TONEAREST:
         return FPBits::inf(sign).get_val();
@@ -248,6 +264,10 @@ template <size_t Bits> struct DyadicFloat {
     StorageType result =
         FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    if (round && (lsb || sticky))
+      ++result;
+#else
     switch (quick_get_round()) {
     case FE_TONEAREST:
       if (round && (lsb || sticky))
@@ -264,6 +284,7 @@ template <size_t Bits> struct DyadicFloat {
     default:
       break;
     }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
     if (ShouldSignalExceptions && (round || sticky)) {
       int excepts = FE_INEXACT;
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 37ecc52784c16..a125c3aafa827 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -58,6 +58,9 @@ template <typename T, size_t N> struct ExceptValues {
     for (size_t i = 0; i < N; ++i) {
       if (LIBC_UNLIKELY(x_bits == values[i].input)) {
         StorageType out_bits = values[i].rnd_towardzero_result;
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+        out_bits += values[i].rnd_tonearest_offset;
+#else
         switch (fputil::quick_get_round()) {
         case FE_UPWARD:
           out_bits += values[i].rnd_upward_offset;
@@ -69,6 +72,7 @@ template <typename T, size_t N> struct ExceptValues {
           out_bits += values[i].rnd_tonearest_offset;
           break;
         }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         return FPBits<T>(out_bits).get_val();
       }
     }
@@ -80,6 +84,9 @@ template <typename T, size_t N> struct ExceptValues {
     for (size_t i = 0; i < N; ++i) {
       if (LIBC_UNLIKELY(x_abs == values[i].input)) {
         StorageType out_bits = values[i].rnd_towardzero_result;
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+        out_bits += values[i].rnd_tonearest_offset;
+#else
         switch (fputil::quick_get_round()) {
         case FE_UPWARD:
           if (sign)
@@ -100,6 +107,7 @@ template <typename T, size_t N> struct ExceptValues {
           out_bits += values[i].rnd_tonearest_offset;
           break;
         }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         T result = FPBits<T>(out_bits).get_val();
         if (sign)
           result = -result;
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 0de4f98969b72..978583870629a 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -18,7 +18,7 @@
 #include "src/__support/FPUtil/dyadic_float.h"
 #include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/big_int.h"
-#include "src/__support/macros/attributes.h"   // LIBC_INLINE
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
@@ -275,10 +275,14 @@ fma(InType x, InType y, InType z) {
   if (prod_mant == 0) {
     // When there is exact cancellation, i.e., x*y == -z exactly, return -0.0 if
     // rounding downward and +0.0 for other rounding modes.
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    prod_sign = Sign::POS;
+#else
     if (fputil::quick_get_round() == FE_DOWNWARD)
       prod_sign = Sign::NEG;
     else
       prod_sign = Sign::POS;
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   }
 
   DyadicFloat result(prod_sign, prod_lsb_exp - InFPBits::EXP_BIAS, prod_mant);
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 1dc16e4d4fce4..3142344e65abb 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -98,12 +98,16 @@ add_or_sub(InType x, InType y) {
       if (y_bits.is_zero()) {
         if (is_effectively_add)
           return OutFPBits::zero(x_bits.sign()).get_val();
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+        return OutFPBits::zero(Sign::POS).get_val();
+#else
         switch (fputil::quick_get_round()) {
         case FE_DOWNWARD:
           return OutFPBits::zero(Sign::NEG).get_val();
         default:
           return OutFPBits::zero(Sign::POS).get_val();
         }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       }
 
       if constexpr (cpp::is_same_v<InType, bfloat16> &&
@@ -136,12 +140,16 @@ add_or_sub(InType x, InType y) {
   InType y_abs = y_bits.abs().get_val();
 
   if (x_abs == y_abs && !is_effectively_add) {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    return OutFPBits::zero(Sign::POS).get_val();
+#else
     switch (fputil::quick_get_round()) {
     case FE_DOWNWARD:
       return OutFPBits::zero(Sign::NEG).get_val();
     default:
       return OutFPBits::zero(Sign::POS).get_val();
     }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   }
 
   Sign result_sign = Sign::POS;
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 cc692d0fc4c26..ad383e9eaf9d8 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
@@ -110,7 +110,11 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x) {
     // Append the exponent field.
     x_exp = ((x_exp >> 1) + LDBits::EXP_BIAS);
     y |= (static_cast<StorageType>(x_exp) << (LDBits::FRACTION_LEN + 1));
-
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    // Round to nearest, ties to even
+    if (rb && (lsb || (r != 0)))
+      ++y;
+#else
     switch (quick_get_round()) {
     case FE_TONEAREST:
       // Round to nearest, ties to even
@@ -122,6 +126,7 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x) {
         ++y;
       break;
     }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
     // Extract output
     FPBits<long double> out(0.0L);
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 3a4a41d8beacc..83ad911ed17f2 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -44,6 +44,9 @@ LIBC_INLINE bool fenv_is_round_down() {
 //   1.5f - 2^-24 = 1.5f           for FE_TONEAREST, FE_UPWARD
 //                = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
 LIBC_INLINE bool fenv_is_round_to_nearest() {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return true;
+#endif
   static volatile float x = 0x1.0p-24f;
   float y = 1.5f + x;
   return (y == 1.5f - x);
@@ -67,7 +70,6 @@ LIBC_INLINE bool fenv_is_round_to_zero() {
 
 // Quick free standing get rounding mode based on the above observations.
 LIBC_INLINE int quick_get_round() {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   static volatile float x = 0x1.0p-24f;
   float y = x;
   float z = (0x1.000002p0f + y) + (-1.0f - y);
@@ -77,11 +79,6 @@ LIBC_INLINE int quick_get_round() {
   if (z == 0x1.0p-23f)
     return FE_TOWARDZERO;
   return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
-#else
-  // the optimization should've happened in each user of this function,
-  // but just in case
-  return FE_TONEAREST;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 } // namespace generic
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index b291852762d73..b0edce0577d40 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -45,11 +45,13 @@ LIBC_INLINE LIBC_CONSTEXPR bfloat16 asinbf16(bfloat16 x) {
       return x; // with sign
 
     if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       int rounding = fputil::quick_get_round();
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD)) {
         return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-9f, xf));
       }
+#endif
       return x;
     }
 
diff --git a/libc/src/__support/math/asinf16.h b/libc/src/__support/math/asinf16.h
index e9c9c6fca9184..86bedbdaba752 100644
--- a/libc/src/__support/math/asinf16.h
+++ b/libc/src/__support/math/asinf16.h
@@ -73,11 +73,13 @@ LIBC_INLINE constexpr float16 asinf16(float16 x) {
     // else, in other rounding modes,
     // asin(x) = x
     if (LIBC_UNLIKELY(x_abs <= 0x1a1e)) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       int rounding = fputil::quick_get_round();
 
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD))
         return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
+#endif
       return x;
     }
 
diff --git a/libc/src/__support/math/asinhf16.h b/libc/src/__support/math/asinhf16.h
index 39118d9357043..aaeec0dabb0f2 100644
--- a/libc/src/__support/math/asinhf16.h
+++ b/libc/src/__support/math/asinhf16.h
@@ -87,11 +87,13 @@ LIBC_INLINE constexpr float16 asinhf16(float16 x) {
     // when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
     // rounding types.
     if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       int rounding = fputil::quick_get_round();
       if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
         return fputil::cast<float16>(xf + 0x1p-24f);
       if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
         return fputil::cast<float16>(xf - 0x1p-24f);
+#endif
       return fputil::cast<float16>(xf);
     }
 
diff --git a/libc/src/__support/math/asinpi.h b/libc/src/__support/math/asinpi.h
index 2ee855d20455f..7979e7db9f939 100644
--- a/libc/src/__support/math/asinpi.h
+++ b/libc/src/__support/math/asinpi.h
@@ -84,6 +84,10 @@ LIBC_INLINE double asinpi(double x) {
             MantT sticky_mask = (MantT(1) << (SHIFT_53 - 1)) - 1;
             bool sticky = (r.mantissa & sticky_mask) != 0;
             bool lsb = static_cast<bool>(m53 & 1);
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+            // Carry if round_bit && (lsb || sticky) (round half to even).
+            raise_underflow = !(round_bit && (lsb || sticky));
+#else
             switch (fputil::quick_get_round()) {
             case FE_TONEAREST:
               // Carry if round_bit && (lsb || sticky) (round half to even).
@@ -100,6 +104,7 @@ LIBC_INLINE double asinpi(double x) {
               raise_underflow = true; // truncation never carries
               break;
             }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
           }
         }
         if (raise_underflow)
diff --git a/libc/src/__support/math/coshf.h b/libc/src/__support/math/coshf.h
index d80d86af301ab..a993d29aae0bd 100644
--- a/libc/src/__support/math/coshf.h
+++ b/libc/src/__support/math/coshf.h
@@ -40,9 +40,11 @@ LIBC_INLINE float coshf(float x) {
     if (xbits.is_inf_or_nan())
       return x + FPBits::inf().get_val();
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     int rounding = fputil::quick_get_round();
     if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
       return FPBits::max_normal().get_val();
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/coshf16.h b/libc/src/__support/math/coshf16.h
index dc39944d89f85..ca3fda873329a 100644
--- a/libc/src/__support/math/coshf16.h
+++ b/libc/src/__support/math/coshf16.h
@@ -90,6 +90,11 @@ LIBC_INLINE constexpr float16 coshf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -99,6 +104,7 @@ LIBC_INLINE constexpr float16 coshf16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
   }
 
diff --git a/libc/src/__support/math/exp.h b/libc/src/__support/math/exp.h
index 6c9f5a210a6a4..4a0247850a4c6 100644
--- a/libc/src/__support/math/exp.h
+++ b/libc/src/__support/math/exp.h
@@ -211,8 +211,10 @@ LIBC_INLINE double set_exceptional(double x) {
     if (xbits.is_nan())
       return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     if (fputil::quick_get_round() == FE_UPWARD)
       return FPBits::min_subnormal().get_val();
+#endif
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW);
     return 0.0;
@@ -221,9 +223,11 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= round(log(MAX_NORMAL), D, RU) = 0x1.62e42fefa39fp+9 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/exp10.h b/libc/src/__support/math/exp10.h
index 6a8153cd90ff9..9dee8ef849db8 100644
--- a/libc/src/__support/math/exp10.h
+++ b/libc/src/__support/math/exp10.h
@@ -259,8 +259,10 @@ LIBC_INLINE double exp10_set_exceptional(double x) {
       if (xbits.is_nan())
         return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::quick_get_round() == FE_UPWARD)
         return FPBits::min_subnormal().get_val();
+#endif
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0;
@@ -272,9 +274,11 @@ LIBC_INLINE double exp10_set_exceptional(double x) {
   // x >= log10(2^1024) or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/exp10f.h b/libc/src/__support/math/exp10f.h
index 41f9a73a09935..d4761adf2962d 100644
--- a/libc/src/__support/math/exp10f.h
+++ b/libc/src/__support/math/exp10f.h
@@ -47,9 +47,11 @@ LIBC_INLINE float exp10f(float x) {
     if (xbits.is_pos() && (x_u >= 0x421a'209bU)) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
+#endif
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
@@ -62,8 +64,12 @@ LIBC_INLINE float exp10f(float x) {
   // When |x| <= log10(2)*2^-6
   if (LIBC_UNLIKELY(x_abs <= 0x3b9a'209bU)) {
     if (LIBC_UNLIKELY(x_u == 0xb25e'5bd9U)) { // x = -0x1.bcb7b2p-27f
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return 0x1.fffffep-1f;
+#else
       if (fputil::fenv_is_round_to_nearest())
         return 0x1.fffffep-1f;
+#endif
     }
     // |x| < 2^-25
     // 10^x ~ 1 + log(10) * x
diff --git a/libc/src/__support/math/exp10f16.h b/libc/src/__support/math/exp10f16.h
index 935a301544edf..2d0f20ed15cf4 100644
--- a/libc/src/__support/math/exp10f16.h
+++ b/libc/src/__support/math/exp10f16.h
@@ -82,6 +82,11 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -91,6 +96,7 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     }
 
     // When x <= -8.
diff --git a/libc/src/__support/math/exp10m1f.h b/libc/src/__support/math/exp10m1f.h
index c45d3752d6f6c..cb8bb4fb05225 100644
--- a/libc/src/__support/math/exp10m1f.h
+++ b/libc/src/__support/math/exp10m1f.h
@@ -115,9 +115,11 @@ LIBC_INLINE float exp10m1f(float x) {
   // When x >= log10(2^128), or x is nan
   if (LIBC_UNLIKELY(xbits.is_pos() && x_u >= 0x421a'209bU)) {
     if (xbits.is_finite()) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
       int rounding = fputil::quick_get_round();
       if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
         return FPBits::max_normal().get_val();
+#endif
 
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
@@ -164,10 +166,15 @@ LIBC_INLINE float exp10m1f(float x) {
     if (xbits.is_nan())
       return x;
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+    if (x_u == 0xc0f0d2f1)     // x = log10(2^-25)
+      return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
+#else
     int rounding = fputil::quick_get_round();
     if (rounding == FE_UPWARD || rounding == FE_TOWARDZERO ||
         (rounding == FE_TONEAREST && x_u == 0xc0f0d2f1))
       return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW);
@@ -193,21 +200,27 @@ LIBC_INLINE float exp10m1f(float x) {
     case 0x40e00000U: // x = 7.0f
       return 9'999'999.0f;
     case 0x41000000U: { // x = 8.0f
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 100'000'000.0f;
+#endif
       return 99'999'992.0f;
     }
     case 0x41100000U: { // x = 9.0f
       int rounding = fputil::quick_get_round();
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 1'000'000'000.0f;
+#endif
       return 999'999'936.0f;
     }
     case 0x41200000U: { // x = 10.0f
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 10'000'000'000.0f;
+#endif
       return 9'999'998'976.0f;
     }
     }
diff --git a/libc/src/__support/math/exp10m1f16.h b/libc/src/__support/math/exp10m1f16.h
index 7ee43a0092476..f9044f333676b 100644
--- a/libc/src/__support/math/exp10m1f16.h
+++ b/libc/src/__support/math/exp10m1f16.h
@@ -93,6 +93,11 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -102,6 +107,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When x < -11 * log10(2).
@@ -117,6 +123,9 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       }
 
       // When x < -0x1.ce4p+1, round(10^x - 1, HP, RN) = -1.
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return FPBits::one(Sign::NEG).get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_DOWNWARD:
@@ -124,6 +133,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       default:
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When |x| <= 2^(-3).
@@ -150,8 +160,8 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
   }
 
   // When x is 1, 2, or 3. These are hard-to-round cases with exact results.
-  // 10^4 - 1 = 9'999 is not exactly representable as a float16, but luckily the
-  // polynomial approximation gives the correct result for x = 4 in all
+  // 10^4 - 1 = 9'999 is not exactly representable as a float16, but luckily
+  // the polynomial approximation gives the correct result for x = 4 in all
   // rounding modes.
   if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) {
     switch (x_u) {
diff --git a/libc/src/__support/math/exp2.h b/libc/src/__support/math/exp2.h
index 8f025bfa83227..eadcb423dcc13 100644
--- a/libc/src/__support/math/exp2.h
+++ b/libc/src/__support/math/exp2.h
@@ -238,8 +238,10 @@ LIBC_INLINE double set_exceptional(double x) {
       if (xbits.is_nan())
         return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::quick_get_round() == FE_UPWARD)
         return FPBits::min_subnormal().get_val();
+#endif
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0;
@@ -251,9 +253,11 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= 1024 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/exp2f.h b/libc/src/__support/math/exp2f.h
index 439c752969b4d..b79341518c631 100644
--- a/libc/src/__support/math/exp2f.h
+++ b/libc/src/__support/math/exp2f.h
@@ -76,9 +76,11 @@ LIBC_INLINE float exp2f(float x) {
     if (xbits.is_pos()) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
+#endif
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/exp2f16.h b/libc/src/__support/math/exp2f16.h
index 8ff918b665a6f..878d291c87a5d 100644
--- a/libc/src/__support/math/exp2f16.h
+++ b/libc/src/__support/math/exp2f16.h
@@ -66,6 +66,11 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -75,6 +80,7 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     }
 
     // When x <= -25.
diff --git a/libc/src/__support/math/exp2m1f.h b/libc/src/__support/math/exp2m1f.h
index 49cd4589ace85..63b360ef70705 100644
--- a/libc/src/__support/math/exp2m1f.h
+++ b/libc/src/__support/math/exp2m1f.h
@@ -96,9 +96,11 @@ LIBC_INLINE float exp2m1f(float x) {
     // x >= 128, or x is nan
     if (xbits.is_pos()) {
       if (xbits.is_finite()) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
+#endif
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
@@ -117,9 +119,11 @@ LIBC_INLINE float exp2m1f(float x) {
     if (xbits.is_nan())
       return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_UPWARD || rounding == FE_TOWARDZERO)
       return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW);
diff --git a/libc/src/__support/math/exp2m1f16.h b/libc/src/__support/math/exp2m1f16.h
index 196fc52158cfc..e1499735b0a3a 100644
--- a/libc/src/__support/math/exp2m1f16.h
+++ b/libc/src/__support/math/exp2m1f16.h
@@ -106,6 +106,11 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -115,6 +120,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     }
 
     // When x < -11.
@@ -129,6 +135,9 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
             fputil::cast<float16>(-0x1.ffcp-1));
 
       // When x <= -12, round(2^x - 1, HP, RN) = -1.
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return FPBits::one(Sign::NEG).get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_DOWNWARD:
@@ -136,6 +145,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       default:
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     }
 
     // When |x| <= 2^(-3).
diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index a635c01d22772..711c0bc51eb4e 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -63,9 +63,11 @@ LIBC_INLINE float expf(float x) {
     if (xbits.is_pos() && (xbits.uintval() >= 0x42b2'0000)) {
       // x is finite
       if (xbits.uintval() < 0x7f80'0000U) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
+#endif
 
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/expf16.h b/libc/src/__support/math/expf16.h
index 2ca7c021e36b9..a6e848cd093ef 100644
--- a/libc/src/__support/math/expf16.h
+++ b/libc/src/__support/math/expf16.h
@@ -75,6 +75,11 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -84,6 +89,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     }
 
     // When x <= -18.
@@ -95,12 +101,16 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+      return FPBits::zero().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_UPWARD:
         return FPBits::min_subnormal().get_val();
       default:
         return FPBits::zero().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
     }
 
     // When 0 < |x| <= 2^(-5).
diff --git a/libc/src/__support/math/expm1.h b/libc/src/__support/math/expm1.h
index 5902fc94578f4..4b82e08b27c51 100644
--- a/libc/src/__support/math/expm1.h
+++ b/libc/src/__support/math/expm1.h
@@ -265,9 +265,11 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= round(log(MAX_NORMAL), D, RU) = 0x1.62e42fefa39fp+9 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
+#endif
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/expm1f.h b/libc/src/__support/math/expm1f.h
index 60dd62bf7be8d..601fd133f804a 100644
--- a/libc/src/__support/math/expm1f.h
+++ b/libc/src/__support/math/expm1f.h
@@ -38,9 +38,13 @@ LIBC_INLINE float expm1f(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   // Exceptional value
   if (LIBC_UNLIKELY(x_u == 0x3e35'bec5U)) { // x = 0x1.6b7d8ap-3f
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+    return 0x1.8dbe64p-3f;
+#else
     int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
       return 0x1.8dbe64p-3f;
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     return 0x1.8dbe62p-3f;
   }
 #if !defined(LIBC_TARGET_CPU_HAS_FMA_DOUBLE)
@@ -63,17 +67,21 @@ LIBC_INLINE float expm1f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       int round_mode = fputil::quick_get_round();
       if (round_mode == FE_UPWARD || round_mode == FE_TOWARDZERO)
         return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
+#endif
       return -1.0f;
     } else {
       // x >= 89 or nan
       if (xbits.uintval() >= 0x42b2'0000) {
         if (xbits.uintval() < 0x7f80'0000U) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
           int rounding = fputil::quick_get_round();
           if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
             return FPBits::max_normal().get_val();
+#endif
 
           fputil::set_errno_if_required(ERANGE);
           fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/expm1f16.h b/libc/src/__support/math/expm1f16.h
index a14a6f051a834..edb8ce56e1a26 100644
--- a/libc/src/__support/math/expm1f16.h
+++ b/libc/src/__support/math/expm1f16.h
@@ -86,6 +86,11 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -95,6 +100,7 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
     }
 
     // When x <= -11 * log(2).
diff --git a/libc/src/__support/math/sin.h b/libc/src/__support/math/sin.h
index bd53ec617a301..41322a361ec69 100644
--- a/libc/src/__support/math/sin.h
+++ b/libc/src/__support/math/sin.h
@@ -94,11 +94,13 @@ LIBC_INLINE double sin(double x) {
         return fputil::multiply_add(x, -0x1.0p-54, x);
 #else
         if (LIBC_UNLIKELY(x_e < 4)) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
           int rounding_mode = fputil::quick_get_round();
           if (rounding_mode == FE_TOWARDZERO ||
               (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD))
             return FPBits(xbits.uintval() - 1).get_val();
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
         }
         return fputil::multiply_add(x, -0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/sincos.h b/libc/src/__support/math/sincos.h
index f7dbb0e0adcc6..5cf3fae72b9b8 100644
--- a/libc/src/__support/math/sincos.h
+++ b/libc/src/__support/math/sincos.h
@@ -67,11 +67,13 @@ LIBC_INLINE void sincos(double x, double *sin_x, double *cos_x) {
         *cos_x = fputil::round_result_slightly_down(1.0);
 
         if (LIBC_UNLIKELY(x_e < 4)) {
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
           int rounding_mode = fputil::quick_get_round();
           if (rounding_mode == FE_TOWARDZERO ||
               (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD))
             *sin_x = FPBits(xbits.uintval() - 1).get_val();
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
         }
         *sin_x = fputil::multiply_add(x, -0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/sincosf.h b/libc/src/__support/math/sincosf.h
index a6b1cd8ae3010..64fc3e01f032a 100644
--- a/libc/src/__support/math/sincosf.h
+++ b/libc/src/__support/math/sincosf.h
@@ -176,6 +176,10 @@ LIBC_INLINE void sincosf(float x, float *sinp, float *cosp) {
       uint32_t s = EXCEPT_OUTPUTS_SIN[i][0]; // FE_TOWARDZERO
       uint32_t c = EXCEPT_OUTPUTS_COS[i][0]; // FE_TOWARDZERO
       bool x_sign = x < 0;
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+      s += EXCEPT_OUTPUTS_SIN[i][3];
+      c += EXCEPT_OUTPUTS_COS[i][3];
+#else
       switch (fputil::quick_get_round()) {
       case FE_UPWARD:
         s += x_sign ? EXCEPT_OUTPUTS_SIN[i][2] : EXCEPT_OUTPUTS_SIN[i][1];
@@ -190,6 +194,7 @@ LIBC_INLINE void sincosf(float x, float *sinp, float *cosp) {
         c += EXCEPT_OUTPUTS_COS[i][3];
         break;
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       *sinp = x_sign ? -FPBits(s).get_val() : FPBits(s).get_val();
       *cosp = FPBits(c).get_val();
 
diff --git a/libc/src/__support/math/sinf.h b/libc/src/__support/math/sinf.h
index c61beed749900..3641b306efdf9 100644
--- a/libc/src/__support/math/sinf.h
+++ b/libc/src/__support/math/sinf.h
@@ -152,10 +152,12 @@ LIBC_INLINE float sinf(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
     float r = -0x1.63f4bap-2f;
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     int rounding = fputil::quick_get_round();
     if ((rounding == FE_DOWNWARD && xbits.is_pos()) ||
         (rounding == FE_UPWARD && xbits.is_neg()))
       r = -0x1.63f4bcp-2f;
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     return xbits.is_neg() ? -r : r;
   }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
diff --git a/libc/src/__support/math/sinf16.h b/libc/src/__support/math/sinf16.h
index ec27c4ec61c53..86972c7379371 100644
--- a/libc/src/__support/math/sinf16.h
+++ b/libc/src/__support/math/sinf16.h
@@ -79,7 +79,9 @@ LIBC_INLINE float16 sinf16(float16 x) {
     return r.value();
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
   int rounding = fputil::quick_get_round();
+#endif
 
   // Exhaustive tests show that for |x| <= 0x1.f4p-11, 1ULP rounding errors
   // occur. To fix this, the following apply:
@@ -88,6 +90,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
     if (LIBC_UNLIKELY(x_abs == 0U))
       return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     // When x > 0, and rounding upward, sin(x) == x.
     // When x < 0, and rounding downward, sin(x) == x.
     if ((rounding == FE_UPWARD && xbits.is_pos()) ||
@@ -99,6 +102,10 @@ LIBC_INLINE float16 sinf16(float16 x) {
       x_u--;
       return FPBits(x_u).get_val();
     }
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+
+    // TODO: what about the case with rounding nearest and we're in here?
+    // Previously, it's an UB
   }
 
   if (xbits.is_inf_or_nan()) {
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
index 141d87ba72bd2..258ddd290295f 100644
--- a/libc/src/__support/math/sinhf.h
+++ b/libc/src/__support/math/sinhf.h
@@ -61,6 +61,7 @@ LIBC_INLINE float sinhf(float x) {
     if (xbits.is_inf())
       return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     int rounding = fputil::quick_get_round();
     if (xbits.is_neg()) {
       if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
@@ -69,6 +70,7 @@ LIBC_INLINE float sinhf(float x) {
       if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
         return FPBits::max_normal().get_val();
     }
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/sinhf16.h b/libc/src/__support/math/sinhf16.h
index 19ff5a3e12423..845fb7e736eec 100644
--- a/libc/src/__support/math/sinhf16.h
+++ b/libc/src/__support/math/sinhf16.h
@@ -129,6 +129,11 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf(x_bits.sign()).get_val();
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf(x_bits.sign()).get_val();
+#else
       int rounding_mode = fputil::quick_get_round();
       if (rounding_mode == FE_TONEAREST ||
           (x_bits.is_pos() && rounding_mode == FE_UPWARD) ||
@@ -137,6 +142,7 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
         fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return FPBits::inf(x_bits.sign()).get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
       return FPBits::max_normal(x_bits.sign()).get_val();
     }
 
diff --git a/libc/src/__support/math/tan.h b/libc/src/__support/math/tan.h
index d1ebc035566f7..5f825ce10951a 100644
--- a/libc/src/__support/math/tan.h
+++ b/libc/src/__support/math/tan.h
@@ -149,10 +149,13 @@ LIBC_INLINE double tan(double x) {
         return fputil::multiply_add(x, 0x1.0p-54, x);
 #else
         if (LIBC_UNLIKELY(x_e < 4)) {
+          // TODO: UB for rounding nearest
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
           int rounding_mode = fputil::quick_get_round();
           if ((xbits.sign() == Sign::POS && rounding_mode == FE_UPWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_DOWNWARD))
             return FPBits(xbits.uintval() + 1).get_val();
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
         }
         return fputil::multiply_add(x, 0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/tanf16.h b/libc/src/__support/math/tanf16.h
index 6b9b9224fb84d..bbf5115dc0607 100644
--- a/libc/src/__support/math/tanf16.h
+++ b/libc/src/__support/math/tanf16.h
@@ -68,6 +68,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
       if (LIBC_UNLIKELY(x_abs == 0))
         return x;
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       int rounding = fputil::quick_get_round();
 
       // Exhaustive tests show that, when:
@@ -77,6 +78,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD))
         return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       return x;
     }
 
diff --git a/libc/src/__support/math/tanhf16.h b/libc/src/__support/math/tanhf16.h
index 80671691203c9..3119d4d850e8b 100644
--- a/libc/src/__support/math/tanhf16.h
+++ b/libc/src/__support/math/tanhf16.h
@@ -64,6 +64,9 @@ LIBC_INLINE float16 tanhf16(float16 x) {
 
     // When -2^(-14) <= x <= -2^(-9).
     if (x_u >= 0x8400U && x_u <= 0x9800U) {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+      return x;
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_DOWNWARD:
@@ -71,6 +74,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
       default:
         return FPBits(static_cast<uint16_t>(x_u - 1U)).get_val();
       }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     }
 
     // When |x| <= 0x1.d2p-4.
@@ -98,12 +102,18 @@ LIBC_INLINE float16 tanhf16(float16 x) {
     // When |x| >= atanh(1 - 2^(-11)).
     fputil::raise_except_if_required(FE_INEXACT);
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+    if (x_abs >= 0x4482U) {
+      return FPBits::one(x_bits.sign()).get_val();
+    }
+#else
     int rounding_mode = fputil::quick_get_round();
     if ((rounding_mode == FE_TONEAREST && x_abs >= 0x4482U) ||
         (rounding_mode == FE_UPWARD && x_bits.is_pos()) ||
         (rounding_mode == FE_DOWNWARD && x_bits.is_neg())) {
       return FPBits::one(x_bits.sign()).get_val();
     }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
     if (x_bits.is_pos())
       return fputil::cast<float16>(0x1.ffcp-1);
     return fputil::cast<float16>(-0x1.ffcp-1);
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 830db2485fad8..25d049549d3f8 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1146,6 +1146,9 @@ strtofloatingpoint(const CharType *__restrict src) {
     }
 
     RoundDirection round_direction = RoundDirection::Nearest;
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+    round_direction = RoundDirection::Nearest;
+#else
     switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       round_direction = RoundDirection::Nearest;
@@ -1160,6 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) {
       round_direction = RoundDirection::Down;
       break;
     }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
 
     StrToNumResult<ExpandedFloat<T>> parse_result({0, 0});
     if (base == 16) {
diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index 8b99688cb993c..e2a5198752b07 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -49,6 +49,14 @@ constexpr uint32_t MAX_BLOCK = 999999999;
 
 LIBC_INLINE RoundDirection get_round_direction(int last_digit, bool truncated,
                                                Sign sign) {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  if (last_digit != 5) {
+    return last_digit > 5 ? RoundDirection::Up : RoundDirection::Down;
+  } else {
+    return !truncated ? RoundDirection::Even : RoundDirection::Up;
+  }
+#endif
+
   switch (fputil::quick_get_round()) {
   case FE_TONEAREST:
     // Round to nearest, if it's exactly halfway then round to even.
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index 5c6899156ccba..660b067aeba15 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -112,6 +112,13 @@ LIBC_INLINE int convert_float_hex_exp(Writer<write_mode> *writer,
 
     mantissa >>= shift_amount;
 
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    // Round to nearest, if it's exactly halfway then round to even.
+    if (truncated_bits > halfway_const)
+      ++mantissa;
+    else if (truncated_bits == halfway_const)
+      mantissa = mantissa + (mantissa & 1);
+#else
     switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       // Round to nearest, if it's exactly halfway then round to even.
@@ -131,6 +138,7 @@ LIBC_INLINE int convert_float_hex_exp(Writer<write_mode> *writer,
     case FE_TOWARDZERO:
       break;
     }
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
     // If the rounding caused an overflow, shift the mantissa and adjust the
     // exponent to match.

>From e437cae0edcd636f5aa2d38e35f29bc8e0fece91 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Tue, 2 Jun 2026 23:35:59 +0700
Subject: [PATCH 3/9] updated to also handle `fenv_is_round_to_nearest()`'s
 dependant

---
 libc/src/__support/FPUtil/rounding_mode.h | 3 ---
 libc/src/__support/math/sinhf.h           | 4 ++++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 83ad911ed17f2..6ce693d41da50 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -44,9 +44,6 @@ LIBC_INLINE bool fenv_is_round_down() {
 //   1.5f - 2^-24 = 1.5f           for FE_TONEAREST, FE_UPWARD
 //                = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
 LIBC_INLINE bool fenv_is_round_to_nearest() {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
-  return true;
-#endif
   static volatile float x = 0x1.0p-24f;
   float y = 1.5f + x;
   return (y == 1.5f - x);
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
index 258ddd290295f..084b0d6586204 100644
--- a/libc/src/__support/math/sinhf.h
+++ b/libc/src/__support/math/sinhf.h
@@ -32,8 +32,12 @@ LIBC_INLINE float sinhf(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
       // |x| = 0.0005589424981735646724700927734375
       if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+        return x;
+#else
         if (fputil::fenv_is_round_to_nearest())
           return x;
+#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
       }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 

>From 4464ea3b01a50aece79c53bfcd71b6dd3914cd7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Wed, 3 Jun 2026 11:09:52 +0700
Subject: [PATCH 4/9] wrong guarding in ldexp

---
 libc/src/__support/FPUtil/ManipulationFunctions.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index a8c034cfaa118..6dc673daf45e5 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -171,15 +171,16 @@ ldexp(T x, U exp) {
   // Make sure that we can safely cast exp to int when not returning early.
   static_assert(EXP_LIMIT <= INT_MAX && -EXP_LIMIT >= INT_MIN);
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   if (LIBC_UNLIKELY(exp > EXP_LIMIT)) {
-    int rounding_mode = quick_get_round();
     Sign sign = bits.sign();
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    int rounding_mode = quick_get_round();
 
     if ((sign == Sign::POS && rounding_mode == FE_DOWNWARD) ||
         (sign == Sign::NEG && rounding_mode == FE_UPWARD) ||
         (rounding_mode == FE_TOWARDZERO))
       return FPBits<T>::max_normal(sign).get_val();
+#endif
 
     set_errno_if_required(ERANGE);
     raise_except_if_required(FE_OVERFLOW);
@@ -188,18 +189,18 @@ ldexp(T x, U exp) {
 
   // Similarly on the negative side we return zero early if |exp| is too small.
   if (LIBC_UNLIKELY(exp < -EXP_LIMIT)) {
-    int rounding_mode = quick_get_round();
     Sign sign = bits.sign();
-
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    int rounding_mode = quick_get_round();
     if ((sign == Sign::POS && rounding_mode == FE_UPWARD) ||
         (sign == Sign::NEG && rounding_mode == FE_DOWNWARD))
       return FPBits<T>::min_subnormal(sign).get_val();
+#endif
 
     set_errno_if_required(ERANGE);
     raise_except_if_required(FE_UNDERFLOW);
     return FPBits<T>::zero(sign).get_val();
   }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
   // For all other values, NormalFloat to T conversion handles it the right way.
   DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val());

>From d115b284d3075b74085efc86d8dcae91403d290a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Wed, 3 Jun 2026 21:33:47 +0700
Subject: [PATCH 5/9] fix: wrong option names everywhere, inverted option
 checking in `sqrt_80_bit_long_double.h`

this is also the root cause of against-MPFR sqrt tests failing on x86_64 Ubuntu CI target
---
 libc/src/__support/FPUtil/Hypot.h                      |  2 +-
 .../__support/FPUtil/generic/sqrt_80_bit_long_double.h |  2 +-
 libc/src/__support/math/asinbf16.h                     |  2 +-
 libc/src/__support/math/asinf16.h                      |  2 +-
 libc/src/__support/math/asinhf16.h                     |  2 +-
 libc/src/__support/math/coshf.h                        |  2 +-
 libc/src/__support/math/exp.h                          |  4 ++--
 libc/src/__support/math/exp10f.h                       |  2 +-
 libc/src/__support/math/exp10f16.h                     |  2 +-
 libc/src/__support/math/exp10m1f.h                     | 10 +++++-----
 libc/src/__support/math/exp2.h                         |  2 +-
 libc/src/__support/math/exp2f.h                        |  2 +-
 libc/src/__support/math/exp2f16.h                      |  4 ++--
 libc/src/__support/math/exp2m1f.h                      |  4 ++--
 libc/src/__support/math/exp2m1f16.h                    |  6 +++---
 libc/src/__support/math/expf.h                         |  2 +-
 libc/src/__support/math/expf16.h                       |  8 ++++----
 libc/src/__support/math/expm1.h                        |  2 +-
 libc/src/__support/math/expm1f.h                       |  8 ++++----
 libc/src/__support/math/expm1f16.h                     |  4 ++--
 libc/src/__support/math/sin.h                          |  4 ++--
 libc/src/__support/math/sincos.h                       |  4 ++--
 libc/src/__support/math/sincosf.h                      |  4 ++--
 libc/src/__support/math/sinf.h                         |  4 ++--
 libc/src/__support/math/sinf16.h                       |  6 +++---
 libc/src/__support/math/sinhf.h                        |  8 ++++----
 libc/src/__support/math/sinhf16.h                      |  4 ++--
 libc/src/__support/math/tan.h                          |  4 ++--
 libc/src/__support/math/tanf16.h                       |  4 ++--
 libc/src/__support/math/tanhf16.h                      |  8 ++++----
 libc/src/__support/str_to_float.h                      |  4 ++--
 31 files changed, 63 insertions(+), 63 deletions(-)

diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 480dbb3be195e..8610ec8e69774 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -206,7 +206,7 @@ LIBC_INLINE T hypot(T x, T y) {
         return FPBits_t::max_normal().get_val();
 #else
         return FPBits_t::inf().get_val();
-#endif // LIBC_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
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 ad383e9eaf9d8..5e62511cc8afc 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
@@ -110,7 +110,7 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x) {
     // Append the exponent field.
     x_exp = ((x_exp >> 1) + LDBits::EXP_BIAS);
     y |= (static_cast<StorageType>(x_exp) << (LDBits::FRACTION_LEN + 1));
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     // Round to nearest, ties to even
     if (rb && (lsb || (r != 0)))
       ++y;
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index b0edce0577d40..b6cacc6275d08 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -45,7 +45,7 @@ LIBC_INLINE LIBC_CONSTEXPR bfloat16 asinbf16(bfloat16 x) {
       return x; // with sign
 
     if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD)) {
diff --git a/libc/src/__support/math/asinf16.h b/libc/src/__support/math/asinf16.h
index 86bedbdaba752..7d9f908ba202b 100644
--- a/libc/src/__support/math/asinf16.h
+++ b/libc/src/__support/math/asinf16.h
@@ -73,7 +73,7 @@ LIBC_INLINE constexpr float16 asinf16(float16 x) {
     // else, in other rounding modes,
     // asin(x) = x
     if (LIBC_UNLIKELY(x_abs <= 0x1a1e)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
 
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
diff --git a/libc/src/__support/math/asinhf16.h b/libc/src/__support/math/asinhf16.h
index aaeec0dabb0f2..9031b1347ed51 100644
--- a/libc/src/__support/math/asinhf16.h
+++ b/libc/src/__support/math/asinhf16.h
@@ -87,7 +87,7 @@ LIBC_INLINE constexpr float16 asinhf16(float16 x) {
     // when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
     // rounding types.
     if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
       if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
         return fputil::cast<float16>(xf + 0x1p-24f);
diff --git a/libc/src/__support/math/coshf.h b/libc/src/__support/math/coshf.h
index a993d29aae0bd..bb76f34592844 100644
--- a/libc/src/__support/math/coshf.h
+++ b/libc/src/__support/math/coshf.h
@@ -40,7 +40,7 @@ LIBC_INLINE float coshf(float x) {
     if (xbits.is_inf_or_nan())
       return x + FPBits::inf().get_val();
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp.h b/libc/src/__support/math/exp.h
index 4a0247850a4c6..4ac4b183dd02d 100644
--- a/libc/src/__support/math/exp.h
+++ b/libc/src/__support/math/exp.h
@@ -211,7 +211,7 @@ LIBC_INLINE double set_exceptional(double x) {
     if (xbits.is_nan())
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (fputil::quick_get_round() == FE_UPWARD)
       return FPBits::min_subnormal().get_val();
 #endif
@@ -223,7 +223,7 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= round(log(MAX_NORMAL), D, RU) = 0x1.62e42fefa39fp+9 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp10f.h b/libc/src/__support/math/exp10f.h
index d4761adf2962d..88acd5ab59b00 100644
--- a/libc/src/__support/math/exp10f.h
+++ b/libc/src/__support/math/exp10f.h
@@ -47,7 +47,7 @@ LIBC_INLINE float exp10f(float x) {
     if (xbits.is_pos() && (x_u >= 0x421a'209bU)) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp10f16.h b/libc/src/__support/math/exp10f16.h
index 2d0f20ed15cf4..dafc74204e15e 100644
--- a/libc/src/__support/math/exp10f16.h
+++ b/libc/src/__support/math/exp10f16.h
@@ -96,7 +96,7 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When x <= -8.
diff --git a/libc/src/__support/math/exp10m1f.h b/libc/src/__support/math/exp10m1f.h
index cb8bb4fb05225..2ef271be19933 100644
--- a/libc/src/__support/math/exp10m1f.h
+++ b/libc/src/__support/math/exp10m1f.h
@@ -115,7 +115,7 @@ LIBC_INLINE float exp10m1f(float x) {
   // When x >= log10(2^128), or x is nan
   if (LIBC_UNLIKELY(xbits.is_pos() && x_u >= 0x421a'209bU)) {
     if (xbits.is_finite()) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
       if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
         return FPBits::max_normal().get_val();
@@ -166,7 +166,7 @@ LIBC_INLINE float exp10m1f(float x) {
     if (xbits.is_nan())
       return x;
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (x_u == 0xc0f0d2f1)     // x = log10(2^-25)
       return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
 #else
@@ -200,7 +200,7 @@ LIBC_INLINE float exp10m1f(float x) {
     case 0x40e00000U: // x = 7.0f
       return 9'999'999.0f;
     case 0x41000000U: { // x = 8.0f
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 100'000'000.0f;
@@ -209,14 +209,14 @@ LIBC_INLINE float exp10m1f(float x) {
     }
     case 0x41100000U: { // x = 9.0f
       int rounding = fputil::quick_get_round();
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 1'000'000'000.0f;
 #endif
       return 999'999'936.0f;
     }
     case 0x41200000U: { // x = 10.0f
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 10'000'000'000.0f;
diff --git a/libc/src/__support/math/exp2.h b/libc/src/__support/math/exp2.h
index eadcb423dcc13..19eafa2141800 100644
--- a/libc/src/__support/math/exp2.h
+++ b/libc/src/__support/math/exp2.h
@@ -253,7 +253,7 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= 1024 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp2f.h b/libc/src/__support/math/exp2f.h
index b79341518c631..5f574351ead65 100644
--- a/libc/src/__support/math/exp2f.h
+++ b/libc/src/__support/math/exp2f.h
@@ -76,7 +76,7 @@ LIBC_INLINE float exp2f(float x) {
     if (xbits.is_pos()) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp2f16.h b/libc/src/__support/math/exp2f16.h
index 878d291c87a5d..40631c606e0e5 100644
--- a/libc/src/__support/math/exp2f16.h
+++ b/libc/src/__support/math/exp2f16.h
@@ -66,7 +66,7 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -80,7 +80,7 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When x <= -25.
diff --git a/libc/src/__support/math/exp2m1f.h b/libc/src/__support/math/exp2m1f.h
index 63b360ef70705..3acd497e3d10d 100644
--- a/libc/src/__support/math/exp2m1f.h
+++ b/libc/src/__support/math/exp2m1f.h
@@ -96,7 +96,7 @@ LIBC_INLINE float exp2m1f(float x) {
     // x >= 128, or x is nan
     if (xbits.is_pos()) {
       if (xbits.is_finite()) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
@@ -119,7 +119,7 @@ LIBC_INLINE float exp2m1f(float x) {
     if (xbits.is_nan())
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_UPWARD || rounding == FE_TOWARDZERO)
       return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
diff --git a/libc/src/__support/math/exp2m1f16.h b/libc/src/__support/math/exp2m1f16.h
index e1499735b0a3a..a63d96bb227e6 100644
--- a/libc/src/__support/math/exp2m1f16.h
+++ b/libc/src/__support/math/exp2m1f16.h
@@ -106,7 +106,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -120,7 +120,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When x < -11.
@@ -145,7 +145,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       default:
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When |x| <= 2^(-3).
diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index 711c0bc51eb4e..13c17f1004185 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -63,7 +63,7 @@ LIBC_INLINE float expf(float x) {
     if (xbits.is_pos() && (xbits.uintval() >= 0x42b2'0000)) {
       // x is finite
       if (xbits.uintval() < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/expf16.h b/libc/src/__support/math/expf16.h
index a6e848cd093ef..0c96ebf07357f 100644
--- a/libc/src/__support/math/expf16.h
+++ b/libc/src/__support/math/expf16.h
@@ -75,7 +75,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -89,7 +89,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When x <= -18.
@@ -101,7 +101,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return FPBits::zero().get_val();
 #else
       switch (fputil::quick_get_round()) {
@@ -110,7 +110,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       default:
         return FPBits::zero().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When 0 < |x| <= 2^(-5).
diff --git a/libc/src/__support/math/expm1.h b/libc/src/__support/math/expm1.h
index 4b82e08b27c51..0a44afd1fcd60 100644
--- a/libc/src/__support/math/expm1.h
+++ b/libc/src/__support/math/expm1.h
@@ -265,7 +265,7 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= round(log(MAX_NORMAL), D, RU) = 0x1.62e42fefa39fp+9 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/expm1f.h b/libc/src/__support/math/expm1f.h
index 601fd133f804a..abe969c80a670 100644
--- a/libc/src/__support/math/expm1f.h
+++ b/libc/src/__support/math/expm1f.h
@@ -38,13 +38,13 @@ LIBC_INLINE float expm1f(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   // Exceptional value
   if (LIBC_UNLIKELY(x_u == 0x3e35'bec5U)) { // x = 0x1.6b7d8ap-3f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     return 0x1.8dbe64p-3f;
 #else
     int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
       return 0x1.8dbe64p-3f;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     return 0x1.8dbe62p-3f;
   }
 #if !defined(LIBC_TARGET_CPU_HAS_FMA_DOUBLE)
@@ -67,7 +67,7 @@ LIBC_INLINE float expm1f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int round_mode = fputil::quick_get_round();
       if (round_mode == FE_UPWARD || round_mode == FE_TOWARDZERO)
         return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
@@ -77,7 +77,7 @@ LIBC_INLINE float expm1f(float x) {
       // x >= 89 or nan
       if (xbits.uintval() >= 0x42b2'0000) {
         if (xbits.uintval() < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
           int rounding = fputil::quick_get_round();
           if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
             return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/expm1f16.h b/libc/src/__support/math/expm1f16.h
index edb8ce56e1a26..b29dffd9aa46c 100644
--- a/libc/src/__support/math/expm1f16.h
+++ b/libc/src/__support/math/expm1f16.h
@@ -86,7 +86,7 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -100,7 +100,7 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When x <= -11 * log(2).
diff --git a/libc/src/__support/math/sin.h b/libc/src/__support/math/sin.h
index 41322a361ec69..ff59a163c3eab 100644
--- a/libc/src/__support/math/sin.h
+++ b/libc/src/__support/math/sin.h
@@ -94,13 +94,13 @@ LIBC_INLINE double sin(double x) {
         return fputil::multiply_add(x, -0x1.0p-54, x);
 #else
         if (LIBC_UNLIKELY(x_e < 4)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
           int rounding_mode = fputil::quick_get_round();
           if (rounding_mode == FE_TOWARDZERO ||
               (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD))
             return FPBits(xbits.uintval() - 1).get_val();
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         }
         return fputil::multiply_add(x, -0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/sincos.h b/libc/src/__support/math/sincos.h
index 5cf3fae72b9b8..ee153eb831cb7 100644
--- a/libc/src/__support/math/sincos.h
+++ b/libc/src/__support/math/sincos.h
@@ -67,13 +67,13 @@ LIBC_INLINE void sincos(double x, double *sin_x, double *cos_x) {
         *cos_x = fputil::round_result_slightly_down(1.0);
 
         if (LIBC_UNLIKELY(x_e < 4)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
           int rounding_mode = fputil::quick_get_round();
           if (rounding_mode == FE_TOWARDZERO ||
               (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD))
             *sin_x = FPBits(xbits.uintval() - 1).get_val();
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         }
         *sin_x = fputil::multiply_add(x, -0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/sincosf.h b/libc/src/__support/math/sincosf.h
index 64fc3e01f032a..d6f39edbffa90 100644
--- a/libc/src/__support/math/sincosf.h
+++ b/libc/src/__support/math/sincosf.h
@@ -176,7 +176,7 @@ LIBC_INLINE void sincosf(float x, float *sinp, float *cosp) {
       uint32_t s = EXCEPT_OUTPUTS_SIN[i][0]; // FE_TOWARDZERO
       uint32_t c = EXCEPT_OUTPUTS_COS[i][0]; // FE_TOWARDZERO
       bool x_sign = x < 0;
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       s += EXCEPT_OUTPUTS_SIN[i][3];
       c += EXCEPT_OUTPUTS_COS[i][3];
 #else
@@ -194,7 +194,7 @@ LIBC_INLINE void sincosf(float x, float *sinp, float *cosp) {
         c += EXCEPT_OUTPUTS_COS[i][3];
         break;
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       *sinp = x_sign ? -FPBits(s).get_val() : FPBits(s).get_val();
       *cosp = FPBits(c).get_val();
 
diff --git a/libc/src/__support/math/sinf.h b/libc/src/__support/math/sinf.h
index 3641b306efdf9..601413697c568 100644
--- a/libc/src/__support/math/sinf.h
+++ b/libc/src/__support/math/sinf.h
@@ -152,12 +152,12 @@ LIBC_INLINE float sinf(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
     float r = -0x1.63f4bap-2f;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if ((rounding == FE_DOWNWARD && xbits.is_pos()) ||
         (rounding == FE_UPWARD && xbits.is_neg()))
       r = -0x1.63f4bcp-2f;
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     return xbits.is_neg() ? -r : r;
   }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
diff --git a/libc/src/__support/math/sinf16.h b/libc/src/__support/math/sinf16.h
index 86972c7379371..3ac7afb4add02 100644
--- a/libc/src/__support/math/sinf16.h
+++ b/libc/src/__support/math/sinf16.h
@@ -79,7 +79,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
     return r.value();
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   int rounding = fputil::quick_get_round();
 #endif
 
@@ -90,7 +90,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
     if (LIBC_UNLIKELY(x_abs == 0U))
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     // When x > 0, and rounding upward, sin(x) == x.
     // When x < 0, and rounding downward, sin(x) == x.
     if ((rounding == FE_UPWARD && xbits.is_pos()) ||
@@ -102,7 +102,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
       x_u--;
       return FPBits(x_u).get_val();
     }
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
     // TODO: what about the case with rounding nearest and we're in here?
     // Previously, it's an UB
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
index 084b0d6586204..5c10ba8de07d1 100644
--- a/libc/src/__support/math/sinhf.h
+++ b/libc/src/__support/math/sinhf.h
@@ -32,12 +32,12 @@ LIBC_INLINE float sinhf(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
       // |x| = 0.0005589424981735646724700927734375
       if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         return x;
 #else
         if (fputil::fenv_is_round_to_nearest())
           return x;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
@@ -65,7 +65,7 @@ LIBC_INLINE float sinhf(float x) {
     if (xbits.is_inf())
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     int rounding = fputil::quick_get_round();
     if (xbits.is_neg()) {
       if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
@@ -74,7 +74,7 @@ LIBC_INLINE float sinhf(float x) {
       if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
         return FPBits::max_normal().get_val();
     }
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/sinhf16.h b/libc/src/__support/math/sinhf16.h
index 845fb7e736eec..47b680507eb23 100644
--- a/libc/src/__support/math/sinhf16.h
+++ b/libc/src/__support/math/sinhf16.h
@@ -129,7 +129,7 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf(x_bits.sign()).get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf(x_bits.sign()).get_val();
@@ -142,7 +142,7 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
         fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return FPBits::inf(x_bits.sign()).get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_TO_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return FPBits::max_normal(x_bits.sign()).get_val();
     }
 
diff --git a/libc/src/__support/math/tan.h b/libc/src/__support/math/tan.h
index 5f825ce10951a..cfa8940e594de 100644
--- a/libc/src/__support/math/tan.h
+++ b/libc/src/__support/math/tan.h
@@ -150,12 +150,12 @@ LIBC_INLINE double tan(double x) {
 #else
         if (LIBC_UNLIKELY(x_e < 4)) {
           // TODO: UB for rounding nearest
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
           int rounding_mode = fputil::quick_get_round();
           if ((xbits.sign() == Sign::POS && rounding_mode == FE_UPWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_DOWNWARD))
             return FPBits(xbits.uintval() + 1).get_val();
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
         }
         return fputil::multiply_add(x, 0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/tanf16.h b/libc/src/__support/math/tanf16.h
index bbf5115dc0607..b219837387318 100644
--- a/libc/src/__support/math/tanf16.h
+++ b/libc/src/__support/math/tanf16.h
@@ -68,7 +68,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
       if (LIBC_UNLIKELY(x_abs == 0))
         return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       int rounding = fputil::quick_get_round();
 
       // Exhaustive tests show that, when:
@@ -78,7 +78,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD))
         return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return x;
     }
 
diff --git a/libc/src/__support/math/tanhf16.h b/libc/src/__support/math/tanhf16.h
index 3119d4d850e8b..e56eab55bf548 100644
--- a/libc/src/__support/math/tanhf16.h
+++ b/libc/src/__support/math/tanhf16.h
@@ -64,7 +64,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
 
     // When -2^(-14) <= x <= -2^(-9).
     if (x_u >= 0x8400U && x_u <= 0x9800U) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return x;
 #else
       switch (fputil::quick_get_round()) {
@@ -74,7 +74,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
       default:
         return FPBits(static_cast<uint16_t>(x_u - 1U)).get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     }
 
     // When |x| <= 0x1.d2p-4.
@@ -102,7 +102,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
     // When |x| >= atanh(1 - 2^(-11)).
     fputil::raise_except_if_required(FE_INEXACT);
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (x_abs >= 0x4482U) {
       return FPBits::one(x_bits.sign()).get_val();
     }
@@ -113,7 +113,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
         (rounding_mode == FE_DOWNWARD && x_bits.is_neg())) {
       return FPBits::one(x_bits.sign()).get_val();
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (x_bits.is_pos())
       return fputil::cast<float16>(0x1.ffcp-1);
     return fputil::cast<float16>(-0x1.ffcp-1);
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 25d049549d3f8..1f84e5bbb0951 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1146,7 +1146,7 @@ strtofloatingpoint(const CharType *__restrict src) {
     }
 
     RoundDirection round_direction = RoundDirection::Nearest;
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     round_direction = RoundDirection::Nearest;
 #else
     switch (fputil::quick_get_round()) {
@@ -1163,7 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) {
       round_direction = RoundDirection::Down;
       break;
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUNDING_NEAREST
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 
     StrToNumResult<ExpandedFloat<T>> parse_result({0, 0});
     if (base == 16) {

>From 61d558f65b625ca25e09f6c427f82ff99ceafc22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Wed, 3 Jun 2026 23:04:39 +0700
Subject: [PATCH 6/9] fix reviews

---
 libc/src/__support/FPUtil/generic/FMA.h | 2 +-
 libc/src/__support/str_to_float.h       | 4 +---
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 978583870629a..cf7edffe6b321 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -18,7 +18,7 @@
 #include "src/__support/FPUtil/dyadic_float.h"
 #include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/big_int.h"
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/attributes.h"   // LIBC_INLINE
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 1f84e5bbb0951..90a67f74c4a67 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1146,9 +1146,7 @@ strtofloatingpoint(const CharType *__restrict src) {
     }
 
     RoundDirection round_direction = RoundDirection::Nearest;
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
-    round_direction = RoundDirection::Nearest;
-#else
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       round_direction = RoundDirection::Nearest;

>From 98836e7510860b7c7e88406d9870dd7cbdc67f65 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Thu, 4 Jun 2026 13:16:33 +0700
Subject: [PATCH 7/9] fix: inaccurate guardings and reviews

---
 libc/src/__support/FPUtil/rounding_mode.h | 20 ++++++++++++++++++++
 libc/src/__support/math/erfcf16.h         |  2 ++
 libc/src/__support/math/exp10f.h          |  4 ++++
 libc/src/__support/math/exp10f16.h        |  2 ++
 libc/src/__support/math/exp10m1f.h        | 18 ++++++++++++------
 libc/src/__support/math/exp10m1f16.h      |  2 +-
 libc/src/__support/math/exp2f.h           |  2 ++
 libc/src/__support/math/exp2f16.h         |  2 ++
 libc/src/__support/math/exp2m1f16.h       |  2 +-
 libc/src/__support/math/expf.h            |  2 ++
 libc/src/__support/math/expm1f.h          |  4 ++++
 libc/src/__support/math/expm1f16.h        |  2 +-
 libc/src/__support/math/sinhf16.h         |  4 +++-
 13 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 6ce693d41da50..eadae91621fe6 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -24,8 +24,12 @@ namespace generic {
 //   1.0f + 2^-25 = 1.0f        for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
 //                = 0x1.000002f for FE_UPWARD.
 LIBC_INLINE bool fenv_is_round_up() {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return false;
+#else
   static volatile float x = 0x1.0p-25f;
   return (1.0f + x != 1.0f);
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 // Quick free-standing test whether fegetround() == FE_DOWNWARD.
@@ -33,8 +37,12 @@ LIBC_INLINE bool fenv_is_round_up() {
 //   -1.0f - 2^-25 = -1.0f        for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
 //                 = -0x1.000002f for FE_DOWNWARD.
 LIBC_INLINE bool fenv_is_round_down() {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return false;
+#else
   static volatile float x = 0x1.0p-25f;
   return (-1.0f - x != -1.0f);
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 // Quick free-standing test whether fegetround() == FE_TONEAREST.
@@ -44,9 +52,13 @@ LIBC_INLINE bool fenv_is_round_down() {
 //   1.5f - 2^-24 = 1.5f           for FE_TONEAREST, FE_UPWARD
 //                = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
 LIBC_INLINE bool fenv_is_round_to_nearest() {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return true;
+#else
   static volatile float x = 0x1.0p-24f;
   float y = 1.5f + x;
   return (y == 1.5f - x);
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 // Quick free-standing test whether fegetround() == FE_TOWARDZERO.
@@ -60,13 +72,20 @@ LIBC_INLINE bool fenv_is_round_to_nearest() {
 //                                           = 2^-22 for FE_TONEAREST, FE_UPWARD
 //                                           = 0 for FE_DOWNWARD
 LIBC_INLINE bool fenv_is_round_to_zero() {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return false;
+#else
   static volatile float x = 0x1.0p-24f;
   float y = x;
   return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 // Quick free standing get rounding mode based on the above observations.
 LIBC_INLINE int quick_get_round() {
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+  return FE_TONEAREST;
+#else
   static volatile float x = 0x1.0p-24f;
   float y = x;
   float z = (0x1.000002p0f + y) + (-1.0f - y);
@@ -76,6 +95,7 @@ LIBC_INLINE int quick_get_round() {
   if (z == 0x1.0p-23f)
     return FE_TOWARDZERO;
   return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
 }
 
 } // namespace generic
diff --git a/libc/src/__support/math/erfcf16.h b/libc/src/__support/math/erfcf16.h
index 6fc37d7467de7..9acff0b609407 100644
--- a/libc/src/__support/math/erfcf16.h
+++ b/libc/src/__support/math/erfcf16.h
@@ -105,8 +105,10 @@ LIBC_INLINE float16 erfcf16(float16 x) {
     }
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (fputil::fenv_is_round_up())
       return FPBits::min_subnormal().get_val();
+#endif
     return 0.0f16;
   }
 
diff --git a/libc/src/__support/math/exp10f.h b/libc/src/__support/math/exp10f.h
index 88acd5ab59b00..b52f117f6988f 100644
--- a/libc/src/__support/math/exp10f.h
+++ b/libc/src/__support/math/exp10f.h
@@ -37,8 +37,10 @@ LIBC_INLINE float exp10f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
+#endif
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0f;
@@ -82,8 +84,10 @@ LIBC_INLINE float exp10f(float x) {
 
   // Exceptional value.
   if (LIBC_UNLIKELY(x_u == 0x3d14'd956U)) { // x = 0x1.29b2acp-5f
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (fputil::fenv_is_round_up())
       return 0x1.1657c4p+0f;
+#endif
   }
 
   // Exact outputs when x = 1, 2, ..., 10.
diff --git a/libc/src/__support/math/exp10f16.h b/libc/src/__support/math/exp10f16.h
index dafc74204e15e..2a5dbc049c5fc 100644
--- a/libc/src/__support/math/exp10f16.h
+++ b/libc/src/__support/math/exp10f16.h
@@ -108,8 +108,10 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
+#endif
       return FPBits::zero().get_val();
     }
   }
diff --git a/libc/src/__support/math/exp10m1f.h b/libc/src/__support/math/exp10m1f.h
index 2ef271be19933..5d68fe5cf83a7 100644
--- a/libc/src/__support/math/exp10m1f.h
+++ b/libc/src/__support/math/exp10m1f.h
@@ -200,27 +200,33 @@ LIBC_INLINE float exp10m1f(float x) {
     case 0x40e00000U: // x = 7.0f
       return 9'999'999.0f;
     case 0x41000000U: { // x = 8.0f
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return 100'000'000.0f;
+#else
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 100'000'000.0f;
-#endif
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return 99'999'992.0f;
     }
     case 0x41100000U: { // x = 9.0f
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return 1'000'000'000.0f;
+#else
       int rounding = fputil::quick_get_round();
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 1'000'000'000.0f;
-#endif
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return 999'999'936.0f;
     }
     case 0x41200000U: { // x = 10.0f
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+      return 10'000'000'000.0f;
+#else
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 10'000'000'000.0f;
-#endif
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       return 9'999'998'976.0f;
     }
     }
diff --git a/libc/src/__support/math/exp10m1f16.h b/libc/src/__support/math/exp10m1f16.h
index f9044f333676b..c25f351caf867 100644
--- a/libc/src/__support/math/exp10m1f16.h
+++ b/libc/src/__support/math/exp10m1f16.h
@@ -95,7 +95,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
 
 #ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
-      fputil::raise_except_if_required(FE_OVERFLOW);
+      fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
 #else
       switch (fputil::quick_get_round()) {
diff --git a/libc/src/__support/math/exp2f.h b/libc/src/__support/math/exp2f.h
index 5f574351ead65..91528c162a7ad 100644
--- a/libc/src/__support/math/exp2f.h
+++ b/libc/src/__support/math/exp2f.h
@@ -96,8 +96,10 @@ LIBC_INLINE float exp2f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
+#endif
       if (x != 0.0f) {
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_UNDERFLOW);
diff --git a/libc/src/__support/math/exp2f16.h b/libc/src/__support/math/exp2f16.h
index 40631c606e0e5..12c2278eb6b34 100644
--- a/libc/src/__support/math/exp2f16.h
+++ b/libc/src/__support/math/exp2f16.h
@@ -92,8 +92,10 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
+#endif
       return FPBits::zero().get_val();
     }
   }
diff --git a/libc/src/__support/math/exp2m1f16.h b/libc/src/__support/math/exp2m1f16.h
index a63d96bb227e6..6158275a841d9 100644
--- a/libc/src/__support/math/exp2m1f16.h
+++ b/libc/src/__support/math/exp2m1f16.h
@@ -108,7 +108,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
 
 #ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
-      fputil::raise_except_if_required(FE_OVERFLOW);
+      fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
 #else
       switch (fputil::quick_get_round()) {
diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index 13c17f1004185..061cf4a8bb13b 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -53,8 +53,10 @@ LIBC_INLINE float expf(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
+#endif
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
       return 0.0f;
diff --git a/libc/src/__support/math/expm1f.h b/libc/src/__support/math/expm1f.h
index abe969c80a670..baf109648f487 100644
--- a/libc/src/__support/math/expm1f.h
+++ b/libc/src/__support/math/expm1f.h
@@ -49,10 +49,14 @@ LIBC_INLINE float expm1f(float x) {
   }
 #if !defined(LIBC_TARGET_CPU_HAS_FMA_DOUBLE)
   if (LIBC_UNLIKELY(x_u == 0xbdc1'c6cbU)) { // x = -0x1.838d96p-4f
+#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+    return -0x1.71c884p-4f;
+#else
     int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_DOWNWARD)
       return -0x1.71c884p-4f;
     return -0x1.71c882p-4f;
+#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
   }
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
diff --git a/libc/src/__support/math/expm1f16.h b/libc/src/__support/math/expm1f16.h
index b29dffd9aa46c..d6a136becdf4f 100644
--- a/libc/src/__support/math/expm1f16.h
+++ b/libc/src/__support/math/expm1f16.h
@@ -88,7 +88,7 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
 
 #ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
-      fputil::raise_except_if_required(FE_OVERFLOW);
+      fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
 #else
       switch (fputil::quick_get_round()) {
diff --git a/libc/src/__support/math/sinhf16.h b/libc/src/__support/math/sinhf16.h
index 47b680507eb23..e14994144815b 100644
--- a/libc/src/__support/math/sinhf16.h
+++ b/libc/src/__support/math/sinhf16.h
@@ -131,7 +131,7 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
 
 #ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
       fputil::set_errno_if_required(ERANGE);
-      fputil::raise_except_if_required(FE_OVERFLOW);
+      fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf(x_bits.sign()).get_val();
 #else
       int rounding_mode = fputil::quick_get_round();
@@ -147,8 +147,10 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
     }
 
     // When -2^(-14) <= x <= -2^(-9).
+#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
     if (fputil::fenv_is_round_down())
       return FPBits(static_cast<uint16_t>(x_u + 1)).get_val();
+#endif
     return FPBits(static_cast<uint16_t>(x_u)).get_val();
   }
 

>From 978dfde7915af15b2f35524a37aad59dad0d4958 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Tue, 9 Jun 2026 20:47:36 +0700
Subject: [PATCH 8/9] fix: rename option and make tests skip other rounding
 modes when this new option is set

---
 libc/config/config.json                       |  2 +-
 libc/src/__support/FPUtil/Hypot.h             |  8 +-
 .../__support/FPUtil/ManipulationFunctions.h  |  4 +-
 .../FPUtil/NearestIntegerOperations.h         |  4 +-
 libc/src/__support/FPUtil/dyadic_float.h      | 10 +-
 .../src/__support/FPUtil/except_value_utils.h | 20 +++-
 libc/src/__support/FPUtil/generic/FMA.h       |  4 +-
 libc/src/__support/FPUtil/generic/add_sub.h   |  8 +-
 .../FPUtil/generic/sqrt_80_bit_long_double.h  |  4 +-
 libc/src/__support/FPUtil/rounding_mode.h     | 20 ++--
 libc/src/__support/macros/optimization.h      | 11 ++-
 libc/src/__support/math/asinbf16.h            |  2 +-
 libc/src/__support/math/asinf16.h             |  2 +-
 libc/src/__support/math/asinhf16.h            |  2 +-
 libc/src/__support/math/asinpi.h              |  4 +-
 libc/src/__support/math/coshf.h               |  2 +-
 libc/src/__support/math/coshf16.h             |  4 +-
 libc/src/__support/math/erfcf16.h             |  2 +-
 libc/src/__support/math/exp.h                 |  4 +-
 libc/src/__support/math/exp10.h               |  4 +-
 libc/src/__support/math/exp10f.h              |  8 +-
 libc/src/__support/math/exp10f16.h            |  6 +-
 libc/src/__support/math/exp10m1f.h            | 16 ++--
 libc/src/__support/math/exp10m1f16.h          |  8 +-
 libc/src/__support/math/exp2.h                |  4 +-
 libc/src/__support/math/exp2f.h               |  4 +-
 libc/src/__support/math/exp2f16.h             |  6 +-
 libc/src/__support/math/exp2m1f.h             |  4 +-
 libc/src/__support/math/exp2m1f16.h           |  8 +-
 libc/src/__support/math/expf.h                |  4 +-
 libc/src/__support/math/expf16.h              |  8 +-
 libc/src/__support/math/expm1.h               |  2 +-
 libc/src/__support/math/expm1f.h              | 12 +--
 libc/src/__support/math/expm1f16.h            |  4 +-
 libc/src/__support/math/sin.h                 |  4 +-
 libc/src/__support/math/sincos.h              |  4 +-
 libc/src/__support/math/sincosf.h             |  4 +-
 libc/src/__support/math/sinf.h                |  4 +-
 libc/src/__support/math/sinf16.h              |  6 +-
 libc/src/__support/math/sinhf.h               |  8 +-
 libc/src/__support/math/sinhf16.h             |  6 +-
 libc/src/__support/math/tan.h                 |  4 +-
 libc/src/__support/math/tanf16.h              |  4 +-
 libc/src/__support/math/tanhf16.h             |  8 +-
 libc/src/__support/str_to_float.h             |  6 +-
 .../stdio/printf_core/float_dec_converter.h   |  2 +-
 .../stdio/printf_core/float_hex_converter.h   |  4 +-
 libc/test/UnitTest/FPMatcher.h                | 59 ++++++++++++
 libc/test/UnitTest/RoundingModeUtils.cpp      |  9 ++
 libc/utils/MPFRWrapper/MPFRUtils.h            | 91 +++++++++++++++++--
 50 files changed, 296 insertions(+), 142 deletions(-)

diff --git a/libc/config/config.json b/libc/config/config.json
index 510a6c1b1990c..d576d7d14e4af 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -144,7 +144,7 @@
   "math": {
     "LIBC_CONF_MATH_OPTIMIZATIONS": {
       "value": 0,
-      "doc": "Configure optimizations for math functions. Values accepted are LIBC_MATH_SKIP_ACCURATE_PASS, LIBC_MATH_SMALL_TABLES, LIBC_MATH_NO_ERRNO, LIBC_MATH_NO_EXCEPT, LIBC_MATH_FAST, and LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT."
+      "doc": "Configure optimizations for math functions. Values accepted are LIBC_MATH_SKIP_ACCURATE_PASS, LIBC_MATH_SMALL_TABLES, LIBC_MATH_NO_ERRNO, LIBC_MATH_NO_EXCEPT, LIBC_MATH_FAST, LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT, and LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY."
     },
     "LIBC_CONF_FREXP_INF_NAN_EXPONENT": {
       "value": "",
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 8610ec8e69774..fdbd7b4acf088 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -199,14 +199,14 @@ LIBC_INLINE T hypot(T x, T y) {
       sum >>= 2;
       ++out_exp;
       if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         if (int round_mode = quick_get_round();
             round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
           return FPBits_t::inf().get_val();
         return FPBits_t::max_normal().get_val();
 #else
         return FPBits_t::inf().get_val();
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
@@ -245,7 +245,7 @@ LIBC_INLINE T hypot(T x, T y) {
 
   y_new >>= 1;
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   // Round to the nearest, tie to even.
   if (round_bit && (lsb || sticky_bits || (r != 0)))
     ++y_new;
@@ -279,7 +279,7 @@ LIBC_INLINE T hypot(T x, T y) {
       return FPBits_t::max_normal().get_val();
     }
   }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
   y_new |= static_cast<StorageType>(out_exp) << FPBits_t::FRACTION_LEN;
 
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index 6dc673daf45e5..02dded2f47913 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -173,7 +173,7 @@ ldexp(T x, U exp) {
 
   if (LIBC_UNLIKELY(exp > EXP_LIMIT)) {
     Sign sign = bits.sign();
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding_mode = quick_get_round();
 
     if ((sign == Sign::POS && rounding_mode == FE_DOWNWARD) ||
@@ -190,7 +190,7 @@ ldexp(T x, U exp) {
   // Similarly on the negative side we return zero early if |exp| is too small.
   if (LIBC_UNLIKELY(exp < -EXP_LIMIT)) {
     Sign sign = bits.sign();
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding_mode = quick_get_round();
     if ((sign == Sign::POS && rounding_mode == FE_UPWARD) ||
         (sign == Sign::NEG && rounding_mode == FE_DOWNWARD))
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 9329d2985ac6e..6499090c43d23 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -246,9 +246,9 @@ round_using_specific_rounding_mode(T x, int rnd) {
 template <typename T>
 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
 round_using_current_rounding_mode(T x) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   return round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
   int rounding_mode = quick_get_round();
 
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 4f436a71d2876..bd7e85bfa248e 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -46,7 +46,7 @@ rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
       (rshift >= Bits && value == 0))
     return 0; // exact
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   if (rshift > 0 && rshift <= Bits && value.get_bit(rshift - 1)) {
     // We round up, unless the value is an exact halfway case and
     // the bit that will end up in the units place is 0, in which
@@ -202,9 +202,9 @@ template <size_t Bits> struct DyadicFloat {
         raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       }
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return FPBits::inf(sign).get_val();
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
       switch (quick_get_round()) {
       case FE_TONEAREST:
@@ -264,7 +264,7 @@ template <size_t Bits> struct DyadicFloat {
     StorageType result =
         FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (round && (lsb || sticky))
       ++result;
 #else
@@ -284,7 +284,7 @@ template <size_t Bits> struct DyadicFloat {
     default:
       break;
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
     if (ShouldSignalExceptions && (round || sticky)) {
       int excepts = FE_INEXACT;
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index a125c3aafa827..4e7f50c580d02 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -58,7 +58,7 @@ template <typename T, size_t N> struct ExceptValues {
     for (size_t i = 0; i < N; ++i) {
       if (LIBC_UNLIKELY(x_bits == values[i].input)) {
         StorageType out_bits = values[i].rnd_towardzero_result;
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         out_bits += values[i].rnd_tonearest_offset;
 #else
         switch (fputil::quick_get_round()) {
@@ -72,7 +72,7 @@ template <typename T, size_t N> struct ExceptValues {
           out_bits += values[i].rnd_tonearest_offset;
           break;
         }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         return FPBits<T>(out_bits).get_val();
       }
     }
@@ -84,7 +84,7 @@ template <typename T, size_t N> struct ExceptValues {
     for (size_t i = 0; i < N; ++i) {
       if (LIBC_UNLIKELY(x_abs == values[i].input)) {
         StorageType out_bits = values[i].rnd_towardzero_result;
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         out_bits += values[i].rnd_tonearest_offset;
 #else
         switch (fputil::quick_get_round()) {
@@ -107,7 +107,7 @@ template <typename T, size_t N> struct ExceptValues {
           out_bits += values[i].rnd_tonearest_offset;
           break;
         }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         T result = FPBits<T>(out_bits).get_val();
         if (sign)
           result = -result;
@@ -133,6 +133,9 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_down(T value_rn) {
 
 template <typename T>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_up(T value_rn) {
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  return value_rn;
+#else
   if (cpp::is_constant_evaluated()) {
     return value_rn;
   } else {
@@ -140,6 +143,7 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_up(T value_rn) {
     tmp += FPBits<T>::min_normal().get_val();
     return tmp;
   }
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 #if defined(LIBC_TYPES_HAS_FLOAT16) &&                                         \
@@ -147,6 +151,9 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_up(T value_rn) {
 template <>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float16
 round_result_slightly_down(float16 value_rn) {
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  return value_rn;
+#else
   if (cpp::is_constant_evaluated()) {
     return value_rn;
   } else {
@@ -154,11 +161,15 @@ round_result_slightly_down(float16 value_rn) {
     tmp -= FPBits<float16>::min_normal().get_val();
     return cast<float16>(tmp);
   }
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 template <>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float16
 round_result_slightly_up(float16 value_rn) {
+#ifdef LIBC_HAS_ASSUME_ROUND_NEAREST_ONLY
+  return value_rn;
+#else
   if (cpp::is_constant_evaluated()) {
     return value_rn;
   } else {
@@ -166,6 +177,7 @@ round_result_slightly_up(float16 value_rn) {
     tmp += FPBits<float16>::min_normal().get_val();
     return cast<float16>(tmp);
   }
+#endif // LIBC_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 #endif
 
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index cf7edffe6b321..f08f92d8febc0 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -275,14 +275,14 @@ fma(InType x, InType y, InType z) {
   if (prod_mant == 0) {
     // When there is exact cancellation, i.e., x*y == -z exactly, return -0.0 if
     // rounding downward and +0.0 for other rounding modes.
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     prod_sign = Sign::POS;
 #else
     if (fputil::quick_get_round() == FE_DOWNWARD)
       prod_sign = Sign::NEG;
     else
       prod_sign = Sign::POS;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   }
 
   DyadicFloat result(prod_sign, prod_lsb_exp - InFPBits::EXP_BIAS, prod_mant);
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 3142344e65abb..cf662d051c162 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -98,7 +98,7 @@ add_or_sub(InType x, InType y) {
       if (y_bits.is_zero()) {
         if (is_effectively_add)
           return OutFPBits::zero(x_bits.sign()).get_val();
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         return OutFPBits::zero(Sign::POS).get_val();
 #else
         switch (fputil::quick_get_round()) {
@@ -107,7 +107,7 @@ add_or_sub(InType x, InType y) {
         default:
           return OutFPBits::zero(Sign::POS).get_val();
         }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       }
 
       if constexpr (cpp::is_same_v<InType, bfloat16> &&
@@ -140,7 +140,7 @@ add_or_sub(InType x, InType y) {
   InType y_abs = y_bits.abs().get_val();
 
   if (x_abs == y_abs && !is_effectively_add) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     return OutFPBits::zero(Sign::POS).get_val();
 #else
     switch (fputil::quick_get_round()) {
@@ -149,7 +149,7 @@ add_or_sub(InType x, InType y) {
     default:
       return OutFPBits::zero(Sign::POS).get_val();
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   }
 
   Sign result_sign = Sign::POS;
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 5e62511cc8afc..d88162e7243c8 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
@@ -110,7 +110,7 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x) {
     // Append the exponent field.
     x_exp = ((x_exp >> 1) + LDBits::EXP_BIAS);
     y |= (static_cast<StorageType>(x_exp) << (LDBits::FRACTION_LEN + 1));
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     // Round to nearest, ties to even
     if (rb && (lsb || (r != 0)))
       ++y;
@@ -126,7 +126,7 @@ LIBC_INLINE LIBC_CONSTEXPR_DEFAULT long double sqrt(long double x) {
         ++y;
       break;
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
     // Extract output
     FPBits<long double> out(0.0L);
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index eadae91621fe6..3159c1c82ad7f 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -24,12 +24,12 @@ namespace generic {
 //   1.0f + 2^-25 = 1.0f        for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
 //                = 0x1.000002f for FE_UPWARD.
 LIBC_INLINE bool fenv_is_round_up() {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   return false;
 #else
   static volatile float x = 0x1.0p-25f;
   return (1.0f + x != 1.0f);
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 // Quick free-standing test whether fegetround() == FE_DOWNWARD.
@@ -37,12 +37,12 @@ LIBC_INLINE bool fenv_is_round_up() {
 //   -1.0f - 2^-25 = -1.0f        for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
 //                 = -0x1.000002f for FE_DOWNWARD.
 LIBC_INLINE bool fenv_is_round_down() {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   return false;
 #else
   static volatile float x = 0x1.0p-25f;
   return (-1.0f - x != -1.0f);
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 // Quick free-standing test whether fegetround() == FE_TONEAREST.
@@ -52,13 +52,13 @@ LIBC_INLINE bool fenv_is_round_down() {
 //   1.5f - 2^-24 = 1.5f           for FE_TONEAREST, FE_UPWARD
 //                = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
 LIBC_INLINE bool fenv_is_round_to_nearest() {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   return true;
 #else
   static volatile float x = 0x1.0p-24f;
   float y = 1.5f + x;
   return (y == 1.5f - x);
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 // Quick free-standing test whether fegetround() == FE_TOWARDZERO.
@@ -72,18 +72,18 @@ LIBC_INLINE bool fenv_is_round_to_nearest() {
 //                                           = 2^-22 for FE_TONEAREST, FE_UPWARD
 //                                           = 0 for FE_DOWNWARD
 LIBC_INLINE bool fenv_is_round_to_zero() {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   return false;
 #else
   static volatile float x = 0x1.0p-24f;
   float y = x;
   return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 // Quick free standing get rounding mode based on the above observations.
 LIBC_INLINE int quick_get_round() {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   return FE_TONEAREST;
 #else
   static volatile float x = 0x1.0p-24f;
@@ -95,7 +95,7 @@ LIBC_INLINE int quick_get_round() {
   if (z == 0x1.0p-23f)
     return FE_TOWARDZERO;
   return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 } // namespace generic
diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h
index ecfadc8a86ca0..51091b6d46404 100644
--- a/libc/src/__support/macros/optimization.h
+++ b/libc/src/__support/macros/optimization.h
@@ -52,11 +52,12 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
 #define LIBC_MATH_SMALL_TABLES 0x02
 #define LIBC_MATH_NO_ERRNO 0x04
 #define LIBC_MATH_NO_EXCEPT 0x08
+#define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
+#define LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY 0x20
 #define LIBC_MATH_FAST                                                         \
   (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES |                     \
-   LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)
-#define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
-#define LIBC_MATH_ALWAYS_ROUND_NEAREST 0x20
+   LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT |                                  \
+   LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY)
 
 #ifndef LIBC_MATH
 #define LIBC_MATH 0
@@ -82,8 +83,8 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
 #define LIBC_MATH_HAS_NO_EXCEPT
 #endif
 
-#if ((LIBC_MATH) & LIBC_MATH_ALWAYS_ROUND_NEAREST)
-#define LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#if ((LIBC_MATH) & LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY)
+#define LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 #endif
 
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index b6cacc6275d08..904263f390383 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -45,7 +45,7 @@ LIBC_INLINE LIBC_CONSTEXPR bfloat16 asinbf16(bfloat16 x) {
       return x; // with sign
 
     if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       int rounding = fputil::quick_get_round();
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD)) {
diff --git a/libc/src/__support/math/asinf16.h b/libc/src/__support/math/asinf16.h
index 7d9f908ba202b..367a034521146 100644
--- a/libc/src/__support/math/asinf16.h
+++ b/libc/src/__support/math/asinf16.h
@@ -73,7 +73,7 @@ LIBC_INLINE constexpr float16 asinf16(float16 x) {
     // else, in other rounding modes,
     // asin(x) = x
     if (LIBC_UNLIKELY(x_abs <= 0x1a1e)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       int rounding = fputil::quick_get_round();
 
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
diff --git a/libc/src/__support/math/asinhf16.h b/libc/src/__support/math/asinhf16.h
index 9031b1347ed51..e6f108763969b 100644
--- a/libc/src/__support/math/asinhf16.h
+++ b/libc/src/__support/math/asinhf16.h
@@ -87,7 +87,7 @@ LIBC_INLINE constexpr float16 asinhf16(float16 x) {
     // when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
     // rounding types.
     if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       int rounding = fputil::quick_get_round();
       if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
         return fputil::cast<float16>(xf + 0x1p-24f);
diff --git a/libc/src/__support/math/asinpi.h b/libc/src/__support/math/asinpi.h
index 7979e7db9f939..c4bdd6cf3f107 100644
--- a/libc/src/__support/math/asinpi.h
+++ b/libc/src/__support/math/asinpi.h
@@ -84,7 +84,7 @@ LIBC_INLINE double asinpi(double x) {
             MantT sticky_mask = (MantT(1) << (SHIFT_53 - 1)) - 1;
             bool sticky = (r.mantissa & sticky_mask) != 0;
             bool lsb = static_cast<bool>(m53 & 1);
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
             // Carry if round_bit && (lsb || sticky) (round half to even).
             raise_underflow = !(round_bit && (lsb || sticky));
 #else
@@ -104,7 +104,7 @@ LIBC_INLINE double asinpi(double x) {
               raise_underflow = true; // truncation never carries
               break;
             }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
           }
         }
         if (raise_underflow)
diff --git a/libc/src/__support/math/coshf.h b/libc/src/__support/math/coshf.h
index bb76f34592844..5d5e4ff496c9e 100644
--- a/libc/src/__support/math/coshf.h
+++ b/libc/src/__support/math/coshf.h
@@ -40,7 +40,7 @@ LIBC_INLINE float coshf(float x) {
     if (xbits.is_inf_or_nan())
       return x + FPBits::inf().get_val();
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/coshf16.h b/libc/src/__support/math/coshf16.h
index ca3fda873329a..f5015199b3f93 100644
--- a/libc/src/__support/math/coshf16.h
+++ b/libc/src/__support/math/coshf16.h
@@ -90,7 +90,7 @@ LIBC_INLINE constexpr float16 coshf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
@@ -104,7 +104,7 @@ LIBC_INLINE constexpr float16 coshf16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
   }
 
diff --git a/libc/src/__support/math/erfcf16.h b/libc/src/__support/math/erfcf16.h
index 9acff0b609407..ad096527855d5 100644
--- a/libc/src/__support/math/erfcf16.h
+++ b/libc/src/__support/math/erfcf16.h
@@ -105,7 +105,7 @@ LIBC_INLINE float16 erfcf16(float16 x) {
     }
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (fputil::fenv_is_round_up())
       return FPBits::min_subnormal().get_val();
 #endif
diff --git a/libc/src/__support/math/exp.h b/libc/src/__support/math/exp.h
index 4ac4b183dd02d..dfb2a2efc5e79 100644
--- a/libc/src/__support/math/exp.h
+++ b/libc/src/__support/math/exp.h
@@ -211,7 +211,7 @@ LIBC_INLINE double set_exceptional(double x) {
     if (xbits.is_nan())
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (fputil::quick_get_round() == FE_UPWARD)
       return FPBits::min_subnormal().get_val();
 #endif
@@ -223,7 +223,7 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= round(log(MAX_NORMAL), D, RU) = 0x1.62e42fefa39fp+9 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp10.h b/libc/src/__support/math/exp10.h
index 9dee8ef849db8..04588c2673c4f 100644
--- a/libc/src/__support/math/exp10.h
+++ b/libc/src/__support/math/exp10.h
@@ -259,7 +259,7 @@ LIBC_INLINE double exp10_set_exceptional(double x) {
       if (xbits.is_nan())
         return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::quick_get_round() == FE_UPWARD)
         return FPBits::min_subnormal().get_val();
 #endif
@@ -274,7 +274,7 @@ LIBC_INLINE double exp10_set_exceptional(double x) {
   // x >= log10(2^1024) or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp10f.h b/libc/src/__support/math/exp10f.h
index b52f117f6988f..642370a3d2aa3 100644
--- a/libc/src/__support/math/exp10f.h
+++ b/libc/src/__support/math/exp10f.h
@@ -37,7 +37,7 @@ LIBC_INLINE float exp10f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
 #endif
@@ -49,7 +49,7 @@ LIBC_INLINE float exp10f(float x) {
     if (xbits.is_pos() && (x_u >= 0x421a'209bU)) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
@@ -66,7 +66,7 @@ LIBC_INLINE float exp10f(float x) {
   // When |x| <= log10(2)*2^-6
   if (LIBC_UNLIKELY(x_abs <= 0x3b9a'209bU)) {
     if (LIBC_UNLIKELY(x_u == 0xb25e'5bd9U)) { // x = -0x1.bcb7b2p-27f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 0x1.fffffep-1f;
 #else
       if (fputil::fenv_is_round_to_nearest())
@@ -84,7 +84,7 @@ LIBC_INLINE float exp10f(float x) {
 
   // Exceptional value.
   if (LIBC_UNLIKELY(x_u == 0x3d14'd956U)) { // x = 0x1.29b2acp-5f
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (fputil::fenv_is_round_up())
       return 0x1.1657c4p+0f;
 #endif
diff --git a/libc/src/__support/math/exp10f16.h b/libc/src/__support/math/exp10f16.h
index 2a5dbc049c5fc..727914f1bb601 100644
--- a/libc/src/__support/math/exp10f16.h
+++ b/libc/src/__support/math/exp10f16.h
@@ -82,7 +82,7 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -96,7 +96,7 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When x <= -8.
@@ -108,7 +108,7 @@ LIBC_INLINE constexpr float16 exp10f16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
 #endif
diff --git a/libc/src/__support/math/exp10m1f.h b/libc/src/__support/math/exp10m1f.h
index 5d68fe5cf83a7..6aef47b7fae1e 100644
--- a/libc/src/__support/math/exp10m1f.h
+++ b/libc/src/__support/math/exp10m1f.h
@@ -115,7 +115,7 @@ LIBC_INLINE float exp10m1f(float x) {
   // When x >= log10(2^128), or x is nan
   if (LIBC_UNLIKELY(xbits.is_pos() && x_u >= 0x421a'209bU)) {
     if (xbits.is_finite()) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       int rounding = fputil::quick_get_round();
       if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
         return FPBits::max_normal().get_val();
@@ -166,7 +166,7 @@ LIBC_INLINE float exp10m1f(float x) {
     if (xbits.is_nan())
       return x;
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (x_u == 0xc0f0d2f1)     // x = log10(2^-25)
       return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
 #else
@@ -200,33 +200,33 @@ LIBC_INLINE float exp10m1f(float x) {
     case 0x40e00000U: // x = 7.0f
       return 9'999'999.0f;
     case 0x41000000U: { // x = 8.0f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 100'000'000.0f;
 #else
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 100'000'000.0f;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 99'999'992.0f;
     }
     case 0x41100000U: { // x = 9.0f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 1'000'000'000.0f;
 #else
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 1'000'000'000.0f;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 999'999'936.0f;
     }
     case 0x41200000U: { // x = 10.0f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 10'000'000'000.0f;
 #else
       int rounding = fputil::quick_get_round();
       if (rounding == FE_UPWARD || rounding == FE_TONEAREST)
         return 10'000'000'000.0f;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return 9'999'998'976.0f;
     }
     }
diff --git a/libc/src/__support/math/exp10m1f16.h b/libc/src/__support/math/exp10m1f16.h
index c25f351caf867..4c176e3a9ea53 100644
--- a/libc/src/__support/math/exp10m1f16.h
+++ b/libc/src/__support/math/exp10m1f16.h
@@ -93,7 +93,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
@@ -107,7 +107,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When x < -11 * log10(2).
@@ -123,7 +123,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       }
 
       // When x < -0x1.ce4p+1, round(10^x - 1, HP, RN) = -1.
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return FPBits::one(Sign::NEG).get_val();
 #else
       switch (fputil::quick_get_round()) {
@@ -133,7 +133,7 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
       default:
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When |x| <= 2^(-3).
diff --git a/libc/src/__support/math/exp2.h b/libc/src/__support/math/exp2.h
index 19eafa2141800..90790e435a721 100644
--- a/libc/src/__support/math/exp2.h
+++ b/libc/src/__support/math/exp2.h
@@ -238,7 +238,7 @@ LIBC_INLINE double set_exceptional(double x) {
       if (xbits.is_nan())
         return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::quick_get_round() == FE_UPWARD)
         return FPBits::min_subnormal().get_val();
 #endif
@@ -253,7 +253,7 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= 1024 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/exp2f.h b/libc/src/__support/math/exp2f.h
index 91528c162a7ad..1fa24c2013ede 100644
--- a/libc/src/__support/math/exp2f.h
+++ b/libc/src/__support/math/exp2f.h
@@ -76,7 +76,7 @@ LIBC_INLINE float exp2f(float x) {
     if (xbits.is_pos()) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
@@ -96,7 +96,7 @@ LIBC_INLINE float exp2f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
 #endif
diff --git a/libc/src/__support/math/exp2f16.h b/libc/src/__support/math/exp2f16.h
index 12c2278eb6b34..fe2c78faeef98 100644
--- a/libc/src/__support/math/exp2f16.h
+++ b/libc/src/__support/math/exp2f16.h
@@ -66,7 +66,7 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -80,7 +80,7 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When x <= -25.
@@ -92,7 +92,7 @@ LIBC_INLINE constexpr float16 exp2f16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
 #endif
diff --git a/libc/src/__support/math/exp2m1f.h b/libc/src/__support/math/exp2m1f.h
index 3acd497e3d10d..80db977f2f2b8 100644
--- a/libc/src/__support/math/exp2m1f.h
+++ b/libc/src/__support/math/exp2m1f.h
@@ -96,7 +96,7 @@ LIBC_INLINE float exp2m1f(float x) {
     // x >= 128, or x is nan
     if (xbits.is_pos()) {
       if (xbits.is_finite()) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
@@ -119,7 +119,7 @@ LIBC_INLINE float exp2m1f(float x) {
     if (xbits.is_nan())
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (rounding == FE_UPWARD || rounding == FE_TOWARDZERO)
       return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
diff --git a/libc/src/__support/math/exp2m1f16.h b/libc/src/__support/math/exp2m1f16.h
index 6158275a841d9..49922df4cd79d 100644
--- a/libc/src/__support/math/exp2m1f16.h
+++ b/libc/src/__support/math/exp2m1f16.h
@@ -106,7 +106,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
@@ -120,7 +120,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When x < -11.
@@ -135,7 +135,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
             fputil::cast<float16>(-0x1.ffcp-1));
 
       // When x <= -12, round(2^x - 1, HP, RN) = -1.
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return FPBits::one(Sign::NEG).get_val();
 #else
       switch (fputil::quick_get_round()) {
@@ -145,7 +145,7 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
       default:
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When |x| <= 2^(-3).
diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index 061cf4a8bb13b..f2c2c5319d221 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -53,7 +53,7 @@ LIBC_INLINE float expf(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       if (fputil::fenv_is_round_up())
         return FPBits::min_subnormal().get_val();
 #endif
@@ -65,7 +65,7 @@ LIBC_INLINE float expf(float x) {
     if (xbits.is_pos() && (xbits.uintval() >= 0x42b2'0000)) {
       // x is finite
       if (xbits.uintval() < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/expf16.h b/libc/src/__support/math/expf16.h
index 0c96ebf07357f..fd0c92b791ecf 100644
--- a/libc/src/__support/math/expf16.h
+++ b/libc/src/__support/math/expf16.h
@@ -75,7 +75,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW);
       return FPBits::inf().get_val();
@@ -89,7 +89,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When x <= -18.
@@ -101,7 +101,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return FPBits::zero().get_val();
 #else
       switch (fputil::quick_get_round()) {
@@ -110,7 +110,7 @@ LIBC_INLINE constexpr float16 expf16(float16 x) {
       default:
         return FPBits::zero().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When 0 < |x| <= 2^(-5).
diff --git a/libc/src/__support/math/expm1.h b/libc/src/__support/math/expm1.h
index 0a44afd1fcd60..3d2aa57b589cb 100644
--- a/libc/src/__support/math/expm1.h
+++ b/libc/src/__support/math/expm1.h
@@ -265,7 +265,7 @@ LIBC_INLINE double set_exceptional(double x) {
   // x >= round(log(MAX_NORMAL), D, RU) = 0x1.62e42fefa39fp+9 or +inf/nan
   // x is finite
   if (x_u < 0x7ff0'0000'0000'0000ULL) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
       return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/expm1f.h b/libc/src/__support/math/expm1f.h
index baf109648f487..436fb1ca4e876 100644
--- a/libc/src/__support/math/expm1f.h
+++ b/libc/src/__support/math/expm1f.h
@@ -38,25 +38,25 @@ LIBC_INLINE float expm1f(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   // Exceptional value
   if (LIBC_UNLIKELY(x_u == 0x3e35'bec5U)) { // x = 0x1.6b7d8ap-3f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     return 0x1.8dbe64p-3f;
 #else
     int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
       return 0x1.8dbe64p-3f;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     return 0x1.8dbe62p-3f;
   }
 #if !defined(LIBC_TARGET_CPU_HAS_FMA_DOUBLE)
   if (LIBC_UNLIKELY(x_u == 0xbdc1'c6cbU)) { // x = -0x1.838d96p-4f
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     return -0x1.71c884p-4f;
 #else
     int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_DOWNWARD)
       return -0x1.71c884p-4f;
     return -0x1.71c882p-4f;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   }
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
@@ -71,7 +71,7 @@ LIBC_INLINE float expm1f(float x) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       int round_mode = fputil::quick_get_round();
       if (round_mode == FE_UPWARD || round_mode == FE_TOWARDZERO)
         return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
@@ -81,7 +81,7 @@ LIBC_INLINE float expm1f(float x) {
       // x >= 89 or nan
       if (xbits.uintval() >= 0x42b2'0000) {
         if (xbits.uintval() < 0x7f80'0000U) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
           int rounding = fputil::quick_get_round();
           if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
             return FPBits::max_normal().get_val();
diff --git a/libc/src/__support/math/expm1f16.h b/libc/src/__support/math/expm1f16.h
index d6a136becdf4f..08234a0ad4ace 100644
--- a/libc/src/__support/math/expm1f16.h
+++ b/libc/src/__support/math/expm1f16.h
@@ -86,7 +86,7 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf().get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf().get_val();
@@ -100,7 +100,7 @@ LIBC_INLINE constexpr float16 expm1f16(float16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When x <= -11 * log(2).
diff --git a/libc/src/__support/math/sin.h b/libc/src/__support/math/sin.h
index ff59a163c3eab..0c8933c10fd31 100644
--- a/libc/src/__support/math/sin.h
+++ b/libc/src/__support/math/sin.h
@@ -94,13 +94,13 @@ LIBC_INLINE double sin(double x) {
         return fputil::multiply_add(x, -0x1.0p-54, x);
 #else
         if (LIBC_UNLIKELY(x_e < 4)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
           int rounding_mode = fputil::quick_get_round();
           if (rounding_mode == FE_TOWARDZERO ||
               (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD))
             return FPBits(xbits.uintval() - 1).get_val();
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         }
         return fputil::multiply_add(x, -0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/sincos.h b/libc/src/__support/math/sincos.h
index ee153eb831cb7..4d8cf96dc4511 100644
--- a/libc/src/__support/math/sincos.h
+++ b/libc/src/__support/math/sincos.h
@@ -67,13 +67,13 @@ LIBC_INLINE void sincos(double x, double *sin_x, double *cos_x) {
         *cos_x = fputil::round_result_slightly_down(1.0);
 
         if (LIBC_UNLIKELY(x_e < 4)) {
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
           int rounding_mode = fputil::quick_get_round();
           if (rounding_mode == FE_TOWARDZERO ||
               (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD))
             *sin_x = FPBits(xbits.uintval() - 1).get_val();
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         }
         *sin_x = fputil::multiply_add(x, -0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/sincosf.h b/libc/src/__support/math/sincosf.h
index d6f39edbffa90..b5f700011bfd4 100644
--- a/libc/src/__support/math/sincosf.h
+++ b/libc/src/__support/math/sincosf.h
@@ -176,7 +176,7 @@ LIBC_INLINE void sincosf(float x, float *sinp, float *cosp) {
       uint32_t s = EXCEPT_OUTPUTS_SIN[i][0]; // FE_TOWARDZERO
       uint32_t c = EXCEPT_OUTPUTS_COS[i][0]; // FE_TOWARDZERO
       bool x_sign = x < 0;
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       s += EXCEPT_OUTPUTS_SIN[i][3];
       c += EXCEPT_OUTPUTS_COS[i][3];
 #else
@@ -194,7 +194,7 @@ LIBC_INLINE void sincosf(float x, float *sinp, float *cosp) {
         c += EXCEPT_OUTPUTS_COS[i][3];
         break;
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       *sinp = x_sign ? -FPBits(s).get_val() : FPBits(s).get_val();
       *cosp = FPBits(c).get_val();
 
diff --git a/libc/src/__support/math/sinf.h b/libc/src/__support/math/sinf.h
index 601413697c568..1f72618a2962f 100644
--- a/libc/src/__support/math/sinf.h
+++ b/libc/src/__support/math/sinf.h
@@ -152,12 +152,12 @@ LIBC_INLINE float sinf(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
     float r = -0x1.63f4bap-2f;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if ((rounding == FE_DOWNWARD && xbits.is_pos()) ||
         (rounding == FE_UPWARD && xbits.is_neg()))
       r = -0x1.63f4bcp-2f;
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     return xbits.is_neg() ? -r : r;
   }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
diff --git a/libc/src/__support/math/sinf16.h b/libc/src/__support/math/sinf16.h
index 3ac7afb4add02..65ac5639acbc7 100644
--- a/libc/src/__support/math/sinf16.h
+++ b/libc/src/__support/math/sinf16.h
@@ -79,7 +79,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
     return r.value();
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   int rounding = fputil::quick_get_round();
 #endif
 
@@ -90,7 +90,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
     if (LIBC_UNLIKELY(x_abs == 0U))
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     // When x > 0, and rounding upward, sin(x) == x.
     // When x < 0, and rounding downward, sin(x) == x.
     if ((rounding == FE_UPWARD && xbits.is_pos()) ||
@@ -102,7 +102,7 @@ LIBC_INLINE float16 sinf16(float16 x) {
       x_u--;
       return FPBits(x_u).get_val();
     }
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
     // TODO: what about the case with rounding nearest and we're in here?
     // Previously, it's an UB
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
index 5c10ba8de07d1..e754577a80e66 100644
--- a/libc/src/__support/math/sinhf.h
+++ b/libc/src/__support/math/sinhf.h
@@ -32,12 +32,12 @@ LIBC_INLINE float sinhf(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
       // |x| = 0.0005589424981735646724700927734375
       if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         return x;
 #else
         if (fputil::fenv_is_round_to_nearest())
           return x;
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
@@ -65,7 +65,7 @@ LIBC_INLINE float sinhf(float x) {
     if (xbits.is_inf())
       return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     int rounding = fputil::quick_get_round();
     if (xbits.is_neg()) {
       if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
@@ -74,7 +74,7 @@ LIBC_INLINE float sinhf(float x) {
       if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
         return FPBits::max_normal().get_val();
     }
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
     fputil::set_errno_if_required(ERANGE);
     fputil::raise_except_if_required(FE_OVERFLOW);
diff --git a/libc/src/__support/math/sinhf16.h b/libc/src/__support/math/sinhf16.h
index e14994144815b..45d7eddd01fed 100644
--- a/libc/src/__support/math/sinhf16.h
+++ b/libc/src/__support/math/sinhf16.h
@@ -129,7 +129,7 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
       if (x_bits.is_inf())
         return FPBits::inf(x_bits.sign()).get_val();
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
       return FPBits::inf(x_bits.sign()).get_val();
@@ -142,12 +142,12 @@ LIBC_INLINE constexpr float16 sinhf16(float16 x) {
         fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return FPBits::inf(x_bits.sign()).get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return FPBits::max_normal(x_bits.sign()).get_val();
     }
 
     // When -2^(-14) <= x <= -2^(-9).
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (fputil::fenv_is_round_down())
       return FPBits(static_cast<uint16_t>(x_u + 1)).get_val();
 #endif
diff --git a/libc/src/__support/math/tan.h b/libc/src/__support/math/tan.h
index cfa8940e594de..7ff6f4f795cfb 100644
--- a/libc/src/__support/math/tan.h
+++ b/libc/src/__support/math/tan.h
@@ -150,12 +150,12 @@ LIBC_INLINE double tan(double x) {
 #else
         if (LIBC_UNLIKELY(x_e < 4)) {
           // TODO: UB for rounding nearest
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
           int rounding_mode = fputil::quick_get_round();
           if ((xbits.sign() == Sign::POS && rounding_mode == FE_UPWARD) ||
               (xbits.sign() == Sign::NEG && rounding_mode == FE_DOWNWARD))
             return FPBits(xbits.uintval() + 1).get_val();
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
         }
         return fputil::multiply_add(x, 0x1.0p-54, x);
 #endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/tanf16.h b/libc/src/__support/math/tanf16.h
index b219837387318..761990f73a90b 100644
--- a/libc/src/__support/math/tanf16.h
+++ b/libc/src/__support/math/tanf16.h
@@ -68,7 +68,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
       if (LIBC_UNLIKELY(x_abs == 0))
         return x;
 
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       int rounding = fputil::quick_get_round();
 
       // Exhaustive tests show that, when:
@@ -78,7 +78,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
       if ((xbits.is_pos() && rounding == FE_UPWARD) ||
           (xbits.is_neg() && rounding == FE_DOWNWARD))
         return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
-#endif // !LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return x;
     }
 
diff --git a/libc/src/__support/math/tanhf16.h b/libc/src/__support/math/tanhf16.h
index e56eab55bf548..768ec6845fe94 100644
--- a/libc/src/__support/math/tanhf16.h
+++ b/libc/src/__support/math/tanhf16.h
@@ -64,7 +64,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
 
     // When -2^(-14) <= x <= -2^(-9).
     if (x_u >= 0x8400U && x_u <= 0x9800U) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       return x;
 #else
       switch (fputil::quick_get_round()) {
@@ -74,7 +74,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
       default:
         return FPBits(static_cast<uint16_t>(x_u - 1U)).get_val();
       }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // When |x| <= 0x1.d2p-4.
@@ -102,7 +102,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
     // When |x| >= atanh(1 - 2^(-11)).
     fputil::raise_except_if_required(FE_INEXACT);
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (x_abs >= 0x4482U) {
       return FPBits::one(x_bits.sign()).get_val();
     }
@@ -113,7 +113,7 @@ LIBC_INLINE float16 tanhf16(float16 x) {
         (rounding_mode == FE_DOWNWARD && x_bits.is_neg())) {
       return FPBits::one(x_bits.sign()).get_val();
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     if (x_bits.is_pos())
       return fputil::cast<float16>(0x1.ffcp-1);
     return fputil::cast<float16>(-0x1.ffcp-1);
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 90a67f74c4a67..ace2e130a5e19 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1129,7 +1129,9 @@ strtofloatingpoint(const CharType *__restrict src) {
 
   size_t index = first_non_whitespace(src);
   int sign = get_sign(src + index);
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   bool is_positive = (sign >= 0);
+#endif
   index += (sign != 0);
 
   if (sign < 0) {
@@ -1146,7 +1148,7 @@ strtofloatingpoint(const CharType *__restrict src) {
     }
 
     RoundDirection round_direction = RoundDirection::Nearest;
-#ifndef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       round_direction = RoundDirection::Nearest;
@@ -1161,7 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) {
       round_direction = RoundDirection::Down;
       break;
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
     StrToNumResult<ExpandedFloat<T>> parse_result({0, 0});
     if (base == 16) {
diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index e2a5198752b07..005481b24426c 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -49,7 +49,7 @@ constexpr uint32_t MAX_BLOCK = 999999999;
 
 LIBC_INLINE RoundDirection get_round_direction(int last_digit, bool truncated,
                                                Sign sign) {
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   if (last_digit != 5) {
     return last_digit > 5 ? RoundDirection::Up : RoundDirection::Down;
   } else {
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index 660b067aeba15..efa01970c365f 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -112,7 +112,7 @@ LIBC_INLINE int convert_float_hex_exp(Writer<write_mode> *writer,
 
     mantissa >>= shift_amount;
 
-#ifdef LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     // Round to nearest, if it's exactly halfway then round to even.
     if (truncated_bits > halfway_const)
       ++mantissa;
@@ -138,7 +138,7 @@ LIBC_INLINE int convert_float_hex_exp(Writer<write_mode> *writer,
     case FE_TOWARDZERO:
       break;
     }
-#endif // LIBC_MATH_HAS_ALWAYS_ROUND_NEAREST
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
     // If the rounding caused an overflow, shift the mantissa and adjust the
     // exponent to match.
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index cba41f4f107de..949ecbf28c455 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -196,6 +196,12 @@ template <typename T> struct FPTest : public ErrnoCheckingTest {
   static constexpr T min_denormal = FPBits::min_subnormal().get_val();
   static constexpr T max_denormal = FPBits::max_subnormal().get_val();
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  static constexpr int N_ROUNDING_MODES = 1;
+  static constexpr fputil::testing::RoundingMode ROUNDING_MODES[1] = {
+      fputil::testing::RoundingMode::Nearest,
+  };
+#else
   static constexpr int N_ROUNDING_MODES = 4;
   static constexpr fputil::testing::RoundingMode ROUNDING_MODES[4] = {
       fputil::testing::RoundingMode::Nearest,
@@ -203,6 +209,7 @@ template <typename T> struct FPTest : public ErrnoCheckingTest {
       fputil::testing::RoundingMode::Downward,
       fputil::testing::RoundingMode::TowardZero,
   };
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
   void TearDown() override {
     // TODO (PR 135320): Remove this override once all FPTest instances are
@@ -395,6 +402,20 @@ struct ModifyMXCSR {
 #define EXPECT_FP_EQ_ROUNDING_NEAREST(expected, actual)                        \
   EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Nearest)
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define EXPECT_FP_EQ_ROUNDING_UPWARD(expected, actual)                         \
+  do {                                                                         \
+  } while (0)
+#define EXPECT_FP_EQ_ROUNDING_DOWNWARD(expected, actual)                       \
+  do {                                                                         \
+  } while (0)
+#define EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                    \
+  do {                                                                         \
+  } while (0)
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_FP_EQ_ROUNDING_UPWARD(expected, actual)                         \
   EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Upward)
 
@@ -404,6 +425,8 @@ struct ModifyMXCSR {
 #define EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                    \
   EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::TowardZero)
 
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_FP_EQ_ALL_ROUNDING_1(expected, actual)                          \
   do {                                                                         \
     EXPECT_FP_EQ_ROUNDING_NEAREST((expected), (actual));                       \
@@ -450,6 +473,19 @@ struct ModifyMXCSR {
 #define ASSERT_FP_EQ_ROUNDING_NEAREST(expected, actual)                        \
   ASSERT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Nearest)
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+#define ASSERT_FP_EQ_ROUNDING_UPWARD(expected, actual)                         \
+  do {                                                                         \
+  } while (0)
+#define ASSERT_FP_EQ_ROUNDING_DOWNWARD(expected, actual)                       \
+  do {                                                                         \
+  } while (0)
+#define ASSERT_FP_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                    \
+  do {                                                                         \
+  } while (0)
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define ASSERT_FP_EQ_ROUNDING_UPWARD(expected, actual)                         \
   ASSERT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Upward)
 
@@ -459,6 +495,8 @@ struct ModifyMXCSR {
 #define ASSERT_FP_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                    \
   ASSERT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::TowardZero)
 
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                             \
     expected, actual, expected_except, rounding_mode)                          \
   do {                                                                         \
@@ -476,6 +514,25 @@ struct ModifyMXCSR {
   EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
       (expected), (actual), (expected_except), RoundingMode::Nearest)
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(expected, actual,          \
+                                                    expected_except)           \
+  do {                                                                         \
+  } while (0)
+
+#define EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(expected, actual,        \
+                                                      expected_except)         \
+  do {                                                                         \
+  } while (0)
+
+#define EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(expected, actual,     \
+                                                         expected_except)      \
+  do {                                                                         \
+  } while (0)
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(expected, actual,          \
                                                     expected_except)           \
   EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
@@ -491,6 +548,8 @@ struct ModifyMXCSR {
   EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
       (expected), (actual), (expected_except), RoundingMode::TowardZero)
 
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(expected, actual,             \
                                                  expected_except)              \
   do {                                                                         \
diff --git a/libc/test/UnitTest/RoundingModeUtils.cpp b/libc/test/UnitTest/RoundingModeUtils.cpp
index 15b8a36f83fff..077d421c243e3 100644
--- a/libc/test/UnitTest/RoundingModeUtils.cpp
+++ b/libc/test/UnitTest/RoundingModeUtils.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <cfenv>
 #undef LIBC_MATH_USE_SYSTEM_FENV
 
 #include "RoundingModeUtils.h"
@@ -34,6 +35,11 @@ int get_fe_rounding(RoundingMode mode) {
 }
 
 ForceRoundingMode::ForceRoundingMode(RoundingMode mode) {
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  old_rounding_mode = FE_TONEAREST;
+  rounding_mode = FE_TONEAREST;
+  success = (mode == RoundingMode::Nearest);
+#else
   old_rounding_mode = quick_get_round();
   rounding_mode = get_fe_rounding(mode);
   if (old_rounding_mode != rounding_mode) {
@@ -42,11 +48,14 @@ ForceRoundingMode::ForceRoundingMode(RoundingMode mode) {
   } else {
     success = true;
   }
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 ForceRoundingMode::~ForceRoundingMode() {
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
   if (old_rounding_mode != rounding_mode)
     set_round(old_rounding_mode);
+#endif
 }
 
 } // namespace testing
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index 6c1b15598b0f2..64343fde2969f 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -396,28 +396,78 @@ template <typename T> bool round_to_long(T x, RoundingMode mode, long &result);
                   input, match_value, ulp_tolerance,                           \
                   LIBC_NAMESPACE::testing::mpfr::RoundingMode::Nearest))
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define EXPECT_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,      \
+                                   rounding)                                   \
+  EXPECT_MPFR_MATCH_DEFAULT(op, input, match_value, ulp_tolerance)
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,      \
                                    rounding)                                   \
   EXPECT_THAT(match_value,                                                     \
               LIBC_NAMESPACE::testing::mpfr::get_mpfr_matcher<op>(             \
                   input, match_value, ulp_tolerance, rounding))
 
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define EXPECT_MPFR_MATCH(...)                                                 \
   GET_MPFR_MACRO(__VA_ARGS__, EXPECT_MPFR_MATCH_ROUNDING,                      \
                  EXPECT_MPFR_MATCH_DEFAULT, GET_MPFR_DUMMY_ARG)                \
   (__VA_ARGS__)
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define TEST_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,        \
+                                 rounding)                                     \
+  LIBC_NAMESPACE::testing::mpfr::get_mpfr_matcher<op>(                         \
+      input, match_value, ulp_tolerance,                                       \
+      LIBC_NAMESPACE::testing::mpfr::RoundingMode::Nearest)                    \
+      .match(match_value)
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define TEST_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,        \
                                  rounding)                                     \
   LIBC_NAMESPACE::testing::mpfr::get_mpfr_matcher<op>(input, match_value,      \
                                                       ulp_tolerance, rounding) \
       .match(match_value)
 
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define TEST_MPFR_MATCH(...)                                                   \
   GET_MPFR_MACRO(__VA_ARGS__, TEST_MPFR_MATCH_ROUNDING,                        \
                  EXPECT_MPFR_MATCH_DEFAULT, GET_MPFR_DUMMY_ARG)                \
   (__VA_ARGS__)
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define TEST_MPFR_MATCH_ROUNDING_SILENTLY(op, input, match_value,              \
+                                          ulp_tolerance, rounding)             \
+  LIBC_NAMESPACE::testing::mpfr::get_silent_mpfr_matcher<op>(                  \
+      input, match_value, ulp_tolerance,                                       \
+      LIBC_NAMESPACE::testing::mpfr::RoundingMode::Nearest)                    \
+      .match(match_value)
+
+#define EXPECT_MPFR_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance)  \
+  {                                                                            \
+    namespace mpfr = LIBC_NAMESPACE::testing::mpfr;                            \
+    mpfr::ForceRoundingMode __r1(mpfr::RoundingMode::Nearest);                 \
+    if (__r1.success) {                                                        \
+      EXPECT_MPFR_MATCH(op, input, match_value, ulp_tolerance,                 \
+                        mpfr::RoundingMode::Nearest);                          \
+    }                                                                          \
+  }
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define TEST_MPFR_MATCH_ROUNDING_SILENTLY(op, input, match_value,              \
+                                          ulp_tolerance, rounding)             \
+  LIBC_NAMESPACE::testing::mpfr::get_silent_mpfr_matcher<op>(                  \
+      input, match_value, ulp_tolerance, rounding)                             \
+      .match(match_value)
+
 #define EXPECT_MPFR_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance)  \
   {                                                                            \
     namespace mpfr = LIBC_NAMESPACE::testing::mpfr;                            \
@@ -443,29 +493,48 @@ template <typename T> bool round_to_long(T x, RoundingMode mode, long &result);
     }                                                                          \
   }
 
-#define TEST_MPFR_MATCH_ROUNDING_SILENTLY(op, input, match_value,              \
-                                          ulp_tolerance, rounding)             \
-  LIBC_NAMESPACE::testing::mpfr::get_silent_mpfr_matcher<op>(                  \
-      input, match_value, ulp_tolerance, rounding)                             \
-      .match(match_value)
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
-#define ASSERT_MPFR_MATCH_DEFAULT(op, input, match_value, ulp_tolerance)       \
-  ASSERT_THAT(match_value,                                                     \
-              LIBC_NAMESPACE::testing::mpfr::get_mpfr_matcher<op>(             \
-                  input, match_value, ulp_tolerance,                           \
-                  LIBC_NAMESPACE::testing::mpfr::RoundingMode::Nearest))
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define ASSERT_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,      \
+                                   rounding)                                   \
+  ASSERT_MPFR_MATCH_DEFAULT(op, input, match_value, ulp_tolerance)
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
 #define ASSERT_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,      \
                                    rounding)                                   \
   ASSERT_THAT(match_value,                                                     \
               LIBC_NAMESPACE::testing::mpfr::get_mpfr_matcher<op>(             \
                   input, match_value, ulp_tolerance, rounding))
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
 #define ASSERT_MPFR_MATCH(...)                                                 \
   GET_MPFR_MACRO(__VA_ARGS__, ASSERT_MPFR_MATCH_ROUNDING,                      \
                  ASSERT_MPFR_MATCH_DEFAULT, GET_MPFR_DUMMY_ARG)                \
   (__VA_ARGS__)
 
+#define ASSERT_MPFR_MATCH_DEFAULT(op, input, match_value, ulp_tolerance)       \
+  ASSERT_THAT(                                                                 \
+      match_value,                                                             \
+      LIBC_NAMESPACE::testing::mpfr::get_mpfr_matcher<op>(                     \
+          input, match_value, ulp_tolerance, mpfr::RoundingMode::Nearest))
+
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define ASSERT_MPFR_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance)  \
+  {                                                                            \
+    namespace mpfr = LIBC_NAMESPACE::testing::mpfr;                            \
+    mpfr::ForceRoundingMode __r1(mpfr::RoundingMode::Nearest);                 \
+    if (__r1.success) {                                                        \
+      ASSERT_MPFR_MATCH(op, input, match_value, ulp_tolerance,                 \
+                        mpfr::RoundingMode::Nearest);                          \
+    }                                                                          \
+  }
+
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #define ASSERT_MPFR_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance)  \
   {                                                                            \
     namespace mpfr = LIBC_NAMESPACE::testing::mpfr;                            \
@@ -491,4 +560,6 @@ template <typename T> bool round_to_long(T x, RoundingMode mode, long &result);
     }                                                                          \
   }
 
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
 #endif // LLVM_LIBC_UTILS_MPFRWRAPPER_MPFRUTILS_H

>From 7922a63d5d44cc1fda3e368d4677500cc1709164 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Wed, 10 Jun 2026 18:44:00 +0700
Subject: [PATCH 9/9] test: fix failing tests when enabling LIBC_MATH_FAST or
 LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY

---
 .../src/__support/FPUtil/except_value_utils.h |  18 +-
 libc/src/__support/math/exp10m1f16.h          |   3 +
 libc/src/__support/math/exp2m1f16.h           |   3 +
 libc/test/UnitTest/FPMatcher.h                | 184 ++++++++++++++++++
 libc/test/src/math/RIntTest.h                 |  91 ++++-----
 libc/test/src/math/RoundToIntegerTest.h       | 176 ++++++-----------
 libc/test/src/math/smoke/NearbyIntTest.h      |   3 -
 libc/test/src/math/smoke/RIntTest.h           |  16 +-
 libc/test/src/math/smoke/RoundToIntegerTest.h |  82 +++-----
 9 files changed, 338 insertions(+), 238 deletions(-)

diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 4e7f50c580d02..50e27720e7591 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -122,25 +122,35 @@ template <typename T, size_t N> struct ExceptValues {
 // Helper functions to set results for exceptional cases.
 template <typename T>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_down(T value_rn) {
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  fputil::raise_except_if_required(FE_INEXACT);
+  return value_rn;
+#else
   if (cpp::is_constant_evaluated()) {
+    fputil::raise_except_if_required(FE_INEXACT);
     return value_rn;
   } else {
     volatile T tmp = value_rn;
     tmp -= FPBits<T>::min_normal().get_val();
+    fputil::raise_except_if_required(FE_INEXACT);
     return tmp;
   }
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 
 template <typename T>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T round_result_slightly_up(T value_rn) {
 #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  fputil::raise_except_if_required(FE_INEXACT);
   return value_rn;
 #else
   if (cpp::is_constant_evaluated()) {
+    fputil::raise_except_if_required(FE_INEXACT);
     return value_rn;
   } else {
     volatile T tmp = value_rn;
     tmp += FPBits<T>::min_normal().get_val();
+    fputil::raise_except_if_required(FE_INEXACT);
     return tmp;
   }
 #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
@@ -152,6 +162,7 @@ template <>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float16
 round_result_slightly_down(float16 value_rn) {
 #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  fputil::raise_except_if_required(FE_INEXACT);
   return value_rn;
 #else
   if (cpp::is_constant_evaluated()) {
@@ -159,6 +170,7 @@ round_result_slightly_down(float16 value_rn) {
   } else {
     volatile float tmp = value_rn;
     tmp -= FPBits<float16>::min_normal().get_val();
+    fputil::raise_except_if_required(FE_INEXACT);
     return cast<float16>(tmp);
   }
 #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
@@ -167,7 +179,8 @@ round_result_slightly_down(float16 value_rn) {
 template <>
 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT float16
 round_result_slightly_up(float16 value_rn) {
-#ifdef LIBC_HAS_ASSUME_ROUND_NEAREST_ONLY
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+  fputil::raise_except_if_required(FE_INEXACT);
   return value_rn;
 #else
   if (cpp::is_constant_evaluated()) {
@@ -175,9 +188,10 @@ round_result_slightly_up(float16 value_rn) {
   } else {
     volatile float tmp = value_rn;
     tmp += FPBits<float16>::min_normal().get_val();
+    fputil::raise_except_if_required(FE_INEXACT);
     return cast<float16>(tmp);
   }
-#endif // LIBC_HAS_ASSUME_ROUND_NEAREST_ONLY
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 }
 #endif
 
diff --git a/libc/src/__support/math/exp10m1f16.h b/libc/src/__support/math/exp10m1f16.h
index 4c176e3a9ea53..cb685298f01c7 100644
--- a/libc/src/__support/math/exp10m1f16.h
+++ b/libc/src/__support/math/exp10m1f16.h
@@ -124,13 +124,16 @@ LIBC_INLINE constexpr float16 exp10m1f16(float16 x) {
 
       // When x < -0x1.ce4p+1, round(10^x - 1, HP, RN) = -1.
 #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+      fputil::raise_except_if_required(FE_INEXACT);
       return FPBits::one(Sign::NEG).get_val();
 #else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_DOWNWARD:
+        fputil::raise_except_if_required(FE_INEXACT);
         return FPBits::one(Sign::NEG).get_val();
       default:
+        fputil::raise_except_if_required(FE_INEXACT);
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
 #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
diff --git a/libc/src/__support/math/exp2m1f16.h b/libc/src/__support/math/exp2m1f16.h
index 49922df4cd79d..7ea8898200259 100644
--- a/libc/src/__support/math/exp2m1f16.h
+++ b/libc/src/__support/math/exp2m1f16.h
@@ -136,13 +136,16 @@ LIBC_INLINE constexpr float16 exp2m1f16(float16 x) {
 
       // When x <= -12, round(2^x - 1, HP, RN) = -1.
 #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+      fputil::raise_except_if_required(FE_INEXACT);
       return FPBits::one(Sign::NEG).get_val();
 #else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_DOWNWARD:
+        fputil::raise_except_if_required(FE_INEXACT);
         return FPBits::one(Sign::NEG).get_val();
       default:
+        fputil::raise_except_if_required(FE_INEXACT);
         return fputil::cast<float16>(-0x1.ffcp-1);
       }
 #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 949ecbf28c455..943b8e8f05641 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -514,6 +514,108 @@ struct ModifyMXCSR {
   EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
       (expected), (actual), (expected_except), RoundingMode::Nearest)
 
+#define ASSERT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                             \
+    expected, actual, expected_except, rounding_mode)                          \
+  do {                                                                         \
+    using namespace LIBC_NAMESPACE::fputil::testing;                           \
+    ForceRoundingMode __r((rounding_mode));                                    \
+    if (__r.success) {                                                         \
+      LIBC_NAMESPACE::fputil::clear_except(static_cast<int>(FE_ALL_EXCEPT));   \
+      ASSERT_FP_EQ((expected), (actual));                                      \
+      ASSERT_FP_EXCEPTION(expected_except);                                    \
+    }                                                                          \
+  } while (0)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_1(expected, actual)                          \
+  do {                                                                         \
+    ASSERT_FP_EQ_ROUNDING_NEAREST((expected), (actual));                       \
+    ASSERT_FP_EQ_ROUNDING_UPWARD((expected), (actual));                        \
+    ASSERT_FP_EQ_ROUNDING_DOWNWARD((expected), (actual));                      \
+    ASSERT_FP_EQ_ROUNDING_TOWARD_ZERO((expected), (actual));                   \
+  } while (0)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_4(expected_nearest, expected_upward,         \
+                                    expected_downward, expected_toward_zero,   \
+                                    actual)                                    \
+  do {                                                                         \
+    ASSERT_FP_EQ_ROUNDING_NEAREST((expected_nearest), (actual));               \
+    ASSERT_FP_EQ_ROUNDING_UPWARD((expected_upward), (actual));                 \
+    ASSERT_FP_EQ_ROUNDING_DOWNWARD((expected_downward), (actual));             \
+    ASSERT_FP_EQ_ROUNDING_TOWARD_ZERO((expected_toward_zero), (actual));       \
+  } while (0)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_UNSUPPORTED(...)                             \
+  static_assert(false, "Unsupported number of arguments")
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_GET_6TH_ARG(ARG1, ARG2, ARG3, ARG4, ARG5,    \
+                                              ARG6, ...)                       \
+  ARG6
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_SELECTION(...)                               \
+  ASSERT_FP_EQ_ALL_ROUNDING_GET_6TH_ARG(                                       \
+      __VA_ARGS__, ASSERT_FP_EQ_ALL_ROUNDING_4,                                \
+      ASSERT_FP_EQ_ALL_ROUNDING_UNSUPPORTED,                                   \
+      ASSERT_FP_EQ_ALL_ROUNDING_UNSUPPORTED, ASSERT_FP_EQ_ALL_ROUNDING_1)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING(...)                                         \
+  ASSERT_FP_EQ_ALL_ROUNDING_SELECTION(__VA_ARGS__)(__VA_ARGS__)
+
+#define ASSERT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(expected, actual,         \
+                                                     expected_except)          \
+  ASSERT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
+      (expected), (actual), (expected_except), RoundingMode::Nearest)
+
+#define ASSERT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                             \
+    expected, actual, expected_except, rounding_mode)                          \
+  do {                                                                         \
+    using namespace LIBC_NAMESPACE::fputil::testing;                           \
+    ForceRoundingMode __r((rounding_mode));                                    \
+    if (__r.success) {                                                         \
+      LIBC_NAMESPACE::fputil::clear_except(static_cast<int>(FE_ALL_EXCEPT));   \
+      ASSERT_FP_EQ((expected), (actual));                                      \
+      ASSERT_FP_EXCEPTION(expected_except);                                    \
+    }                                                                          \
+  } while (0)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_1(expected, actual)                          \
+  do {                                                                         \
+    ASSERT_FP_EQ_ROUNDING_NEAREST((expected), (actual));                       \
+    ASSERT_FP_EQ_ROUNDING_UPWARD((expected), (actual));                        \
+    ASSERT_FP_EQ_ROUNDING_DOWNWARD((expected), (actual));                      \
+    ASSERT_FP_EQ_ROUNDING_TOWARD_ZERO((expected), (actual));                   \
+  } while (0)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_4(expected_nearest, expected_upward,         \
+                                    expected_downward, expected_toward_zero,   \
+                                    actual)                                    \
+  do {                                                                         \
+    ASSERT_FP_EQ_ROUNDING_NEAREST((expected_nearest), (actual));               \
+    ASSERT_FP_EQ_ROUNDING_UPWARD((expected_upward), (actual));                 \
+    ASSERT_FP_EQ_ROUNDING_DOWNWARD((expected_downward), (actual));             \
+    ASSERT_FP_EQ_ROUNDING_TOWARD_ZERO((expected_toward_zero), (actual));       \
+  } while (0)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_UNSUPPORTED(...)                             \
+  static_assert(false, "Unsupported number of arguments")
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_GET_6TH_ARG(ARG1, ARG2, ARG3, ARG4, ARG5,    \
+                                              ARG6, ...)                       \
+  ARG6
+
+#define ASSERT_FP_EQ_ALL_ROUNDING_SELECTION(...)                               \
+  ASSERT_FP_EQ_ALL_ROUNDING_GET_6TH_ARG(                                       \
+      __VA_ARGS__, ASSERT_FP_EQ_ALL_ROUNDING_4,                                \
+      ASSERT_FP_EQ_ALL_ROUNDING_UNSUPPORTED,                                   \
+      ASSERT_FP_EQ_ALL_ROUNDING_UNSUPPORTED, ASSERT_FP_EQ_ALL_ROUNDING_1)
+
+#define ASSERT_FP_EQ_ALL_ROUNDING(...)                                         \
+  ASSERT_FP_EQ_ALL_ROUNDING_SELECTION(__VA_ARGS__)(__VA_ARGS__)
+
+#define ASSERT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(expected, actual,         \
+                                                     expected_except)          \
+  ASSERT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
+      (expected), (actual), (expected_except), RoundingMode::Nearest)
+
 #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
 
 #define EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(expected, actual,          \
@@ -563,4 +665,86 @@ struct ModifyMXCSR {
                                                      (expected_except));       \
   } while (0)
 
+#define ASSERT_EQ_ROUNDING_MODE(expected, actual, rounding_mode)               \
+  do {                                                                         \
+    using namespace LIBC_NAMESPACE::fputil::testing;                            \
+    ForceRoundingMode __r((rounding_mode));                                     \
+    if (__r.success) {                                                         \
+      ASSERT_EQ((expected), (actual));                                          \
+    }                                                                          \
+  } while (0)
+
+#define ASSERT_EQ_ROUNDING_NEAREST(expected, actual)                           \
+  ASSERT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Nearest)
+
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+#define ASSERT_EQ_ROUNDING_UPWARD(expected, actual)                            \
+  do {                                                                         \
+  } while (0)
+#define ASSERT_EQ_ROUNDING_DOWNWARD(expected, actual)                          \
+  do {                                                                         \
+  } while (0)
+#define ASSERT_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                       \
+  do {                                                                         \
+  } while (0)
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+#define ASSERT_EQ_ROUNDING_UPWARD(expected, actual)                            \
+  ASSERT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Upward)
+
+#define ASSERT_EQ_ROUNDING_DOWNWARD(expected, actual)                          \
+  ASSERT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Downward)
+
+#define ASSERT_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                       \
+  ASSERT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::TowardZero)
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define ASSERT_EQ_ALL_ROUNDING_1(expected, actual)                             \
+  do {                                                                         \
+    ASSERT_EQ_ROUNDING_NEAREST((expected), (actual));                          \
+    ASSERT_EQ_ROUNDING_UPWARD((expected), (actual));                           \
+    ASSERT_EQ_ROUNDING_DOWNWARD((expected), (actual));                         \
+    ASSERT_EQ_ROUNDING_TOWARD_ZERO((expected), (actual));                      \
+  } while (0)
+
+#define EXPECT_EQ_ROUNDING_MODE(expected, actual, rounding_mode)               \
+  do {                                                                         \
+    using namespace LIBC_NAMESPACE::fputil::testing;                            \
+    ForceRoundingMode __r((rounding_mode));                                     \
+    if (__r.success) {                                                         \
+      EXPECT_EQ((expected), (actual));                                          \
+    }                                                                          \
+  } while (0)
+
+#define EXPECT_EQ_ROUNDING_NEAREST(expected, actual)                           \
+  EXPECT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Nearest)
+
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+#define EXPECT_EQ_ROUNDING_UPWARD(expected, actual)                            \
+  do {                                                                         \
+  } while (0)
+#define EXPECT_EQ_ROUNDING_DOWNWARD(expected, actual)                          \
+  do {                                                                         \
+  } while (0)
+#define EXPECT_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                       \
+  do {                                                                         \
+  } while (0)
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+#define EXPECT_EQ_ROUNDING_UPWARD(expected, actual)                            \
+  EXPECT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Upward)
+
+#define EXPECT_EQ_ROUNDING_DOWNWARD(expected, actual)                          \
+  EXPECT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Downward)
+
+#define EXPECT_EQ_ROUNDING_TOWARD_ZERO(expected, actual)                       \
+  EXPECT_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::TowardZero)
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+
+#define EXPECT_EQ_ALL_ROUNDING_1(expected, actual)                             \
+  do {                                                                         \
+    EXPECT_EQ_ROUNDING_NEAREST((expected), (actual));                          \
+    EXPECT_EQ_ROUNDING_UPWARD((expected), (actual));                           \
+    EXPECT_EQ_ROUNDING_DOWNWARD((expected), (actual));                         \
+    EXPECT_EQ_ROUNDING_TOWARD_ZERO((expected), (actual));                      \
+  } while (0)
+
 #endif // LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H
diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h
index 0ee7690c8f46b..caa74c5623f39 100644
--- a/libc/test/src/math/RIntTest.h
+++ b/libc/test/src/math/RIntTest.h
@@ -12,7 +12,6 @@
 #undef LIBC_MATH_USE_SYSTEM_FENV
 
 #include "src/__support/CPP/algorithm.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "test/UnitTest/FEnvSafeTest.h"
 #include "test/UnitTest/FPMatcher.h"
@@ -25,9 +24,6 @@
 namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
 using LIBC_NAMESPACE::Sign;
 
-static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
-                                          FE_TONEAREST};
-
 template <typename T>
 class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 public:
@@ -35,6 +31,7 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 
 private:
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
+  using FPTest = LIBC_NAMESPACE::testing::FPTest<T>;
   using StorageType = typename FPBits::StorageType;
 
   const T inf = FPBits::inf(Sign::POS).get_val();
@@ -50,56 +47,46 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
   static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
 
-  static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) {
-    switch (mode) {
-    case FE_UPWARD:
-      return mpfr::RoundingMode::Upward;
-    case FE_DOWNWARD:
-      return mpfr::RoundingMode::Downward;
-    case FE_TOWARDZERO:
-      return mpfr::RoundingMode::TowardZero;
-    case FE_TONEAREST:
-      return mpfr::RoundingMode::Nearest;
-    default:
-      __builtin_unreachable();
-    }
-  }
-
 public:
   void testSpecialNumbers(RIntFunc func) {
-    for (int mode : ROUNDING_MODES) {
-      LIBC_NAMESPACE::fputil::set_round(mode);
-      ASSERT_FP_EQ(inf, func(inf));
-      ASSERT_FP_EQ(neg_inf, func(neg_inf));
-      ASSERT_FP_EQ(nan, func(nan));
-      ASSERT_FP_EQ(zero, func(zero));
-      ASSERT_FP_EQ(neg_zero, func(neg_zero));
-    }
+    ASSERT_FP_EQ_ALL_ROUNDING_1(inf, func(inf));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(neg_inf, func(neg_inf));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(nan, func(nan));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(zero, func(zero));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(neg_zero, func(neg_zero));
   }
 
   void testRoundNumbers(RIntFunc func) {
-    for (int mode : ROUNDING_MODES) {
-      LIBC_NAMESPACE::fputil::set_round(mode);
-      mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
-      ASSERT_FP_EQ(func(T(1.0)), mpfr::round(T(1.0), mpfr_mode));
-      ASSERT_FP_EQ(func(T(-1.0)), mpfr::round(T(-1.0), mpfr_mode));
-      ASSERT_FP_EQ(func(T(10.0)), mpfr::round(T(10.0), mpfr_mode));
-      ASSERT_FP_EQ(func(T(-10.0)), mpfr::round(T(-10.0), mpfr_mode));
-      ASSERT_FP_EQ(func(T(1234.0)), mpfr::round(T(1234.0), mpfr_mode));
-      ASSERT_FP_EQ(func(T(-1234.0)), mpfr::round(T(-1234.0), mpfr_mode));
+    for (auto mpfr_mode : FPTest::ROUNDING_MODES) {
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(1.0), mpfr_mode), func(T(1.0)),
+                                 mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(-1.0), mpfr_mode), func(T(-1.0)),
+                                 mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(10.0), mpfr_mode), func(T(10.0)),
+                                 mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(-10.0), mpfr_mode),
+                                 func(T(-10.0)), mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(1234.0), mpfr_mode),
+                                 func(T(1234.0)), mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(-1234.0), mpfr_mode),
+                                 func(T(-1234.0)), mpfr_mode);
     }
   }
 
   void testFractions(RIntFunc func) {
-    for (int mode : ROUNDING_MODES) {
-      LIBC_NAMESPACE::fputil::set_round(mode);
-      mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
-      ASSERT_FP_EQ(func(T(0.5)), mpfr::round(T(0.5), mpfr_mode));
-      ASSERT_FP_EQ(func(T(-0.5)), mpfr::round(T(-0.5), mpfr_mode));
-      ASSERT_FP_EQ(func(T(0.115)), mpfr::round(T(0.115), mpfr_mode));
-      ASSERT_FP_EQ(func(T(-0.115)), mpfr::round(T(-0.115), mpfr_mode));
-      ASSERT_FP_EQ(func(T(0.715)), mpfr::round(T(0.715), mpfr_mode));
-      ASSERT_FP_EQ(func(T(-0.715)), mpfr::round(T(-0.715), mpfr_mode));
+    for (auto mpfr_mode : FPTest::ROUNDING_MODES) {
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(0.5), mpfr_mode), func(T(0.5)),
+                                 mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(-0.5), mpfr_mode), func(T(-0.5)),
+                                 mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(0.115), mpfr_mode),
+                                 func(T(0.115)), mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(-0.115), mpfr_mode),
+                                 func(T(-0.115)), mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(0.715), mpfr_mode),
+                                 func(T(0.715)), mpfr_mode);
+      ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(T(-0.715), mpfr_mode),
+                                 func(T(-0.715)), mpfr_mode);
     }
   }
 
@@ -110,10 +97,9 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
         StorageType(1));
     for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) {
       T x = FPBits(i).get_val();
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
-        ASSERT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
+      for (auto mpfr_mode : FPTest::ROUNDING_MODES) {
+        ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(x, mpfr_mode), func(x),
+                                   mpfr_mode);
       }
     }
   }
@@ -131,10 +117,9 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
       if (xbits.is_nan())
         continue;
 
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
-        ASSERT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
+      for (auto mpfr_mode : FPTest::ROUNDING_MODES) {
+        ASSERT_FP_EQ_ROUNDING_MODE(mpfr::round(x, mpfr_mode), func(x),
+                                   mpfr_mode);
       }
     }
   }
diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h
index 1795b85576649..dc9d904e0ab89 100644
--- a/libc/test/src/math/RoundToIntegerTest.h
+++ b/libc/test/src/math/RoundToIntegerTest.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H
 
+#include "test/UnitTest/RoundingModeUtils.h"
+#include <cfenv>
 #undef LIBC_MATH_USE_SYSTEM_FENV
 
 #include "src/__support/CPP/algorithm.h"
@@ -25,9 +27,6 @@
 namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
 using LIBC_NAMESPACE::Sign;
 
-static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
-                                          FE_TONEAREST};
-
 template <typename FloatType, typename IntType, bool TestModes = false>
 class RoundToIntegerTestTemplate
     : public LIBC_NAMESPACE::testing::FEnvSafeTest {
@@ -36,6 +35,8 @@ class RoundToIntegerTestTemplate
 
 private:
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<FloatType>;
+  using FPTest = LIBC_NAMESPACE::testing::FPTest<FloatType>;
+  using RoundingMode = LIBC_NAMESPACE::fputil::testing::RoundingMode;
   using StorageType = typename FPBits::StorageType;
 
   const FloatType zero = FPBits::zero().get_val();
@@ -59,9 +60,7 @@ class RoundToIntegerTestTemplate
                       IntType expected, bool expectError) {
     libc_errno = 0;
     LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
-
     ASSERT_EQ(func(input), expected);
-
     // TODO: Handle the !expectError case. It used to expect
     // 0 for errno and exceptions, but this doesn't hold for
     // all math functions using RoundToInteger test:
@@ -72,21 +71,6 @@ class RoundToIntegerTestTemplate
     }
   }
 
-  static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) {
-    switch (mode) {
-    case FE_UPWARD:
-      return mpfr::RoundingMode::Upward;
-    case FE_DOWNWARD:
-      return mpfr::RoundingMode::Downward;
-    case FE_TOWARDZERO:
-      return mpfr::RoundingMode::TowardZero;
-    case FE_TONEAREST:
-      return mpfr::RoundingMode::Nearest;
-    default:
-      __builtin_unreachable();
-    }
-  }
-
 public:
   void SetUp() override {
     LIBC_NAMESPACE::testing::FEnvSafeTest::SetUp();
@@ -99,9 +83,13 @@ class RoundToIntegerTestTemplate
     }
   }
 
-  void do_infinity_and_na_n_test(RoundToIntegerFunc func) {
-    test_one_input(func, inf, INTEGER_MAX, true);
-    test_one_input(func, neg_inf, INTEGER_MIN, true);
+  void testInfinityAndNaN(RoundToIntegerFunc func) {
+    libc_errno = 0;
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+    ASSERT_EQ_ALL_ROUNDING_1(INTEGER_MAX, func(inf));
+    ASSERT_EQ_ALL_ROUNDING_1(INTEGER_MIN, func(neg_inf));
+    ASSERT_FP_EXCEPTION(FE_INVALID);
+    ASSERT_MATH_ERRNO(EDOM);
     // This is currently never enabled, the
     // LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR CMake option in
     // libc/CMakeLists.txt is not forwarded to C++.
@@ -111,26 +99,15 @@ class RoundToIntegerTestTemplate
 #endif // LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
   }
 
-  void testInfinityAndNaN(RoundToIntegerFunc func) {
-    if (TestModes) {
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        do_infinity_and_na_n_test(func);
-      }
-    } else {
-      do_infinity_and_na_n_test(func);
-    }
-  }
-
-  void do_round_numbers_test(RoundToIntegerFunc func) {
-    test_one_input(func, zero, IntType(0), false);
-    test_one_input(func, neg_zero, IntType(0), false);
-    test_one_input(func, FloatType(1.0), IntType(1), false);
-    test_one_input(func, FloatType(-1.0), IntType(-1), false);
-    test_one_input(func, FloatType(10.0), IntType(10), false);
-    test_one_input(func, FloatType(-10.0), IntType(-10), false);
-    test_one_input(func, FloatType(1232.0), IntType(1232), false);
-    test_one_input(func, FloatType(-1232.0), IntType(-1232), false);
+  void testRoundNumbers(RoundToIntegerFunc func) {
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(0), func(zero));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(0), func(neg_zero));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(1), func(FloatType(1.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(-1), func(FloatType(-1.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(10), func(FloatType(10.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(-10), func(FloatType(-10.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(1232), func(FloatType(1232.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(-1232), func(FloatType(-1232.0)));
 
     // The rest of this function compares with an equivalent MPFR function
     // which rounds floating point numbers to long values. There is no MPFR
@@ -155,49 +132,32 @@ class RoundToIntegerTestTemplate
     long mpfr_result;
     bool erangeflag = mpfr::round_to_long(x, mpfr_result);
     ASSERT_FALSE(erangeflag);
-    test_one_input(func, x, mpfr_result, false);
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(mpfr_result), func(x));
   }
 
-  void testRoundNumbers(RoundToIntegerFunc func) {
-    if (TestModes) {
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        do_round_numbers_test(func);
-      }
-    } else {
-      do_round_numbers_test(func);
-    }
-  }
-
-  void do_fractions_test(RoundToIntegerFunc func, int mode) {
+  void testFractions(RoundToIntegerFunc func) {
     constexpr FloatType FRACTIONS[] = {
         FloatType(0.5),    FloatType(-0.5),  FloatType(0.115),
         FloatType(-0.115), FloatType(0.715), FloatType(-0.715),
     };
-    for (FloatType x : FRACTIONS) {
-      long mpfr_long_result;
-      bool erangeflag;
-      if (TestModes)
-        erangeflag = mpfr::round_to_long(x, to_mpfr_rounding_mode(mode),
-                                         mpfr_long_result);
-      else
-        erangeflag = mpfr::round_to_long(x, mpfr_long_result);
-      ASSERT_FALSE(erangeflag);
-      IntType mpfr_result = mpfr_long_result;
-      test_one_input(func, x, mpfr_result, false);
-    }
-  }
-
-  void testFractions(RoundToIntegerFunc func) {
     if (TestModes) {
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        do_fractions_test(func, mode);
+      for (auto mpfr_mode : FPTest::ROUNDING_MODES) {
+        for (FloatType x : FRACTIONS) {
+          long mpfr_long_result;
+          bool erangeflag =
+              mpfr::round_to_long(x, mpfr_mode, mpfr_long_result);
+          ASSERT_FALSE(erangeflag);
+          ASSERT_EQ_ROUNDING_MODE(IntType(mpfr_long_result), func(x),
+                                  mpfr_mode);
+        }
       }
     } else {
-      // Passing 0 for mode has no effect as it is not used in doFractionsTest
-      // when `TestModes` is false;
-      do_fractions_test(func, 0);
+      for (FloatType x : FRACTIONS) {
+        long mpfr_long_result;
+        bool erangeflag = mpfr::round_to_long(x, mpfr_long_result);
+        ASSERT_FALSE(erangeflag);
+        test_one_input(func, x, IntType(mpfr_long_result), false);
+      }
     }
   }
 
@@ -223,18 +183,12 @@ class RoundToIntegerTestTemplate
 
     FloatType x = bits.get_val();
     if (TestModes) {
-      for (int m : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(m);
-        long mpfr_long_result;
-        bool erangeflag =
-            mpfr::round_to_long(x, to_mpfr_rounding_mode(m), mpfr_long_result);
-        ASSERT_TRUE(erangeflag);
-        test_one_input(func, x, INTEGER_MIN, true);
+      for (auto m : FPTest::ROUNDING_MODES) {
+        LIBC_NAMESPACE::fputil::testing::ForceRoundingMode _r(m);
+        if (_r.success)
+          test_one_input(func, x, INTEGER_MIN, true);
       }
     } else {
-      long mpfr_long_result;
-      bool erangeflag = mpfr::round_to_long(x, mpfr_long_result);
-      ASSERT_TRUE(erangeflag);
       test_one_input(func, x, INTEGER_MIN, true);
     }
   }
@@ -251,26 +205,18 @@ class RoundToIntegerTestTemplate
       // All subnormal numbers should round to zero.
       if (TestModes) {
         if (x > 0) {
-          LIBC_NAMESPACE::fputil::set_round(FE_UPWARD);
-          test_one_input(func, x, IntType(1), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST);
-          test_one_input(func, x, IntType(0), false);
+          ASSERT_EQ_ROUNDING_UPWARD(IntType(1), func(x));
+          ASSERT_EQ_ROUNDING_DOWNWARD(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_TOWARD_ZERO(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_NEAREST(IntType(0), func(x));
         } else {
-          LIBC_NAMESPACE::fputil::set_round(FE_UPWARD);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD);
-          test_one_input(func, x, IntType(-1), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST);
-          test_one_input(func, x, IntType(0), false);
+          ASSERT_EQ_ROUNDING_UPWARD(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_DOWNWARD(IntType(-1), func(x));
+          ASSERT_EQ_ROUNDING_TOWARD_ZERO(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_NEAREST(IntType(0), func(x));
         }
       } else {
-        test_one_input(func, x, 0L, false);
+        test_one_input(func, x, IntType(0), false);
       }
     }
   }
@@ -297,25 +243,25 @@ class RoundToIntegerTestTemplate
         continue;
 
       if (TestModes) {
-        for (int m : ROUNDING_MODES) {
+        for (auto m : FPTest::ROUNDING_MODES) {
           long mpfr_long_result;
-          bool erangeflag = mpfr::round_to_long(x, to_mpfr_rounding_mode(m),
-                                                mpfr_long_result);
-          IntType mpfr_result = mpfr_long_result;
-          LIBC_NAMESPACE::fputil::set_round(m);
-          if (erangeflag)
-            test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
-          else
-            test_one_input(func, x, mpfr_result, false);
+          bool erangeflag = mpfr::round_to_long(x, m, mpfr_long_result);
+          LIBC_NAMESPACE::fputil::testing::ForceRoundingMode _r(m);
+          if (_r.success) {
+            if (erangeflag)
+              test_one_input(func, x,
+                             x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
+            else
+              test_one_input(func, x, IntType(mpfr_long_result), false);
+          }
         }
       } else {
         long mpfr_long_result;
         bool erangeflag = mpfr::round_to_long(x, mpfr_long_result);
-        IntType mpfr_result = mpfr_long_result;
         if (erangeflag)
           test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
         else
-          test_one_input(func, x, mpfr_result, false);
+          test_one_input(func, x, IntType(mpfr_long_result), false);
       }
     }
   }
diff --git a/libc/test/src/math/smoke/NearbyIntTest.h b/libc/test/src/math/smoke/NearbyIntTest.h
index aa6c6bfbf52da..9b6615824bdde 100644
--- a/libc/test/src/math/smoke/NearbyIntTest.h
+++ b/libc/test/src/math/smoke/NearbyIntTest.h
@@ -19,9 +19,6 @@
 
 using LIBC_NAMESPACE::Sign;
 
-static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
-                                          FE_TONEAREST};
-
 template <typename T>
 class NearbyIntTestTemplate : public LIBC_NAMESPACE::testing::Test {
 
diff --git a/libc/test/src/math/smoke/RIntTest.h b/libc/test/src/math/smoke/RIntTest.h
index d4cfc1b40445b..3b2ddeecc74e1 100644
--- a/libc/test/src/math/smoke/RIntTest.h
+++ b/libc/test/src/math/smoke/RIntTest.h
@@ -22,9 +22,6 @@
 
 using LIBC_NAMESPACE::Sign;
 
-static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
-                                          FE_TONEAREST};
-
 template <typename T>
 class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 public:
@@ -42,14 +39,11 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 
 public:
   void testSpecialNumbers(RIntFunc func) {
-    for (int mode : ROUNDING_MODES) {
-      LIBC_NAMESPACE::fputil::set_round(mode);
-      ASSERT_FP_EQ(inf, func(inf));
-      ASSERT_FP_EQ(neg_inf, func(neg_inf));
-      ASSERT_FP_EQ(nan, func(nan));
-      ASSERT_FP_EQ(zero, func(zero));
-      ASSERT_FP_EQ(neg_zero, func(neg_zero));
-    }
+    ASSERT_FP_EQ_ALL_ROUNDING_1(inf, func(inf));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(neg_inf, func(neg_inf));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(nan, func(nan));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(zero, func(zero));
+    ASSERT_FP_EQ_ALL_ROUNDING_1(neg_zero, func(neg_zero));
   }
 };
 
diff --git a/libc/test/src/math/smoke/RoundToIntegerTest.h b/libc/test/src/math/smoke/RoundToIntegerTest.h
index 857bc72b77fe3..36e06d47cc326 100644
--- a/libc/test/src/math/smoke/RoundToIntegerTest.h
+++ b/libc/test/src/math/smoke/RoundToIntegerTest.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_ROUNDTOINTEGERTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_SMOKE_ROUNDTOINTEGERTEST_H
 
+#include "test/UnitTest/RoundingModeUtils.h"
 #undef LIBC_MATH_USE_SYSTEM_FENV
 
 #include "src/__support/CPP/algorithm.h"
@@ -21,9 +22,6 @@
 
 #include "hdr/math_macros.h"
 
-static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
-                                          FE_TONEAREST};
-
 template <typename FloatType, typename IntType, bool TestModes = false>
 class RoundToIntegerTestTemplate
     : public LIBC_NAMESPACE::testing::FEnvSafeTest {
@@ -32,6 +30,8 @@ class RoundToIntegerTestTemplate
 
 private:
   DECLARE_SPECIAL_CONSTANTS(FloatType)
+  using FPTest = LIBC_NAMESPACE::testing::FPTest<FloatType>;
+  using RoundingMode = LIBC_NAMESPACE::fputil::testing::RoundingMode;
 
   static constexpr StorageType MAX_SUBNORMAL =
       FPBits::max_subnormal().uintval();
@@ -71,9 +71,13 @@ class RoundToIntegerTestTemplate
     }
   }
 
-  void do_infinity_and_na_n_test(RoundToIntegerFunc func) {
-    test_one_input(func, inf, INTEGER_MAX, true);
-    test_one_input(func, neg_inf, INTEGER_MIN, true);
+  void testInfinityAndNaN(RoundToIntegerFunc func) {
+    libc_errno = 0;
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+    ASSERT_EQ_ALL_ROUNDING_1(INTEGER_MAX, func(inf));
+    ASSERT_EQ_ALL_ROUNDING_1(INTEGER_MIN, func(neg_inf));
+    ASSERT_FP_EXCEPTION(FE_INVALID);
+    ASSERT_MATH_ERRNO(EDOM);
     // This is currently never enabled, the
     // LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR CMake option in
     // libc/CMakeLists.txt is not forwarded to C++.
@@ -83,37 +87,15 @@ class RoundToIntegerTestTemplate
 #endif // LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
   }
 
-  void testInfinityAndNaN(RoundToIntegerFunc func) {
-    if (TestModes) {
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        do_infinity_and_na_n_test(func);
-      }
-    } else {
-      do_infinity_and_na_n_test(func);
-    }
-  }
-
-  void do_round_numbers_test(RoundToIntegerFunc func) {
-    test_one_input(func, zero, IntType(0), false);
-    test_one_input(func, neg_zero, IntType(0), false);
-    test_one_input(func, FloatType(1.0), IntType(1), false);
-    test_one_input(func, FloatType(-1.0), IntType(-1), false);
-    test_one_input(func, FloatType(10.0), IntType(10), false);
-    test_one_input(func, FloatType(-10.0), IntType(-10), false);
-    test_one_input(func, FloatType(1232.0), IntType(1232), false);
-    test_one_input(func, FloatType(-1232.0), IntType(-1232), false);
-  }
-
   void testRoundNumbers(RoundToIntegerFunc func) {
-    if (TestModes) {
-      for (int mode : ROUNDING_MODES) {
-        LIBC_NAMESPACE::fputil::set_round(mode);
-        do_round_numbers_test(func);
-      }
-    } else {
-      do_round_numbers_test(func);
-    }
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(0), func(zero));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(0), func(neg_zero));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(1), func(FloatType(1.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(-1), func(FloatType(-1.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(10), func(FloatType(10.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(-10), func(FloatType(-10.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(1232), func(FloatType(1232.0)));
+    ASSERT_EQ_ALL_ROUNDING_1(IntType(-1232), func(FloatType(-1232.0)));
   }
 
   void testSubnormalRange(RoundToIntegerFunc func) {
@@ -128,27 +110,19 @@ class RoundToIntegerTestTemplate
         continue;
       // All subnormal numbers should round to zero.
       if (TestModes) {
-        if (x > zero) {
-          LIBC_NAMESPACE::fputil::set_round(FE_UPWARD);
-          test_one_input(func, x, IntType(1), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST);
-          test_one_input(func, x, IntType(0), false);
+        if (x > 0) {
+          ASSERT_EQ_ROUNDING_UPWARD(IntType(1), func(x));
+          ASSERT_EQ_ROUNDING_DOWNWARD(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_TOWARD_ZERO(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_NEAREST(IntType(0), func(x));
         } else {
-          LIBC_NAMESPACE::fputil::set_round(FE_UPWARD);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD);
-          test_one_input(func, x, IntType(-1), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO);
-          test_one_input(func, x, IntType(0), false);
-          LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST);
-          test_one_input(func, x, IntType(0), false);
+          ASSERT_EQ_ROUNDING_UPWARD(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_DOWNWARD(IntType(-1), func(x));
+          ASSERT_EQ_ROUNDING_TOWARD_ZERO(IntType(0), func(x));
+          ASSERT_EQ_ROUNDING_NEAREST(IntType(0), func(x));
         }
       } else {
-        test_one_input(func, x, 0L, false);
+        test_one_input(func, x, IntType(0), false);
       }
     }
   }



More information about the libc-commits mailing list