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

Krishna Pandey via libc-commits libc-commits at lists.llvm.org
Thu Jun 25 04:04:33 PDT 2026


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 01/20] 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 02/20] 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 03/20] 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 04/20] 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 05/20] 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 06/20] 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 07/20] 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);
 }

>From 0816194c3a92df6aa879885f5b96ccffb3ccd3aa Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Mon, 6 Oct 2025 17:31:27 +0530
Subject: [PATCH 08/20] chore: remove redundant comment

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/test/src/math/expbf16_test.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/test/src/math/expbf16_test.cpp b/libc/test/src/math/expbf16_test.cpp
index 14889d4fa9ee4..c2288af74fe12 100644
--- a/libc/test/src/math/expbf16_test.cpp
+++ b/libc/test/src/math/expbf16_test.cpp
@@ -19,7 +19,6 @@ 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;

>From 9e9d4719e2029142484d84a965822cdc91137fa1 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 18 Jun 2026 18:26:40 +0530
Subject: [PATCH 09/20] add: expbf16 to shared math functions

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/shared/math.h         |  1 +
 libc/shared/math/expbf16.h | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 libc/shared/math/expbf16.h

diff --git a/libc/shared/math.h b/libc/shared/math.h
index f4b28e3aa139d..f9b847b835f57 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -114,6 +114,7 @@
 #include "math/exp2f16.h"
 #include "math/exp2m1f.h"
 #include "math/exp2m1f16.h"
+#include "math/expbf16.h"
 #include "math/expf.h"
 #include "math/expf16.h"
 #include "math/expm1.h"
diff --git a/libc/shared/math/expbf16.h b/libc/shared/math/expbf16.h
new file mode 100644
index 0000000000000..0aae861917f7f
--- /dev/null
+++ b/libc/shared/math/expbf16.h
@@ -0,0 +1,23 @@
+//===-- Shared expbf16 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_EXPBF16_H
+#define LLVM_LIBC_SHARED_MATH_EXPBF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/expbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::expbf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_EXPBF16_H

>From c4c0a5761261485d6c6b367ed2e0ffabc8563037 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 18 Jun 2026 18:27:09 +0530
Subject: [PATCH 10/20] refactor: expbf16 to __support math functions

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/math/CMakeLists.txt |  21 +++
 libc/src/__support/math/expbf16.h      | 194 +++++++++++++++++++++++++
 libc/src/math/generic/expbf16.cpp      | 178 +----------------------
 3 files changed, 217 insertions(+), 176 deletions(-)
 create mode 100644 libc/src/__support/math/expbf16.h

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index b57e82a036665..4c57f8333cc5c 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3125,6 +3125,27 @@ add_header_library(
     libc.src.__support.math.exp10_float16_constants
 )
 
+
+add_header_library(
+  expbf16
+  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_header_library(
   f16add
   HDRS
diff --git a/libc/src/__support/math/expbf16.h b/libc/src/__support/math/expbf16.h
new file mode 100644
index 0000000000000..b9a6f7689de1b
--- /dev/null
+++ b/libc/src/__support/math/expbf16.h
@@ -0,0 +1,194 @@
+//===-- 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___SUPPORT_MATH_EXPBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_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"
+
+// bfloat16 expbf16(bfloat16 x);
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+// 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,");
+LIBC_INLINE_VAR 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,");
+LIBC_INLINE_VAR 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,
+};
+
+LIBC_INLINE 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 x;
+
+      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 <= -92.5
+    if (x_u >= 0xc2b9U) {
+      // 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:
+      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();
+      }
+    }
+
+    // 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);
+  }
+
+  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},
+  }};
+
+  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 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 math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXPBF16_H
diff --git a/libc/src/math/generic/expbf16.cpp b/libc/src/math/generic/expbf16.cpp
index 6bb6d2e0f5288..ba48185d9864e 100644
--- a/libc/src/math/generic/expbf16.cpp
+++ b/libc/src/math/generic/expbf16.cpp
@@ -6,182 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/math/expbf16.h"
 #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 <= -92.5
-    if (x_u >= 0xc2b9U) {
-      // 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:
-      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();
-      }
-    }
-
-    // 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 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
+LLVM_LIBC_FUNCTION(bfloat16, expbf16, (bfloat16 x)) { return math::expbf16(x); }

>From 10a38c3f4e2902734b1a9f98c98efcb32c79b8df Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 18 Jun 2026 18:27:27 +0530
Subject: [PATCH 11/20] chore: add shared math tests for expbf16

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

diff --git a/libc/src/math/generic/expbf16.cpp b/libc/src/math/generic/expbf16.cpp
index ba48185d9864e..9f946b8d1ac4e 100644
--- a/libc/src/math/generic/expbf16.cpp
+++ b/libc/src/math/generic/expbf16.cpp
@@ -10,4 +10,7 @@
 #include "src/math/expbf16.h"
 
 namespace LIBC_NAMESPACE_DECL {
+
 LLVM_LIBC_FUNCTION(bfloat16, expbf16, (bfloat16 x)) { return math::expbf16(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 17e1570f1b19a..529b00a58097b 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -125,6 +125,7 @@ add_fp_unittest(
     libc.src.__support.math.exp10f
     libc.src.__support.math.exp10f16
     libc.src.__support.math.expf
+    libc.src.__support.math.expbf16
     libc.src.__support.math.expf16
     libc.src.__support.math.f16add
     libc.src.__support.math.f16addf
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index e26532773c69b..cafaf83f42766 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -802,6 +802,7 @@ TEST(LlvmLibcSharedMathTest, AllBFloat16) {
                                                          bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0), setpayloadsigbf16_res);
 
+  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)));
 
   bfloat16 neg_min_denormal = FPBits::min_subnormal(Sign::NEG).get_val();

>From 62170843ae8e1423b09e635a5ebb7f41f57c384d Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 14:00:50 +0530
Subject: [PATCH 12/20] chore: address changes

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

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 4c57f8333cc5c..1fcf801f4afab 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3134,6 +3134,7 @@ add_header_library(
     libc.hdr.errno_macros
     libc.hdr.fenv_macros
     libc.src.__support.CPP.array
+    libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.except_value_utils
     libc.src.__support.FPUtil.fenv_impl
@@ -3142,7 +3143,8 @@ add_header_library(
     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.config
+    libc.src.__support.macros.properties.types
     libc.src.__support.macros.optimization
 )
 
diff --git a/libc/src/__support/math/expbf16.h b/libc/src/__support/math/expbf16.h
index b9a6f7689de1b..d21680a60eabd 100644
--- a/libc/src/__support/math/expbf16.h
+++ b/libc/src/__support/math/expbf16.h
@@ -10,7 +10,6 @@
 #define LLVM_LIBC_SRC___SUPPORT_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"
@@ -20,7 +19,6 @@
 #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"
@@ -31,6 +29,8 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
+namespace expbf16_internal {
+
 // 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,");
@@ -57,6 +57,8 @@ LIBC_INLINE_VAR constexpr float EXP_MID[32] = {
     0x1.122886p10f, 0x1.6006b6p10f, 0x1.c402b6p10f, 0x1.223252p11f,
 };
 
+} // namespace expbf16_internal
+
 LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
   using FPBits = fputil::FPBits<bfloat16>;
   FPBits x_bits(x);
@@ -114,8 +116,12 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       }
     }
 
+    // exp(0) = 1
+    if (x_bits.is_zero())
+      return bfloat16(1.0f);
+
     // 0 < |x| <= 2^(-3)
-    if (x_abs <= 0x3e00U && !x_bits.is_zero()) {
+    if (x_abs <= 0x3e00U) {
       float xf = static_cast<float>(x);
       // Degree-3 minimax polynomial generated by Sollya with the following
       // commands:
@@ -126,10 +132,6 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       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);
   }
 
   constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
@@ -174,8 +176,8 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
   // 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];
+  float exp_hi = expbf16_internal::EXP_HI[x_hi + 12];
+  float exp_mid = expbf16_internal::EXP_MID[x_mid];
 
   // Degree-3 minimax polynomial generated by Sollya with the following
   // commands:
@@ -188,6 +190,7 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
 
   return fputil::cast<bfloat16>(exp_hi * exp_mid * exp_lo);
 }
+
 } // namespace math
 } // namespace LIBC_NAMESPACE_DECL
 

>From 85722055f7f08ca47e36fb257a4842b810a92b9a Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 14:07:01 +0530
Subject: [PATCH 13/20] chore: make use of macros

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/math/expbf16.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/libc/src/__support/math/expbf16.h b/libc/src/__support/math/expbf16.h
index d21680a60eabd..6cd54f61454fb 100644
--- a/libc/src/__support/math/expbf16.h
+++ b/libc/src/__support/math/expbf16.h
@@ -85,6 +85,11 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       if (x_bits.is_inf())
         return x;
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+      fputil::set_errno_if_required(ERANGE);
+      fputil::raise_except_if_required(FE_OVERFLOW);
+      return FPBits::inf().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_TONEAREST:
       case FE_UPWARD:
@@ -94,6 +99,7 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       default:
         return FPBits::max_normal().get_val();
       }
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // x <= -92.5
@@ -105,6 +111,9 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
+#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+      return FPBits::zero().get_val();
+#else
       switch (fputil::quick_get_round()) {
       case FE_UPWARD:
       case FE_TONEAREST:
@@ -114,6 +123,7 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       default:
         return FPBits::zero().get_val();
       }
+#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     }
 
     // exp(0) = 1
@@ -134,6 +144,7 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
     }
   }
 
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   constexpr fputil::ExceptValues<bfloat16, 4> EXPBF16_EXCEPTS = {{
       // (input, RZ output, RU offset, RD offset, RN offset)
       // x = 0x40DB (6.84375)
@@ -151,6 +162,7 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
 
   if (auto r = EXPBF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
     return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
   // For -93 < x < 89, we do the following range reduction:
   // x = hi + mid + lo

>From 4a733dc395c5ae1ee3e77716b6fe8d282f8ef090 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 15:07:05 +0530
Subject: [PATCH 14/20] chore: address more changes

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/math/expbf16.h         |   3 +-
 libc/src/math/generic/CMakeLists.txt      |  14 +--
 libc/test/src/math/smoke/expbf16_test.cpp | 104 ++++++++++++----------
 3 files changed, 57 insertions(+), 64 deletions(-)

diff --git a/libc/src/__support/math/expbf16.h b/libc/src/__support/math/expbf16.h
index 6cd54f61454fb..eaef906b05410 100644
--- a/libc/src/__support/math/expbf16.h
+++ b/libc/src/__support/math/expbf16.h
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_SRC___SUPPORT_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"
@@ -23,8 +24,6 @@
 #include "src/__support/macros/optimization.h"
 #include "src/__support/macros/properties/types.h"
 
-// bfloat16 expbf16(bfloat16 x);
-
 namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 9dbcc0989b580..01465f599e930 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1238,19 +1238,7 @@ add_entrypoint_object(
   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
+    libc.src.__support.math.expbf16
 )
 
 add_entrypoint_object(
diff --git a/libc/test/src/math/smoke/expbf16_test.cpp b/libc/test/src/math/smoke/expbf16_test.cpp
index cc501571383e3..04526bebc4685 100644
--- a/libc/test/src/math/smoke/expbf16_test.cpp
+++ b/libc/test/src/math/smoke/expbf16_test.cpp
@@ -11,53 +11,59 @@
 #include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/FPUtil/cast.h"
 #include "src/math/expbf16.h"
+#include "test/UnitTest/FEnvSafeTest.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>(-93.0f)),
-      FE_UNDERFLOW | FE_INEXACT);
-  EXPECT_MATH_ERRNO(ERANGE);
-}
+
+class LlvmLibcExpf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(bfloat16)
+public:
+  void test_special_numbers() {
+    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);
+  }
+
+  void test_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);
+  }
+
+  void test_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>(-93.0f)),
+        FE_UNDERFLOW | FE_INEXACT);
+    EXPECT_MATH_ERRNO(ERANGE);
+  }
+};
+
+TEST_F(LlvmLibcExpf16Test, SpecialNumbers) { test_special_numbers(); }
+TEST_F(LlvmLibcExpf16Test, Overflow) { test_overflow(); }
+TEST_F(LlvmLibcExpf16Test, Undeflow) { test_underflow(); }

>From a0e220f34c5157f6baf0e62af1b88afc4e802bf3 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 15:18:52 +0530
Subject: [PATCH 15/20] chore: nit, freebsd entrypoint and bazel updates

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/config/freebsd/x86_64/entrypoints.txt    |  1 +
 libc/src/__support/math/expbf16.h             |  2 +-
 .../llvm-project-overlay/libc/BUILD.bazel     | 22 +++++++++++++++++++
 .../libc/test/src/math/BUILD.bazel            |  2 ++
 .../libc/test/src/math/smoke/BUILD.bazel      |  2 ++
 5 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index b4745d9400335..18b01b76c6bf2 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -579,6 +579,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/src/__support/math/expbf16.h b/libc/src/__support/math/expbf16.h
index eaef906b05410..77006a8ad3440 100644
--- a/libc/src/__support/math/expbf16.h
+++ b/libc/src/__support/math/expbf16.h
@@ -197,7 +197,7 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
   //   > 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);
+      fputil::polyeval(lo, 0x1p+0f, 0x1p+0f, 0x1.00004p-1f, 0x1.555578p-3f);
 
   return fputil::cast<bfloat16>(exp_hi * exp_mid * exp_lo);
 }
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index fd71a06b382d8..bf25a3757738b 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -6907,6 +6907,28 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_expbf16",
+    hdrs = ["src/__support/math/expbf16.h"],
+    deps = [
+        ":hdr_errno_macros",
+        ":hdr_fenv_macros",
+        ":__support_cpp_array",
+        ":__support_fputil_bfloat16",
+        ":__support_fputil_cast",
+        ":__support_fputil_except_value_utils",
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_nearest_integer",
+        ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
+        ":__support_macros_config",
+        ":__support_macros_properties_types",
+        ":__support_macros_optimization",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_expxf16_utils",
     hdrs = ["src/__support/math/expxf16_utils.h"],
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 a49a852becfb6..ced7b0bddd93f 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
@@ -623,6 +623,8 @@ math_mpfr_test(name = "tanpif16")
 
 math_mpfr_test(name = "expf16")
 
+math_mpfr_test(name = "expbf16")
+
 math_mpfr_test(name = "exp2f16")
 
 math_mpfr_test(name = "exp2m1f16")
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 c4281d3993afb..a8d344351cfb7 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
@@ -1696,6 +1696,8 @@ math_test(name = "exp2m1f16")
 
 math_test(name = "expf16")
 
+math_test(name = "expbf16")
+
 math_test(name = "expm1f16")
 
 math_test(

>From cbe190c69318dfc7c785d3754a77044c87a949a0 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 15:23:55 +0530
Subject: [PATCH 16/20] fix: bazel

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index bf25a3757738b..b1695e935e061 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -6911,8 +6911,6 @@ libc_support_library(
     name = "__support_math_expbf16",
     hdrs = ["src/__support/math/expbf16.h"],
     deps = [
-        ":hdr_errno_macros",
-        ":hdr_fenv_macros",
         ":__support_cpp_array",
         ":__support_fputil_bfloat16",
         ":__support_fputil_cast",
@@ -6924,8 +6922,10 @@ libc_support_library(
         ":__support_fputil_polyeval",
         ":__support_fputil_rounding_mode",
         ":__support_macros_config",
-        ":__support_macros_properties_types",
         ":__support_macros_optimization",
+        ":__support_macros_properties_types",
+        ":hdr_errno_macros",
+        ":hdr_fenv_macros",
     ],
 )
 

>From 21ad61d52d84a6ffe6301d3a1ee131f215b83faf Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 15:32:19 +0530
Subject: [PATCH 17/20] nit: match polyeval args with sollya

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/math/expbf16.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/math/expbf16.h b/libc/src/__support/math/expbf16.h
index 77006a8ad3440..5fdde6d6204f7 100644
--- a/libc/src/__support/math/expbf16.h
+++ b/libc/src/__support/math/expbf16.h
@@ -138,8 +138,8 @@ LIBC_INLINE bfloat16 expbf16(bfloat16 x) {
       //   > 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));
+      return fputil::cast<bfloat16>(fputil::polyeval(
+          xf, 0x1p+0f, 0x1p+0f, 0x1.00004p-1f, 0x1.555578p-3f));
     }
   }
 

>From f015cca4c42cdcaa19ac6484cbc514f687b0f243 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 15:45:44 +0530
Subject: [PATCH 18/20] fix: bazel

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index b1695e935e061..2fb1552e811cd 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -10573,6 +10573,13 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "expbf16",
+    additional_deps = [
+        ":__support_math_expbf16",
+    ],
+)
+
 libc_math_function(
     name = "exp10",
     additional_deps = [

>From 95077d2b086a59319df1705def382394a8a12fa4 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 10:36:33 +0000
Subject: [PATCH 19/20] Update libc/src/__support/math/CMakeLists.txt

Co-authored-by: Zorojuro <sawantsukumar at gmail.com>
---
 libc/src/__support/math/CMakeLists.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 1fcf801f4afab..d4c51208514da 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3125,7 +3125,6 @@ add_header_library(
     libc.src.__support.math.exp10_float16_constants
 )
 
-
 add_header_library(
   expbf16
   HDRS

>From 7a60688be600c515ed605cda5ce131f5d20c9bc9 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 25 Jun 2026 16:33:17 +0530
Subject: [PATCH 20/20] fix: bfloat16 bazel

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../llvm-project-overlay/libc/test/src/math/BUILD.bazel    | 7 ++++++-
 .../libc/test/src/math/smoke/BUILD.bazel                   | 7 ++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

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 ced7b0bddd93f..9b5fa61303f10 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
@@ -623,7 +623,12 @@ math_mpfr_test(name = "tanpif16")
 
 math_mpfr_test(name = "expf16")
 
-math_mpfr_test(name = "expbf16")
+math_mpfr_test(
+    name = "expbf16",
+    deps = [
+        "//libc:__support_fputil_bfloat16",
+    ],
+)
 
 math_mpfr_test(name = "exp2f16")
 
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 a8d344351cfb7..3f0874110e140 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
@@ -1696,7 +1696,12 @@ math_test(name = "exp2m1f16")
 
 math_test(name = "expf16")
 
-math_test(name = "expbf16")
+math_test(
+    name = "expbf16",
+    deps = [
+        "//libc:__support_fputil_bfloat16",
+    ],
+)
 
 math_test(name = "expm1f16")
 



More information about the libc-commits mailing list