[libc-commits] [libc] [libc][math] Adding LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY option (PR #201154)
Hoàng Minh Thiên via libc-commits
libc-commits at lists.llvm.org
Wed Jun 10 20:52:42 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 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 09/11] 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);
}
}
}
>From 03ef93cd12c69e3759e2873bc669330998d29a6f 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 21:51:16 +0700
Subject: [PATCH 10/11] fix: formatting and inaccurate cfenv import
---
libc/test/UnitTest/FPMatcher.h | 12 ++++++------
libc/test/UnitTest/RoundingModeUtils.cpp | 1 -
libc/test/src/math/RoundToIntegerTest.h | 6 ++----
3 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 943b8e8f05641..ed13bdc9b3d61 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -667,10 +667,10 @@ struct ModifyMXCSR {
#define ASSERT_EQ_ROUNDING_MODE(expected, actual, rounding_mode) \
do { \
- using namespace LIBC_NAMESPACE::fputil::testing; \
- ForceRoundingMode __r((rounding_mode)); \
+ using namespace LIBC_NAMESPACE::fputil::testing; \
+ ForceRoundingMode __r((rounding_mode)); \
if (__r.success) { \
- ASSERT_EQ((expected), (actual)); \
+ ASSERT_EQ((expected), (actual)); \
} \
} while (0)
@@ -708,10 +708,10 @@ struct ModifyMXCSR {
#define EXPECT_EQ_ROUNDING_MODE(expected, actual, rounding_mode) \
do { \
- using namespace LIBC_NAMESPACE::fputil::testing; \
- ForceRoundingMode __r((rounding_mode)); \
+ using namespace LIBC_NAMESPACE::fputil::testing; \
+ ForceRoundingMode __r((rounding_mode)); \
if (__r.success) { \
- EXPECT_EQ((expected), (actual)); \
+ EXPECT_EQ((expected), (actual)); \
} \
} while (0)
diff --git a/libc/test/UnitTest/RoundingModeUtils.cpp b/libc/test/UnitTest/RoundingModeUtils.cpp
index 077d421c243e3..598b56464ec28 100644
--- a/libc/test/UnitTest/RoundingModeUtils.cpp
+++ b/libc/test/UnitTest/RoundingModeUtils.cpp
@@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#include <cfenv>
#undef LIBC_MATH_USE_SYSTEM_FENV
#include "RoundingModeUtils.h"
diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h
index dc9d904e0ab89..d4d84a01a36f0 100644
--- a/libc/test/src/math/RoundToIntegerTest.h
+++ b/libc/test/src/math/RoundToIntegerTest.h
@@ -144,8 +144,7 @@ class RoundToIntegerTestTemplate
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);
+ 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);
@@ -249,8 +248,7 @@ class RoundToIntegerTestTemplate
LIBC_NAMESPACE::fputil::testing::ForceRoundingMode _r(m);
if (_r.success) {
if (erangeflag)
- test_one_input(func, x,
- x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
+ test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true);
else
test_one_input(func, x, IntType(mpfr_long_result), false);
}
>From 25d04c9d9e2976194e3d0e0d18346210b36d8951 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
<hoangminhthien05022009 at gmail.com>
Date: Thu, 11 Jun 2026 10:52:10 +0700
Subject: [PATCH 11/11] fix: inaccurate guardings and test macro usages
---
.../FPUtil/NearestIntegerOperations.h | 4 +-
libc/src/__support/FPUtil/dyadic_float.h | 57 ++++++++++---------
libc/test/src/math/RIntTest.h | 10 ++--
libc/test/src/math/smoke/RIntTest.h | 10 ++--
4 files changed, 43 insertions(+), 38 deletions(-)
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 6499090c43d23..203e3c43ae9c9 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -248,8 +248,7 @@ 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_ASSUME_ROUND_NEAREST_ONLY
return round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
-#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
-
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
int rounding_mode = quick_get_round();
switch (rounding_mode) {
@@ -264,6 +263,7 @@ round_using_current_rounding_mode(T x) {
default:
__builtin_unreachable();
}
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
}
template <bool IsSigned, typename T>
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index bd7e85bfa248e..2c065e48e7632 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -17,6 +17,7 @@
#include "rounding_mode.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/big_int.h"
+#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/macros/properties/types.h"
@@ -41,7 +42,11 @@ namespace fputil {
template <size_t Bits>
LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int
rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
- Sign logical_sign) {
+ [[maybe_unused]] Sign logical_sign) {
+ // logical_sign only affects FE_DOWNWARD and FE_UPWARD rounding modes. In the
+ // case of LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY being enabled, this option
+ // is no-op
+
if (rshift == 0 || (rshift < Bits && (value << (Bits - rshift)) == 0) ||
(rshift >= Bits && value == 0))
return 0; // exact
@@ -56,8 +61,7 @@ rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
} else {
return -1;
}
-#endif
-
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
switch (quick_get_round()) {
case FE_TONEAREST:
if (rshift > 0 && rshift <= Bits && value.get_bit(rshift - 1)) {
@@ -84,6 +88,7 @@ rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
default:
__builtin_unreachable();
}
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
}
// A generic class to perform computations of high precision floating points.
@@ -204,8 +209,7 @@ template <size_t Bits> struct DyadicFloat {
#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
return FPBits::inf(sign).get_val();
-#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
-
+#else // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
switch (quick_get_round()) {
case FE_TONEAREST:
return FPBits::inf(sign).get_val();
@@ -222,6 +226,7 @@ template <size_t Bits> struct DyadicFloat {
default:
__builtin_unreachable();
}
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
}
StorageType out_biased_exp = 0;
@@ -406,14 +411,14 @@ template <size_t Bits> struct DyadicFloat {
output_bits_t r_bits = FPBits<T>(r).uintval() - clear_exp;
if (!(r_bits & FPBits<T>::EXP_MASK)) {
- // Output is denormal after rounding, clear the implicit bit for 80-bit
- // long double.
+ // Output is denormal after rounding, clear the implicit bit for
+ // 80-bit long double.
r_bits -= IMPLICIT_MASK;
- // TODO: IEEE Std 754-2019 lets implementers choose whether to check for
- // "tininess" before or after rounding for base-2 formats, as long as
- // the same choice is made for all operations. Our choice to check after
- // rounding might not be the same as the hardware's.
+ // TODO: IEEE Std 754-2019 lets implementers choose whether to check
+ // for "tininess" before or after rounding for base-2 formats, as long
+ // as the same choice is made for all operations. Our choice to check
+ // after rounding might not be the same as the hardware's.
if (ShouldSignalExceptions && round_and_sticky) {
set_errno_if_required(ERANGE);
raise_except_if_required(FE_UNDERFLOW);
@@ -486,9 +491,9 @@ template <size_t Bits> struct DyadicFloat {
new_mant <<= exponent;
} else if (exponent < 0) {
// Cast the exponent to size_t before negating it, rather than after,
- // to avoid undefined behavior negating INT_MIN as an integer (although
- // exponents coming in to this function _shouldn't_ be that large). The
- // result should always end up as a positive size_t.
+ // to avoid undefined behavior negating INT_MIN as an integer
+ // (although exponents coming in to this function _shouldn't_ be that
+ // large). The result should always end up as a positive size_t.
size_t shift = -static_cast<size_t>(exponent);
if (shift >= Bits)
new_mant = 0;
@@ -515,8 +520,8 @@ template <size_t Bits> struct DyadicFloat {
}
};
-// Quick add - Add 2 dyadic floats with rounding toward 0 and then normalize the
-// output:
+// Quick add - Add 2 dyadic floats with rounding toward 0 and then normalize
+// the output:
// - Align the exponents so that:
// new a.exponent = new b.exponent = max(a.exponent, b.exponent)
// - Add or subtract the mantissas depending on the signs.
@@ -524,9 +529,9 @@ template <size_t Bits> struct DyadicFloat {
// The absolute errors compared to the mathematical sum is bounded by:
// | quick_add(a, b) - (a + b) | < MSB(a + b) * 2^(-Bits + 2),
// i.e., errors are up to 2 ULPs.
-// Assume inputs are normalized (by constructors or other functions) so that we
-// don't need to normalize the inputs again in this function. If the inputs are
-// not normalized, the results might lose precision significantly.
+// Assume inputs are normalized (by constructors or other functions) so that
+// we don't need to normalize the inputs again in this function. If the
+// inputs are not normalized, the results might lose precision significantly.
template <size_t Bits>
LIBC_INLINE constexpr DyadicFloat<Bits> quick_add(DyadicFloat<Bits> a,
DyadicFloat<Bits> b) {
@@ -585,9 +590,9 @@ LIBC_INLINE constexpr DyadicFloat<Bits> quick_sub(DyadicFloat<Bits> a,
// ~ (full product a.mantissa * b.mantissa) >> Bits.
// The errors compared to the mathematical product is bounded by:
// 2 * errors of quick_mul_hi = 2 * (UInt<Bits>::WORD_COUNT - 1) in ULPs.
-// Assume inputs are normalized (by constructors or other functions) so that we
-// don't need to normalize the inputs again in this function. If the inputs are
-// not normalized, the results might lose precision significantly.
+// Assume inputs are normalized (by constructors or other functions) so that
+// we don't need to normalize the inputs again in this function. If the
+// inputs are not normalized, the results might lose precision significantly.
template <size_t Bits>
LIBC_INLINE constexpr DyadicFloat<Bits> quick_mul(const DyadicFloat<Bits> &a,
const DyadicFloat<Bits> &b) {
@@ -627,8 +632,8 @@ rounded_mul(const DyadicFloat<Bits> &a, const DyadicFloat<Bits> &b) {
return DyadicFloat<Bits>::round(result_sign, result_exponent, product, Bits);
}
-// Approximate reciprocal - given a nonzero a, make a good approximation to 1/a.
-// The method is Newton-Raphson iteration, based on quick_mul.
+// Approximate reciprocal - given a nonzero a, make a good approximation to
+// 1/a. The method is Newton-Raphson iteration, based on quick_mul.
template <size_t Bits, typename = cpp::enable_if_t<(Bits >= 32)>>
LIBC_INLINE constexpr DyadicFloat<Bits>
approx_reciprocal(const DyadicFloat<Bits> &a) {
@@ -637,8 +642,8 @@ approx_reciprocal(const DyadicFloat<Bits> &a) {
// You can derive this by using the Newton-Raphson formula with the function
// f(x) = 1/x - a. But another way to see that it works is to say: suppose
// that ax = 1-e for some small error e. Then ax' = ax(2-ax) = (1-e)(1+e) =
- // 1-e^2. So the error in x' is the square of the error in x, i.e. the number
- // of correct bits in x' is double the number in x.
+ // 1-e^2. So the error in x' is the square of the error in x, i.e. the
+ // number of correct bits in x' is double the number in x.
// An initial approximation to the reciprocal
DyadicFloat<Bits> x(Sign::POS, -32 - a.exponent - int(Bits),
diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h
index caa74c5623f39..f77f80e6b6110 100644
--- a/libc/test/src/math/RIntTest.h
+++ b/libc/test/src/math/RIntTest.h
@@ -49,11 +49,11 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
public:
void testSpecialNumbers(RIntFunc func) {
- 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));
+ ASSERT_FP_EQ_ALL_ROUNDING(inf, func(inf));
+ ASSERT_FP_EQ_ALL_ROUNDING(neg_inf, func(neg_inf));
+ ASSERT_FP_EQ_ALL_ROUNDING(nan, func(nan));
+ ASSERT_FP_EQ_ALL_ROUNDING(zero, func(zero));
+ ASSERT_FP_EQ_ALL_ROUNDING(neg_zero, func(neg_zero));
}
void testRoundNumbers(RIntFunc func) {
diff --git a/libc/test/src/math/smoke/RIntTest.h b/libc/test/src/math/smoke/RIntTest.h
index 3b2ddeecc74e1..82adf25b8a968 100644
--- a/libc/test/src/math/smoke/RIntTest.h
+++ b/libc/test/src/math/smoke/RIntTest.h
@@ -39,11 +39,11 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
public:
void testSpecialNumbers(RIntFunc func) {
- 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));
+ ASSERT_FP_EQ_ALL_ROUNDING(inf, func(inf));
+ ASSERT_FP_EQ_ALL_ROUNDING(neg_inf, func(neg_inf));
+ ASSERT_FP_EQ_ALL_ROUNDING(nan, func(nan));
+ ASSERT_FP_EQ_ALL_ROUNDING(zero, func(zero));
+ ASSERT_FP_EQ_ALL_ROUNDING(neg_zero, func(neg_zero));
}
};
More information about the libc-commits
mailing list