[libc-commits] [libc] [libc][math] Fix spurious log10p1f16 underflow (PR #194148)
via libc-commits
libc-commits at lists.llvm.org
Sat Apr 25 07:45:11 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Shikhar Soni (shikharish)
<details>
<summary>Changes</summary>
Fixes a spurious `FE_UNDERFLOW` in `log10p1f16` when a tiny intermediate result rounds to normal `0x1p-14`. Tested with `cmake --build build --target libc.test.src.math.smoke.log10p1f16_test.__unit__ libc.test.src.math.log10p1f16_test.__unit__ -j8`.
---
Full diff: https://github.com/llvm/llvm-project/pull/194148.diff
4 Files Affected:
- (modified) libc/src/__support/math/CMakeLists.txt (+1)
- (modified) libc/src/__support/math/log10p1f16.h (+18-4)
- (modified) libc/test/src/math/smoke/CMakeLists.txt (+1)
- (modified) libc/test/src/math/smoke/log10p1f16_test.cpp (+13)
``````````diff
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 095028c644d37..ad2c331648343 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3009,6 +3009,7 @@ add_header_library(
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.dyadic_float
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
diff --git a/libc/src/__support/math/log10p1f16.h b/libc/src/__support/math/log10p1f16.h
index 54533c994df81..d8965d9b81a04 100644
--- a/libc/src/__support/math/log10p1f16.h
+++ b/libc/src/__support/math/log10p1f16.h
@@ -21,6 +21,7 @@
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/dyadic_float.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/common.h"
@@ -105,10 +106,23 @@ LIBC_INLINE float16 log10p1f16(float16 x) {
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
float xf = x;
- return fputil::cast<float16>(
- xf * fputil::polyeval(xf, 0x1.bcb7b2p-2f, -0x1.bcb4cp-3f,
- 0x1.2875bcp-3f, -0x1.c2946ep-4f,
- 0x1.69da2p-4f));
+ float r = xf * fputil::polyeval(xf, 0x1.bcb7b2p-2f, -0x1.bcb4cp-3f,
+ 0x1.2875bcp-3f, -0x1.c2946ep-4f,
+ 0x1.69da2p-4f);
+ float16 result =
+ fputil::DyadicFloat<32>(r).template as<float16, false>();
+
+ if (LIBC_UNLIKELY(static_cast<float>(result) != r)) {
+ int excepts = FE_INEXACT;
+ FPBits result_bits(result);
+ if (result_bits.is_zero() || result_bits.is_subnormal()) {
+ fputil::set_errno_if_required(ERANGE);
+ excepts |= FE_UNDERFLOW;
+ }
+ fputil::raise_except_if_required(excepts);
+ }
+
+ return result;
}
}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 28b85b1a25bbd..28b39a37defc0 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4481,6 +4481,7 @@ add_fp_unittest(
libc.hdr.fenv_macros
libc.src.math.log10p1f16
libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.fenv_impl
)
add_fp_unittest(
diff --git a/libc/test/src/math/smoke/log10p1f16_test.cpp b/libc/test/src/math/smoke/log10p1f16_test.cpp
index b4afd89546264..c7cf372bde8bb 100644
--- a/libc/test/src/math/smoke/log10p1f16_test.cpp
+++ b/libc/test/src/math/smoke/log10p1f16_test.cpp
@@ -8,6 +8,7 @@
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/cast.h"
#include "src/math/log10p1f16.h"
#include "test/UnitTest/FPMatcher.h"
@@ -46,3 +47,15 @@ TEST_F(LlvmLibcLog10p1f16Test, SpecialNumbers) {
LIBC_NAMESPACE::log10p1f16(LIBC_NAMESPACE::fputil::cast<float16>(-2.0)));
EXPECT_MATH_ERRNO(EDOM);
}
+
+TEST_F(LlvmLibcLog10p1f16Test, NoSpuriousUnderflow) {
+ constexpr uint16_t INPUT = 0x089BU; // x = 0x1.26cp-13
+ constexpr uint16_t EXPECTED = 0x0400U; // y = 0x1p-14
+
+ LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+ EXPECT_FP_EQ(FPBits(EXPECTED).get_val(),
+ LIBC_NAMESPACE::log10p1f16(FPBits(INPUT).get_val()));
+ EXPECT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_UNDERFLOW), 0);
+ EXPECT_MATH_ERRNO(0);
+ LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/194148
More information about the libc-commits
mailing list