[libc-commits] [libc] [libc][math] Fix signed zeros for erff. (PR #97742)
via libc-commits
libc-commits at lists.llvm.org
Thu Jul 4 08:26:56 PDT 2024
https://github.com/lntue created https://github.com/llvm/llvm-project/pull/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.
>From 684cffaa1ccfde3b24780f57d4ae87d179d03d11 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 4 Jul 2024 15:23:20 +0000
Subject: [PATCH] [libc][math] Fix signed zeros for erff.
---
libc/src/math/generic/erff.cpp | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/libc/src/math/generic/erff.cpp b/libc/src/math/generic/erff.cpp
index f120d5646e043..aa7baffc7815e 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