[libc-commits] [libc] [libc][math][c++23] Add log10bf16 math function (PR #177269)

Krishna Pandey via libc-commits libc-commits at lists.llvm.org
Sat Feb 21 10:34:38 PST 2026


https://github.com/krishna2803 updated https://github.com/llvm/llvm-project/pull/177269

>From edbf97d3e7cb8b513531cd542ca4181aa3633e87 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 22 Jan 2026 04:31:16 +0530
Subject: [PATCH 1/7] feat: implement log10bf16 higher math function

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/math/CMakeLists.txt         |   1 +
 libc/src/math/generic/CMakeLists.txt |  17 ++++
 libc/src/math/generic/log10bf16.cpp  | 146 +++++++++++++++++++++++++++
 libc/src/math/log10bf16.h            |  21 ++++
 4 files changed, 185 insertions(+)
 create mode 100644 libc/src/math/generic/log10bf16.cpp
 create mode 100644 libc/src/math/log10bf16.h

diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index e37e22fdb58e6..30b7afbf4e53e 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -381,6 +381,7 @@ add_math_entrypoint_object(ldexpbf16)
 add_math_entrypoint_object(log10)
 add_math_entrypoint_object(log10f)
 add_math_entrypoint_object(log10f16)
+add_math_entrypoint_object(log10bf16)
 
 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 6e58434415ead..9d9e6f256872b 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1997,6 +1997,23 @@ add_entrypoint_object(
     libc.src.__support.math.expxf16_utils
 )
 
+add_entrypoint_object(
+  log10bf16
+  SRCS
+    log10bf16.cpp
+  HDRS
+    ../log10bf16.h
+  DEPENDS
+    libc.src.__support.common
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.except_value_utils
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_entrypoint_object(
   log1p
   SRCS
diff --git a/libc/src/math/generic/log10bf16.cpp b/libc/src/math/generic/log10bf16.cpp
new file mode 100644
index 0000000000000..4bae8e66cc80f
--- /dev/null
+++ b/libc/src/math/generic/log10bf16.cpp
@@ -0,0 +1,146 @@
+//===-- BFloat16 log10(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/log10bf16.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/cpu_features.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > round(log10(2), SG, RN);
+static constexpr float LOG10F_2 = 0x1.344136p-2f;
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 127 do print(round(log(1 + i * 2^-7), SG, RN));
+static constexpr float LOG10F_1_PLUS_M[128] = {
+    0x0.0p0f,       0x1.bafd48p-9f, 0x1.b9476ap-8f, 0x1.49b086p-7f,
+    0x1.b5e908p-7f, 0x1.10a83ap-6f, 0x1.45f4f6p-6f, 0x1.7adc3ep-6f,
+    0x1.af5f92p-6f, 0x1.e3806ap-6f, 0x1.0ba01ap-5f, 0x1.25502cp-5f,
+    0x1.3ed11ap-5f, 0x1.58238ep-5f, 0x1.714834p-5f, 0x1.8a3faep-5f,
+    0x1.a30a9ep-5f, 0x1.bba9ap-5f,  0x1.d41d52p-5f, 0x1.ec6648p-5f,
+    0x1.02428cp-4f, 0x1.0e3d2ap-4f, 0x1.1a2344p-4f, 0x1.25f522p-4f,
+    0x1.31b306p-4f, 0x1.3d5d34p-4f, 0x1.48f3eep-4f, 0x1.547774p-4f,
+    0x1.5fe804p-4f, 0x1.6b45ep-4f,  0x1.76914p-4f,  0x1.81ca64p-4f,
+    0x1.8cf184p-4f, 0x1.9806dap-4f, 0x1.a30a9ep-4f, 0x1.adfd08p-4f,
+    0x1.b8de4ep-4f, 0x1.c3aea4p-4f, 0x1.ce6e42p-4f, 0x1.d91d58p-4f,
+    0x1.e3bc1ap-4f, 0x1.ee4abap-4f, 0x1.f8c968p-4f, 0x1.019c2ap-3f,
+    0x1.06cbd6p-3f, 0x1.0bf3dp-3f,  0x1.11143p-3f,  0x1.162d08p-3f,
+    0x1.1b3e72p-3f, 0x1.204882p-3f, 0x1.254b4ep-3f, 0x1.2a46e8p-3f,
+    0x1.2f3b6ap-3f, 0x1.3428e2p-3f, 0x1.390f68p-3f, 0x1.3def0ep-3f,
+    0x1.42c7e8p-3f, 0x1.479a08p-3f, 0x1.4c658p-3f,  0x1.512a64p-3f,
+    0x1.55e8c6p-3f, 0x1.5aa0b4p-3f, 0x1.5f5244p-3f, 0x1.63fd86p-3f,
+    0x1.68a288p-3f, 0x1.6d415ep-3f, 0x1.71da18p-3f, 0x1.766cc4p-3f,
+    0x1.7af974p-3f, 0x1.7f8036p-3f, 0x1.84011ap-3f, 0x1.887c2ep-3f,
+    0x1.8cf184p-3f, 0x1.916128p-3f, 0x1.95cb28p-3f, 0x1.9a2f96p-3f,
+    0x1.9e8e7cp-3f, 0x1.a2e7e8p-3f, 0x1.a73beap-3f, 0x1.ab8a9p-3f,
+    0x1.afd3e4p-3f, 0x1.b417f4p-3f, 0x1.b856dp-3f,  0x1.bc908p-3f,
+    0x1.c0c514p-3f, 0x1.c4f496p-3f, 0x1.c91f14p-3f, 0x1.cd4498p-3f,
+    0x1.d1653p-3f,  0x1.d580e6p-3f, 0x1.d997c8p-3f, 0x1.dda9dep-3f,
+    0x1.e1b734p-3f, 0x1.e5bfd6p-3f, 0x1.e9c3cep-3f, 0x1.edc328p-3f,
+    0x1.f1bdeep-3f, 0x1.f5b42ap-3f, 0x1.f9a5e8p-3f, 0x1.fd933p-3f,
+    0x1.00be06p-2f, 0x1.02b044p-2f, 0x1.04a054p-2f, 0x1.068e4p-2f,
+    0x1.087a08p-2f, 0x1.0a63b4p-2f, 0x1.0c4b46p-2f, 0x1.0e30c4p-2f,
+    0x1.101432p-2f, 0x1.11f594p-2f, 0x1.13d4fp-2f,  0x1.15b24ap-2f,
+    0x1.178da6p-2f, 0x1.196706p-2f, 0x1.1b3e72p-2f, 0x1.1d13ecp-2f,
+    0x1.1ee778p-2f, 0x1.20b91ap-2f, 0x1.2288d8p-2f, 0x1.2456b4p-2f,
+    0x1.2622bp-2f,  0x1.27ecd4p-2f, 0x1.29b522p-2f, 0x1.2b7b9ep-2f,
+    0x1.2d404cp-2f, 0x1.2f032cp-2f, 0x1.30c448p-2f, 0x1.32839ep-2f,
+};
+
+constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
+    // x = 0x4120 (10.0)
+    {0x4120U, 0x3F80U, 0U, 0U, 0U},
+    // x = 0x42C8 (100.0)
+    {0x42C8U, 0x4000U, 0U, 0U, 0U},
+    // x =0x447A (1000.0)
+    {0x447AU, 0x4040U, 0U, 0U, 0U},
+}};
+
+LLVM_LIBC_FUNCTION(bfloat16, log10bf16, (bfloat16 x)) {
+  using FPBits = fputil::FPBits<bfloat16>;
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+
+  // If x <= 0, or x is 1, or x is +inf, or x is NaN.
+  if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3f80U || x_u >= 0x7f80U)) {
+    // log(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;
+    }
+
+    // log(+/-0) = −inf
+    if ((x_u & 0x7fffU) == 0U) {
+      fputil::raise_except_if_required(FE_DIVBYZERO);
+      return FPBits::inf(Sign::NEG).get_val();
+    }
+
+    // log(1) = 0
+    if (x_u == 0x3f80U)
+      return FPBits::zero().get_val();
+
+    // x < 0
+    if (x_u > 0x8000U) {
+      fputil::set_errno_if_required(EDOM);
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+
+    // log(+inf) = +inf
+    return FPBits::inf().get_val();
+  }
+
+  if (fputil::fenv_is_round_up()) {
+    if (auto r = EXPBF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+      return r.value();
+  }
+
+  int e = -FPBits::EXP_BIAS;
+
+  // When x is subnormal, normalize it.
+  if ((x_u & FPBits::EXP_MASK) == 0U) {
+    // Can't pass an integer to fputil::cast directly.
+    constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN;
+    x_bits = FPBits(x_bits.get_val() * fputil::cast<bfloat16>(NORMALIZE_EXP));
+    x_u = x_bits.uintval();
+    e -= FPBits::FRACTION_LEN;
+  }
+
+  // To compute log10(x), we perform the following range reduction:
+  //   x = 2^e * (1 + m),
+  //   log10(x) = e * log10(2) + log10(1 + m).
+  // for BFloat16, mantissa is at most 7 explicit bits, so we lookup
+  // log10(1 + m) in LOG10F_1_PLUS_M table using `m` as key.
+
+  // Get the 7-bit mantissa directly as the table index
+  uint16_t m = x_bits.get_mantissa();
+
+  // Get unbiased exponent
+  e += x_u >> FPBits::FRACTION_LEN;
+
+  return fputil::cast<bfloat16>(fputil::multiply_add(
+      static_cast<float>(e), LOG10F_2, LOG10F_1_PLUS_M[m]));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/log10bf16.h b/libc/src/math/log10bf16.h
new file mode 100644
index 0000000000000..9ee9846afdea3
--- /dev/null
+++ b/libc/src/math/log10bf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for log10bf16 ---------------------*- 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_LOG10BF16_H
+#define LLVM_LIBC_SRC_MATH_LOG10BF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 log10bf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_LOG10BF16_H

>From b640ff32f1e89e48e46f95ff7b4980cde58d047e Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 22 Jan 2026 04:31:48 +0530
Subject: [PATCH 2/7] chore: add smoke and general tests for log10bf16 higher
 math function

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/test/src/math/CMakeLists.txt           | 12 +++++
 libc/test/src/math/log10bf16_test.cpp       | 41 ++++++++++++++++
 libc/test/src/math/smoke/CMakeLists.txt     | 13 ++++++
 libc/test/src/math/smoke/log10bf16_test.cpp | 52 +++++++++++++++++++++
 4 files changed, 118 insertions(+)
 create mode 100644 libc/test/src/math/log10bf16_test.cpp
 create mode 100644 libc/test/src/math/smoke/log10bf16_test.cpp

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index ff5c511922171..4767becd56d60 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2163,6 +2163,18 @@ add_fp_unittest(
     libc.src.math.log10f16
 )
 
+add_fp_unittest(
+  log10bf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    log10bf16_test.cpp
+  DEPENDS
+    libc.src.math.log10bf16
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
 log1p_test
  NEED_MPFR
diff --git a/libc/test/src/math/log10bf16_test.cpp b/libc/test/src/math/log10bf16_test.cpp
new file mode 100644
index 0000000000000..45e64fb725ae3
--- /dev/null
+++ b/libc/test/src/math/log10bf16_test.cpp
@@ -0,0 +1,41 @@
+//===-- Full range tests for BFloat16 log10(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/log10bf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcLogBf16Test = 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(LlvmLibcLogBf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10, x,
+                                   LIBC_NAMESPACE::log10bf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcLogBf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10, x,
+                                   LIBC_NAMESPACE::log10bf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 5afd3a9f22967..4688d457430d7 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4442,6 +4442,19 @@ add_fp_unittest(
     libc.src.__support.FPUtil.cast
 )
 
+add_fp_unittest(
+  log10bf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    log10bf16_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.math.log10bf16
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   log1p_test
   SUITE
diff --git a/libc/test/src/math/smoke/log10bf16_test.cpp b/libc/test/src/math/smoke/log10bf16_test.cpp
new file mode 100644
index 0000000000000..2c4c3b5876252
--- /dev/null
+++ b/libc/test/src/math/smoke/log10bf16_test.cpp
@@ -0,0 +1,52 @@
+//===-- Unittests for BFloat16 log10(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/bfloat16.h"
+#include "src/__support/macros/properties/types.h"
+#include "src/math/log10bf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcLogBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(bfloat16)
+
+public:
+  void test_special_numbers() {
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log10bf16(aNaN));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::log10bf16(sNaN),
+                                FE_INVALID);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::log10bf16(inf));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log10bf16(neg_inf));
+    EXPECT_MATH_ERRNO(EDOM);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        neg_inf, LIBC_NAMESPACE::log10bf16(zero), FE_DIVBYZERO);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        neg_inf, LIBC_NAMESPACE::log10bf16(neg_zero), FE_DIVBYZERO);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::log10bf16(bfloat16(1.0)));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log10bf16(bfloat16(-1.0)));
+    EXPECT_MATH_ERRNO(EDOM);
+  }
+};
+
+TEST_F(LlvmLibcLogBf16Test, SpecialNumbers) { test_special_numbers(); }

>From 8c56e1fb87bb93a1b38098f688ab57e474dbf0d0 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 22 Jan 2026 04:33:08 +0530
Subject: [PATCH 3/7] chore: update entrypoints

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/config/baremetal/aarch64/entrypoints.txt | 1 +
 libc/config/baremetal/arm/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/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 +
 12 files changed, 12 insertions(+)

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 742d96761c415..adf5e5470785c 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -817,6 +817,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 95cb0dea8e49e..ae495aef6cdd2 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -820,6 +820,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 3fc71280f5163..cfbfa072bb2f3 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -818,6 +818,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 3909417f9730d..d849f424cbf82 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -634,6 +634,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 e899bf97ea3f6..e52243ebcabaa 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -276,6 +276,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 0dda7d5c683ec..a88774f23f4de 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -659,6 +659,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 6070fb5b17b3c..7a7394cf838ce 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -661,6 +661,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 970c825bbfc96..f89ccf9fe22fc 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -890,6 +890,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 f04ac40145d3a..4969f47e09c4a 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -503,6 +503,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 7baf4de9d8a5b..4d6bfb1682378 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -911,6 +911,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 9399b284fa2da..53b9085afbae6 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -957,6 +957,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   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 3a76595b258e2..f1ceb56b11c69 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -349,6 +349,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log10bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16

>From c6bd25e37852a6f7e61a4e8700051cb5dc321096 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 22 Jan 2026 04:33:53 +0530
Subject: [PATCH 4/7] docs: add log10bf16 higher math function

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/docs/headers/math/index.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 51bb17ff8dab6..f03a626894c01 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -321,7 +321,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | 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                  |
+| log10     | |check|          | |check|         |                        | |check|              |                        | |check|                | 7.12.6.12              | F.10.3.12                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | log10p1   |                  |                 |                        |                      |                        |                        | 7.12.6.13              | F.10.3.13                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
@@ -636,4 +636,4 @@ References
 * `The GNU C Library (glibc) <https://www.gnu.org/software/libc/>`_.
 * `The GNU MPFR Library <https://www.mpfr.org/>`_.
 * `C++23 Standard <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf>`_.
-* `BFloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_.
\ No newline at end of file
+* `BFloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_.

>From 683c8ce12ec6528246d5097c2f10d4e222c571c7 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 00:45:47 +0530
Subject: [PATCH 5/7] refactor: header only log10bf16

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/shared/math.h                     |   1 +
 libc/shared/math/log10bf16.h           |  23 ++++
 libc/src/__support/math/CMakeLists.txt |  15 +++
 libc/src/__support/math/log10bf16.h    | 154 +++++++++++++++++++++++++
 libc/src/math/generic/CMakeLists.txt   |   9 +-
 libc/src/math/generic/log10bf16.cpp    | 133 +--------------------
 6 files changed, 196 insertions(+), 139 deletions(-)
 create mode 100644 libc/shared/math/log10bf16.h
 create mode 100644 libc/src/__support/math/log10bf16.h

diff --git a/libc/shared/math.h b/libc/shared/math.h
index bad2b07ecb993..419fcdc5eea98 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -74,6 +74,7 @@
 #include "math/llogbf.h"
 #include "math/log.h"
 #include "math/log10.h"
+#include "math/log10bf16.h"
 #include "math/log1p.h"
 #include "math/log2.h"
 #include "math/logbf.h"
diff --git a/libc/shared/math/log10bf16.h b/libc/shared/math/log10bf16.h
new file mode 100644
index 0000000000000..1bb1442212318
--- /dev/null
+++ b/libc/shared/math/log10bf16.h
@@ -0,0 +1,23 @@
+//===-- Shared log10bf16 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_LOG10BF16_H
+#define LLVM_LIBC_SHARED_MATH_LOG10BF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/log10bf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::log10bf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_LOG10BF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index bcc5b1024b8da..19cabd2b87e70 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -1139,6 +1139,21 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  log10bf16
+  HDRS
+    log10bf16.h
+  DEPENDS
+    libc.src.__support.common
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.except_value_utils
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   log1p
   HDRS
diff --git a/libc/src/__support/math/log10bf16.h b/libc/src/__support/math/log10bf16.h
new file mode 100644
index 0000000000000..e04b7fe885071
--- /dev/null
+++ b/libc/src/__support/math/log10bf16.h
@@ -0,0 +1,154 @@
+//===-- Implementation header for BFloat16 log10(x) 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_SRC___SUPPORT_MATH_LOG10BF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOG10BF16_H
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > round(log10(2), SG, RN);
+static constexpr float LOG10F_2 = 0x1.344136p-2f;
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 127 do print(round(log(1 + i * 2^-7), SG, RN));
+static constexpr float LOG10F_1_PLUS_M[128] = {
+    0x0.0p0f,       0x1.bafd48p-9f, 0x1.b9476ap-8f, 0x1.49b086p-7f,
+    0x1.b5e908p-7f, 0x1.10a83ap-6f, 0x1.45f4f6p-6f, 0x1.7adc3ep-6f,
+    0x1.af5f92p-6f, 0x1.e3806ap-6f, 0x1.0ba01ap-5f, 0x1.25502cp-5f,
+    0x1.3ed11ap-5f, 0x1.58238ep-5f, 0x1.714834p-5f, 0x1.8a3faep-5f,
+    0x1.a30a9ep-5f, 0x1.bba9ap-5f,  0x1.d41d52p-5f, 0x1.ec6648p-5f,
+    0x1.02428cp-4f, 0x1.0e3d2ap-4f, 0x1.1a2344p-4f, 0x1.25f522p-4f,
+    0x1.31b306p-4f, 0x1.3d5d34p-4f, 0x1.48f3eep-4f, 0x1.547774p-4f,
+    0x1.5fe804p-4f, 0x1.6b45ep-4f,  0x1.76914p-4f,  0x1.81ca64p-4f,
+    0x1.8cf184p-4f, 0x1.9806dap-4f, 0x1.a30a9ep-4f, 0x1.adfd08p-4f,
+    0x1.b8de4ep-4f, 0x1.c3aea4p-4f, 0x1.ce6e42p-4f, 0x1.d91d58p-4f,
+    0x1.e3bc1ap-4f, 0x1.ee4abap-4f, 0x1.f8c968p-4f, 0x1.019c2ap-3f,
+    0x1.06cbd6p-3f, 0x1.0bf3dp-3f,  0x1.11143p-3f,  0x1.162d08p-3f,
+    0x1.1b3e72p-3f, 0x1.204882p-3f, 0x1.254b4ep-3f, 0x1.2a46e8p-3f,
+    0x1.2f3b6ap-3f, 0x1.3428e2p-3f, 0x1.390f68p-3f, 0x1.3def0ep-3f,
+    0x1.42c7e8p-3f, 0x1.479a08p-3f, 0x1.4c658p-3f,  0x1.512a64p-3f,
+    0x1.55e8c6p-3f, 0x1.5aa0b4p-3f, 0x1.5f5244p-3f, 0x1.63fd86p-3f,
+    0x1.68a288p-3f, 0x1.6d415ep-3f, 0x1.71da18p-3f, 0x1.766cc4p-3f,
+    0x1.7af974p-3f, 0x1.7f8036p-3f, 0x1.84011ap-3f, 0x1.887c2ep-3f,
+    0x1.8cf184p-3f, 0x1.916128p-3f, 0x1.95cb28p-3f, 0x1.9a2f96p-3f,
+    0x1.9e8e7cp-3f, 0x1.a2e7e8p-3f, 0x1.a73beap-3f, 0x1.ab8a9p-3f,
+    0x1.afd3e4p-3f, 0x1.b417f4p-3f, 0x1.b856dp-3f,  0x1.bc908p-3f,
+    0x1.c0c514p-3f, 0x1.c4f496p-3f, 0x1.c91f14p-3f, 0x1.cd4498p-3f,
+    0x1.d1653p-3f,  0x1.d580e6p-3f, 0x1.d997c8p-3f, 0x1.dda9dep-3f,
+    0x1.e1b734p-3f, 0x1.e5bfd6p-3f, 0x1.e9c3cep-3f, 0x1.edc328p-3f,
+    0x1.f1bdeep-3f, 0x1.f5b42ap-3f, 0x1.f9a5e8p-3f, 0x1.fd933p-3f,
+    0x1.00be06p-2f, 0x1.02b044p-2f, 0x1.04a054p-2f, 0x1.068e4p-2f,
+    0x1.087a08p-2f, 0x1.0a63b4p-2f, 0x1.0c4b46p-2f, 0x1.0e30c4p-2f,
+    0x1.101432p-2f, 0x1.11f594p-2f, 0x1.13d4fp-2f,  0x1.15b24ap-2f,
+    0x1.178da6p-2f, 0x1.196706p-2f, 0x1.1b3e72p-2f, 0x1.1d13ecp-2f,
+    0x1.1ee778p-2f, 0x1.20b91ap-2f, 0x1.2288d8p-2f, 0x1.2456b4p-2f,
+    0x1.2622bp-2f,  0x1.27ecd4p-2f, 0x1.29b522p-2f, 0x1.2b7b9ep-2f,
+    0x1.2d404cp-2f, 0x1.2f032cp-2f, 0x1.30c448p-2f, 0x1.32839ep-2f,
+};
+
+constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
+    // x = 0x4120 (10.0)
+    {0x4120U, 0x3F80U, 0U, 0U, 0U},
+    // x = 0x42C8 (100.0)
+    {0x42C8U, 0x4000U, 0U, 0U, 0U},
+    // x =0x447A (1000.0)
+    {0x447AU, 0x4040U, 0U, 0U, 0U},
+}};
+
+LLVM_LIBC_FUNCTION(bfloat16, log10bf16, (bfloat16 x)) {
+  using FPBits = fputil::FPBits<bfloat16>;
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+
+  // If x <= 0, or x is 1, or x is +inf, or x is NaN.
+  if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3f80U || x_u >= 0x7f80U)) {
+    // log(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;
+    }
+
+    // log(+/-0) = −inf
+    if ((x_u & 0x7fffU) == 0U) {
+      fputil::raise_except_if_required(FE_DIVBYZERO);
+      return FPBits::inf(Sign::NEG).get_val();
+    }
+
+    // log(1) = 0
+    if (x_u == 0x3f80U)
+      return FPBits::zero().get_val();
+
+    // x < 0
+    if (x_u > 0x8000U) {
+      fputil::set_errno_if_required(EDOM);
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+
+    // log(+inf) = +inf
+    return FPBits::inf().get_val();
+  }
+
+  if (fputil::fenv_is_round_up()) {
+    if (auto r = EXPBF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+      return r.value();
+  }
+
+  int e = -FPBits::EXP_BIAS;
+
+  // When x is subnormal, normalize it.
+  if ((x_u & FPBits::EXP_MASK) == 0U) {
+    // Can't pass an integer to fputil::cast directly.
+    constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN;
+    x_bits = FPBits(x_bits.get_val() * fputil::cast<bfloat16>(NORMALIZE_EXP));
+    x_u = x_bits.uintval();
+    e -= FPBits::FRACTION_LEN;
+  }
+
+  // To compute log10(x), we perform the following range reduction:
+  //   x = 2^e * (1 + m),
+  //   log10(x) = e * log10(2) + log10(1 + m).
+  // for BFloat16, mantissa is at most 7 explicit bits, so we lookup
+  // log10(1 + m) in LOG10F_1_PLUS_M table using `m` as key.
+
+  // Get the 7-bit mantissa directly as the table index
+  uint16_t m = x_bits.get_mantissa();
+
+  // Get unbiased exponent
+  e += x_u >> FPBits::FRACTION_LEN;
+
+  return fputil::cast<bfloat16>(fputil::multiply_add(
+      static_cast<float>(e), LOG10F_2, LOG10F_1_PLUS_M[m]));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOG10BF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 9d9e6f256872b..b8e8040b5af4a 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2004,14 +2004,7 @@ add_entrypoint_object(
   HDRS
     ../log10bf16.h
   DEPENDS
-    libc.src.__support.common
-    libc.src.__support.FPUtil.bfloat16
-    libc.src.__support.FPUtil.cast
-    libc.src.__support.FPUtil.except_value_utils
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.multiply_add
-    libc.src.__support.macros.config
-    libc.src.__support.macros.optimization
+    libc.src.__support.math.log10bf16
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/log10bf16.cpp b/libc/src/math/generic/log10bf16.cpp
index 4bae8e66cc80f..8d22eb1e4418a 100644
--- a/libc/src/math/generic/log10bf16.cpp
+++ b/libc/src/math/generic/log10bf16.cpp
@@ -7,140 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/log10bf16.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/bfloat16.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
-#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/math/log10bf16.h"
 
 namespace LIBC_NAMESPACE_DECL {
-
-// Generated by Sollya with the following commands:
-//   > display = hexadecimal;
-//   > round(log10(2), SG, RN);
-static constexpr float LOG10F_2 = 0x1.344136p-2f;
-
-// Generated by Sollya with the following commands:
-//   > display = hexadecimal;
-//   > for i from 0 to 127 do print(round(log(1 + i * 2^-7), SG, RN));
-static constexpr float LOG10F_1_PLUS_M[128] = {
-    0x0.0p0f,       0x1.bafd48p-9f, 0x1.b9476ap-8f, 0x1.49b086p-7f,
-    0x1.b5e908p-7f, 0x1.10a83ap-6f, 0x1.45f4f6p-6f, 0x1.7adc3ep-6f,
-    0x1.af5f92p-6f, 0x1.e3806ap-6f, 0x1.0ba01ap-5f, 0x1.25502cp-5f,
-    0x1.3ed11ap-5f, 0x1.58238ep-5f, 0x1.714834p-5f, 0x1.8a3faep-5f,
-    0x1.a30a9ep-5f, 0x1.bba9ap-5f,  0x1.d41d52p-5f, 0x1.ec6648p-5f,
-    0x1.02428cp-4f, 0x1.0e3d2ap-4f, 0x1.1a2344p-4f, 0x1.25f522p-4f,
-    0x1.31b306p-4f, 0x1.3d5d34p-4f, 0x1.48f3eep-4f, 0x1.547774p-4f,
-    0x1.5fe804p-4f, 0x1.6b45ep-4f,  0x1.76914p-4f,  0x1.81ca64p-4f,
-    0x1.8cf184p-4f, 0x1.9806dap-4f, 0x1.a30a9ep-4f, 0x1.adfd08p-4f,
-    0x1.b8de4ep-4f, 0x1.c3aea4p-4f, 0x1.ce6e42p-4f, 0x1.d91d58p-4f,
-    0x1.e3bc1ap-4f, 0x1.ee4abap-4f, 0x1.f8c968p-4f, 0x1.019c2ap-3f,
-    0x1.06cbd6p-3f, 0x1.0bf3dp-3f,  0x1.11143p-3f,  0x1.162d08p-3f,
-    0x1.1b3e72p-3f, 0x1.204882p-3f, 0x1.254b4ep-3f, 0x1.2a46e8p-3f,
-    0x1.2f3b6ap-3f, 0x1.3428e2p-3f, 0x1.390f68p-3f, 0x1.3def0ep-3f,
-    0x1.42c7e8p-3f, 0x1.479a08p-3f, 0x1.4c658p-3f,  0x1.512a64p-3f,
-    0x1.55e8c6p-3f, 0x1.5aa0b4p-3f, 0x1.5f5244p-3f, 0x1.63fd86p-3f,
-    0x1.68a288p-3f, 0x1.6d415ep-3f, 0x1.71da18p-3f, 0x1.766cc4p-3f,
-    0x1.7af974p-3f, 0x1.7f8036p-3f, 0x1.84011ap-3f, 0x1.887c2ep-3f,
-    0x1.8cf184p-3f, 0x1.916128p-3f, 0x1.95cb28p-3f, 0x1.9a2f96p-3f,
-    0x1.9e8e7cp-3f, 0x1.a2e7e8p-3f, 0x1.a73beap-3f, 0x1.ab8a9p-3f,
-    0x1.afd3e4p-3f, 0x1.b417f4p-3f, 0x1.b856dp-3f,  0x1.bc908p-3f,
-    0x1.c0c514p-3f, 0x1.c4f496p-3f, 0x1.c91f14p-3f, 0x1.cd4498p-3f,
-    0x1.d1653p-3f,  0x1.d580e6p-3f, 0x1.d997c8p-3f, 0x1.dda9dep-3f,
-    0x1.e1b734p-3f, 0x1.e5bfd6p-3f, 0x1.e9c3cep-3f, 0x1.edc328p-3f,
-    0x1.f1bdeep-3f, 0x1.f5b42ap-3f, 0x1.f9a5e8p-3f, 0x1.fd933p-3f,
-    0x1.00be06p-2f, 0x1.02b044p-2f, 0x1.04a054p-2f, 0x1.068e4p-2f,
-    0x1.087a08p-2f, 0x1.0a63b4p-2f, 0x1.0c4b46p-2f, 0x1.0e30c4p-2f,
-    0x1.101432p-2f, 0x1.11f594p-2f, 0x1.13d4fp-2f,  0x1.15b24ap-2f,
-    0x1.178da6p-2f, 0x1.196706p-2f, 0x1.1b3e72p-2f, 0x1.1d13ecp-2f,
-    0x1.1ee778p-2f, 0x1.20b91ap-2f, 0x1.2288d8p-2f, 0x1.2456b4p-2f,
-    0x1.2622bp-2f,  0x1.27ecd4p-2f, 0x1.29b522p-2f, 0x1.2b7b9ep-2f,
-    0x1.2d404cp-2f, 0x1.2f032cp-2f, 0x1.30c448p-2f, 0x1.32839ep-2f,
-};
-
-constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
-    // x = 0x4120 (10.0)
-    {0x4120U, 0x3F80U, 0U, 0U, 0U},
-    // x = 0x42C8 (100.0)
-    {0x42C8U, 0x4000U, 0U, 0U, 0U},
-    // x =0x447A (1000.0)
-    {0x447AU, 0x4040U, 0U, 0U, 0U},
-}};
-
 LLVM_LIBC_FUNCTION(bfloat16, log10bf16, (bfloat16 x)) {
-  using FPBits = fputil::FPBits<bfloat16>;
-  FPBits x_bits(x);
-
-  uint16_t x_u = x_bits.uintval();
-
-  // If x <= 0, or x is 1, or x is +inf, or x is NaN.
-  if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3f80U || x_u >= 0x7f80U)) {
-    // log(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;
-    }
-
-    // log(+/-0) = −inf
-    if ((x_u & 0x7fffU) == 0U) {
-      fputil::raise_except_if_required(FE_DIVBYZERO);
-      return FPBits::inf(Sign::NEG).get_val();
-    }
-
-    // log(1) = 0
-    if (x_u == 0x3f80U)
-      return FPBits::zero().get_val();
-
-    // x < 0
-    if (x_u > 0x8000U) {
-      fputil::set_errno_if_required(EDOM);
-      fputil::raise_except_if_required(FE_INVALID);
-      return FPBits::quiet_nan().get_val();
-    }
-
-    // log(+inf) = +inf
-    return FPBits::inf().get_val();
-  }
-
-  if (fputil::fenv_is_round_up()) {
-    if (auto r = EXPBF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
-      return r.value();
-  }
-
-  int e = -FPBits::EXP_BIAS;
-
-  // When x is subnormal, normalize it.
-  if ((x_u & FPBits::EXP_MASK) == 0U) {
-    // Can't pass an integer to fputil::cast directly.
-    constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN;
-    x_bits = FPBits(x_bits.get_val() * fputil::cast<bfloat16>(NORMALIZE_EXP));
-    x_u = x_bits.uintval();
-    e -= FPBits::FRACTION_LEN;
-  }
-
-  // To compute log10(x), we perform the following range reduction:
-  //   x = 2^e * (1 + m),
-  //   log10(x) = e * log10(2) + log10(1 + m).
-  // for BFloat16, mantissa is at most 7 explicit bits, so we lookup
-  // log10(1 + m) in LOG10F_1_PLUS_M table using `m` as key.
-
-  // Get the 7-bit mantissa directly as the table index
-  uint16_t m = x_bits.get_mantissa();
-
-  // Get unbiased exponent
-  e += x_u >> FPBits::FRACTION_LEN;
-
-  return fputil::cast<bfloat16>(fputil::multiply_add(
-      static_cast<float>(e), LOG10F_2, LOG10F_1_PLUS_M[m]));
+  return math::log10bf16(x);
 }
 
 } // namespace LIBC_NAMESPACE_DECL

>From 84fe15ed20d55eae01bf1f1afa6508254454937c Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 00:46:10 +0530
Subject: [PATCH 6/7] chore: add shader tests for log10bf16

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/test/shared/CMakeLists.txt       | 1 +
 libc/test/shared/shared_math_test.cpp | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 3fc36ed0c2198..464ce2b2f8107 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -67,6 +67,7 @@ add_fp_unittest(
     libc.src.__support.math.ldexpf
     libc.src.__support.math.log
     libc.src.__support.math.log10
+    libc.src.__support.math.log10bf16
     libc.src.__support.math.log1p
     libc.src.__support.math.log2
     libc.src.__support.math.logbf
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 45ba79de87226..aeb77c825a317 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "shared/math.h"
+#include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
@@ -134,3 +135,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
 }
 
 #endif // LIBC_TYPES_HAS_FLOAT128
+
+TEST(LlvmLibcSharedMathTest, AllBFloat16) {
+  EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::log10bf16(bfloat16(1.0)));
+}

>From ac20abd35f4a3b760c443e13d51a15ac4f30a380 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 00:55:46 +0530
Subject: [PATCH 7/7] fix: headers and mangling issue

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/math/CMakeLists.txt | 1 +
 libc/src/__support/math/log10bf16.h    | 3 +--
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 19cabd2b87e70..ae1b6cdbad141 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -1150,6 +1150,7 @@ add_header_library(
     libc.src.__support.FPUtil.except_value_utils
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.config
     libc.src.__support.macros.optimization
 )
diff --git a/libc/src/__support/math/log10bf16.h b/libc/src/__support/math/log10bf16.h
index e04b7fe885071..63a5a6dadfb67 100644
--- a/libc/src/__support/math/log10bf16.h
+++ b/libc/src/__support/math/log10bf16.h
@@ -18,7 +18,6 @@
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h"
-#include "src/__support/macros/properties/types.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -76,7 +75,7 @@ constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
     {0x447AU, 0x4040U, 0U, 0U, 0U},
 }};
 
-LLVM_LIBC_FUNCTION(bfloat16, log10bf16, (bfloat16 x)) {
+LIBC_INLINE static bfloat16 log10bf16(bfloat16 x) {
   using FPBits = fputil::FPBits<bfloat16>;
   FPBits x_bits(x);
 



More information about the libc-commits mailing list