[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