[libc-commits] [libc] [libc][math] Fix spurious underflow exception in atan2f16 (PR #188047)
via libc-commits
libc-commits at lists.llvm.org
Mon Mar 23 07:43:00 PDT 2026
https://github.com/AnonMiraj created https://github.com/llvm/llvm-project/pull/188047
Core-math exhaustive test passes
CC: @lntue
>From 890dcf189d430c2e7d5de63b1d0a04631946bbb7 Mon Sep 17 00:00:00 2001
From: Anonmiraj <ezzibrahimx at gmail.com>
Date: Mon, 23 Mar 2026 16:41:26 +0200
Subject: [PATCH] [libc][math] Fix spurious underflow exception in atan2f16
---
libc/src/__support/math/atan2f16.h | 10 ++++++++++
libc/test/src/math/atan2f16_test.cpp | 26 ++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/libc/src/__support/math/atan2f16.h b/libc/src/__support/math/atan2f16.h
index 297167a429d9f..06b0e961c5912 100644
--- a/libc/src/__support/math/atan2f16.h
+++ b/libc/src/__support/math/atan2f16.h
@@ -96,6 +96,16 @@ LIBC_INLINE float16 atan2f16(float16 y, float16 x) {
double p = atan_eval(q_d, static_cast<unsigned>(idx));
double r = final_sign *
fputil::multiply_add(q_d, p, const_term + ATAN_K_OVER_16[idx]);
+
+ double abs_r = r > 0 ? r : -r;
+ double min_normal = 0x1.0p-14;
+ double half_ulp = 0x1.0p-25;
+ if (LIBC_UNLIKELY(abs_r > (min_normal - half_ulp) && abs_r < min_normal)) {
+ if (fputil::fenv_is_round_to_nearest()) {
+ r = r > 0 ? min_normal : -min_normal;
+ }
+ }
+
return fputil::cast<float16>(r);
}
diff --git a/libc/test/src/math/atan2f16_test.cpp b/libc/test/src/math/atan2f16_test.cpp
index b4214e932f591..5a1df3af47b3f 100644
--- a/libc/test/src/math/atan2f16_test.cpp
+++ b/libc/test/src/math/atan2f16_test.cpp
@@ -56,6 +56,32 @@ TEST_F(LlvmLibcAtan2f16Test, TrickyInputs) {
}
}
+TEST_F(LlvmLibcAtan2f16Test, SpuriousUnderflow) {
+ mpfr::ForceRoundingMode r(mpfr::RoundingMode::Nearest);
+ if (!r.success)
+ return;
+
+ constexpr int N = 1;
+ mpfr::BinaryInput<float16> INPUTS[N] = {
+ {0x1.0p-24f16, 0x1.0p-10f16},
+ };
+
+ for (int i = 0; i < N; ++i) {
+ float16 y = INPUTS[i].x;
+ float16 x = INPUTS[i].y;
+
+ LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+ float16 result = LIBC_NAMESPACE::atan2f16(y, x);
+ int excepts = LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT);
+
+ EXPECT_EQ(excepts & FE_UNDERFLOW, 0);
+ EXPECT_NE(excepts & FE_INEXACT, 0);
+
+ ASSERT_MPFR_MATCH(mpfr::Operation::Atan2, INPUTS[i], result, 0.5,
+ mpfr::RoundingMode::Nearest);
+ }
+}
+
TEST_F(LlvmLibcAtan2f16Test, InFloat16Range) {
constexpr uint16_t X_START = FPBits(static_cast<float16>(0.25f)).uintval();
constexpr uint16_t X_STOP = FPBits(static_cast<float16>(4.0f)).uintval();
More information about the libc-commits
mailing list