[libc-commits] [libc] [llvm] [libc][math][c++23] Add log10p1bf16 math function (PR #235343)

Uppala Prajin via libc-commits libc-commits at lists.llvm.org
Wed Oct 28 04:12:21 PDT 2026


https://github.com/prajin-uppala updated https://github.com/llvm/llvm-project/pull/235343

>From f2d12fefe749a79a04c574c4f018882194402cb2 Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Sat, 24 Oct 2026 20:11:55 +0530
Subject: [PATCH 1/7] feat: add log10p1bf16 implementation and tests

---
 libc/config/baremetal/aarch64/entrypoints.txt |   1 +
 libc/config/baremetal/arm/entrypoints.txt     |   1 +
 libc/config/baremetal/hexagon/entrypoints.txt |   1 +
 libc/config/baremetal/riscv/entrypoints.txt   |   1 +
 libc/config/darwin/aarch64/entrypoints.txt    |   1 +
 libc/config/darwin/x86_64/entrypoints.txt     |   1 +
 libc/config/freebsd/x86_64/entrypoints.txt    |   1 +
 libc/config/gpu/amdgpu/entrypoints.txt        |   1 +
 libc/config/gpu/nvptx/entrypoints.txt         |   1 +
 libc/config/linux/aarch64/entrypoints.txt     |   1 +
 libc/config/linux/arm/entrypoints.txt         |   1 +
 libc/config/linux/riscv/entrypoints.txt       |   1 +
 libc/config/linux/x86_64/entrypoints.txt      |   1 +
 libc/config/windows/entrypoints.txt           |   1 +
 libc/shared/math.h                            |   1 +
 libc/shared/math/log10p1bf16.h                |  23 +++
 libc/src/__support/math/CMakeLists.txt        |  29 ++++
 libc/src/__support/math/log10p1bf16.h         | 139 ++++++++++++++++++
 libc/src/math/CMakeLists.txt                  |   1 +
 libc/src/math/generic/CMakeLists.txt          |  11 ++
 libc/src/math/generic/log10p1bf16.cpp         |  18 +++
 libc/src/math/log10p1bf16.h                   |  21 +++
 libc/test/shared/CMakeLists.txt               |   1 +
 libc/test/shared/shared_math_test.cpp         |   2 +
 libc/test/src/math/CMakeLists.txt             |  13 ++
 libc/test/src/math/log10p1bf16_test.cpp       |  41 ++++++
 libc/test/src/math/smoke/CMakeLists.txt       |  14 ++
 libc/test/src/math/smoke/log10p1bf16_test.cpp |  85 +++++++++++
 .../llvm-project-overlay/libc/BUILD.bazel     |  26 ++++
 .../libc/test/src/math/BUILD.bazel            |   5 +
 .../libc/test/src/math/smoke/BUILD.bazel      |   5 +
 31 files changed, 449 insertions(+)
 create mode 100644 libc/shared/math/log10p1bf16.h
 create mode 100644 libc/src/__support/math/log10p1bf16.h
 create mode 100644 libc/src/math/generic/log10p1bf16.cpp
 create mode 100644 libc/src/math/log10p1bf16.h
 create mode 100644 libc/test/src/math/log10p1bf16_test.cpp
 create mode 100644 libc/test/src/math/smoke/log10p1bf16_test.cpp

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 0202bc7a2dc56b..632a6a2f13bf64 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -856,6 +856,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index b7322502d570d4..0a964d3b05474b 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -867,6 +867,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/baremetal/hexagon/entrypoints.txt b/libc/config/baremetal/hexagon/entrypoints.txt
index 61f869457b3282..3fd82f0cee4e54 100644
--- a/libc/config/baremetal/hexagon/entrypoints.txt
+++ b/libc/config/baremetal/hexagon/entrypoints.txt
@@ -856,6 +856,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 7e68a3c374249d..210acad836d904 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -859,6 +859,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index c0ce5870c862ec..44d83686afcb6e 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -678,6 +678,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index e3fc845d2ed3af..6b0f337f22828d 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -313,6 +313,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.cbrtbf16
   libc.src.math.logbbf16
diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index 42d52b3ebc6c2c..687cac9d4d0571 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -610,6 +610,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index ffbcc4b1672403..7cf18751eb98f3 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -731,6 +731,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index ff31536073543e..f918678a163290 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -747,6 +747,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 7a94716e74032c..849a8760a088d9 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1090,6 +1090,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 31561b52bdca51..e503f2728baba0 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -695,6 +695,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 8c31aaad07015f..8cda1133b17b79 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1168,6 +1168,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 02aef4a1297186..0cdd971ac809ba 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1190,6 +1190,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index e0477cbf5a6f00..e9260c15f02f7c 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -406,6 +406,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10p1bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/shared/math.h b/libc/shared/math.h
index eb72bebcb53bfa..db7105164aa2b0 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -335,6 +335,7 @@
 #include "math/log10.h"
 #include "math/log10f.h"
 #include "math/log10f16.h"
+#include "math/log10p1bf16.h"
 #include "math/log10p1f16.h"
 #include "math/log1p.h"
 #include "math/log1pf.h"
diff --git a/libc/shared/math/log10p1bf16.h b/libc/shared/math/log10p1bf16.h
new file mode 100644
index 00000000000000..60c869fc1b991f
--- /dev/null
+++ b/libc/shared/math/log10p1bf16.h
@@ -0,0 +1,23 @@
+//===-- Shared log10p1bf16 function -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SHARED_MATH_LOG10P1BF16_H
+#define LLVM_LIBC_SHARED_MATH_LOG10P1BF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/log10p1bf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::log10p1bf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_LOG10P1BF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 400e5e2d6aeaa8..e8b7bbc2315cf6 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3125,6 +3125,17 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  check.exp_exceptions
+  HDRS
+    check/exp_exceptions.h
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.common
+    libc.src.__support.macros.config
+)
+
 add_header_library(
   expf_double_eval
   HDRS
@@ -5515,6 +5526,24 @@ add_header_library(
     libc.src.__support.uint128
 )
 
+add_header_library(
+  log10p1bf16
+  HDRS
+    log10p1bf16.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.macros.attributes
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   log_bf16
   HDRS
diff --git a/libc/src/__support/math/log10p1bf16.h b/libc/src/__support/math/log10p1bf16.h
new file mode 100644
index 00000000000000..98b79cd91ccf6d
--- /dev/null
+++ b/libc/src/__support/math/log10p1bf16.h
@@ -0,0 +1,139 @@
+//===-- Implementation header for log10p1bf16 -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_LOG10P1BF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOG10P1BF16_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+namespace log10p1bf16_internal {
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 31 do print(round(log10(1 + i * 2^-5), SG, RN));
+LIBC_INLINE_VAR constexpr float LOG10F_F[32] = {
+    0x0p+0f,        0x1.b5e908p-7f, 0x1.af5f92p-6f, 0x1.3ed11ap-5f,
+    0x1.a30a9ep-5f, 0x1.02428cp-4f, 0x1.31b306p-4f, 0x1.5fe804p-4f,
+    0x1.8cf184p-4f, 0x1.b8de4ep-4f, 0x1.e3bc1ap-4f, 0x1.06cbd6p-3f,
+    0x1.1b3e72p-3f, 0x1.2f3b6ap-3f, 0x1.42c7e8p-3f, 0x1.55e8c6p-3f,
+    0x1.68a288p-3f, 0x1.7af974p-3f, 0x1.8cf184p-3f, 0x1.9e8e7cp-3f,
+    0x1.afd3e4p-3f, 0x1.c0c514p-3f, 0x1.d1653p-3f,  0x1.e1b734p-3f,
+    0x1.f1bdeep-3f, 0x1.00be06p-2f, 0x1.087a08p-2f, 0x1.101432p-2f,
+    0x1.178da6p-2f, 0x1.1ee778p-2f, 0x1.2622bp-2f,  0x1.2d404cp-2f,
+};
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 31 do print(round(1 / (1 + i * 2^-5), SG, RN));
+LIBC_INLINE_VAR constexpr float ONE_OVER_F_F[32] = {
+    0x1p+0f,        0x1.f07c2p-1f,  0x1.e1e1e2p-1f, 0x1.d41d42p-1f,
+    0x1.c71c72p-1f, 0x1.bacf92p-1f, 0x1.af286cp-1f, 0x1.a41a42p-1f,
+    0x1.99999ap-1f, 0x1.8f9c18p-1f, 0x1.861862p-1f, 0x1.7d05f4p-1f,
+    0x1.745d18p-1f, 0x1.6c16c2p-1f, 0x1.642c86p-1f, 0x1.5c9882p-1f,
+    0x1.555556p-1f, 0x1.4e5e0ap-1f, 0x1.47ae14p-1f, 0x1.414142p-1f,
+    0x1.3b13b2p-1f, 0x1.3521dp-1f,  0x1.2f684cp-1f, 0x1.29e412p-1f,
+    0x1.24924ap-1f, 0x1.1f7048p-1f, 0x1.1a7b96p-1f, 0x1.15b1e6p-1f,
+    0x1.111112p-1f, 0x1.0c9714p-1f, 0x1.08421p-1f,  0x1.041042p-1f,
+};
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > round(log10(2), SG, RN);
+LIBC_INLINE_VAR constexpr float LOG10F_2 = 0x1.344136p-2f;
+
+} // namespace log10p1bf16_internal
+
+LIBC_INLINE bfloat16 log10p1bf16(bfloat16 x) {
+  using namespace log10p1bf16_internal;
+  using FPBits = fputil::FPBits<bfloat16>;
+  FPBits x_bits(x);
+  uint16_t x_u = x_bits.uintval();
+  uint16_t x_abs = x_u & 0x7fffU;
+
+  // Handle special values and use the small-input polynomial for |x| <= 0.125.
+  if (LIBC_UNLIKELY(x_abs <= 0x3e00U || x_abs >= 0x7f80U)) {
+    // log10p1(NaN) = NaN
+    if (x_bits.is_nan()) {
+      if (x_bits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+      return x;
+    }
+
+    // log10p1(+/-0) = +/-0
+    if (x_abs == 0U)
+      return x;
+
+    // log10p1(+inf) = +inf
+    if (x_u == 0x7f80U)
+      return x;
+
+    // log10p1(-inf) = NaN
+    if (x_abs >= 0x7f80U) {
+      fputil::set_errno_if_required(EDOM);
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+
+    float xf = static_cast<float>(x);
+    return fputil::cast<bfloat16>(
+        xf * fputil::polyeval(xf, 0x1.bcb7b2p-2f, -0x1.bcb4cp-3f,
+                              0x1.2875bcp-3f, -0x1.c2946ep-4f, 0x1.69da2p-4f));
+  }
+
+  if (LIBC_UNLIKELY(x_u == 0xbf80U)) {
+    fputil::raise_except_if_required(FE_DIVBYZERO);
+    return FPBits::inf(Sign::NEG).get_val();
+  }
+
+  if (LIBC_UNLIKELY(x_u > 0xbf80U)) {
+    fputil::set_errno_if_required(EDOM);
+    fputil::raise_except_if_required(FE_INVALID);
+    return FPBits::quiet_nan().get_val();
+  }
+
+  if (LIBC_UNLIKELY(x_u == 0x4110U))
+    return FPBits(static_cast<uint16_t>(0x3f80U)).get_val();
+  if (LIBC_UNLIKELY(x_u == 0x42c6U))
+    return FPBits(static_cast<uint16_t>(0x4000U)).get_val();
+
+  float y = 1.0f + static_cast<float>(x);
+  using FPBitsFloat = fputil::FPBits<float>;
+  FPBitsFloat y_bits(y);
+
+  int e = y_bits.get_exponent();
+  y_bits.set_biased_exponent(FPBitsFloat::EXP_BIAS);
+  float mant_f = y_bits.get_val();
+
+  int f = y_bits.get_mantissa() >> (FPBitsFloat::FRACTION_LEN - 5);
+  float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f);
+  float log10p1_d_over_f =
+      v * fputil::polyeval(v, 0x1.bcb7bp-2f, -0x1.bce168p-3f, 0x1.28acb8p-3f);
+  float log10_1_mant = LOG10F_F[f] + log10p1_d_over_f;
+  return fputil::cast<bfloat16>(
+      fputil::multiply_add(static_cast<float>(e), LOG10F_2, log10_1_mant));
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOG10P1BF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 4f1dd95a6993da..3a1ab15e19a84b 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -403,6 +403,7 @@ add_math_entrypoint_object(log10)
 add_math_entrypoint_object(log10f)
 add_math_entrypoint_object(log10f16)
 add_math_entrypoint_object(log10p1f16)
+add_math_entrypoint_object(log10p1bf16)
 
 add_math_entrypoint_object(log1p)
 add_math_entrypoint_object(log1pf)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index b4b2465b384b10..9317c208442661 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1788,6 +1788,17 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  log10p1bf16
+  SRCS
+    log10p1bf16.cpp
+  HDRS
+    ../log10p1bf16.h
+  DEPENDS
+    libc.src.__support.math.log10p1bf16
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   log10p1f16
   SRCS
diff --git a/libc/src/math/generic/log10p1bf16.cpp b/libc/src/math/generic/log10p1bf16.cpp
new file mode 100644
index 00000000000000..64a327b9347ead
--- /dev/null
+++ b/libc/src/math/generic/log10p1bf16.cpp
@@ -0,0 +1,18 @@
+//===-- BFloat16 log10(1 + x) function ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/log10p1bf16.h"
+#include "src/__support/math/log10p1bf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, log10p1bf16, (bfloat16 x)) {
+  return math::log10p1bf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/log10p1bf16.h b/libc/src/math/log10p1bf16.h
new file mode 100644
index 00000000000000..cc4e952df08d91
--- /dev/null
+++ b/libc/src/math/log10p1bf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for log10p1bf16 -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_LOG10P1BF16_H
+#define LLVM_LIBC_SRC_MATH_LOG10P1BF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 log10p1bf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_LOG10P1BF16_H
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index eff5bea2970fd1..70875774a8537d 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -331,6 +331,7 @@ else()
       libc.src.__support.math.log
       libc.src.__support.math.log10
       libc.src.__support.math.log10f16
+      libc.src.__support.math.log10p1bf16
       libc.src.__support.math.log10p1f16
       libc.src.__support.math.log10f
       libc.src.__support.math.log1p
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 68b562c48931aa..5e68ddea5214c1 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -819,6 +819,8 @@ TEST(LlvmLibcSharedMathTest, AllBFloat16) {
   EXPECT_FP_EQ(bfloat16(1.0), LIBC_NAMESPACE::shared::exp2bf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(1.0), LIBC_NAMESPACE::shared::expbf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::log_bf16(bfloat16(1.0)));
+  EXPECT_FP_EQ(bfloat16(1.0),
+               LIBC_NAMESPACE::shared::log10p1bf16(bfloat16(9.0)));
 
   bfloat16 neg_min_denormal = FPBits::min_subnormal(Sign::NEG).get_val();
   EXPECT_FP_EQ(neg_min_denormal,
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index d88afe6370e27b..ce3526f0d33329 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2393,6 +2393,19 @@ add_fp_unittest(
     libc.src.math.logf16
 )
 
+add_fp_unittest(
+  log10p1bf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    log10p1bf16_test.cpp
+  DEPENDS
+    libc.src.math.log10p1bf16
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   log_bf16_test
   NEED_MPFR
diff --git a/libc/test/src/math/log10p1bf16_test.cpp b/libc/test/src/math/log10p1bf16_test.cpp
new file mode 100644
index 00000000000000..4208e2348103c8
--- /dev/null
+++ b/libc/test/src/math/log10p1bf16_test.cpp
@@ -0,0 +1,41 @@
+//===-- Full range tests for BFloat16 log10(1 + x) function ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/log10p1bf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcLog10p1bf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcLog10p1bf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10p1, x,
+                                   LIBC_NAMESPACE::log10p1bf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcLog10p1bf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10p1, x,
+                                   LIBC_NAMESPACE::log10p1bf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index d68eb7786e3b58..dc0fbb6a949f14 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4500,6 +4500,20 @@ add_fp_unittest(
     libc.src.__support.FPUtil.cast
 )
 
+add_fp_unittest(
+  log10p1bf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    log10p1bf16_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.math.log10p1bf16
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   log_bf16_test
   SUITE
diff --git a/libc/test/src/math/smoke/log10p1bf16_test.cpp b/libc/test/src/math/smoke/log10p1bf16_test.cpp
new file mode 100644
index 00000000000000..8d635f39f9dfa4
--- /dev/null
+++ b/libc/test/src/math/smoke/log10p1bf16_test.cpp
@@ -0,0 +1,85 @@
+//===-- Unittests for BFloat16 log10(1 + x) function ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/macros/properties/types.h"
+#include "src/math/log10p1bf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
+
+class LlvmLibcLog10p1bf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(bfloat16)
+
+public:
+  void test_special_numbers() {
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::log10p1bf16(aNaN), 0);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::log10p1bf16(sNaN), FE_INVALID);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        inf, LIBC_NAMESPACE::log10p1bf16(inf), 0);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::log10p1bf16(neg_inf), FE_INVALID);
+    EXPECT_MATH_ERRNO(EDOM);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        zero, LIBC_NAMESPACE::log10p1bf16(zero), 0);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        neg_zero, LIBC_NAMESPACE::log10p1bf16(neg_zero), 0);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        neg_inf, LIBC_NAMESPACE::log10p1bf16(bfloat16(-1.0)), FE_DIVBYZERO);
+    EXPECT_MATH_ERRNO(0);
+
+    const bfloat16 neg_two = FPBits(static_cast<uint16_t>(0xc000U)).get_val();
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::log10p1bf16(neg_two), FE_INVALID);
+    EXPECT_MATH_ERRNO(EDOM);
+
+    bfloat16 neg_one_adjacent =
+        FPBits(static_cast<uint16_t>(0xbf81U)).get_val();
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::log10p1bf16(neg_one_adjacent), FE_INVALID);
+    EXPECT_MATH_ERRNO(EDOM);
+
+    bfloat16 neg_inf_adjacent =
+        FPBits(static_cast<uint16_t>(0xff7fU)).get_val();
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::log10p1bf16(neg_inf_adjacent), FE_INVALID);
+    EXPECT_MATH_ERRNO(EDOM);
+
+    const bfloat16 one = bfloat16(1.0);
+    const bfloat16 nine = bfloat16(9.0);
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        one, LIBC_NAMESPACE::log10p1bf16(nine), 0);
+    EXPECT_MATH_ERRNO(0);
+
+    const bfloat16 two = bfloat16(2.0);
+    const bfloat16 ninety_nine = bfloat16(99.0);
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        two, LIBC_NAMESPACE::log10p1bf16(ninety_nine), 0);
+    EXPECT_MATH_ERRNO(0);
+  }
+};
+
+TEST_F(LlvmLibcLog10p1bf16Test, SpecialNumbers) { test_special_numbers(); }
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 751e08c7323cfb..b66995b86e7d99 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -10475,6 +10475,25 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_log10p1bf16",
+    hdrs = ["src/__support/math/log10p1bf16.h"],
+    deps = [
+        ":__support_common",
+        ":__support_fputil_bfloat16",
+        ":__support_fputil_cast",
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_polyeval",
+        ":__support_macros_attributes",
+        ":__support_macros_config",
+        ":__support_macros_optimization",
+        ":hdr_errno_macros",
+        ":hdr_fenv_macros",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_log10p1f16",
     hdrs = ["src/__support/math/log10p1f16.h"],
@@ -14561,6 +14580,13 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "log10p1bf16",
+    additional_deps = [
+        ":__support_math_log10p1bf16",
+    ],
+)
+
 libc_math_function(
     name = "log10p1f16",
     additional_deps = [
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
index c39dc612851536..742efe13a98871 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
@@ -1115,6 +1115,11 @@ math_mpfr_test(name = "log2p1f16")
 
 math_mpfr_test(name = "log10f16")
 
+math_mpfr_test(
+    name = "log10p1bf16",
+    deps = ["//libc:__support_fputil_bfloat16"],
+)
+
 math_mpfr_test(name = "log10p1f16")
 
 math_mpfr_test(name = "lgammaf16")
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
index dad78bc78a3545..01f25d838a8b25 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/smoke/BUILD.bazel
@@ -2405,6 +2405,11 @@ math_test(name = "log2f16")
 
 math_test(name = "log2p1f16")
 
+math_test(
+    name = "log10p1bf16",
+    deps = ["//libc:__support_fputil_bfloat16"],
+)
+
 math_test(name = "log10p1f16")
 
 math_test(name = "logf16")

>From a83c202b35185fff2a666fd7274abb814a1cc331 Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Sun, 25 Oct 2026 00:05:08 +0530
Subject: [PATCH 2/7] chore: update log10p1bf16 comments and build files

---
 libc/src/__support/math/log10p1bf16.h         | 22 ++++++++++++++++---
 libc/src/math/CMakeLists.txt                  |  2 +-
 .../llvm-project-overlay/libc/BUILD.bazel     |  1 -
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/math/log10p1bf16.h b/libc/src/__support/math/log10p1bf16.h
index 98b79cd91ccf6d..b1de5fd6e10d3a 100644
--- a/libc/src/__support/math/log10p1bf16.h
+++ b/libc/src/__support/math/log10p1bf16.h
@@ -26,9 +26,12 @@ namespace math {
 
 namespace log10p1bf16_internal {
 
+// The top five mantissa bits select F = 1 + f * 2^-5, where f is in [0, 31].
+// BFloat16 has seven explicit mantissa bits, so the table uses five of those
+// bits for lookup and the remaining two bits to refine the residual.
 // Generated by Sollya with the following commands:
 //   > display = hexadecimal;
-//   > for i from 0 to 31 do print(round(log10(1 + i * 2^-5), SG, RN));
+//   > for f from 0 to 31 do print(round(log10(1 + f * 2^-5), SG, RN));
 LIBC_INLINE_VAR constexpr float LOG10F_F[32] = {
     0x0p+0f,        0x1.b5e908p-7f, 0x1.af5f92p-6f, 0x1.3ed11ap-5f,
     0x1.a30a9ep-5f, 0x1.02428cp-4f, 0x1.31b306p-4f, 0x1.5fe804p-4f,
@@ -40,9 +43,11 @@ LIBC_INLINE_VAR constexpr float LOG10F_F[32] = {
     0x1.178da6p-2f, 0x1.1ee778p-2f, 0x1.2622bp-2f,  0x1.2d404cp-2f,
 };
 
+// ONE_OVER_F_F[f] stores the reciprocal of the same representative F. It is
+// used to form the residual v = M * (1 / F) - 1.
 // Generated by Sollya with the following commands:
 //   > display = hexadecimal;
-//   > for i from 0 to 31 do print(round(1 / (1 + i * 2^-5), SG, RN));
+//   > for f from 0 to 31 do print(round(1 / (1 + f * 2^-5), SG, RN));
 LIBC_INLINE_VAR constexpr float ONE_OVER_F_F[32] = {
     0x1p+0f,        0x1.f07c2p-1f,  0x1.e1e1e2p-1f, 0x1.d41d42p-1f,
     0x1.c71c72p-1f, 0x1.bacf92p-1f, 0x1.af286cp-1f, 0x1.a41a42p-1f,
@@ -68,7 +73,8 @@ LIBC_INLINE bfloat16 log10p1bf16(bfloat16 x) {
   uint16_t x_u = x_bits.uintval();
   uint16_t x_abs = x_u & 0x7fffU;
 
-  // Handle special values and use the small-input polynomial for |x| <= 0.125.
+  // Handle special values; for |x| <= 0.125 (bits <= 0x3e00), use a direct
+  // polynomial to avoid cancellation in the range-reduction residual.
   if (LIBC_UNLIKELY(x_abs <= 0x3e00U || x_abs >= 0x7f80U)) {
     // log10p1(NaN) = NaN
     if (x_bits.is_nan()) {
@@ -94,12 +100,15 @@ LIBC_INLINE bfloat16 log10p1bf16(bfloat16 x) {
       return FPBits::quiet_nan().get_val();
     }
 
+    // This degree-4 polynomial is shared with log10p1f16 and approximates
+    // log10(1 + x) / x; multiplying by x gives log10(1 + x).
     float xf = static_cast<float>(x);
     return fputil::cast<bfloat16>(
         xf * fputil::polyeval(xf, 0x1.bcb7b2p-2f, -0x1.bcb4cp-3f,
                               0x1.2875bcp-3f, -0x1.c2946ep-4f, 0x1.69da2p-4f));
   }
 
+  // x = -1 has bits 0xbf80 and is the domain boundary log10(1 + x) = -inf.
   if (LIBC_UNLIKELY(x_u == 0xbf80U)) {
     fputil::raise_except_if_required(FE_DIVBYZERO);
     return FPBits::inf(Sign::NEG).get_val();
@@ -111,11 +120,18 @@ LIBC_INLINE bfloat16 log10p1bf16(bfloat16 x) {
     return FPBits::quiet_nan().get_val();
   }
 
+  // log10(1 + 9) = 1 and log10(1 + 99) = 2 exactly; return them directly.
   if (LIBC_UNLIKELY(x_u == 0x4110U))
     return FPBits(static_cast<uint16_t>(0x3f80U)).get_val();
   if (LIBC_UNLIKELY(x_u == 0x42c6U))
     return FPBits(static_cast<uint16_t>(0x4000U)).get_val();
 
+  // For y = 1 + x, write y = 2^e * M, where M is in [1, 2), and select
+  // F = 1 + f * 2^-5 from the lookup tables. Then:
+  //   log10(y) = e * log10(2) + log10(F) + log10(M / F).
+  // The residual v = M / F - 1 is computed using the reciprocal table. This
+  // degree-2 polynomial is shared with log10p1f16 and approximates
+  // log10(1 + v) / v, giving the correction log10(M / F).
   float y = 1.0f + static_cast<float>(x);
   using FPBitsFloat = fputil::FPBits<float>;
   FPBitsFloat y_bits(y);
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 3a1ab15e19a84b..46e98ba38e4cdc 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -402,8 +402,8 @@ add_math_entrypoint_object(ldexpbf16)
 add_math_entrypoint_object(log10)
 add_math_entrypoint_object(log10f)
 add_math_entrypoint_object(log10f16)
-add_math_entrypoint_object(log10p1f16)
 add_math_entrypoint_object(log10p1bf16)
+add_math_entrypoint_object(log10p1f16)
 
 add_math_entrypoint_object(log1p)
 add_math_entrypoint_object(log1pf)
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index b66995b86e7d99..c7a2fbd4573c9a 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -10479,7 +10479,6 @@ libc_support_library(
     name = "__support_math_log10p1bf16",
     hdrs = ["src/__support/math/log10p1bf16.h"],
     deps = [
-        ":__support_common",
         ":__support_fputil_bfloat16",
         ":__support_fputil_cast",
         ":__support_fputil_fenv_impl",

>From 7e9e60340c51182cf8bf2b381594ea2df56f0557 Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Sun, 25 Oct 2026 19:26:45 +0530
Subject: [PATCH 3/7] fix: use correct suite for log10p1bf16 test

---
 libc/test/src/math/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index ce3526f0d33329..6937dffaf0100a 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2397,7 +2397,7 @@ add_fp_unittest(
   log10p1bf16_test
   NEED_MPFR
   SUITE
-    libc-math-unittests
+    libc-math-tests
   SRCS
     log10p1bf16_test.cpp
   DEPENDS

>From c2d2ae9be8fc8df3fc8f98d2e1ef22749ad2a149 Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Tue, 27 Oct 2026 00:41:37 +0530
Subject: [PATCH 4/7] [libc][math] Remove unrelated check.exp_exceptions target

---
 libc/src/__support/math/CMakeLists.txt | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index e8b7bbc2315cf6..b61112fe050d34 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3125,17 +3125,6 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
-add_header_library(
-  check.exp_exceptions
-  HDRS
-    check/exp_exceptions.h
-  DEPENDS
-    libc.hdr.fenv_macros
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.common
-    libc.src.__support.macros.config
-)
-
 add_header_library(
   expf_double_eval
   HDRS

>From aed0bba5b0df5ea3a689f41c8d22802d45384609 Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Tue, 27 Oct 2026 01:25:00 +0530
Subject: [PATCH 5/7] [libc][math] Fix spurious underflow in log10p1bf16

---
 libc/src/__support/math/log10p1bf16.h         | 6 ++++++
 libc/test/src/math/smoke/log10p1bf16_test.cpp | 9 +++++++++
 2 files changed, 15 insertions(+)

diff --git a/libc/src/__support/math/log10p1bf16.h b/libc/src/__support/math/log10p1bf16.h
index b1de5fd6e10d3a..c8cbd3e28eff3c 100644
--- a/libc/src/__support/math/log10p1bf16.h
+++ b/libc/src/__support/math/log10p1bf16.h
@@ -103,6 +103,12 @@ LIBC_INLINE bfloat16 log10p1bf16(bfloat16 x) {
     // This degree-4 polynomial is shared with log10p1f16 and approximates
     // log10(1 + x) / x; multiplying by x gives log10(1 + x).
     float xf = static_cast<float>(x);
+
+    // For tiny |x|, log10(1 + x) is approximately x / ln(10).
+    // Avoid subnormal intermediate products in the polynomial evaluation.
+    if (x_abs < 0x0d80U)
+      return fputil::cast<bfloat16>(xf * 0x1.bcb7b2p-2f);
+
     return fputil::cast<bfloat16>(
         xf * fputil::polyeval(xf, 0x1.bcb7b2p-2f, -0x1.bcb4cp-3f,
                               0x1.2875bcp-3f, -0x1.c2946ep-4f, 0x1.69da2p-4f));
diff --git a/libc/test/src/math/smoke/log10p1bf16_test.cpp b/libc/test/src/math/smoke/log10p1bf16_test.cpp
index 8d635f39f9dfa4..c1dc695dfa9cb8 100644
--- a/libc/test/src/math/smoke/log10p1bf16_test.cpp
+++ b/libc/test/src/math/smoke/log10p1bf16_test.cpp
@@ -79,6 +79,15 @@ class LlvmLibcLog10p1bf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
         two, LIBC_NAMESPACE::log10p1bf16(ninety_nine), 0);
     EXPECT_MATH_ERRNO(0);
+
+    const bfloat16 tiny_input =
+        FPBits(static_cast<uint16_t>(0x0114U)).get_val();
+    const bfloat16 expected_tiny_result =
+        FPBits(static_cast<uint16_t>(0x0081U)).get_val();
+
+    EXPECT_FP_EQ_WITH_EXCEPTION(expected_tiny_result,
+                                LIBC_NAMESPACE::log10p1bf16(tiny_input),
+                                FE_INEXACT);
   }
 };
 

>From e9e4f1ee9516492b94cc6b36c72f9b1458467b7b Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Wed, 28 Oct 2026 16:17:36 +0530
Subject: [PATCH 6/7] chore: update log10p1bf16 file headers

---
 libc/shared/math/log10p1bf16.h                |  6 +++++-
 libc/src/__support/math/log10p1bf16.h         | 11 +++++++++--
 libc/src/math/generic/log10p1bf16.cpp         |  6 +++++-
 libc/src/math/log10p1bf16.h                   |  6 +++++-
 libc/test/src/math/log10p1bf16_test.cpp       |  6 +++++-
 libc/test/src/math/smoke/log10p1bf16_test.cpp |  6 +++++-
 6 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/libc/shared/math/log10p1bf16.h b/libc/shared/math/log10p1bf16.h
index 60c869fc1b991f..2563c24cd90917 100644
--- a/libc/shared/math/log10p1bf16.h
+++ b/libc/shared/math/log10p1bf16.h
@@ -1,10 +1,14 @@
-//===-- Shared log10p1bf16 function -----------------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+/// \file
+/// Shared wrapper for the log10p1bf16 function.
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_LIBC_SHARED_MATH_LOG10P1BF16_H
 #define LLVM_LIBC_SHARED_MATH_LOG10P1BF16_H
diff --git a/libc/src/__support/math/log10p1bf16.h b/libc/src/__support/math/log10p1bf16.h
index c8cbd3e28eff3c..3405371b0d1089 100644
--- a/libc/src/__support/math/log10p1bf16.h
+++ b/libc/src/__support/math/log10p1bf16.h
@@ -1,10 +1,14 @@
-//===-- Implementation header for log10p1bf16 -------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+/// \file
+/// Implementation of the log10p1bf16 function.
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_LOG10P1BF16_H
 #define LLVM_LIBC_SRC___SUPPORT_MATH_LOG10P1BF16_H
@@ -25,6 +29,9 @@ namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
 namespace log10p1bf16_internal {
+// TODO: Reuse the lookup tables from expxf16_utils.h when they can be
+// shared with the bfloat16 implementation. See
+// https://github.com/llvm/llvm-project/pull/184283.
 
 // The top five mantissa bits select F = 1 + f * 2^-5, where f is in [0, 31].
 // BFloat16 has seven explicit mantissa bits, so the table uses five of those
@@ -94,7 +101,7 @@ LIBC_INLINE bfloat16 log10p1bf16(bfloat16 x) {
       return x;
 
     // log10p1(-inf) = NaN
-    if (x_abs >= 0x7f80U) {
+    if (x_abs == 0xff80U) {
       fputil::set_errno_if_required(EDOM);
       fputil::raise_except_if_required(FE_INVALID);
       return FPBits::quiet_nan().get_val();
diff --git a/libc/src/math/generic/log10p1bf16.cpp b/libc/src/math/generic/log10p1bf16.cpp
index 64a327b9347ead..c8ab4e325eadd2 100644
--- a/libc/src/math/generic/log10p1bf16.cpp
+++ b/libc/src/math/generic/log10p1bf16.cpp
@@ -1,10 +1,14 @@
-//===-- BFloat16 log10(1 + x) function ------------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+/// \file
+/// Generic implementation of the log10p1bf16 function.
+//
+//===----------------------------------------------------------------------===//
 
 #include "src/math/log10p1bf16.h"
 #include "src/__support/math/log10p1bf16.h"
diff --git a/libc/src/math/log10p1bf16.h b/libc/src/math/log10p1bf16.h
index cc4e952df08d91..9e7f993e790f55 100644
--- a/libc/src/math/log10p1bf16.h
+++ b/libc/src/math/log10p1bf16.h
@@ -1,10 +1,14 @@
-//===-- Implementation header for log10p1bf16 -------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+/// \file
+/// Declaration of the log10p1bf16 function.
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_LIBC_SRC_MATH_LOG10P1BF16_H
 #define LLVM_LIBC_SRC_MATH_LOG10P1BF16_H
diff --git a/libc/test/src/math/log10p1bf16_test.cpp b/libc/test/src/math/log10p1bf16_test.cpp
index 4208e2348103c8..680b1ee9c65013 100644
--- a/libc/test/src/math/log10p1bf16_test.cpp
+++ b/libc/test/src/math/log10p1bf16_test.cpp
@@ -1,10 +1,14 @@
-//===-- Full range tests for BFloat16 log10(1 + x) function ---------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+/// \file
+/// Full-range tests for the log10p1bf16 function.
+//
+//===----------------------------------------------------------------------===//
 
 #include "src/__support/FPUtil/bfloat16.h"
 #include "src/math/log10p1bf16.h"
diff --git a/libc/test/src/math/smoke/log10p1bf16_test.cpp b/libc/test/src/math/smoke/log10p1bf16_test.cpp
index c1dc695dfa9cb8..7f8a80365e502c 100644
--- a/libc/test/src/math/smoke/log10p1bf16_test.cpp
+++ b/libc/test/src/math/smoke/log10p1bf16_test.cpp
@@ -1,10 +1,14 @@
-//===-- Unittests for BFloat16 log10(1 + x) function ----------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+/// \file
+/// Smoke tests for the log10p1bf16 function.
+//
+//===----------------------------------------------------------------------===//
 
 #include "hdr/errno_macros.h"
 #include "hdr/fenv_macros.h"

>From 8a175a19fc541bd07a2fb625f9bae7f77ba1f560 Mon Sep 17 00:00:00 2001
From: prajin-uppala <cs24btech11064 at iith.ac.in>
Date: Wed, 28 Oct 2026 16:29:37 +0530
Subject: [PATCH 7/7] chore: update log10p1bf16 header documentation

---
 libc/docs/headers/math/index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/docs/headers/math/index.md b/libc/docs/headers/math/index.md
index 30aba90c60a9bc..f15c6f092f8bac 100644
--- a/libc/docs/headers/math/index.md
+++ b/libc/docs/headers/math/index.md
@@ -198,7 +198,7 @@ log
 | lgamma    |                   |                  |                         | {{ check }}           |                         |                         | 7.12.8.3               | F.10.5.3                   |
 | log       | {{ check }}       | {{ check }}      |                         | {{ check }}           |                         | {{ check }} ?           | 7.12.6.11              | F.10.3.11                  |
 | log10     | {{ check }}       | {{ check }}      |                         | {{ check }}           |                         |                         | 7.12.6.12              | F.10.3.12                  |
-| log10p1   |                   |                  |                         | {{ check }}           |                         |                         | 7.12.6.13              | F.10.3.13                  |
+| log10p1   |                   |                  |                         | {{ check }}           |                         | {{ check }}             | 7.12.6.13              | F.10.3.13                  |
 | log1p     | {{ check }}       | {{ check }}      |                         |                       |                         |                         | 7.12.6.14              | F.10.3.14                  |
 | log2      | {{ check }}       | {{ check }}      |                         | {{ check }}           |                         |                         | 7.12.6.15              | F.10.3.15                  |
 | log2p1    |                   |                  |                         | {{ check }}           |                         |                         | 7.12.6.16              | F.10.3.16                  |



More information about the libc-commits mailing list