[libc-commits] [libc] [libc][math][c++23] Add expbf16 math function (PR #161919)
Krishna Pandey via libc-commits
libc-commits at lists.llvm.org
Sat Oct 4 10:30:03 PDT 2025
https://github.com/krishna2803 updated https://github.com/llvm/llvm-project/pull/161919
>From df2bd8ae5b7f8d5433ec6695df623f57b383315c Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 03:38:34 +0530
Subject: [PATCH 1/7] feat: implement expbf16 higher math function
Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/expbf16.h | 21 +++
libc/src/math/generic/CMakeLists.txt | 22 ++++
libc/src/math/generic/expbf16.cpp | 184 +++++++++++++++++++++++++++
4 files changed, 228 insertions(+)
create mode 100644 libc/src/math/expbf16.h
create mode 100644 libc/src/math/generic/expbf16.cpp
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 3c7e99f4a9c46..d74b43e0f923b 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -139,6 +139,7 @@ add_math_entrypoint_object(erff)
add_math_entrypoint_object(exp)
add_math_entrypoint_object(expf)
add_math_entrypoint_object(expf16)
+add_math_entrypoint_object(expbf16)
add_math_entrypoint_object(exp2)
add_math_entrypoint_object(exp2f)
diff --git a/libc/src/math/expbf16.h b/libc/src/math/expbf16.h
new file mode 100644
index 0000000000000..7c7aed30b4a51
--- /dev/null
+++ b/libc/src/math/expbf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for expbf16 -----------------------*- 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_EXPBF16_H
+#define LLVM_LIBC_SRC_MATH_EXPBF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 expbf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_EXPBF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 8074a3925626c..0adcc7fd31015 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1441,6 +1441,28 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ expbf16
+ SRCS
+ expbf16.cpp
+ HDRS
+ ../expbf16.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.nearest_integer
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.FPUtil.rounding_mode
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.macros.optimization
+)
+
add_entrypoint_object(
exp2
SRCS
diff --git a/libc/src/math/generic/expbf16.cpp b/libc/src/math/generic/expbf16.cpp
new file mode 100644
index 0000000000000..bd03660a4a11d
--- /dev/null
+++ b/libc/src/math/generic/expbf16.cpp
@@ -0,0 +1,184 @@
+//===-- BFloat16 e^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/expbf16.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/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/nearest_integer.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 {
+
+// Generated by Sollya with the following commands:
+// > display = hexadecimal;
+// > for i from -96 to 88 by 8 do print(i, round(exp(i), SG, RN) @ "f,");
+static constexpr float EXP_HI[24] = {
+ 0x1.6a4p-139f, 0x1.07b71p-127f, 0x1.7fd974p-116f, 0x1.175afp-104f,
+ 0x1.969d48p-93f, 0x1.27ec46p-81f, 0x1.aebabap-70f, 0x1.397924p-58f,
+ 0x1.c8465p-47f, 0x1.4c1078p-35f, 0x1.e355bcp-24f, 0x1.5fc21p-12f,
+ 0x1p0f, 0x1.749ea8p11f, 0x1.0f2ebep23f, 0x1.8ab7fcp34f,
+ 0x1.1f43fcp46f, 0x1.a220d4p57f, 0x1.304d6ap69f, 0x1.baed16p80f,
+ 0x1.425982p92f, 0x1.d531d8p103f, 0x1.55779cp115f, 0x1.f1056ep126f,
+};
+
+// Generated by Sollya with the following commands:
+// > display = hexadecimal;
+// > for i from 0 to 7.75 by 0.25 do print(round(exp(i), SG, RN) @ "f,");
+static constexpr float EXP_MID[32] = {
+ 0x1p0f, 0x1.48b5e4p0f, 0x1.a61298p0f, 0x1.0ef9dcp1f,
+ 0x1.5bf0a8p1f, 0x1.bec38ep1f, 0x1.1ed3fep2f, 0x1.704b6ap2f,
+ 0x1.d8e64cp2f, 0x1.2f9b88p3f, 0x1.85d6fep3f, 0x1.f4907p3f,
+ 0x1.415e5cp4f, 0x1.9ca53cp4f, 0x1.08ec72p5f, 0x1.542b2ep5f,
+ 0x1.b4c902p5f, 0x1.186bf2p6f, 0x1.68118ap6f, 0x1.ce564ep6f,
+ 0x1.28d38ap7f, 0x1.7d21eep7f, 0x1.e96244p7f, 0x1.3a30dp8f,
+ 0x1.936dc6p8f, 0x1.0301a4p9f, 0x1.4c9222p9f, 0x1.ab0786p9f,
+ 0x1.122886p10f, 0x1.6006b6p10f, 0x1.c402b6p10f, 0x1.223252p11f,
+};
+
+constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ // x = 0x40DB (6.84375)
+ // MPFR: RU=0x446B, RD=0x446A, RZ=0x446A, RN=0x446B
+ {0x40DBU, 0x446AU, 1U, 0U, 1U},
+ // x = 0x419D, keep original
+ {0x419DU, 0x4D9FU, 1U, 0U, 0U},
+ // x = 0x41F9 (31.125)
+ // MPFR: RU=0x55F0, RD=0x55EF, RZ=0x55EF, RN=0x55F0
+ {0x41F9U, 0x55EFU, 1U, 0U, 1U},
+ // x = 0xC19F (-19.875)
+ // MPFR: RU=0x3121, RD=0x3120, RZ=0x3120, RN=0x3121
+ {0xC19FU, 0x3120U, 1U, 0U, 1U},
+}};
+
+LLVM_LIBC_FUNCTION(bfloat16, expbf16, (bfloat16 x)) {
+ using FPBits = fputil::FPBits<bfloat16>;
+ FPBits x_bits(x);
+
+ uint16_t x_u = x_bits.uintval();
+ uint16_t x_abs = x_u & 0x7fffU;
+
+ // 0 <= |x| <= 2^(-3), or |x| >= 89, or x is NaN
+ if (LIBC_UNLIKELY(x_abs <= 0x3e00U || x_abs >= 0x42b2U)) {
+
+ // exp(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;
+ }
+
+ // if x >= 89
+ if (x_bits.is_pos() && x_abs >= 0x42b2U) {
+ // exp(inf) = inf
+ if (x_bits.is_inf())
+ return FPBits::inf().get_val();
+
+ switch (fputil::quick_get_round()) {
+ case FE_TONEAREST:
+ case FE_UPWARD:
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
+ return FPBits::inf().get_val();
+ default:
+ return FPBits::max_normal().get_val();
+ }
+ }
+
+ // x <= -93
+ if (x_u >= 0xc2baU) {
+ // exp(-inf) = +0
+ if (x_bits.is_inf())
+ return FPBits::zero().get_val();
+
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
+
+ switch (fputil::quick_get_round()) {
+ case FE_UPWARD:
+ return FPBits::min_subnormal().get_val();
+ default:
+ return FPBits::zero().get_val();
+ }
+ }
+
+ // 0 < |x| <= 2^(-3)
+ if (x_abs <= 0x3e00U && !x_bits.is_zero()) {
+ float xf = static_cast<float>(x);
+ // Degree-3 minimax polynomial generated by Sollya with the following
+ // commands:
+ // > display = hexadecimal;
+ // > P = fpminimax(expm1(x)/x, 2, [|SG...|], [-2^-7, 2^-7]);
+ // > 1 + x * P;
+ // 0x1p0 + x * (0x1p0 + x * (0x1.00004p-1 + x * 0x1.555578p-3))
+ return fputil::cast<bfloat16>(
+ fputil::polyeval(xf, 0x1p+0f, 0x1p+0f, 0x1.0004p-1f, 0x1.555778p-3f));
+ }
+
+ // exp(0) = 1
+ if (x_bits.is_zero())
+ return bfloat16(1.0f);
+ }
+
+ if (auto r = EXPBF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+
+ // For -93 < x < 89, we do the following range reduction:
+ // x = hi + mid + lo
+ // where,
+ // hi / 2^3 is an integer
+ // mid * 2^2 is an integer
+ // -2^3 <= lo <= 2^3
+ // also, hi + mid = round(4 * x) / x
+ // then,
+ // exp(x) = exp(hi + mid + lo)
+ // = exp(hi) * exp(mid) * exp(lo)
+ // we store 184/8 + 1 = 24 values for looking up exp(hi)
+ // from -96 to 88
+ // we store 8*4 = 32 values for looking up exp(mid) since
+ // mid will always have the bit pattern |bbb.bb| where
+ // b can be either 0 or 1
+
+ float xf = static_cast<float>(x);
+ float kf = fputil::nearest_integer(xf * 4.0f);
+ int x_hi_mid = static_cast<int>(kf);
+ int x_hi = x_hi_mid >> 5;
+ int x_mid = x_hi_mid & 0b11111;
+ // lo = x - (hi + mid) = round(x * 4) / (-4) + x
+ float lo = fputil::multiply_add(kf, -0.25f, xf);
+
+ float exp_hi = EXP_HI[x_hi + 12];
+ float exp_mid = EXP_MID[x_mid];
+
+ // Degree-3 minimax polynomial generated by Sollya with the following
+ // commands:
+ // > display = hexadecimal;
+ // > P = fpminimax(expm1(x)/x, 2, [|SG...|], [-2^-7, 2^-7]);
+ // > 1 + x * P;
+ // 0x1p0 + x * (0x1p0 + x * (0x1.00004p-1 + x * 0x1.555578p-3))
+ float exp_lo =
+ fputil::polyeval(lo, 0x1p+0f, 0x1p+0f, 0x1.0004p-1f, 0x1.555778p-3f);
+
+ return fputil::cast<bfloat16>(exp_hi * exp_mid * exp_lo);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
>From a0d196c92de60888072f07ac0d13b987d776c08e Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 03:39:00 +0530
Subject: [PATCH 2/7] chore: add smoke and general tests for expbf16 higher
math function
Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
libc/test/src/math/CMakeLists.txt | 12 +++++
libc/test/src/math/expbf16_test.cpp | 59 +++++++++++++++++++++
libc/test/src/math/smoke/CMakeLists.txt | 14 +++++
libc/test/src/math/smoke/expbf16_test.cpp | 63 +++++++++++++++++++++++
4 files changed, 148 insertions(+)
create mode 100644 libc/test/src/math/expbf16_test.cpp
create mode 100644 libc/test/src/math/smoke/expbf16_test.cpp
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 2d2d5287bb384..299762cbbc808 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1138,6 +1138,18 @@ add_fp_unittest(
libc.src.math.expf16
)
+add_fp_unittest(
+ expbf16_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ expbf16_test.cpp
+ DEPENDS
+ libc.src.math.expbf16
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
exp2_test
NEED_MPFR
diff --git a/libc/test/src/math/expbf16_test.cpp b/libc/test/src/math/expbf16_test.cpp
new file mode 100644
index 0000000000000..35f247348f9dc
--- /dev/null
+++ b/libc/test/src/math/expbf16_test.cpp
@@ -0,0 +1,59 @@
+//===-- Exhaustive test for expbf16 ---------------------------------------===//
+//
+// 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/expbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcExpBf16Test = 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;
+// static constexpr uint16_t POS_STOP = 0x3e00U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcExpBf16Test, PositiveRange) {
+ for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+ bfloat16 x = FPBits(v).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
+ LIBC_NAMESPACE::expbf16(x), 0.5);
+ }
+
+ auto test_value = [&](uint16_t v) {
+ bfloat16 x = FPBits(v).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
+ LIBC_NAMESPACE::expbf16(x), 0.5);
+ };
+
+ auto test_value_f = [&](float v) {
+ bfloat16 x(v);
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
+ LIBC_NAMESPACE::expbf16(x), 0.5);
+ };
+
+ test_value(0xc2c8);
+ test_value(0xc2ba);
+
+ test_value_f(17.45f);
+}
+
+TEST_F(LlvmLibcExpBf16Test, NegativeRange) {
+ for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+ bfloat16 x = FPBits(v).get_val();
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
+ LIBC_NAMESPACE::expbf16(x), 0.5);
+ }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 42a97ba10b601..8373423b7bc13 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1395,6 +1395,20 @@ add_fp_unittest(
libc.src.__support.FPUtil.cast
)
+add_fp_unittest(
+ expbf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ expbf16_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.math.expbf16
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.cast
+)
+
add_fp_unittest(
exp2_test
SUITE
diff --git a/libc/test/src/math/smoke/expbf16_test.cpp b/libc/test/src/math/smoke/expbf16_test.cpp
new file mode 100644
index 0000000000000..8576b78e4391e
--- /dev/null
+++ b/libc/test/src/math/smoke/expbf16_test.cpp
@@ -0,0 +1,63 @@
+//===-- Unittests for expbf16 ---------------------------------------------===//
+//
+// 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/FPUtil/cast.h"
+#include "src/math/expbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcExpf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+TEST_F(LlvmLibcExpf16Test, SpecialNumbers) {
+ EXPECT_FP_IS_NAN(LIBC_NAMESPACE::expbf16(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::expbf16(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::expbf16(inf));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::expbf16(neg_inf));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<bfloat16>(1.0f),
+ LIBC_NAMESPACE::expbf16(zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<bfloat16>(1.0f),
+ LIBC_NAMESPACE::expbf16(neg_zero));
+ EXPECT_MATH_ERRNO(0);
+}
+
+TEST_F(LlvmLibcExpf16Test, Overflow) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, LIBC_NAMESPACE::expbf16(max_normal),
+ FE_OVERFLOW);
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf,
+ LIBC_NAMESPACE::expbf16(LIBC_NAMESPACE::fputil::cast<bfloat16>(89.0f)),
+ FE_OVERFLOW);
+ EXPECT_MATH_ERRNO(ERANGE);
+}
+
+TEST_F(LlvmLibcExpf16Test, Underflow) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, LIBC_NAMESPACE::expbf16(neg_max_normal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ zero,
+ LIBC_NAMESPACE::expbf16(LIBC_NAMESPACE::fputil::cast<bfloat16>(-92.5f)),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+}
>From b4f6ffbb89c8da1076e0e296784abd2432bcd4dc Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 03:40:12 +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 935c95af0d4af..f8d0ed5167d43 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -778,6 +778,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 82e257c1d2b0d..3291d54c6e308 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -778,6 +778,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index c10cc1162cc5a..bf0e7d7108bdb 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -778,6 +778,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index e3c6c2b30c415..d5eba9cdf4f9d 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -608,6 +608,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index e899bf97ea3f6..78dab1d24d20c 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -251,6 +251,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 0dda7d5c683ec..524e42c0f6c94 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -634,6 +634,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index 6070fb5b17b3c..d6450cdba6dce 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -636,6 +636,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index ae8deabc97407..184e7878dbc24 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -861,6 +861,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index f04ac40145d3a..999f863bbba36 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -478,6 +478,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5f407e842121e..c54ce62703131 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -883,6 +883,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index bf2ad4a40ca11..e55e2664f0818 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -918,6 +918,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 3a76595b258e2..750715c83cbca 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -324,6 +324,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.canonicalizebf16
libc.src.math.ceilbf16
libc.src.math.copysignbf16
+ libc.src.math.expbf16
libc.src.math.fabsbf16
libc.src.math.fdimbf16
libc.src.math.floorbf16
>From a317ac67f2b6aa4bb77865d330f73d9746608bc8 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 03:41:23 +0530
Subject: [PATCH 4/7] docs: add expbf16 higher math function
Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
libc/docs/headers/math/index.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 51bf238b950b0..529fb2f798be2 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -289,7 +289,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| cosh | |check| | | | |check| | | | 7.12.5.4 | F.10.2.4 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| cospi | |check| | | | |check| | | | 7.12.4.12 | F.10.1.12 |
+| cospi | |check| | | | |check| | | |check| | 7.12.4.12 | F.10.1.12 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| dsqrt | N/A | N/A | |check| | N/A | |check|\* | | 7.12.14.6 | F.10.11 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
>From 27da1ff10d8eeb700379150646dca8b905ef1cb4 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 03:45:11 +0530
Subject: [PATCH 5/7] docs: fix incorrect check
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 529fb2f798be2..c10c42408eea0 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -289,7 +289,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| cosh | |check| | | | |check| | | | 7.12.5.4 | F.10.2.4 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| cospi | |check| | | | |check| | | |check| | 7.12.4.12 | F.10.1.12 |
+| cospi | |check| | | | |check| | | | 7.12.4.12 | F.10.1.12 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| dsqrt | N/A | N/A | |check| | N/A | |check|\* | | 7.12.14.6 | F.10.11 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
@@ -297,7 +297,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| erfc | | | | | | | 7.12.8.2 | F.10.5.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| exp | |check| | |check| | | |check| | | | 7.12.6.1 | F.10.3.1 |
+| exp | |check| | |check| | | |check| | | |check| | 7.12.6.1 | F.10.3.1 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| exp10 | |check| | |check| | | |check| | | | 7.12.6.2 | F.10.3.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
>From 270f0a190a96a2662be1885547b3735e4b32ada2 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 03:52:01 +0530
Subject: [PATCH 6/7] chore: remove junk tests
Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
libc/test/src/math/expbf16_test.cpp | 17 -----------------
1 file changed, 17 deletions(-)
diff --git a/libc/test/src/math/expbf16_test.cpp b/libc/test/src/math/expbf16_test.cpp
index 35f247348f9dc..14889d4fa9ee4 100644
--- a/libc/test/src/math/expbf16_test.cpp
+++ b/libc/test/src/math/expbf16_test.cpp
@@ -31,23 +31,6 @@ TEST_F(LlvmLibcExpBf16Test, PositiveRange) {
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
LIBC_NAMESPACE::expbf16(x), 0.5);
}
-
- auto test_value = [&](uint16_t v) {
- bfloat16 x = FPBits(v).get_val();
- EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
- LIBC_NAMESPACE::expbf16(x), 0.5);
- };
-
- auto test_value_f = [&](float v) {
- bfloat16 x(v);
- EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
- LIBC_NAMESPACE::expbf16(x), 0.5);
- };
-
- test_value(0xc2c8);
- test_value(0xc2ba);
-
- test_value_f(17.45f);
}
TEST_F(LlvmLibcExpBf16Test, NegativeRange) {
>From d58d2eedd976dec8772dba26e0aaa1b7ea0fe2a1 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 4 Oct 2025 22:59:39 +0530
Subject: [PATCH 7/7] chore: update and fix test
Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
libc/src/math/generic/expbf16.cpp | 11 +++++++----
libc/test/src/math/smoke/expbf16_test.cpp | 2 +-
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/libc/src/math/generic/expbf16.cpp b/libc/src/math/generic/expbf16.cpp
index bd03660a4a11d..6bb6d2e0f5288 100644
--- a/libc/src/math/generic/expbf16.cpp
+++ b/libc/src/math/generic/expbf16.cpp
@@ -104,8 +104,8 @@ LLVM_LIBC_FUNCTION(bfloat16, expbf16, (bfloat16 x)) {
}
}
- // x <= -93
- if (x_u >= 0xc2baU) {
+ // x <= -92.5
+ if (x_u >= 0xc2b9U) {
// exp(-inf) = +0
if (x_bits.is_inf())
return FPBits::zero().get_val();
@@ -115,7 +115,10 @@ LLVM_LIBC_FUNCTION(bfloat16, expbf16, (bfloat16 x)) {
switch (fputil::quick_get_round()) {
case FE_UPWARD:
- return FPBits::min_subnormal().get_val();
+ case FE_TONEAREST:
+ if (LIBC_UNLIKELY(x_u == 0xc2b9U))
+ return FPBits::min_subnormal().get_val();
+ return FPBits::zero().get_val();
default:
return FPBits::zero().get_val();
}
@@ -145,7 +148,7 @@ LLVM_LIBC_FUNCTION(bfloat16, expbf16, (bfloat16 x)) {
// For -93 < x < 89, we do the following range reduction:
// x = hi + mid + lo
// where,
- // hi / 2^3 is an integer
+ // hi is an integer
// mid * 2^2 is an integer
// -2^3 <= lo <= 2^3
// also, hi + mid = round(4 * x) / x
diff --git a/libc/test/src/math/smoke/expbf16_test.cpp b/libc/test/src/math/smoke/expbf16_test.cpp
index 8576b78e4391e..cc501571383e3 100644
--- a/libc/test/src/math/smoke/expbf16_test.cpp
+++ b/libc/test/src/math/smoke/expbf16_test.cpp
@@ -57,7 +57,7 @@ TEST_F(LlvmLibcExpf16Test, Underflow) {
EXPECT_FP_EQ_WITH_EXCEPTION(
zero,
- LIBC_NAMESPACE::expbf16(LIBC_NAMESPACE::fputil::cast<bfloat16>(-92.5f)),
+ LIBC_NAMESPACE::expbf16(LIBC_NAMESPACE::fputil::cast<bfloat16>(-93.0f)),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
More information about the libc-commits
mailing list