[libc-commits] [libc] [libc][math] fix rounding issue in tanhf (PR #197260)
via libc-commits
libc-commits at lists.llvm.org
Tue May 12 10:55:58 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Schrodinger ZHU Yifan (SchrodingerZhu)
<details>
<summary>Changes</summary>
This PR fixes the rounding issue in tanhf. The compiler assumes nearest rounding of `SIGNS[sign_index][0] + SIGNS[sign_index][1]` in the special case of finite `|x| >= 15`, which causes FE_DOWNWARD and FE_TOWARDZERO to return 1.0f instead of the next float below 1.0f for positive inputs. Use fputil::round_result_slightly_down/up to work around the problem. The helpers force the tiny adjustment to be evaluated under the active rounding mode while preserving exact +/-1.0f for infinities.
Assisted-by: Codex with gpt-5.5 high fast
Co-authored-by: lntue <lntue@<!-- -->google.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/197260.diff
1 Files Affected:
- (modified) libc/src/__support/math/tanhf.h (+6-6)
``````````diff
diff --git a/libc/src/__support/math/tanhf.h b/libc/src/__support/math/tanhf.h
index 15c86c6b25f5f..b42b9ae263ffc 100644
--- a/libc/src/__support/math/tanhf.h
+++ b/libc/src/__support/math/tanhf.h
@@ -12,6 +12,7 @@
#include "exp10f_utils.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
#include "src/__support/macros/config.h"
@@ -30,8 +31,6 @@ LIBC_INLINE float tanhf(float x) {
FPBits xbits(x);
uint32_t x_abs = xbits.abs().uintval();
- const int sign_index = xbits.is_neg() ? 1 : 0;
-
// When |x| >= 15, or x is inf or nan, or |x| <= 0.078125
if (LIBC_UNLIKELY((x_abs >= 0x4170'0000U) || (x_abs <= 0x3da0'0000U))) {
if (x_abs <= 0x3da0'0000U) {
@@ -62,12 +61,13 @@ LIBC_INLINE float tanhf(float x) {
if (LIBC_UNLIKELY(xbits.is_nan()))
return x + 1.0f; // sNaN to qNaN + signal
- constexpr float SIGNS[2][2] = {{1.0f, -0x1.0p-25f}, {-1.0f, 0x1.0p-25f}};
-
if (LIBC_UNLIKELY(xbits.is_inf()))
- return SIGNS[sign_index][0];
+ return xbits.is_neg() ? -1.0f : 1.0f;
+
+ if (xbits.is_pos())
+ return fputil::round_result_slightly_down(1.0f);
- return SIGNS[sign_index][0] + SIGNS[sign_index][1];
+ return fputil::round_result_slightly_up(-1.0f);
}
// Range reduction: e^(2x) = 2^(hi + mid) * e^lo
``````````
</details>
https://github.com/llvm/llvm-project/pull/197260
More information about the libc-commits
mailing list