[libc-commits] [libc] [llvm] [libc][math][c23] Implement higher math function `cbrtf16` in LLVM libc (PR #132484)

Krishna Pandey via libc-commits libc-commits at lists.llvm.org
Wed Feb 4 15:50:05 PST 2026


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

>From 07e24a567d92b698024b86193cc6ff4be12a53e4 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:21:48 +0530
Subject: [PATCH 01/23] chore: change polynomial degree comment from 7 to 6

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/generic/cbrtf.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/math/generic/cbrtf.cpp b/libc/src/math/generic/cbrtf.cpp
index 71b23c4a8c742..868790ee7c7c0 100644
--- a/libc/src/math/generic/cbrtf.cpp
+++ b/libc/src/math/generic/cbrtf.cpp
@@ -22,7 +22,7 @@ namespace {
 // Look up table for 2^(i/3) for i = 0, 1, 2.
 constexpr double CBRT2[3] = {1.0, 0x1.428a2f98d728bp0, 0x1.965fea53d6e3dp0};
 
-// Degree-7 polynomials approximation of ((1 + x)^(1/3) - 1)/x for 0 <= x <= 1
+// Degree-6 polynomials approximation of ((1 + x)^(1/3) - 1)/x for 0 <= x <= 1
 // generated by Sollya with:
 // > for i from 0 to 15 do {
 //     P = fpminimax(((1 + x)^(1/3) - 1)/x, 6, [|D...|], [i/16, (i + 1)/16]);

>From f3860e1ea665a13d4078e0806883aa0f1a99aa10 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:22:42 +0530
Subject: [PATCH 02/23] add: implement cbrtf16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/cbrtf16.h           |  21 ++++
 libc/src/math/generic/cbrtf16.cpp | 164 ++++++++++++++++++++++++++++++
 2 files changed, 185 insertions(+)
 create mode 100644 libc/src/math/cbrtf16.h
 create mode 100644 libc/src/math/generic/cbrtf16.cpp

diff --git a/libc/src/math/cbrtf16.h b/libc/src/math/cbrtf16.h
new file mode 100644
index 0000000000000..bddb1eda0a9fa
--- /dev/null
+++ b/libc/src/math/cbrtf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for cbrtf16 -----------------------*- 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_CBRTF16_H
+#define LLVM_LIBC_SRC_MATH_CBRTF16_H
+
+#include "src/__support/macros/config.h"           // LIBC_NAMESPACE_DECL
+#include "src/__support/macros/properties/types.h" // float16
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 cbrtf16(float16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_CBRTF16_H
diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
new file mode 100644
index 0000000000000..782f1bfd1b100
--- /dev/null
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -0,0 +1,164 @@
+//===-- Implementation of sqrtf16 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/cbrtf16.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace {
+
+// Look up table for 2^(i/3) for i = 0, 1, 2 in single precision
+constexpr float CBRT2[3] = {0x1p0f, 0x1.428a3p0f, 0x1.965feap0f};
+
+// Degree-4 polynomials approximation of ((1 + x)^(1/3) - 1)/x for 0 <= x <= 1
+// generated by Sollya with:
+// > display=hexadecimal;
+// for i from 0 to 15 do {
+//   P = fpminimax(((1 + x)^(1/3) - 1)/x, 4, [|SG...|], [i/16, (i + 1)/16]);
+//   print("{", coeff(P, 0), ",", coeff(P, 1), ",", coeff(P, 2), ",",
+//         coeff(P, 3), coeff(P, 4),"},");
+// };
+// Then (1 + x)^(1/3) ~ 1 + x * P(x).
+// For example: for 0 <= x <= 1/8:
+// P(x) = 0x1.555556p-2 + x * (-0x1.c71d38p-4 + x * (0x1.f9b95ap-5 + x *
+// (-0x1.4ebe18p-5 + x * 0x1.9ca9d2p-6)))
+
+constexpr float COEFFS[16][5] = {
+    {0x1.555556p-2f, -0x1.c71ea4p-4f, 0x1.faa5f2p-5f, -0x1.64febep-5f,
+     0x1.733a46p-5f},
+    {0x1.55554ep-2f, -0x1.c715f6p-4f, 0x1.f88a9ep-5f, -0x1.4456e8p-5f,
+     0x1.5b5ef2p-6f},
+    {0x1.555508p-2f, -0x1.c6f404p-4f, 0x1.f56b7ap-5f, -0x1.33cff8p-5f,
+     0x1.18f146p-6f},
+    {0x1.5553fcp-2f, -0x1.c69bacp-4f, 0x1.efed98p-5f, -0x1.204706p-5f,
+     0x1.c90976p-7f},
+    {0x1.55517p-2f, -0x1.c5f996p-4f, 0x1.e85932p-5f, -0x1.0c0c0ep-5f,
+     0x1.77c766p-7f},
+    {0x1.554c96p-2f, -0x1.c501d2p-4f, 0x1.df0fc4p-5f, -0x1.f067f2p-6f,
+     0x1.380ab8p-7f},
+    {0x1.55448cp-2f, -0x1.c3ab1ep-4f, 0x1.d45876p-5f, -0x1.ca3988p-6f,
+     0x1.04f38ap-7f},
+    {0x1.5538aap-2f, -0x1.c1f886p-4f, 0x1.c8b11p-5f, -0x1.a6a16cp-6f,
+     0x1.b847c2p-8f},
+    {0x1.55278ap-2f, -0x1.bfd538p-4f, 0x1.bbde6p-5f, -0x1.846a8cp-6f,
+     0x1.73bfcp-8f},
+    {0x1.5511dp-2f, -0x1.bd6c88p-4f, 0x1.af0a3ap-5f, -0x1.660852p-6f,
+     0x1.3dbe34p-8f},
+    {0x1.54f82ap-2f, -0x1.bada56p-4f, 0x1.a2aa0ep-5f, -0x1.4b8c2ap-6f,
+     0x1.13379cp-8f},
+    {0x1.54d512p-2f, -0x1.b7a936p-4f, 0x1.94b91ep-5f, -0x1.30792cp-6f,
+     0x1.d7883cp-9f},
+    {0x1.54a8d8p-2f, -0x1.b3fde2p-4f, 0x1.861aeep-5f, -0x1.169484p-6f,
+     0x1.92b4cap-9f},
+    {0x1.548126p-2f, -0x1.b0f4a8p-4f, 0x1.7af574p-5f, -0x1.04644ep-6f,
+     0x1.662fb6p-9f},
+    {0x1.544b9p-2f, -0x1.ad2124p-4f, 0x1.6dd75p-5f, -0x1.e0cbecp-7f,
+     0x1.387692p-9f},
+    {0x1.5422c6p-2f, -0x1.aa61bp-4f, 0x1.64f4bap-5f, -0x1.c742b2p-7f,
+     0x1.1cf15ap-9f},
+};
+
+} // anonymous namespace
+
+LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
+  using FPBits = fputil::FPBits<float16>;
+  using FloatBits = fputil::FPBits<float>;
+
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+  uint16_t x_abs = x_u & 0x7fff;
+  uint32_t sign_bit = (x_u >> 15) << FloatBits::EXP_LEN;
+
+  // cbrtf16(0) = 0, cbrtf16(NaN) = NaN
+  if (LIBC_UNLIKELY(x_abs == 0 || x_abs >= 0x7C00)) {
+    if (x_bits.is_signaling_nan()) {
+      fputil::raise_except(FE_INVALID);
+      return FPBits::quiet_nan().uintval();
+    }
+    return x;
+  }
+
+  float xf = static_cast<float>(x);
+  FloatBits xf_bits(xf);
+
+  unsigned x_e = static_cast<unsigned>(xf_bits.get_exponent());
+  unsigned out_e = (x_e / 3 + 127) | sign_bit;
+
+  unsigned shift_e = x_e % 3;
+
+  // Set x_m = 2^(x_e % 3) * (1 + mantissa)
+  uint32_t x_m = xf_bits.get_mantissa();
+
+  // Use the leading 4 bits for look up table
+  unsigned idx = static_cast<unsigned>(x_m >> (FloatBits::FRACTION_LEN - 4));
+
+  x_m |= static_cast<uint32_t>(FloatBits::EXP_BIAS) << FloatBits::FRACTION_LEN;
+
+  float x_reduced = FloatBits(x_m).get_val();
+  float dx = x_reduced - 1.0f;
+
+  float dx_sq = dx * dx;
+
+  // fputil::multiply_add(x, y, z) = x*y + z
+
+  // c0 =  1 + x * a0
+  float c0 = fputil::multiply_add(dx, COEFFS[idx][0], 1.0f);
+  // c1 = a1 + x * a2
+  float c1 = fputil::multiply_add(dx, COEFFS[idx][2], COEFFS[idx][1]);
+  // c2 = a3 + x * a4
+  float c2 = fputil::multiply_add(dx, COEFFS[idx][4], COEFFS[idx][3]);
+  // we save a multiply_add operation by decreasing the polynomial degree by 2
+  // i.e. using a degree-4 polynomial instead of degree 6.
+
+  float dx_4 = dx_sq * dx_sq;
+
+  // p0 = c0 + x^2 * c1
+  // p0 = (1 + x * a0) + x^2 * (a1 + x * a2)
+  // p0 = 1 + x * a0 + x^2 * a1 + x^3 * a2
+  float p0 = fputil::multiply_add(dx_sq, c1, c0);
+
+  // p1 = c2
+  // p1 = x * a4
+  float p1 = c2;
+
+  // r = p0 + x^4 * p1
+  // r = (1 + x * a0 + x^2 * a1 + x^3 * a2) + x^4 (x * a4)
+  // r = 1 + x * a0 + x^2 * a1 + x^3 * a2 + x^5 * a4
+  // r = 1 + x * (a0 + a1 * x + a2 * x^2 + a3 * x^3 + a4 * x^4)
+  // r = 1 + x * P(x)
+  float r = fputil::multiply_add(dx_4, p1, p0) * CBRT2[shift_e];
+
+  uint32_t r_m = FloatBits(r).get_mantissa();
+  // For float, mantissa is 23 bits (instead of 52 for double)
+  // Check if the output is exact. To be exact, the smallest 1-bit of the
+  // output has to be at least 2^-7 or higher. So we check the lowest 15 bits
+  // to see if they are within 2^(-23 + 3) errors from all zeros, then the
+  // result cube root is exact.
+  if (LIBC_UNLIKELY(((r_m + 4) & 0x7fff) <= 8)) {
+    if ((r_m & 0x7fff) <= 4)
+      r_m &= 0xffff'ffe0;
+    else
+      r_m = (r_m & 0xffff'ffe0) + 0x20; // Round up to next multiple of 0x20
+    fputil::clear_except_if_required(FE_INEXACT);
+  }
+
+  uint32_t r_bits =
+      r_m | (static_cast<uint32_t>(out_e) << FloatBits::FRACTION_LEN);
+
+  return static_cast<float16>(FloatBits(r_bits).get_val());
+}
+
+} // namespace LIBC_NAMESPACE_DECL

>From 888ada74207024466b1c402f767d02cd91962227 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:23:44 +0530
Subject: [PATCH 03/23] chore: update CMakeLists.txt

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/CMakeLists.txt         |  1 +
 libc/src/math/generic/CMakeLists.txt | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index f18a73d46f9aa..7bcf4ee294126 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -78,6 +78,7 @@ add_math_entrypoint_object(iscanonicalf128)
 
 add_math_entrypoint_object(cbrt)
 add_math_entrypoint_object(cbrtf)
+add_math_entrypoint_object(cbrtf16)
 
 add_math_entrypoint_object(ceil)
 add_math_entrypoint_object(ceilf)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index db07bd1a098cc..f88f133d8efdd 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4816,6 +4816,24 @@ add_entrypoint_object(
     libc.src.__support.integer_literals
 )
 
+add_entrypoint_object(
+  cbrtf16
+  SRCS
+    cbrtf16.cpp
+  HDRS
+    ../cbrtf16.h
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.double_double
+    libc.src.__support.FPUtil.dyadic_float
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.macros.optimization
+    libc.src.__support.integer_literals
+)
+
 add_entrypoint_object(
   dmull
   SRCS

>From 7fc5a41f26c4be2b0cf34b1bda845fbdaf2d6196 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:23:57 +0530
Subject: [PATCH 04/23] chore: update entrypoints

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/config/gpu/amdgpu/entrypoints.txt    | 1 +
 libc/config/gpu/nvptx/entrypoints.txt     | 1 +
 libc/config/linux/aarch64/entrypoints.txt | 1 +
 libc/config/linux/x86_64/entrypoints.txt  | 1 +
 4 files changed, 4 insertions(+)

diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 291d86b4dd587..0a155e68f307d 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -520,6 +520,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # math.h C23 _Float16 entrypoints
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.coshf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index 1ea0d9b03b37e..010265bd915cb 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -522,6 +522,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # math.h C23 _Float16 entrypoints
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.coshf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 5c4913a658c2f..651bac5b9e79a 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -646,6 +646,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # math.h C23 _Float16 entrypoints
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cospif16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 124b80d03d846..7f22b4a82ce14 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -660,6 +660,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.cosf16
     libc.src.math.coshf16
     libc.src.math.cospif16
+    libc.src.math.cbrtf16
     libc.src.math.exp10f16
     libc.src.math.exp10m1f16
     libc.src.math.exp2f16

>From 974257aa5cc7cd0e024400ba985e40a37a7161a4 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:24:15 +0530
Subject: [PATCH 05/23] feat: add tests for cbrtf16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/cbrtf16_test.cpp       | 56 +++++++++++++++++++++++
 libc/test/src/math/smoke/cbrtf16_test.cpp | 33 +++++++++++++
 2 files changed, 89 insertions(+)
 create mode 100644 libc/test/src/math/cbrtf16_test.cpp
 create mode 100644 libc/test/src/math/smoke/cbrtf16_test.cpp

diff --git a/libc/test/src/math/cbrtf16_test.cpp b/libc/test/src/math/cbrtf16_test.cpp
new file mode 100644
index 0000000000000..2e2cfc079aeb5
--- /dev/null
+++ b/libc/test/src/math/cbrtf16_test.cpp
@@ -0,0 +1,56 @@
+//===-- Unittests for cbrtf16 ---------------------------------------------===//
+//
+// 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/math_macros.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/math/cbrtf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcCbrtf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf];
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7c00U;
+
+// Range: [-Inf, 0]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xfc00U;
+
+TEST_F(LlvmLibcCbrtf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cbrt, x,
+                                   LIBC_NAMESPACE::cbrtf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcCbrtf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cbrt, x,
+                                   LIBC_NAMESPACE::cbrtf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcCbrtf16Test, SpecialValues) {
+  constexpr uint16_t INPUTS[] = {
+      0x4a00, 0x4500, 0x4e00, 0x0c00, 0x4940,
+  };
+  for (uint16_t v : INPUTS) {
+    float16 x = FPBits(v).get_val();
+    mpfr::ForceRoundingMode r(mpfr::RoundingMode::Upward);
+    EXPECT_MPFR_MATCH(mpfr::Operation::Cbrt, x, LIBC_NAMESPACE::cbrtf16(x), 0.5,
+                      mpfr::RoundingMode::Upward);
+  }
+
+  ASSERT_EQ(1, 1);
+}
diff --git a/libc/test/src/math/smoke/cbrtf16_test.cpp b/libc/test/src/math/smoke/cbrtf16_test.cpp
new file mode 100644
index 0000000000000..7c8a7103273a0
--- /dev/null
+++ b/libc/test/src/math/smoke/cbrtf16_test.cpp
@@ -0,0 +1,33 @@
+//===-- Unittests for cbrtf16 ---------------------------------------------===//
+//
+// 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/cbrtf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcCbrtfTest = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+using LIBC_NAMESPACE::testing::tlog;
+
+TEST_F(LlvmLibcCbrtfTest, SpecialNumbers) {
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::cbrtf16(aNaN));
+  EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::cbrtf16(inf));
+  EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, LIBC_NAMESPACE::cbrtf16(neg_inf));
+  EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::cbrtf16(zero));
+  EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::cbrtf16(neg_zero));
+  EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::cbrtf16(1.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(-1.0f, LIBC_NAMESPACE::cbrtf16(-1.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(2.0f, LIBC_NAMESPACE::cbrtf16(8.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(-2.0f, LIBC_NAMESPACE::cbrtf16(-8.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(3.0f, LIBC_NAMESPACE::cbrtf16(27.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(-3.0f, LIBC_NAMESPACE::cbrtf16(-27.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(5.0f, LIBC_NAMESPACE::cbrtf16(125.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(-5.0f, LIBC_NAMESPACE::cbrtf16(-125.0f));
+  EXPECT_FP_EQ_ALL_ROUNDING(40.0f, LIBC_NAMESPACE::cbrtf16(0x1.f4p15));
+  EXPECT_FP_EQ_ALL_ROUNDING(-40.0f, LIBC_NAMESPACE::cbrtf16(-0x1.f4p15));
+}

>From 36d343bd35cfbdea50ac191d4060b2e30c74c1f9 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:24:48 +0530
Subject: [PATCH 06/23] chore: update CMakeLists.txt for tests

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/CMakeLists.txt       | 12 ++++++++++++
 libc/test/src/math/smoke/CMakeLists.txt | 10 ++++++++++
 2 files changed, 22 insertions(+)

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index beafa87e03a77..1fb7f47b1d541 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2655,6 +2655,18 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  cbrtf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    cbrtf16_test.cpp
+  DEPENDS
+    libc.src.math.cbrtf16
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   dmull_test
   NEED_MPFR
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 94ec099ddfcbc..f7311d4f2080c 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5042,6 +5042,16 @@ add_fp_unittest(
     libc.src.math.cbrt
 )
 
+add_fp_unittest(
+  cbrtf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    cbrtf16_test.cpp
+  DEPENDS
+    libc.src.math.cbrtf16
+)
+
 add_fp_unittest(
   dmull_test
   SUITE

>From 08900aab172dbb42f7d49eedaf4be09ae5a69a40 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 04:30:26 +0530
Subject: [PATCH 07/23] chore: remove debugging artefact.

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/cbrtf16_test.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libc/test/src/math/cbrtf16_test.cpp b/libc/test/src/math/cbrtf16_test.cpp
index 2e2cfc079aeb5..eb55234f053bd 100644
--- a/libc/test/src/math/cbrtf16_test.cpp
+++ b/libc/test/src/math/cbrtf16_test.cpp
@@ -51,6 +51,4 @@ TEST_F(LlvmLibcCbrtf16Test, SpecialValues) {
     EXPECT_MPFR_MATCH(mpfr::Operation::Cbrt, x, LIBC_NAMESPACE::cbrtf16(x), 0.5,
                       mpfr::RoundingMode::Upward);
   }
-
-  ASSERT_EQ(1, 1);
 }

>From ebdaeac6d0e0663c1867aa80b829a859a974c40c Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 05:51:01 +0530
Subject: [PATCH 08/23] refactor: separate sign_bit from out_e

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/generic/cbrtf16.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index 782f1bfd1b100..4757eda2da530 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -95,7 +95,7 @@ LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
   FloatBits xf_bits(xf);
 
   unsigned x_e = static_cast<unsigned>(xf_bits.get_exponent());
-  unsigned out_e = (x_e / 3 + 127) | sign_bit;
+  unsigned out_e = x_e / 3 + 127;
 
   unsigned shift_e = x_e % 3;
 
@@ -155,8 +155,8 @@ LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
     fputil::clear_except_if_required(FE_INEXACT);
   }
 
-  uint32_t r_bits =
-      r_m | (static_cast<uint32_t>(out_e) << FloatBits::FRACTION_LEN);
+  uint32_t r_bits = r_m | (static_cast<uint32_t>(out_e | sign_bit)
+                           << FloatBits::FRACTION_LEN);
 
   return static_cast<float16>(FloatBits(r_bits).get_val());
 }

>From a1abd76e6ab808fb3c20042446fe13320534df96 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 06:20:56 +0530
Subject: [PATCH 09/23] chore: fix typo `sqrt` -> `cbrt`

---
 libc/src/math/generic/cbrtf16.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index 4757eda2da530..e0382e8c1a9f3 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of sqrtf16 function --------------------------------===//
+//===-- Implementation of cbrtf16 function --------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

>From 089c0a14a54a6123c1a52d57e6b855664b7f6511 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 19:49:40 +0530
Subject: [PATCH 10/23] chore: add cast to uint32_t

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/generic/cbrtf16.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index e0382e8c1a9f3..94734177df197 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -80,7 +80,7 @@ LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
 
   uint16_t x_u = x_bits.uintval();
   uint16_t x_abs = x_u & 0x7fff;
-  uint32_t sign_bit = (x_u >> 15) << FloatBits::EXP_LEN;
+  uint32_t sign_bit = static_cast<uint32_t>(x_u >> 15) << FloatBits::EXP_LEN;
 
   // cbrtf16(0) = 0, cbrtf16(NaN) = NaN
   if (LIBC_UNLIKELY(x_abs == 0 || x_abs >= 0x7C00)) {

>From 4c9b493a2c7b993e4b742e57d08d6925a866bf5c Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 21:20:40 +0530
Subject: [PATCH 11/23] fix: exponent handling (fixed for negative exponents!)

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/generic/cbrtf16.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index 94734177df197..e715e3d52ef6e 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -94,10 +94,9 @@ LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
   float xf = static_cast<float>(x);
   FloatBits xf_bits(xf);
 
-  unsigned x_e = static_cast<unsigned>(xf_bits.get_exponent());
-  unsigned out_e = x_e / 3 + 127;
-
-  unsigned shift_e = x_e % 3;
+  uint32_t x_e = xf_bits.get_biased_exponent();
+  uint32_t out_e = (x_e - 1) / 3 + (127 - 42);
+  uint32_t shift_e = (x_e - 1) % 3;
 
   // Set x_m = 2^(x_e % 3) * (1 + mantissa)
   uint32_t x_m = xf_bits.get_mantissa();

>From d7052a7ee48839ed0caf03d7af63932feb1f6030 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 21:21:25 +0530
Subject: [PATCH 12/23] fix: update headers

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/generic/CMakeLists.txt |  6 ++----
 libc/src/math/generic/cbrtf16.cpp    | 12 ++++++------
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index f88f133d8efdd..9e4c4251add53 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4824,14 +4824,12 @@ add_entrypoint_object(
     ../cbrtf16.h
   DEPENDS
     libc.hdr.fenv_macros
-    libc.src.__support.FPUtil.double_double
-    libc.src.__support.FPUtil.dyadic_float
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.multiply_add
-    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.common
+    libc.src.__support.macros.config
     libc.src.__support.macros.optimization
-    libc.src.__support.integer_literals
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index e715e3d52ef6e..190d764ff25d3 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -7,12 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/cbrtf16.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "hdr/fenv_macros.h"                   // FE_INVALID, FE_INEXACT
+#include "src/__support/FPUtil/FEnvImpl.h"     // fputil::raise_except
+#include "src/__support/FPUtil/FPBits.h"       // fputil::FPBits
+#include "src/__support/FPUtil/multiply_add.h" // fputil::multiply_add
+#include "src/__support/common.h"              // LLVM_LIBC_FUNCTION
+#include "src/__support/macros/config.h"       // LIBC_NAMESPACE_DECL
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
 namespace LIBC_NAMESPACE_DECL {

>From b761bc9004fca281997ee879766bfb6be2b9d495 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 21:21:38 +0530
Subject: [PATCH 13/23] chore: update docs

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/include/math.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index fbfc51348411a..9b58b50613a24 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -140,6 +140,12 @@ functions:
     return_type: float
     arguments:
       - type: float
+  - name: cbrtf16
+    standards:
+      - stdc
+    return_type: _Float16
+    arguments:
+      - type: _Float16
   - name: ceil
     standards:
       - stdc

>From 26cbd9695b716d7cd6b572dd01f3fa5bf4cd8bfd Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 21:22:48 +0530
Subject: [PATCH 14/23] chore: add better tests for special numbers

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/cbrtf16_test.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/libc/test/src/math/cbrtf16_test.cpp b/libc/test/src/math/cbrtf16_test.cpp
index eb55234f053bd..ac6ee535fcbb7 100644
--- a/libc/test/src/math/cbrtf16_test.cpp
+++ b/libc/test/src/math/cbrtf16_test.cpp
@@ -43,7 +43,12 @@ TEST_F(LlvmLibcCbrtf16Test, NegativeRange) {
 
 TEST_F(LlvmLibcCbrtf16Test, SpecialValues) {
   constexpr uint16_t INPUTS[] = {
-      0x4a00, 0x4500, 0x4e00, 0x0c00, 0x4940,
+      0x4a00, 0x4500, 0x4e00, 0x4940, 0x0c00,
+      0x4248, // ~pi
+      0x7bff, // max positive value
+      0x3800, // 0.5
+      0x3bec, // ~0.99
+      0x3c01, // ~1.01
   };
   for (uint16_t v : INPUTS) {
     float16 x = FPBits(v).get_val();

>From 07dd1fdb88507df0a1a48867176c09aa11f41535 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 22 Mar 2025 21:23:15 +0530
Subject: [PATCH 15/23] chore: update bazel build files

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

diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 6dd425a9f6b5a..90659b93c0373 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2377,6 +2377,18 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "cbrtf16",
+    additional_deps = [
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_multiply_add",
+        ":__support_macros_optimization",
+        ":__support_macros_config",
+        ":__support_common",
+    ],
+)
+
 libc_math_function(name = "ceil")
 
 libc_math_function(name = "ceilf")
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 23cead18de4c1..42633ff884fb8 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
@@ -592,6 +592,8 @@ math_mpfr_test(
     hdrs = ["TruncTest.h"],
 )
 
+math_mpfr_test(name = "cbrtf16")
+
 math_mpfr_test(name = "cosf16")
 
 math_mpfr_test(name = "cospif16")
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 3c9b1f8d71408..3082de6828aa0 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
@@ -81,6 +81,8 @@ math_test(name = "cbrt")
 
 math_test(name = "cbrtf")
 
+math_test(name = "cbrtf16")
+
 math_test(
     name = "ceil",
     hdrs = ["CeilTest.h"],

>From 5c365f9b3c2c9d6729b8bab986b62f0f01e28f2f Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sun, 23 Mar 2025 16:33:28 +0530
Subject: [PATCH 16/23] chore: add comments explaining the exponent
 calculations.

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/generic/cbrtf16.cpp | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index 190d764ff25d3..a9c1b71b401fb 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -94,9 +94,22 @@ LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
   float xf = static_cast<float>(x);
   FloatBits xf_bits(xf);
 
-  uint32_t x_e = xf_bits.get_biased_exponent();
-  uint32_t out_e = (x_e - 1) / 3 + (127 - 42);
-  uint32_t shift_e = (x_e - 1) % 3;
+  // for single precision float, x_e_biased = x_e + 127
+  // Since x_e / 3 will round to 0, we will get incorrect
+  // results for x_e < 0 and x mod 3 != 0, so we take x_e_biased
+  // which is always positive.
+  // To calculate the correct biased exponent of the result,
+  // we need to calculate the exponent as:
+  // out_e = floor(x_e / 3) + 127
+  // now, floor((x_e_biased-1) / 3) = floor((x_e + 127 - 1) / 3)
+  //                                = floor((x_e + 126) / 3)
+  //                                = floor(x_e/3 + 42)
+  //                                = floor(x_e/3) + 42
+  // => out_e = (floor((x_e_biased-1) / 3) - 42) + 127
+  // => out_e = (x_e_biased-1) / 3 + (127 - 42);
+  uint32_t x_e_biased = xf_bits.get_biased_exponent();
+  uint32_t out_e = (x_e_biased - 1) / 3 + (127 - 42);
+  uint32_t shift_e = (x_e_biased - 1) % 3;
 
   // Set x_m = 2^(x_e % 3) * (1 + mantissa)
   uint32_t x_m = xf_bits.get_mantissa();

>From 5e685377929d39f8c8014bf28d75e02de10b5e1a Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 04:51:06 +0530
Subject: [PATCH 17/23] refactor: header only log2bf16

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/shared/math.h                     |   1 +
 libc/shared/math/cbrtf16.h             |  23 ++++
 libc/src/__support/math/CMakeLists.txt |  13 ++
 libc/src/__support/math/cbrtf16.h      | 181 +++++++++++++++++++++++++
 libc/src/math/generic/CMakeLists.txt   |   8 +-
 libc/src/math/generic/cbrtf16.cpp      | 164 +---------------------
 6 files changed, 221 insertions(+), 169 deletions(-)
 create mode 100644 libc/shared/math/cbrtf16.h
 create mode 100644 libc/src/__support/math/cbrtf16.h

diff --git a/libc/shared/math.h b/libc/shared/math.h
index b58d29d1ee480..65d03d6a644a9 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -32,6 +32,7 @@
 #include "math/atanhf16.h"
 #include "math/cbrt.h"
 #include "math/cbrtf.h"
+#include "math/cbrtf16.h"
 #include "math/cos.h"
 #include "math/cosf.h"
 #include "math/cosf16.h"
diff --git a/libc/shared/math/cbrtf16.h b/libc/shared/math/cbrtf16.h
new file mode 100644
index 0000000000000..00fbd8993f5fb
--- /dev/null
+++ b/libc/shared/math/cbrtf16.h
@@ -0,0 +1,23 @@
+//===-- Shared cbrtf16 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_CBRTF16_H
+#define LLVM_LIBC_SHARED_MATH_CBRTF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/cbrtf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::cbrtf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_CBRTF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 58e4040911f8e..d3de8d52be27a 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -358,6 +358,19 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  cbrtf16
+  HDRS
+    cbrtf16.h
+  DEPENDS
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.rounding_mode
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   common_constants
   HDRS
diff --git a/libc/src/__support/math/cbrtf16.h b/libc/src/__support/math/cbrtf16.h
new file mode 100644
index 0000000000000..256270ed61ecd
--- /dev/null
+++ b/libc/src/__support/math/cbrtf16.h
@@ -0,0 +1,181 @@
+//===-- Implementation header for cbrtf16 ----------------------*- 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_CBRTF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_CBRTF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float16 cbrtf16(float16 x) {
+  // look up table for 2^(i/3) for i = 0, 1, 2 in single precision
+  constexpr float CBRT2[3] = {0x1p0f, 0x1.428a3p0f, 0x1.965feap0f};
+
+  // degree-4 polynomials approximation of ((1 + x)^(1/3) - 1)/x for 0 <= x <= 1
+  // generated by Sollya with:
+  // > display=hexadecimal;
+  // for i from 0 to 15 do {
+  //   P = fpminimax(((1 + x)^(1/3) - 1)/x, 4, [|SG...|], [i/16, (i + 1)/16]);
+  //   print("{", coeff(P, 0), ",", coeff(P, 1), ",", coeff(P, 2), ",",
+  //         coeff(P, 3), coeff(P, 4),"},");
+  // };
+  // Then (1 + x)^(1/3) ~ 1 + x * P(x).
+  // For example: for 0 <= x <= 1/8:
+  // P(x) = 0x1.555556p-2 + x * (-0x1.c71d38p-4 + x * (0x1.f9b95ap-5 + x *
+  // (-0x1.4ebe18p-5 + x * 0x1.9ca9d2p-6)))
+  constexpr float COEFFS[16][5] = {
+      {0x1.555556p-2f, -0x1.c71ea4p-4f, 0x1.faa5f2p-5f, -0x1.64febep-5f,
+       0x1.733a46p-5f},
+      {0x1.55554ep-2f, -0x1.c715f6p-4f, 0x1.f88a9ep-5f, -0x1.4456e8p-5f,
+       0x1.5b5ef2p-6f},
+      {0x1.555508p-2f, -0x1.c6f404p-4f, 0x1.f56b7ap-5f, -0x1.33cff8p-5f,
+       0x1.18f146p-6f},
+      {0x1.5553fcp-2f, -0x1.c69bacp-4f, 0x1.efed98p-5f, -0x1.204706p-5f,
+       0x1.c90976p-7f},
+      {0x1.55517p-2f, -0x1.c5f996p-4f, 0x1.e85932p-5f, -0x1.0c0c0ep-5f,
+       0x1.77c766p-7f},
+      {0x1.554c96p-2f, -0x1.c501d2p-4f, 0x1.df0fc4p-5f, -0x1.f067f2p-6f,
+       0x1.380ab8p-7f},
+      {0x1.55448cp-2f, -0x1.c3ab1ep-4f, 0x1.d45876p-5f, -0x1.ca3988p-6f,
+       0x1.04f38ap-7f},
+      {0x1.5538aap-2f, -0x1.c1f886p-4f, 0x1.c8b11p-5f, -0x1.a6a16cp-6f,
+       0x1.b847c2p-8f},
+      {0x1.55278ap-2f, -0x1.bfd538p-4f, 0x1.bbde6p-5f, -0x1.846a8cp-6f,
+       0x1.73bfcp-8f},
+      {0x1.5511dp-2f, -0x1.bd6c88p-4f, 0x1.af0a3ap-5f, -0x1.660852p-6f,
+       0x1.3dbe34p-8f},
+      {0x1.54f82ap-2f, -0x1.bada56p-4f, 0x1.a2aa0ep-5f, -0x1.4b8c2ap-6f,
+       0x1.13379cp-8f},
+      {0x1.54d512p-2f, -0x1.b7a936p-4f, 0x1.94b91ep-5f, -0x1.30792cp-6f,
+       0x1.d7883cp-9f},
+      {0x1.54a8d8p-2f, -0x1.b3fde2p-4f, 0x1.861aeep-5f, -0x1.169484p-6f,
+       0x1.92b4cap-9f},
+      {0x1.548126p-2f, -0x1.b0f4a8p-4f, 0x1.7af574p-5f, -0x1.04644ep-6f,
+       0x1.662fb6p-9f},
+      {0x1.544b9p-2f, -0x1.ad2124p-4f, 0x1.6dd75p-5f, -0x1.e0cbecp-7f,
+       0x1.387692p-9f},
+      {0x1.5422c6p-2f, -0x1.aa61bp-4f, 0x1.64f4bap-5f, -0x1.c742b2p-7f,
+       0x1.1cf15ap-9f},
+  };
+
+  using FPBits = fputil::FPBits<float16>;
+  using FloatBits = fputil::FPBits<float>;
+
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+  uint16_t x_abs = x_u & 0x7fff;
+  uint32_t sign_bit = static_cast<uint32_t>(x_bits.is_neg())
+                      << FloatBits::EXP_LEN;
+
+  // cbrtf16(0) = 0, cbrtf16(NaN) = NaN
+  if (LIBC_UNLIKELY(x_abs == 0 || x_abs >= 0x7C00)) {
+    if (x_bits.is_signaling_nan()) {
+      fputil::raise_except(FE_INVALID);
+      return FPBits::quiet_nan().uintval();
+    }
+    return x;
+  }
+
+  float xf = static_cast<float>(x);
+  FloatBits xf_bits(xf);
+
+  // for single precision float, x_e_biased = x_e + 127
+  // since x_e / 3 will round to 0, we will get incorrect
+  // results for x_e < 0 and x mod 3 != 0, so we take x_e_biased
+  // which is always positive.
+  // to calculate the correct biased exponent of the result,
+  // we need to calculate the exponent as:
+  // out_e = floor(x_e / 3) + 127
+  // now, floor((x_e_biased-1) / 3) = floor((x_e + 127 - 1) / 3)
+  //                                = floor((x_e + 126) / 3)
+  //                                = floor(x_e/3 + 42)
+  //                                = floor(x_e/3) + 42
+  // => out_e = (floor((x_e_biased-1) / 3) - 42) + 127
+  // => out_e = (x_e_biased-1) / 3 + (127 - 42);
+  uint32_t x_e_biased = xf_bits.get_biased_exponent();
+  uint32_t out_e = (x_e_biased - 1) / 3 + (127 - 42);
+  uint32_t shift_e = (x_e_biased - 1) % 3;
+
+  // set x_m = 2^(x_e % 3) * (1 + mantissa)
+  uint32_t x_m = xf_bits.get_mantissa();
+
+  // use the leading 4 bits for look up table
+  unsigned idx = static_cast<unsigned>(x_m >> (FloatBits::FRACTION_LEN - 4));
+
+  x_m |= static_cast<uint32_t>(FloatBits::EXP_BIAS) << FloatBits::FRACTION_LEN;
+
+  float x_reduced = FloatBits(x_m).get_val();
+  float dx = x_reduced - 1.0f;
+
+  float dx_sq = dx * dx;
+
+  // c0 =  1 + x * a0
+  float c0 = fputil::multiply_add(dx, COEFFS[idx][0], 1.0f);
+  // c1 = a1 + x * a2
+  float c1 = fputil::multiply_add(dx, COEFFS[idx][2], COEFFS[idx][1]);
+  // c2 = a3 + x * a4
+  float c2 = fputil::multiply_add(dx, COEFFS[idx][4], COEFFS[idx][3]);
+  // we save a multiply_add operation by decreasing the polynomial degree by 2
+  // i.e. using a degree-4 polynomial instead of degree 6.
+
+  float dx_4 = dx_sq * dx_sq;
+
+  // p0 = c0 + x^2 * c1
+  // p0 = (1 + x * a0) + x^2 * (a1 + x * a2)
+  // p0 = 1 + x * a0 + x^2 * a1 + x^3 * a2
+  float p0 = fputil::multiply_add(dx_sq, c1, c0);
+
+  // p1 = c2
+  // p1 = x * a4
+  float p1 = c2;
+
+  // r = p0 + x^4 * p1
+  // r = (1 + x * a0 + x^2 * a1 + x^3 * a2) + x^4 (x * a4)
+  // r = 1 + x * a0 + x^2 * a1 + x^3 * a2 + x^5 * a4
+  // r = 1 + x * (a0 + a1 * x + a2 * x^2 + a3 * x^3 + a4 * x^4)
+  // r = 1 + x * P(x)
+  float r = fputil::multiply_add(dx_4, p1, p0) * CBRT2[shift_e];
+
+  uint32_t r_m = FloatBits(r).get_mantissa();
+  // for float, mantissa is 23 bits (instead of 52 for double)
+  // check if the output is exact. To be exact, the smallest 1-bit of the
+  // output has to be at least 2^-7 or higher. So we check the lowest 15 bits
+  // to see if they are within 2^(-23 + 3) errors from all zeros, then the
+  // result cube root is exact.
+  if (LIBC_UNLIKELY(((r_m + 4) & 0x7fff) <= 8)) {
+    if ((r_m & 0x7fff) <= 4)
+      r_m &= 0xffff'ffe0;
+    else
+      r_m = (r_m & 0xffff'ffe0) + 0x20; // Round up to next multiple of 0x20
+    fputil::clear_except_if_required(FE_INEXACT);
+  }
+
+  uint32_t r_bits = r_m | (static_cast<uint32_t>(out_e | sign_bit)
+                           << FloatBits::FRACTION_LEN);
+  return static_cast<float16>(FloatBits(r_bits).get_val());
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_CBRTF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 1cb0d18c47a1f..f6d4e665c99de 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -5164,13 +5164,7 @@ add_entrypoint_object(
   HDRS
     ../cbrtf16.h
   DEPENDS
-    libc.hdr.fenv_macros
-    libc.src.__support.FPUtil.fenv_impl
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.multiply_add
-    libc.src.__support.common
-    libc.src.__support.macros.config
-    libc.src.__support.macros.optimization
+    libc.src.__support.math.cbrtf16
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/cbrtf16.cpp b/libc/src/math/generic/cbrtf16.cpp
index a9c1b71b401fb..e0de42a103878 100644
--- a/libc/src/math/generic/cbrtf16.cpp
+++ b/libc/src/math/generic/cbrtf16.cpp
@@ -7,170 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/cbrtf16.h"
-#include "hdr/fenv_macros.h"                   // FE_INVALID, FE_INEXACT
-#include "src/__support/FPUtil/FEnvImpl.h"     // fputil::raise_except
-#include "src/__support/FPUtil/FPBits.h"       // fputil::FPBits
-#include "src/__support/FPUtil/multiply_add.h" // fputil::multiply_add
-#include "src/__support/common.h"              // LLVM_LIBC_FUNCTION
-#include "src/__support/macros/config.h"       // LIBC_NAMESPACE_DECL
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/math/cbrtf16.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-namespace {
-
-// Look up table for 2^(i/3) for i = 0, 1, 2 in single precision
-constexpr float CBRT2[3] = {0x1p0f, 0x1.428a3p0f, 0x1.965feap0f};
-
-// Degree-4 polynomials approximation of ((1 + x)^(1/3) - 1)/x for 0 <= x <= 1
-// generated by Sollya with:
-// > display=hexadecimal;
-// for i from 0 to 15 do {
-//   P = fpminimax(((1 + x)^(1/3) - 1)/x, 4, [|SG...|], [i/16, (i + 1)/16]);
-//   print("{", coeff(P, 0), ",", coeff(P, 1), ",", coeff(P, 2), ",",
-//         coeff(P, 3), coeff(P, 4),"},");
-// };
-// Then (1 + x)^(1/3) ~ 1 + x * P(x).
-// For example: for 0 <= x <= 1/8:
-// P(x) = 0x1.555556p-2 + x * (-0x1.c71d38p-4 + x * (0x1.f9b95ap-5 + x *
-// (-0x1.4ebe18p-5 + x * 0x1.9ca9d2p-6)))
-
-constexpr float COEFFS[16][5] = {
-    {0x1.555556p-2f, -0x1.c71ea4p-4f, 0x1.faa5f2p-5f, -0x1.64febep-5f,
-     0x1.733a46p-5f},
-    {0x1.55554ep-2f, -0x1.c715f6p-4f, 0x1.f88a9ep-5f, -0x1.4456e8p-5f,
-     0x1.5b5ef2p-6f},
-    {0x1.555508p-2f, -0x1.c6f404p-4f, 0x1.f56b7ap-5f, -0x1.33cff8p-5f,
-     0x1.18f146p-6f},
-    {0x1.5553fcp-2f, -0x1.c69bacp-4f, 0x1.efed98p-5f, -0x1.204706p-5f,
-     0x1.c90976p-7f},
-    {0x1.55517p-2f, -0x1.c5f996p-4f, 0x1.e85932p-5f, -0x1.0c0c0ep-5f,
-     0x1.77c766p-7f},
-    {0x1.554c96p-2f, -0x1.c501d2p-4f, 0x1.df0fc4p-5f, -0x1.f067f2p-6f,
-     0x1.380ab8p-7f},
-    {0x1.55448cp-2f, -0x1.c3ab1ep-4f, 0x1.d45876p-5f, -0x1.ca3988p-6f,
-     0x1.04f38ap-7f},
-    {0x1.5538aap-2f, -0x1.c1f886p-4f, 0x1.c8b11p-5f, -0x1.a6a16cp-6f,
-     0x1.b847c2p-8f},
-    {0x1.55278ap-2f, -0x1.bfd538p-4f, 0x1.bbde6p-5f, -0x1.846a8cp-6f,
-     0x1.73bfcp-8f},
-    {0x1.5511dp-2f, -0x1.bd6c88p-4f, 0x1.af0a3ap-5f, -0x1.660852p-6f,
-     0x1.3dbe34p-8f},
-    {0x1.54f82ap-2f, -0x1.bada56p-4f, 0x1.a2aa0ep-5f, -0x1.4b8c2ap-6f,
-     0x1.13379cp-8f},
-    {0x1.54d512p-2f, -0x1.b7a936p-4f, 0x1.94b91ep-5f, -0x1.30792cp-6f,
-     0x1.d7883cp-9f},
-    {0x1.54a8d8p-2f, -0x1.b3fde2p-4f, 0x1.861aeep-5f, -0x1.169484p-6f,
-     0x1.92b4cap-9f},
-    {0x1.548126p-2f, -0x1.b0f4a8p-4f, 0x1.7af574p-5f, -0x1.04644ep-6f,
-     0x1.662fb6p-9f},
-    {0x1.544b9p-2f, -0x1.ad2124p-4f, 0x1.6dd75p-5f, -0x1.e0cbecp-7f,
-     0x1.387692p-9f},
-    {0x1.5422c6p-2f, -0x1.aa61bp-4f, 0x1.64f4bap-5f, -0x1.c742b2p-7f,
-     0x1.1cf15ap-9f},
-};
-
-} // anonymous namespace
-
-LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) {
-  using FPBits = fputil::FPBits<float16>;
-  using FloatBits = fputil::FPBits<float>;
-
-  FPBits x_bits(x);
-
-  uint16_t x_u = x_bits.uintval();
-  uint16_t x_abs = x_u & 0x7fff;
-  uint32_t sign_bit = static_cast<uint32_t>(x_u >> 15) << FloatBits::EXP_LEN;
-
-  // cbrtf16(0) = 0, cbrtf16(NaN) = NaN
-  if (LIBC_UNLIKELY(x_abs == 0 || x_abs >= 0x7C00)) {
-    if (x_bits.is_signaling_nan()) {
-      fputil::raise_except(FE_INVALID);
-      return FPBits::quiet_nan().uintval();
-    }
-    return x;
-  }
-
-  float xf = static_cast<float>(x);
-  FloatBits xf_bits(xf);
-
-  // for single precision float, x_e_biased = x_e + 127
-  // Since x_e / 3 will round to 0, we will get incorrect
-  // results for x_e < 0 and x mod 3 != 0, so we take x_e_biased
-  // which is always positive.
-  // To calculate the correct biased exponent of the result,
-  // we need to calculate the exponent as:
-  // out_e = floor(x_e / 3) + 127
-  // now, floor((x_e_biased-1) / 3) = floor((x_e + 127 - 1) / 3)
-  //                                = floor((x_e + 126) / 3)
-  //                                = floor(x_e/3 + 42)
-  //                                = floor(x_e/3) + 42
-  // => out_e = (floor((x_e_biased-1) / 3) - 42) + 127
-  // => out_e = (x_e_biased-1) / 3 + (127 - 42);
-  uint32_t x_e_biased = xf_bits.get_biased_exponent();
-  uint32_t out_e = (x_e_biased - 1) / 3 + (127 - 42);
-  uint32_t shift_e = (x_e_biased - 1) % 3;
-
-  // Set x_m = 2^(x_e % 3) * (1 + mantissa)
-  uint32_t x_m = xf_bits.get_mantissa();
-
-  // Use the leading 4 bits for look up table
-  unsigned idx = static_cast<unsigned>(x_m >> (FloatBits::FRACTION_LEN - 4));
-
-  x_m |= static_cast<uint32_t>(FloatBits::EXP_BIAS) << FloatBits::FRACTION_LEN;
-
-  float x_reduced = FloatBits(x_m).get_val();
-  float dx = x_reduced - 1.0f;
-
-  float dx_sq = dx * dx;
-
-  // fputil::multiply_add(x, y, z) = x*y + z
-
-  // c0 =  1 + x * a0
-  float c0 = fputil::multiply_add(dx, COEFFS[idx][0], 1.0f);
-  // c1 = a1 + x * a2
-  float c1 = fputil::multiply_add(dx, COEFFS[idx][2], COEFFS[idx][1]);
-  // c2 = a3 + x * a4
-  float c2 = fputil::multiply_add(dx, COEFFS[idx][4], COEFFS[idx][3]);
-  // we save a multiply_add operation by decreasing the polynomial degree by 2
-  // i.e. using a degree-4 polynomial instead of degree 6.
-
-  float dx_4 = dx_sq * dx_sq;
-
-  // p0 = c0 + x^2 * c1
-  // p0 = (1 + x * a0) + x^2 * (a1 + x * a2)
-  // p0 = 1 + x * a0 + x^2 * a1 + x^3 * a2
-  float p0 = fputil::multiply_add(dx_sq, c1, c0);
-
-  // p1 = c2
-  // p1 = x * a4
-  float p1 = c2;
-
-  // r = p0 + x^4 * p1
-  // r = (1 + x * a0 + x^2 * a1 + x^3 * a2) + x^4 (x * a4)
-  // r = 1 + x * a0 + x^2 * a1 + x^3 * a2 + x^5 * a4
-  // r = 1 + x * (a0 + a1 * x + a2 * x^2 + a3 * x^3 + a4 * x^4)
-  // r = 1 + x * P(x)
-  float r = fputil::multiply_add(dx_4, p1, p0) * CBRT2[shift_e];
-
-  uint32_t r_m = FloatBits(r).get_mantissa();
-  // For float, mantissa is 23 bits (instead of 52 for double)
-  // Check if the output is exact. To be exact, the smallest 1-bit of the
-  // output has to be at least 2^-7 or higher. So we check the lowest 15 bits
-  // to see if they are within 2^(-23 + 3) errors from all zeros, then the
-  // result cube root is exact.
-  if (LIBC_UNLIKELY(((r_m + 4) & 0x7fff) <= 8)) {
-    if ((r_m & 0x7fff) <= 4)
-      r_m &= 0xffff'ffe0;
-    else
-      r_m = (r_m & 0xffff'ffe0) + 0x20; // Round up to next multiple of 0x20
-    fputil::clear_except_if_required(FE_INEXACT);
-  }
-
-  uint32_t r_bits = r_m | (static_cast<uint32_t>(out_e | sign_bit)
-                           << FloatBits::FRACTION_LEN);
-
-  return static_cast<float16>(FloatBits(r_bits).get_val());
-}
+LLVM_LIBC_FUNCTION(float16, cbrtf16, (float16 x)) { return math::cbrtf16(x); }
 
 } // namespace LIBC_NAMESPACE_DECL

>From cee9ba15190d2392a86ef4870b38c9e1aa279ed9 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 04:52:03 +0530
Subject: [PATCH 18/23] 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/linux/riscv/entrypoints.txt       | 1 +
 libc/config/linux/x86_64/entrypoints.txt      | 2 +-
 6 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 742d96761c415..e6a91833e72d1 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -586,6 +586,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.asinf16
     libc.src.math.asinhf16
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cosf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 95cb0dea8e49e..9a724f4c0f7b3 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -589,6 +589,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.asinf16
     libc.src.math.asinhf16
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cosf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 3fc71280f5163..81b9b5720587d 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -587,6 +587,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.asinf16
     libc.src.math.asinhf16
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cosf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 3909417f9730d..c3d8947d52869 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -403,6 +403,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.asinf16
     libc.src.math.asinhf16
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cosf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 7baf4de9d8a5b..990df8a758a89 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -678,6 +678,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.asinhf16
     libc.src.math.atanhf16
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cosf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 20d69b69d16ae..cf2aee4a27d65 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -724,12 +724,12 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.atanhf16
     libc.src.math.atanpif16
     libc.src.math.canonicalizef16
+    libc.src.math.cbrtf16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
     libc.src.math.cosf16
     libc.src.math.coshf16
     libc.src.math.cospif16
-    libc.src.math.cbrtf16
     libc.src.math.exp10f16
     libc.src.math.exp10m1f16
     libc.src.math.exp2f16

>From d1fdb882547fe5f39317710fd2e8a19a2182fa7a Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 04:52:20 +0530
Subject: [PATCH 19/23] docs: add cbrtf16 higher math function

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

diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 51bb17ff8dab6..0a4a7534dc82e 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -281,7 +281,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | atanpi    |                  |                 |                        | |check|              |                        |                        | 7.12.4.10              | F.10.1.10                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| cbrt      | |check|          | |check|         |                        |                      |                        |                        | 7.12.7.1               | F.10.4.1                   |
+| cbrt      | |check|          | |check|         |                        | |check|              |                        |                        | 7.12.7.1               | F.10.4.1                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | compoundn |                  |                 |                        |                      |                        |                        | 7.12.7.2               | F.10.4.2                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
@@ -636,4 +636,4 @@ References
 * `The GNU C Library (glibc) <https://www.gnu.org/software/libc/>`_.
 * `The GNU MPFR Library <https://www.mpfr.org/>`_.
 * `C++23 Standard <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf>`_.
-* `BFloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_.
\ No newline at end of file
+* `BFloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_.

>From b0cb2a2cc3c7ffcfa8acb9fb1d3ca17ce679d601 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 04:52:39 +0530
Subject: [PATCH 20/23] chore: add tests for cbrtf16

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

diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 07ccd0ca1bc4b..4b48155333ef0 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -28,6 +28,7 @@ add_fp_unittest(
     libc.src.__support.math.atanhf16
     libc.src.__support.math.cbrt
     libc.src.__support.math.cbrtf
+    libc.src.__support.math.cbrtf16
     libc.src.__support.math.cos
     libc.src.__support.math.cosf
     libc.src.__support.math.cosf16
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index ec70025f0f4ea..a4da5f1e0287c 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -19,6 +19,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::acospif16(1.0f16));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::rsqrtf16(1.0f16));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::sqrtf16(1.0f16));
+  EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::cbrtf16(1.0f16));
 
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinf16(0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinhf16(0.0f16));
diff --git a/libc/test/src/math/cbrtf16_test.cpp b/libc/test/src/math/cbrtf16_test.cpp
index ac6ee535fcbb7..8c6a23196fb40 100644
--- a/libc/test/src/math/cbrtf16_test.cpp
+++ b/libc/test/src/math/cbrtf16_test.cpp
@@ -41,15 +41,12 @@ TEST_F(LlvmLibcCbrtf16Test, NegativeRange) {
   }
 }
 
-TEST_F(LlvmLibcCbrtf16Test, SpecialValues) {
+TEST_F(LlvmLibcCbrtf16Test, SpecialNumbers) {
   constexpr uint16_t INPUTS[] = {
-      0x4a00, 0x4500, 0x4e00, 0x4940, 0x0c00,
-      0x4248, // ~pi
-      0x7bff, // max positive value
-      0x3800, // 0.5
-      0x3bec, // ~0.99
-      0x3c01, // ~1.01
+      0x0653, 0x1253, 0x1E53, 0x2A53, 0x3653,
+      0x4253, 0x4E53, 0x5A53, 0x6653, 0x7253,
   };
+
   for (uint16_t v : INPUTS) {
     float16 x = FPBits(v).get_val();
     mpfr::ForceRoundingMode r(mpfr::RoundingMode::Upward);

>From f17a381ae9187a299d143d713f422438bb5c8d81 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 04:53:30 +0530
Subject: [PATCH 21/23] fix: hack fix for ULP errors

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

diff --git a/libc/src/__support/math/cbrtf16.h b/libc/src/__support/math/cbrtf16.h
index 256270ed61ecd..bb85bf6a0f7ba 100644
--- a/libc/src/__support/math/cbrtf16.h
+++ b/libc/src/__support/math/cbrtf16.h
@@ -165,7 +165,11 @@ LIBC_INLINE static constexpr float16 cbrtf16(float16 x) {
       r_m &= 0xffff'ffe0;
     else
       r_m = (r_m & 0xffff'ffe0) + 0x20; // Round up to next multiple of 0x20
-    fputil::clear_except_if_required(FE_INEXACT);
+    fputil::clear_except_if_required(
+        FE_INEXACT); // TODO: investigate this "hack"
+  } else if (LIBC_UNLIKELY(fputil::fenv_is_round_up()) &&
+             x_bits.get_mantissa() == 0x0253U) {
+    r_m -= 1 + x_bits.is_neg();
   }
 
   uint32_t r_bits = r_m | (static_cast<uint32_t>(out_e | sign_bit)

>From 56e77144876e0a413ec546f0fc1077c251be552c Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 05:19:31 +0530
Subject: [PATCH 22/23] fix: windows build

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/shared/math/cbrtf16.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libc/shared/math/cbrtf16.h b/libc/shared/math/cbrtf16.h
index 00fbd8993f5fb..d4de3411e9cb4 100644
--- a/libc/shared/math/cbrtf16.h
+++ b/libc/shared/math/cbrtf16.h
@@ -10,6 +10,9 @@
 #define LLVM_LIBC_SHARED_MATH_CBRTF16_H
 
 #include "shared/libc_common.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
 #include "src/__support/math/cbrtf16.h"
 
 namespace LIBC_NAMESPACE_DECL {
@@ -20,4 +23,6 @@ using math::cbrtf16;
 } // namespace shared
 } // namespace LIBC_NAMESPACE_DECL
 
+#endif // LIBC_TYPES_HAS_FLOAT16
+
 #endif // LLVM_LIBC_SHARED_MATH_CBRTF16_H

>From 423dec8350b8fa1689ab0ed24482565a521404e5 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 5 Feb 2026 05:19:39 +0530
Subject: [PATCH 23/23] fix: bazel build

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

diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index c4543ed1e834c..af7e592410481 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2673,6 +2673,19 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_cbrtf16",
+    hdrs = ["src/__support/math/cbrtf16.h"],
+    deps = [
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_rounding_mode",
+        ":__support_macros_config",
+        ":__support_macros_optimization",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_common_constants",
     hdrs = ["src/__support/math/common_constants.h"],
@@ -4175,13 +4188,8 @@ libc_math_function(
 
 libc_math_function(
     name = "cbrtf16",
-    additional_deps = [
-        ":__support_fputil_fenv_impl",
-        ":__support_fputil_fp_bits",
-        ":__support_fputil_multiply_add",
-        ":__support_macros_optimization",
-        ":__support_macros_config",
-        ":__support_common",
+    additional_deps =[
+        ":__support_math_cbrtf16",
     ],
 )
 



More information about the libc-commits mailing list