[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:35 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Anonmiraj (AnonMiraj)
<details>
<summary>Changes</summary>
Core-math exhaustive test passes
CC: @<!-- -->lntue
---
Full diff: https://github.com/llvm/llvm-project/pull/188047.diff
2 Files Affected:
- (modified) libc/src/__support/math/atan2f16.h (+10)
- (modified) libc/test/src/math/atan2f16_test.cpp (+26)
``````````diff
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();
``````````
</details>
https://github.com/llvm/llvm-project/pull/188047
More information about the libc-commits
mailing list