[libc-commits] [libc] [libc] Fix #124812 issue (PR #133326)
via libc-commits
libc-commits at lists.llvm.org
Thu Mar 27 14:58:17 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: wldfngrs (wldfngrs)
<details>
<summary>Changes</summary>
Add tests for signaling NaNs, and fix function behavior for handling signaling NaN input
https://github.com/llvm/llvm-project/issues/124812#
---
Patch is 59.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133326.diff
80 Files Affected:
- (modified) libc/src/math/generic/CMakeLists.txt (+3)
- (modified) libc/src/math/generic/acosf.cpp (+7)
- (modified) libc/src/math/generic/asinf.cpp (+6)
- (modified) libc/src/math/generic/asinhf.cpp (+7-1)
- (modified) libc/src/math/generic/atan2.cpp (+5-1)
- (modified) libc/src/math/generic/atan2f.cpp (+6-1)
- (modified) libc/src/math/generic/atanhf.cpp (+4)
- (modified) libc/src/math/generic/cos.cpp (+5-1)
- (modified) libc/src/math/generic/cosf.cpp (+5)
- (modified) libc/src/math/generic/cosf16.cpp (+5)
- (modified) libc/src/math/generic/cospif.cpp (+5)
- (modified) libc/src/math/generic/cospif16.cpp (+4)
- (modified) libc/src/math/generic/erff.cpp (+4)
- (modified) libc/src/math/generic/log1p.cpp (+6-1)
- (modified) libc/src/math/generic/logf.cpp (+5)
- (modified) libc/src/math/generic/pow.cpp (+6-1)
- (modified) libc/src/math/generic/powf.cpp (+5)
- (modified) libc/src/math/generic/sin.cpp (+5)
- (modified) libc/src/math/generic/sincos.cpp (+7-1)
- (modified) libc/src/math/generic/sincosf.cpp (+6)
- (modified) libc/src/math/generic/sinf.cpp (+5)
- (modified) libc/src/math/generic/sinf16.cpp (+5)
- (modified) libc/src/math/generic/sinpif.cpp (+5)
- (modified) libc/src/math/generic/sinpif16.cpp (+4)
- (modified) libc/src/math/generic/tan.cpp (+4)
- (modified) libc/src/math/generic/tanf.cpp (+5)
- (modified) libc/src/math/generic/tanf16.cpp (+4)
- (modified) libc/src/math/generic/tanpif16.cpp (+6-1)
- (modified) libc/test/src/math/smoke/CMakeLists.txt (+1)
- (modified) libc/test/src/math/smoke/acosf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/acoshf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/asinf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/asinhf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/atan2_test.cpp (+9)
- (modified) libc/test/src/math/smoke/atan2f_test.cpp (+9)
- (modified) libc/test/src/math/smoke/atan_test.cpp (+3-1)
- (modified) libc/test/src/math/smoke/atanf_test.cpp (+2)
- (modified) libc/test/src/math/smoke/atanhf_test.cpp (+2-1)
- (modified) libc/test/src/math/smoke/cbrt_test.cpp (+3)
- (modified) libc/test/src/math/smoke/cbrtf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/cos_test.cpp (+3)
- (modified) libc/test/src/math/smoke/cosf16_test.cpp (+3)
- (modified) libc/test/src/math/smoke/cosf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/coshf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/cospif16_test.cpp (+3)
- (modified) libc/test/src/math/smoke/cospif_test.cpp (+3)
- (modified) libc/test/src/math/smoke/erff_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp10_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp10f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp10m1f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp2_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp2f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp2m1f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/exp_test.cpp (+3)
- (modified) libc/test/src/math/smoke/expf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/expm1_test.cpp (+3)
- (modified) libc/test/src/math/smoke/expm1f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log10_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log10f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log1p_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log1pf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log2_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log2f_test.cpp (+3)
- (modified) libc/test/src/math/smoke/log_test.cpp (+3)
- (modified) libc/test/src/math/smoke/logf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/pow_test.cpp (+22-1)
- (modified) libc/test/src/math/smoke/powf_test.cpp (+23-1)
- (modified) libc/test/src/math/smoke/sin_test.cpp (+3)
- (modified) libc/test/src/math/smoke/sincos_test.cpp (+5)
- (modified) libc/test/src/math/smoke/sincosf_test.cpp (+5)
- (modified) libc/test/src/math/smoke/sinf16_test.cpp (+3)
- (modified) libc/test/src/math/smoke/sinf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/sinhf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/sinpif16_test.cpp (+3)
- (modified) libc/test/src/math/smoke/sinpif_test.cpp (+3)
- (modified) libc/test/src/math/smoke/tan_test.cpp (+3)
- (modified) libc/test/src/math/smoke/tanf16_test.cpp (+3)
- (modified) libc/test/src/math/smoke/tanf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/tanhf_test.cpp (+3)
- (modified) libc/test/src/math/smoke/tanpif16_test.cpp (+3)
``````````diff
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 77c6244c5e5da..056f3e61b7e62 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4129,7 +4129,9 @@ add_entrypoint_object(
atan2f_float.h
DEPENDS
.inv_trigf_utils
+ libc.hdr.fenv_macros
libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.multiply_add
libc.src.__support.FPUtil.nearest_integer
@@ -4147,6 +4149,7 @@ add_entrypoint_object(
DEPENDS
.atan_utils
libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.multiply_add
libc.src.__support.FPUtil.nearest_integer
diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp
index 509a5ebc4973e..87a154e6f7b2f 100644
--- a/libc/src/math/generic/acosf.cpp
+++ b/libc/src/math/generic/acosf.cpp
@@ -84,10 +84,17 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
0x1.921fb6p+1f)
: /* x == 1.0f */ 0.0f;
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ // |x| <= +/-inf
if (x_abs <= 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
}
+
return x + FPBits::quiet_nan().get_val();
}
diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp
index da854417e85fe..2172171c3b6c9 100644
--- a/libc/src/math/generic/asinf.cpp
+++ b/libc/src/math/generic/asinf.cpp
@@ -108,10 +108,16 @@ LLVM_LIBC_FUNCTION(float, asinf, (float x)) {
// |x| > 1, return NaNs.
if (LIBC_UNLIKELY(x_abs > 0x3f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (x_abs <= 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
}
+
return FPBits::quiet_nan().get_val();
}
diff --git a/libc/src/math/generic/asinhf.cpp b/libc/src/math/generic/asinhf.cpp
index 37b87a821222a..817a4d4b6a24a 100644
--- a/libc/src/math/generic/asinhf.cpp
+++ b/libc/src/math/generic/asinhf.cpp
@@ -61,8 +61,14 @@ LLVM_LIBC_FUNCTION(float, asinhf, (float x)) {
};
if (LIBC_UNLIKELY(x_abs >= 0x4bdd'65a5U)) {
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
+ if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits_t::quiet_nan().get_val();
+ }
+
return x;
+ }
// Exceptional cases when x > 2^24.
switch (x_abs) {
diff --git a/libc/src/math/generic/atan2.cpp b/libc/src/math/generic/atan2.cpp
index 8adfe3321a9ee..c757b744a91fc 100644
--- a/libc/src/math/generic/atan2.cpp
+++ b/libc/src/math/generic/atan2.cpp
@@ -8,6 +8,7 @@
#include "src/math/atan2.h"
#include "atan_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/double_double.h"
#include "src/__support/FPUtil/multiply_add.h"
@@ -111,8 +112,11 @@ LLVM_LIBC_FUNCTION(double, atan2, (double y, double x)) {
// Check for exceptional cases, whether inputs are 0, inf, nan, or close to
// overflow, or close to underflow.
if (LIBC_UNLIKELY(max_exp > 0x7ffU - 128U || min_exp < 128U)) {
- if (x_bits.is_nan() || y_bits.is_nan())
+ if (x_bits.is_nan() || y_bits.is_nan()) {
+ if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+ fputil::raise_except_if_required(FE_INVALID);
return FPBits::quiet_nan().get_val();
+ }
unsigned x_except = x == 0.0 ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1);
unsigned y_except = y == 0.0 ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1);
diff --git a/libc/src/math/generic/atan2f.cpp b/libc/src/math/generic/atan2f.cpp
index 726cae9c8462b..9b3397f2446a5 100644
--- a/libc/src/math/generic/atan2f.cpp
+++ b/libc/src/math/generic/atan2f.cpp
@@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "src/math/atan2f.h"
+#include "hdr/fenv_macros.h"
#include "inv_trigf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
#include "src/__support/FPUtil/double_double.h"
@@ -264,8 +266,11 @@ LLVM_LIBC_FUNCTION(float, atan2f, (float y, float x)) {
double den_d = static_cast<double>(den_f);
if (LIBC_UNLIKELY(max_abs >= 0x7f80'0000U || num_d == 0.0)) {
- if (x_bits.is_nan() || y_bits.is_nan())
+ if (x_bits.is_nan() || y_bits.is_nan()) {
+ if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+ fputil::raise_except_if_required(FE_INVALID);
return FPBits::quiet_nan().get_val();
+ }
double x_d = static_cast<double>(x);
double y_d = static_cast<double>(y);
size_t x_except = (x_d == 0.0) ? 0 : (x_abs == 0x7f80'0000 ? 2 : 1);
diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp
index a2051bd3e3e67..f0a7529af79d8 100644
--- a/libc/src/math/generic/atanhf.cpp
+++ b/libc/src/math/generic/atanhf.cpp
@@ -24,6 +24,10 @@ LLVM_LIBC_FUNCTION(float, atanhf, (float x)) {
// |x| >= 1.0
if (LIBC_UNLIKELY(x_abs >= 0x3F80'0000U)) {
if (xbits.is_nan()) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
return x;
}
// |x| == 1.0
diff --git a/libc/src/math/generic/cos.cpp b/libc/src/math/generic/cos.cpp
index b60082bf9c308..1cda012280d5d 100644
--- a/libc/src/math/generic/cos.cpp
+++ b/libc/src/math/generic/cos.cpp
@@ -65,7 +65,11 @@ LLVM_LIBC_FUNCTION(double, cos, (double x)) {
} else {
// Inf or NaN
if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
- // sin(+-Inf) = NaN
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ // cos(+-Inf) = NaN
if (xbits.get_mantissa() == 0) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp
index 6ea24f9ccd3fa..b0b573aaf3a66 100644
--- a/libc/src/math/generic/cosf.cpp
+++ b/libc/src/math/generic/cosf.cpp
@@ -117,6 +117,11 @@ LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
// x is inf or nan.
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (x_abs == 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/cosf16.cpp b/libc/src/math/generic/cosf16.cpp
index 4d42db981ce71..3d0145e44ff98 100644
--- a/libc/src/math/generic/cosf16.cpp
+++ b/libc/src/math/generic/cosf16.cpp
@@ -67,6 +67,11 @@ LLVM_LIBC_FUNCTION(float16, cosf16, (float16 x)) {
// cos(+/-inf) = NaN, and cos(NaN) = NaN
if (xbits.is_inf_or_nan()) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (xbits.is_inf()) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/cospif.cpp b/libc/src/math/generic/cospif.cpp
index 29566f4fceacf..cfa7de6064a6e 100644
--- a/libc/src/math/generic/cospif.cpp
+++ b/libc/src/math/generic/cospif.cpp
@@ -66,6 +66,11 @@ LLVM_LIBC_FUNCTION(float, cospif, (float x)) {
// x is inf or nan.
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (x_abs == 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/cospif16.cpp b/libc/src/math/generic/cospif16.cpp
index ee74bdb4a3693..67157a6a65fcc 100644
--- a/libc/src/math/generic/cospif16.cpp
+++ b/libc/src/math/generic/cospif16.cpp
@@ -54,6 +54,10 @@ LLVM_LIBC_FUNCTION(float16, cospif16, (float16 x)) {
// Check for NaN or infintiy values
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
// If value is equal to infinity
if (x_abs == 0x7c00) {
fputil::set_errno_if_required(EDOM);
diff --git a/libc/src/math/generic/erff.cpp b/libc/src/math/generic/erff.cpp
index 016afe4a68140..b5e7d0773f11b 100644
--- a/libc/src/math/generic/erff.cpp
+++ b/libc/src/math/generic/erff.cpp
@@ -135,6 +135,10 @@ LLVM_LIBC_FUNCTION(float, erff, (float x)) {
int sign = xbits.is_neg() ? 1 : 0;
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
return (x_abs > 0x7f80'0000) ? x : ONE[sign];
}
diff --git a/libc/src/math/generic/log1p.cpp b/libc/src/math/generic/log1p.cpp
index 058409fed081d..c97904008e5f7 100644
--- a/libc/src/math/generic/log1p.cpp
+++ b/libc/src/math/generic/log1p.cpp
@@ -910,7 +910,12 @@ LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
return FPBits_t::quiet_nan().get_val();
}
// x is +Inf or NaN
- return x;
+ if (xbits.is_inf() && xbits.is_pos())
+ return x;
+
+ if (xbits.is_signaling_nan())
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits_t::quiet_nan().get_val();
}
x_dd.hi = x;
} else {
diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index 032d658a941be..29247e366ca57 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -132,6 +132,11 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
return FPBits::quiet_nan().get_val();
}
// x is +inf or nan
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
return x;
}
}
diff --git a/libc/src/math/generic/pow.cpp b/libc/src/math/generic/pow.cpp
index 8a12934f6c4ba..45d7fbd581398 100644
--- a/libc/src/math/generic/pow.cpp
+++ b/libc/src/math/generic/pow.cpp
@@ -217,7 +217,12 @@ LLVM_LIBC_FUNCTION(double, pow, (double x, double y)) {
uint64_t sign = 0;
///////// BEGIN - Check exceptional cases ////////////////////////////////////
-
+ // If x or y is signaling NaN
+ if (x_abs.is_signaling_nan() || y_abs.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
// The double precision number that is closest to 1 is (1 - 2^-53), which has
// log2(1 - 2^-53) ~ -1.715...p-53.
// So if |y| > |1075 / log2(1 - 2^-53)|, and x is finite:
diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp
index 2d7deca3c77bb..2df1c57ed2d34 100644
--- a/libc/src/math/generic/powf.cpp
+++ b/libc/src/math/generic/powf.cpp
@@ -657,6 +657,11 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
uint32_t y_abs = ybits.abs().uintval();
///////// BEGIN - Check exceptional cases ////////////////////////////////////
+ // if x or y is signaling NaN
+ if (xbits.is_signaling_nan() || ybits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FloatBits::quiet_nan().get_val();
+ }
// The single precision number that is closest to 1 is (1 - 2^-24), which has
// log2(1 - 2^-24) ~ -1.715...p-24.
diff --git a/libc/src/math/generic/sin.cpp b/libc/src/math/generic/sin.cpp
index 4a58dcf4b173f..64cd8a6072981 100644
--- a/libc/src/math/generic/sin.cpp
+++ b/libc/src/math/generic/sin.cpp
@@ -77,6 +77,11 @@ LLVM_LIBC_FUNCTION(double, sin, (double x)) {
// Inf or NaN
if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
// sin(+-Inf) = NaN
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (xbits.get_mantissa() == 0) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/sincos.cpp b/libc/src/math/generic/sincos.cpp
index 0ac2f7f997527..42b0ade465880 100644
--- a/libc/src/math/generic/sincos.cpp
+++ b/libc/src/math/generic/sincos.cpp
@@ -85,7 +85,13 @@ LLVM_LIBC_FUNCTION(void, sincos, (double x, double *sin_x, double *cos_x)) {
} else {
// Inf or NaN
if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
- // sin(+-Inf) = NaN
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ *sin_x = *cos_x = FPBits::quiet_nan().get_val();
+ return;
+ }
+
+ // sin(+-Inf) = NaN
if (xbits.get_mantissa() == 0) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/sincosf.cpp b/libc/src/math/generic/sincosf.cpp
index 623ef636afb1e..8b23b60103256 100644
--- a/libc/src/math/generic/sincosf.cpp
+++ b/libc/src/math/generic/sincosf.cpp
@@ -145,6 +145,12 @@ LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) {
// x is inf or nan.
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ *sinp = *cosp = FPBits::quiet_nan().get_val();
+ return;
+ }
+
if (x_abs == 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp
index d27ce843a2c92..bc4858c22eef2 100644
--- a/libc/src/math/generic/sinf.cpp
+++ b/libc/src/math/generic/sinf.cpp
@@ -136,6 +136,11 @@ LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (x_abs == 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/sinf16.cpp b/libc/src/math/generic/sinf16.cpp
index 85e55a614588a..da02683997326 100644
--- a/libc/src/math/generic/sinf16.cpp
+++ b/libc/src/math/generic/sinf16.cpp
@@ -87,6 +87,11 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
}
if (xbits.is_inf_or_nan()) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (xbits.is_inf()) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/sinpif.cpp b/libc/src/math/generic/sinpif.cpp
index f572ded06b25a..b78032310b023 100644
--- a/libc/src/math/generic/sinpif.cpp
+++ b/libc/src/math/generic/sinpif.cpp
@@ -83,6 +83,11 @@ LLVM_LIBC_FUNCTION(float, sinpif, (float x)) {
// check for NaN values
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (x_abs == 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/sinpif16.cpp b/libc/src/math/generic/sinpif16.cpp
index 51ea595653b4d..48f8c3fae4f2b 100644
--- a/libc/src/math/generic/sinpif16.cpp
+++ b/libc/src/math/generic/sinpif16.cpp
@@ -50,6 +50,10 @@ LLVM_LIBC_FUNCTION(float16, sinpif16, (float16 x)) {
if (LIBC_UNLIKELY(x_abs >= 0x6400)) {
// Check for NaN or infinity values
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
// If value is equal to infinity
if (x_abs == 0x7c00) {
fputil::set_errno_if_required(EDOM);
diff --git a/libc/src/math/generic/tan.cpp b/libc/src/math/generic/tan.cpp
index a899a2128d384..1228d2153990e 100644
--- a/libc/src/math/generic/tan.cpp
+++ b/libc/src/math/generic/tan.cpp
@@ -163,6 +163,10 @@ LLVM_LIBC_FUNCTION(double, tan, (double x)) {
} else {
// Inf or NaN
if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
// tan(+-Inf) = NaN
if (xbits.get_mantissa() == 0) {
fputil::set_errno_if_required(EDOM);
diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp
index a15aa9796cbd8..974ad69ef8395 100644
--- a/libc/src/math/generic/tanf.cpp
+++ b/libc/src/math/generic/tanf.cpp
@@ -113,6 +113,11 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
if (LIBC_UNLIKELY(x_abs > 0x4d56'd354U)) {
// Inf or NaN
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
if (x_abs == 0x7f80'0000U) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
diff --git a/libc/src/math/generic/tanf16.cpp b/libc/src/math/generic/tanf16.cpp
index 97d201b65bbe6..229f4a363670b 100644
--- a/libc/src/math/generic/tanf16.cpp
+++ b/libc/src/math/generic/tanf16.cpp
@@ -84,6 +84,10 @@ LLVM_LIBC_FUNCTION(float16, tanf16, (float16 x)) {
// tan(+/-inf) = NaN, and tan(NaN) = NaN
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
// x = +/-inf
if (x_abs == 0x7c00) {
fputil::set_errno_if_required(EDOM);
diff --git a/libc/src/math/generic/tanpif16.cpp b/libc/src/math/generic/tanpif16.cpp
index 71cf25c9741a1..aeb41719b9a42 100644
--- a/libc/src/math/generic/tanpif16.cpp
+++ b/libc/src/math/generic/tanpif16.cpp
@@ -63,7 +63,12 @@ LLVM_LIBC_FUNCTION(float16, tanpif16, (float16 x)) {
if (LIBC_UNLIKELY(x_abs >= 0x6400)) {
// Check for NaN or infinity values
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
- if (x_abs == 0x7c00) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ // is inf
+ if (x_abs == 0x7c00) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 660b68687d63c..54f5e40cdce11 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4228,6 +4228,7 @@ add_fp_unittest(
SRCS
pow_test.cpp
DEPENDS
+ libc.src.errno.errno
libc.hdr.fenv_macros
libc.src.math.pow
)
diff --git a/libc/test/src/math/smoke/acosf_test.cpp b/libc/test/src/math/smoke/acosf_test.cpp
index e5d56c70f2722..74f68e00011aa 100644
--- a/libc/test/src/math/smoke/acosf_test.cpp
+++ b/libc/test/src/math/smoke/acosf_test.cpp
@@ -20,6 +20,9 @@ using LlvmLibcAcosfTest = LIBC_NAMESPACE::testing::FPTest<float>;
TEST_F(LlvmLibcAcosfTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;
+ EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::acosf(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acosf(aNaN));
EXPECT_MATH_ERRNO(0);
diff --git a/libc/test/src/math/smoke/acoshf_test.cpp b/libc/test/src/math/smoke/acoshf_test.cpp
index c4e88259919c3..c5ba88055ac57 100644
--- a/libc/test/src/math/smoke/acoshf_test.cpp
+++ b/libc/test/src/math/smoke/acoshf_test.cpp
@@ ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/133326
More information about the libc-commits
mailing list