[libc-commits] [libc] [libc][math] Preserve the sign of tiny asinhf16 zeros (PR #236479)
via libc-commits
libc-commits at lists.llvm.org
Fri Oct 30 07:55:27 PDT 2026
https://github.com/sriramshastry updated https://github.com/llvm/llvm-project/pull/236479
>From 21c48f83ed0d3ced9fec6df11e4df8dcce3a4df2 Mon Sep 17 00:00:00 2001
From: sriramshastry <sriramshastry at gmail.com>
Date: Wed, 28 Oct 2026 16:21:31 +0000
Subject: [PATCH] [libc][math] Preserve the sign of tiny asinhf16 zeros
Restore the input sign after the existing tiny correction rounds to zero.
Cover negative minimum subnormal in upward and toward-zero rounding and
positive minimum subnormal in downward rounding.
Keep the selected magnitude and approximation unchanged. This is not a
general underflow-reporting repair.
Signed-off-by: sriramshastry <sriramshastry at gmail.com>
---
libc/src/__support/math/asinhf16.h | 14 ++++++++++----
libc/test/src/math/smoke/asinhf16_test.cpp | 15 +++++++++++++++
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/libc/src/__support/math/asinhf16.h b/libc/src/__support/math/asinhf16.h
index e6f108763969bc..6c38159c20a766 100644
--- a/libc/src/__support/math/asinhf16.h
+++ b/libc/src/__support/math/asinhf16.h
@@ -89,10 +89,16 @@ LIBC_INLINE constexpr float16 asinhf16(float16 x) {
if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
int rounding = fputil::quick_get_round();
- if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
- return fputil::cast<float16>(xf + 0x1p-24f);
- if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
- return fputil::cast<float16>(xf - 0x1p-24f);
+ if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0) {
+ FPBits result(fputil::cast<float16>(xf + 0x1p-24f));
+ result.set_sign(xbits.sign());
+ return result.get_val();
+ }
+ if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0) {
+ FPBits result(fputil::cast<float16>(xf - 0x1p-24f));
+ result.set_sign(xbits.sign());
+ return result.get_val();
+ }
#endif
return fputil::cast<float16>(xf);
}
diff --git a/libc/test/src/math/smoke/asinhf16_test.cpp b/libc/test/src/math/smoke/asinhf16_test.cpp
index f17300cf980e25..3206320f6278fa 100644
--- a/libc/test/src/math/smoke/asinhf16_test.cpp
+++ b/libc/test/src/math/smoke/asinhf16_test.cpp
@@ -32,3 +32,18 @@ TEST_F(LlvmLibcAsinhf16Test, SpecialNumbers) {
EXPECT_FP_EQ(neg_inf, LIBC_NAMESPACE::asinhf16(neg_inf));
EXPECT_MATH_ERRNO(0);
}
+
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+TEST_F(LlvmLibcAsinhf16Test, TinySignedZeros) {
+ using Bits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+ EXPECT_FP_EQ_ROUNDING_UPWARD(
+ Bits::zero(LIBC_NAMESPACE::Sign::NEG).get_val(),
+ LIBC_NAMESPACE::asinhf16(Bits(uint16_t(0x8001)).get_val()));
+ EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(
+ Bits::zero(LIBC_NAMESPACE::Sign::NEG).get_val(),
+ LIBC_NAMESPACE::asinhf16(Bits(uint16_t(0x8001)).get_val()));
+ EXPECT_FP_EQ_ROUNDING_DOWNWARD(
+ Bits::zero().get_val(),
+ LIBC_NAMESPACE::asinhf16(Bits(uint16_t(1)).get_val()));
+}
+#endif
More information about the libc-commits
mailing list