[libc-commits] [libc] f549bb2 - [libc][math] Adjust rsqrtf16 exception checks. (#159411)
via libc-commits
libc-commits at lists.llvm.org
Wed Sep 17 11:17:57 PDT 2025
Author: lntue
Date: 2025-09-17T14:17:53-04:00
New Revision: f549bb2ddc9c106724d4f443aaf2cbe75d25942d
URL: https://github.com/llvm/llvm-project/commit/f549bb2ddc9c106724d4f443aaf2cbe75d25942d
DIFF: https://github.com/llvm/llvm-project/commit/f549bb2ddc9c106724d4f443aaf2cbe75d25942d.diff
LOG: [libc][math] Adjust rsqrtf16 exception checks. (#159411)
Added:
Modified:
libc/src/__support/math/rsqrtf16.h
libc/test/src/math/rsqrtf16_test.cpp
libc/test/src/math/smoke/rsqrtf16_test.cpp
Removed:
################################################################################
diff --git a/libc/src/__support/math/rsqrtf16.h b/libc/src/__support/math/rsqrtf16.h
index 8a107b4881a66..30ab58f8a5798 100644
--- a/libc/src/__support/math/rsqrtf16.h
+++ b/libc/src/__support/math/rsqrtf16.h
@@ -28,36 +28,39 @@ LIBC_INLINE static constexpr float16 rsqrtf16(float16 x) {
using FPBits = fputil::FPBits<float16>;
FPBits xbits(x);
- const uint16_t x_u = xbits.uintval();
- const uint16_t x_abs = x_u & 0x7fff;
- const uint16_t x_sign = x_u >> 15;
+ uint16_t x_u = xbits.uintval();
+ uint16_t x_abs = x_u & 0x7fff;
+
+ constexpr uint16_t INF_BIT = FPBits::inf().uintval();
+
+ // x is 0, inf/nan, or negative.
+ if (LIBC_UNLIKELY(x_u == 0 || x_u >= INF_BIT)) {
+ // x is NaN
+ if (x_abs > INF_BIT) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x;
+ }
+
+ // |x| = 0
+ if (x_abs == 0) {
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ fputil::set_errno_if_required(ERANGE);
+ return FPBits::inf(xbits.sign()).get_val();
+ }
- // x is NaN
- if (LIBC_UNLIKELY(xbits.is_nan())) {
- if (xbits.is_signaling_nan()) {
+ // -inf <= x < 0
+ if (x_u > 0x7fff) {
fputil::raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
return FPBits::quiet_nan().get_val();
}
- return x;
- }
- // |x| = 0
- if (LIBC_UNLIKELY(x_abs == 0x0)) {
- fputil::raise_except_if_required(FE_DIVBYZERO);
- fputil::set_errno_if_required(ERANGE);
- return FPBits::inf(Sign::POS).get_val();
- }
-
- // -inf <= x < 0
- if (LIBC_UNLIKELY(x_sign == 1)) {
- fputil::raise_except_if_required(FE_INVALID);
- fputil::set_errno_if_required(EDOM);
- return FPBits::quiet_nan().get_val();
- }
-
- // x = +inf => rsqrt(x) = 0
- if (LIBC_UNLIKELY(xbits.is_inf()))
+ // x = +inf => rsqrt(x) = 0
return FPBits::zero().get_val();
+ }
// TODO: add integer based implementation when LIBC_TARGET_CPU_HAS_FPU_FLOAT
// is not defined
diff --git a/libc/test/src/math/rsqrtf16_test.cpp b/libc/test/src/math/rsqrtf16_test.cpp
index d2f3fe8f49b92..d01c3f94f08cc 100644
--- a/libc/test/src/math/rsqrtf16_test.cpp
+++ b/libc/test/src/math/rsqrtf16_test.cpp
@@ -19,8 +19,9 @@ namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
static constexpr uint16_t POS_START = 0x0000U;
static constexpr uint16_t POS_STOP = 0x7c00U;
-// Range: [-Inf, 0]
-static constexpr uint16_t NEG_START = 0x8000U;
+// Range: [-Inf, 0)
+// rsqrt(-0.0) is -inf, not the same for mpfr.
+static constexpr uint16_t NEG_START = 0x8001U;
static constexpr uint16_t NEG_STOP = 0xfc00U;
TEST_F(LlvmLibcRsqrtf16Test, PositiveRange) {
diff --git a/libc/test/src/math/smoke/rsqrtf16_test.cpp b/libc/test/src/math/smoke/rsqrtf16_test.cpp
index be88336e2b195..5eb3e2fd6692c 100644
--- a/libc/test/src/math/smoke/rsqrtf16_test.cpp
+++ b/libc/test/src/math/smoke/rsqrtf16_test.cpp
@@ -7,30 +7,39 @@
//===----------------------------------------------------------------------===//
#include "hdr/errno_macros.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/math/rsqrtf16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
using LlvmLibcRsqrtf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+using LIBC_NAMESPACE::fputil::cast;
+
TEST_F(LlvmLibcRsqrtf16Test, SpecialNumbers) {
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(aNaN));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::rsqrtf16(sNaN), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::rsqrtf16(sNaN), FE_INVALID);
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ(inf, LIBC_NAMESPACE::rsqrtf16(0.0f));
+ EXPECT_FP_EQ(inf, LIBC_NAMESPACE::rsqrtf16(zero));
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ(neg_inf, LIBC_NAMESPACE::rsqrtf16(neg_zero));
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::rsqrtf16(1.0f));
+ EXPECT_FP_EQ(
+ LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
+ LIBC_NAMESPACE::rsqrtf16(LIBC_NAMESPACE::fputil::cast<float16>(1.0f)));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::rsqrtf16(inf));
+ EXPECT_FP_EQ(zero, LIBC_NAMESPACE::rsqrtf16(inf));
EXPECT_MATH_ERRNO(0);
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
- EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(-2.0f));
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(
+ LIBC_NAMESPACE::fputil::cast<float16>(-2.0f)));
EXPECT_MATH_ERRNO(EDOM);
}
More information about the libc-commits
mailing list