[libc-commits] [libc] [libc][math] Added missing floating point exception for atanpif16 (PR #187060)

via libc-commits libc-commits at lists.llvm.org
Tue Mar 17 09:59:08 PDT 2026


https://github.com/Sukumarsawant created https://github.com/llvm/llvm-project/pull/187060

This PR intends to fix the missed FP exceptions for atanpif16

>From e646189ebbe765fc13648eca446039f31ea7b4e3 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 17 Mar 2026 22:25:44 +0530
Subject: [PATCH 1/2] feat: added tests and handling except cases

---
 libc/src/__support/FPUtil/dyadic_float.h    |  1 +
 libc/src/__support/math/atanpif16.h         | 30 +++++++++++++++------
 libc/test/src/math/smoke/CMakeLists.txt     |  1 +
 libc/test/src/math/smoke/atanpif16_test.cpp |  7 +++++
 4 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index cc0710fbf7b02..018429b30272a 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -219,6 +219,7 @@ template <size_t Bits> struct DyadicFloat {
       underflow = true;
     } else if (unbiased_exp == -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) {
       round = true;
+      underflow = true;
       MantissaType sticky_mask = (MantissaType(1) << (Bits - 1)) - 1;
       sticky = (mantissa & sticky_mask) != 0;
     } else {
diff --git a/libc/src/__support/math/atanpif16.h b/libc/src/__support/math/atanpif16.h
index e0eaff6678fc5..468f35a38161f 100644
--- a/libc/src/__support/math/atanpif16.h
+++ b/libc/src/__support/math/atanpif16.h
@@ -95,14 +95,8 @@ LIBC_INLINE float16 atanpif16(float16 x) {
     return signed_result(0.5);
   }
 
-  if (LIBC_UNLIKELY(xbits.is_zero()))
-    return x;
-
   double x_abs = fputil::cast<double>(xbits.abs().get_val());
 
-  if (LIBC_UNLIKELY(x_abs == 1.0))
-    return signed_result(0.25);
-
   // evaluate atan(x)/pi using polynomial approximation, valid for |x| <= 0.5
   constexpr auto atanpi_eval = [](double x) -> double {
     // polynomial coefficients for atan(x)/pi taylor series
@@ -125,14 +119,34 @@ LIBC_INLINE float16 atanpif16(float16 x) {
 
   // case 1: |x| <= 0.5 - direct polynomial evaluation
   if (LIBC_LIKELY(x_abs <= 0.5)) {
+
+    if (LIBC_UNLIKELY(xbits.is_zero()))
+      return x;
+
+    if (LIBC_UNLIKELY(xbits.abs().uintval() == 0x0a48)) {
+      int rounding = fputil::quick_get_round();
+      if (!is_neg) {
+        if (rounding == FE_UPWARD)
+          return fputil::cast<float16>(0x1p-14f);
+        return fputil::cast<float16>(0x1.ffd7ap-15f);
+      } else {
+        if (rounding == FE_DOWNWARD)
+          return fputil::cast<float16>(-0x1p-14f);
+        return fputil::cast<float16>(-0x1.ffd7ap-15f);
+      }
+    }
     double result = atanpi_eval(x_abs);
-    return signed_result(result);
+    float16 s_result = signed_result(result);
+    return s_result;
   }
 
+  if (LIBC_UNLIKELY(x_abs == 1.0))
+    return signed_result(0.25);
+
   // case 2: 0.5 < |x| <= 1 - use double-angle reduction
   // atan(x) = 2 * atan(x / (1 + sqrt(1 + x^2)))
   // so atanpi(x) = 2 * atanpi(x') where x' = x / (1 + sqrt(1 + x^2))
-  if (x_abs <= 1.0) {
+  if (x_abs < 1.0) {
     double x_abs_sq = x_abs * x_abs;
     double sqrt_term = fputil::sqrt<double>(1.0 + x_abs_sq);
     double x_prime = x_abs / (1.0 + sqrt_term);
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index d92e6b728b63e..12f378f7c1128 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4719,6 +4719,7 @@ add_fp_unittest(
     atanpif16_test.cpp
   DEPENDS
     libc.src.math.atanpif16
+    libc.hdr.errno_macros
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/smoke/atanpif16_test.cpp b/libc/test/src/math/smoke/atanpif16_test.cpp
index ffc8ad7296309..b57c53521411a 100644
--- a/libc/test/src/math/smoke/atanpif16_test.cpp
+++ b/libc/test/src/math/smoke/atanpif16_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "hdr/errno_macros.h"
 #include "src/math/atanpif16.h"
 #include "test/UnitTest/FPMatcher.h"
 
@@ -61,3 +62,9 @@ TEST_F(LlvmLibcAtanpif16Test, MonotonicityProperty) {
     EXPECT_TRUE(result1 < result2);
   }
 }
+
+TEST_F(LlvmLibcAtanpif16Test, Underflow) {
+  EXPECT_FP_EQ_WITH_EXCEPTION(0x1p-24f16, LIBC_NAMESPACE::atanpif16(0x1p-23f16),
+                              FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(ERANGE);
+}
\ No newline at end of file

>From 88a9f2e7755b012f96495357da26276ff7bb04b0 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 17 Mar 2026 22:27:35 +0530
Subject: [PATCH 2/2] nit

---
 libc/test/src/math/smoke/atanpif16_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/test/src/math/smoke/atanpif16_test.cpp b/libc/test/src/math/smoke/atanpif16_test.cpp
index b57c53521411a..4521948973419 100644
--- a/libc/test/src/math/smoke/atanpif16_test.cpp
+++ b/libc/test/src/math/smoke/atanpif16_test.cpp
@@ -67,4 +67,4 @@ TEST_F(LlvmLibcAtanpif16Test, Underflow) {
   EXPECT_FP_EQ_WITH_EXCEPTION(0x1p-24f16, LIBC_NAMESPACE::atanpif16(0x1p-23f16),
                               FE_UNDERFLOW | FE_INEXACT);
   EXPECT_MATH_ERRNO(ERANGE);
-}
\ No newline at end of file
+}



More information about the libc-commits mailing list