[libc-commits] [libc] 9f2215a - [libc][math] Fix signed zeros for erff. (#97742)

via libc-commits libc-commits at lists.llvm.org
Fri Jul 5 06:54:40 PDT 2024


Author: lntue
Date: 2024-07-05T09:54:37-04:00
New Revision: 9f2215ae5517a3d6e1d59e597bff83b821b96c7e

URL: https://github.com/llvm/llvm-project/commit/9f2215ae5517a3d6e1d59e597bff83b821b96c7e
DIFF: https://github.com/llvm/llvm-project/commit/9f2215ae5517a3d6e1d59e597bff83b821b96c7e.diff

LOG: [libc][math] Fix signed zeros for erff. (#97742)

The inexact exception flag was raised for the exact cases of signed
zeros. This was reported by Paul Zimmermann using the CORE-MATH test
suites.

Added: 
    

Modified: 
    libc/src/math/generic/erff.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/math/generic/erff.cpp b/libc/src/math/generic/erff.cpp
index f120d5646e0439..aa7baffc7815e9 100644
--- a/libc/src/math/generic/erff.cpp
+++ b/libc/src/math/generic/erff.cpp
@@ -127,15 +127,6 @@ LLVM_LIBC_FUNCTION(float, erff, (float x)) {
   uint32_t x_u = xbits.uintval();
   uint32_t x_abs = x_u & 0x7fff'ffffU;
 
-  // Exceptional values
-  if (LIBC_UNLIKELY(x_abs == 0x3f65'9229U)) // |x| = 0x1.cb2452p-1f
-    return x < 0.0f ? fputil::round_result_slightly_down(-0x1.972ea8p-1f)
-                    : fputil::round_result_slightly_up(0x1.972ea8p-1f);
-  if (LIBC_UNLIKELY(x_abs == 0x4004'1e6aU)) // |x| = 0x1.083cd4p+1f
-    return x < 0.0f ? fputil::round_result_slightly_down(-0x1.fe3462p-1f)
-                    : fputil::round_result_slightly_up(0x1.fe3462p-1f);
-
-  // if (LIBC_UNLIKELY(x_abs > 0x407a'd444U)) {
   if (LIBC_UNLIKELY(x_abs >= 0x4080'0000U)) {
     const float ONE[2] = {1.0f, -1.0f};
     const float SMALL[2] = {-0x1.0p-25f, 0x1.0p-25f};
@@ -149,6 +140,21 @@ LLVM_LIBC_FUNCTION(float, erff, (float x)) {
     return ONE[sign] + SMALL[sign];
   }
 
+  // Exceptional mask = common 0 bits of 2 exceptional values.
+  constexpr uint32_t EXCEPT_MASK = 0x809a'6184U;
+
+  if (LIBC_UNLIKELY((x_abs & EXCEPT_MASK) == 0)) {
+    // Exceptional values
+    if (LIBC_UNLIKELY(x_abs == 0x3f65'9229U)) // |x| = 0x1.cb2452p-1f
+      return x < 0.0f ? fputil::round_result_slightly_down(-0x1.972ea8p-1f)
+                      : fputil::round_result_slightly_up(0x1.972ea8p-1f);
+    if (LIBC_UNLIKELY(x_abs == 0x4004'1e6aU)) // |x| = 0x1.083cd4p+1f
+      return x < 0.0f ? fputil::round_result_slightly_down(-0x1.fe3462p-1f)
+                      : fputil::round_result_slightly_up(0x1.fe3462p-1f);
+    if (x_abs == 0U)
+      return x;
+  }
+
   // Polynomial approximation:
   //   erf(x) ~ x * (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14)
   double xd = static_cast<double>(x);


        


More information about the libc-commits mailing list