[libc-commits] [libc] [libc][math] Fix `sinpif` and `sinpif16` error handling (PR #235780)

Connector Switch via libc-commits libc-commits at lists.llvm.org
Mon Oct 26 07:01:04 PDT 2026


https://github.com/c8ef created https://github.com/llvm/llvm-project/pull/235780

Follow up of https://github.com/llvm/llvm-project/pull/235296, tested both functions with CORE-MATH's exhaustive checker in all four rounding modes. With `CORE_MATH_SUPPORT_ERRNO` and `CORE_MATH_CHECK_INEXACT` enabled.

- Set ERANGE for underflow in sinpif and sinpif16.
- Raise missing underflow exceptions in sinpif16.
- Return exact half-integer results in sinpif16 without raising FE_INEXACT.

>From eb87ecd8aaabc9cce95dfdc0e200dafae0e3e298 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 26 Oct 2026 21:57:53 +0800
Subject: [PATCH] [libc][math] Fix  and  error handling

---
 libc/src/__support/math/sinpif.h           |  4 ++++
 libc/src/__support/math/sinpif16.h         | 15 ++++++++++++---
 libc/test/src/math/smoke/sinpif16_test.cpp |  8 ++++++++
 libc/test/src/math/smoke/sinpif_test.cpp   |  5 +++++
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/math/sinpif.h b/libc/src/__support/math/sinpif.h
index 926e17ba6203c0..8358b6012937ab 100644
--- a/libc/src/__support/math/sinpif.h
+++ b/libc/src/__support/math/sinpif.h
@@ -59,6 +59,10 @@ LIBC_INLINE float sinpif(float x) {
         return x;
       }
 
+      // sinpi(x) underflows for 0 < |x| <= 0x1.45f3p-128.
+      if (LIBC_UNLIKELY(x_abs <= 0x0028'be60U))
+        fputil::set_errno_if_required(ERANGE);
+
       // For very small values we can approximate sinpi(x) with x * pi
       // An exhaustive test shows that this is accurate for |x| < 9.546391 ×
       // 10-8
diff --git a/libc/src/__support/math/sinpif16.h b/libc/src/__support/math/sinpif16.h
index 75d4c0c42fcc69..2d707837c776dc 100644
--- a/libc/src/__support/math/sinpif16.h
+++ b/libc/src/__support/math/sinpif16.h
@@ -17,6 +17,7 @@
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/is_integer.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
@@ -51,9 +52,13 @@ LIBC_INLINE float16 sinpif16(float16 x) {
   //               = sin(k * pi/32) * cos(y * pi/32) +
   //                 sin(y * pi/32) * cos(k * pi/32)
 
-  // For signed zeros
-  if (LIBC_UNLIKELY(x_abs == 0U))
-    return x;
+  // sinpi(x) underflows for 0 < |x| <= 0x1.45p-16.
+  if (LIBC_UNLIKELY(x_abs <= 0x0145U)) {
+    if (x_abs == 0U)
+      return x;
+    fputil::set_errno_if_required(ERANGE);
+    fputil::raise_underflow_except_if_required<float>();
+  }
 
   // Numbers greater or equal to 2^10 are integers, or infinity, or NaN
   if (LIBC_UNLIKELY(x_abs >= 0x6400)) {
@@ -74,6 +79,10 @@ LIBC_INLINE float16 sinpif16(float16 x) {
     return FPBits::zero(xbits.sign()).get_val();
   }
 
+  // Half-integers have exact results of +1 or -1.
+  if (LIBC_UNLIKELY(fputil::is_odd_integer(2.0f * xf)))
+    return fputil::is_odd_integer(xf - 0.5f) ? -1.0f16 : 1.0f16;
+
   float sin_k = 0, cos_k = 0, sin_y = 0, cosm1_y = 0;
   sincospif16_eval(xf, sin_k, cos_k, sin_y, cosm1_y);
 
diff --git a/libc/test/src/math/smoke/sinpif16_test.cpp b/libc/test/src/math/smoke/sinpif16_test.cpp
index e56514ac25fc05..10c7d1d2fdb2ce 100644
--- a/libc/test/src/math/smoke/sinpif16_test.cpp
+++ b/libc/test/src/math/smoke/sinpif16_test.cpp
@@ -32,6 +32,14 @@ TEST_F(LlvmLibcSinpif16Test, SpecialNumbers) {
 
   EXPECT_FP_IS_NAN(LIBC_NAMESPACE::sinpif16(neg_inf));
   EXPECT_MATH_ERRNO(EDOM);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION(1.0f16, LIBC_NAMESPACE::sinpif16(0.5f16), 0);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
+      0x1.63p-16f16, LIBC_NAMESPACE::sinpif16(0x1.c4p-18f16),
+      FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(ERANGE);
 }
 
 TEST_F(LlvmLibcSinpif16Test, Integers) {
diff --git a/libc/test/src/math/smoke/sinpif_test.cpp b/libc/test/src/math/smoke/sinpif_test.cpp
index ca2cac50db27b0..7d6dd031b096f1 100644
--- a/libc/test/src/math/smoke/sinpif_test.cpp
+++ b/libc/test/src/math/smoke/sinpif_test.cpp
@@ -31,6 +31,11 @@ TEST_F(LlvmLibcSinpifTest, SpecialNumbers) {
 
   EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::sinpif(neg_inf));
   EXPECT_MATH_ERRNO(EDOM);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION(0x1.1abe4p-130f,
+                              LIBC_NAMESPACE::sinpif(0x1.68p-132f),
+                              FE_UNDERFLOW | FE_INEXACT);
+  EXPECT_MATH_ERRNO(ERANGE);
 }
 
 TEST_F(LlvmLibcSinpifTest, Integers) {



More information about the libc-commits mailing list