[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