[libc-commits] [libc] [libc][math] Fix spurious log10p1f16 underflow (PR #194148)

Shikhar Soni via libc-commits libc-commits at lists.llvm.org
Sat Apr 25 07:50:11 PDT 2026


https://github.com/shikharish updated https://github.com/llvm/llvm-project/pull/194148

>From 3ae5474ce17a2ac1aa83cafa1dc2ace2b4cca5d2 Mon Sep 17 00:00:00 2001
From: Shikhar Soni <shikharish05 at gmail.com>
Date: Sat, 25 Apr 2026 19:46:00 +0530
Subject: [PATCH 1/2] [libc][math] Fix spurious log10p1f16 underflow

---
 libc/src/__support/math/CMakeLists.txt       |  1 +
 libc/src/__support/math/log10p1f16.h         | 22 ++++++++++++++++----
 libc/test/src/math/smoke/CMakeLists.txt      |  1 +
 libc/test/src/math/smoke/log10p1f16_test.cpp | 13 ++++++++++++
 4 files changed, 33 insertions(+), 4 deletions(-)

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);
+}

>From fb13969041bff3880455d5f6d2cee9751bc3960a Mon Sep 17 00:00:00 2001
From: Shikhar Soni <shikharish05 at gmail.com>
Date: Sat, 25 Apr 2026 20:19:29 +0530
Subject: [PATCH 2/2] [libc][math] Format log10p1f16 fix

---
 libc/src/__support/math/log10p1f16.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/math/log10p1f16.h b/libc/src/__support/math/log10p1f16.h
index d8965d9b81a04..13f4904e76ade 100644
--- a/libc/src/__support/math/log10p1f16.h
+++ b/libc/src/__support/math/log10p1f16.h
@@ -106,11 +106,10 @@ LIBC_INLINE float16 log10p1f16(float16 x) {
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
       float xf = x;
-      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>();
+      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;



More information about the libc-commits mailing list