[libc-commits] [libc] [llvm] [libc][math][c23] Add tanbf16 math function (PR #185100)
via libc-commits
libc-commits at lists.llvm.org
Sun Jun 7 03:35:26 PDT 2026
https://github.com/Sukumarsawant updated https://github.com/llvm/llvm-project/pull/185100
>From 8ce7411296619352162b784c9e7a770f1c814c1c Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 5 Mar 2026 23:47:04 +0530
Subject: [PATCH 01/10] feat: implementation for tanbf16
t1
initial commit
entrypoints
t1
t2
t3
t3
tanbf16_add
---
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 +
libc/shared/math.h | 1 +
libc/shared/math/tanbf16.h | 23 +++++
libc/src/__support/math/CMakeLists.txt | 18 ++++
libc/src/__support/math/tanbf16.h | 82 ++++++++++++++++++
libc/src/__support/math/tanf16.h | 2 +-
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/generic/CMakeLists.txt | 11 +++
libc/src/math/generic/tanbf16.cpp | 17 ++++
libc/src/math/tanbf16.h | 21 +++++
libc/test/shared/CMakeLists.txt | 1 +
libc/test/shared/shared_math_test.cpp | 83 +------------------
libc/test/src/math/CMakeLists.txt | 13 +++
libc/test/src/math/smoke/CMakeLists.txt | 13 +++
libc/test/src/math/smoke/tanbf16_test.cpp | 41 +++++++++
libc/test/src/math/tanbf16_test.cpp | 76 +++++++++++++++++
.../llvm-project-overlay/libc/BUILD.bazel | 26 ++++++
28 files changed, 358 insertions(+), 83 deletions(-)
create mode 100644 libc/shared/math/tanbf16.h
create mode 100644 libc/src/__support/math/tanbf16.h
create mode 100644 libc/src/math/generic/tanbf16.cpp
create mode 100644 libc/src/math/tanbf16.h
create mode 100644 libc/test/src/math/smoke/tanbf16_test.cpp
create mode 100644 libc/test/src/math/tanbf16_test.cpp
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 746bdc0a64ee7..b7af7bf2b0a4a 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -860,6 +860,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index a43bbb865bafd..16b7e60ef97b3 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -871,6 +871,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index fd5d92321a746..efca25685fdd7 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -868,6 +868,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 01ae40c898734..4ad51cea59e40 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -681,6 +681,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index b941c968255e8..afa3e349a5b1d 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -303,6 +303,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index bbd15a131ca24..dc6f1b1a628aa 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -709,6 +709,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index ade635e095994..4dcaeb9949abf 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -711,6 +711,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 4c6b43a3dba8e..f21ef229527ce 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -975,6 +975,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 49b30ef1830f3..670a5d154228e 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -550,6 +550,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index e4116fd4c25ae..9cd47b0f6b147 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -996,6 +996,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 616159737b3f2..3b63b03c277b1 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1061,6 +1061,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 94d1d00e676d9..ea2855d58e11f 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -392,6 +392,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
diff --git a/libc/shared/math.h b/libc/shared/math.h
index e75c4b2d229ba..c09300b3eaaf5 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -471,6 +471,7 @@
#include "math/sqrtf16.h"
#include "math/sqrtl.h"
#include "math/tan.h"
+#include "math/tanbf16.h"
#include "math/tanf.h"
#include "math/tanf16.h"
#include "math/tanhf.h"
diff --git a/libc/shared/math/tanbf16.h b/libc/shared/math/tanbf16.h
new file mode 100644
index 0000000000000..24006da13b4dd
--- /dev/null
+++ b/libc/shared/math/tanbf16.h
@@ -0,0 +1,23 @@
+//===-- Shared tanbf16 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_TANBF16_H
+#define LLVM_LIBC_SHARED_MATH_TANBF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/tanbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::tanbf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_TANBF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index b6b397c88a256..4f0f55f2b2a8c 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -5348,6 +5348,24 @@ add_header_library(
libc.src.__support.macros.optimization
)
+
+add_header_library(
+ tanbf16
+ HDRS
+ tanbf16.h
+ DEPENDS
+ .sincosf16_utils
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.macros.optimization
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_header_library(
tanf
HDRS
diff --git a/libc/src/__support/math/tanbf16.h b/libc/src/__support/math/tanbf16.h
new file mode 100644
index 0000000000000..99d0369bc3dd5
--- /dev/null
+++ b/libc/src/__support/math/tanbf16.h
@@ -0,0 +1,82 @@
+//===-- Single-precision tanbf16 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_TANBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_TANBF16_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "sincosf16_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.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/macros/optimization.h"
+#include "src/__support/FPUtil/bfloat16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
+ using namespace sincosf16_internal;
+ using FPBits = fputil::FPBits<bfloat16>;
+ FPBits xbits(x);
+
+ uint16_t x_u = xbits.uintval();
+ uint16_t x_abs = x_u & 0x7fff;
+
+ //NaN or -/+ INF
+ if(x_abs >= 0x7F80){
+ //NaN
+ if(xbits.is_nan()){
+ if(xbits.is_signaling_nan()){
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x;
+ }
+ //|x| is +/- INF
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ // |x| = {0}
+ if(LIBC_UNLIKELY(x_abs== 0)){
+ return x;
+ }
+ float xf = x;
+ // Through Exhaustive testing
+ // The last value where tan(x) ~ x is 0x3db8
+ if (LIBC_UNLIKELY(x_abs <= 0x3db8)) {
+ int rounding = fputil::quick_get_round();
+
+ // tan(x) is always slightly larger in magnitude than x
+ // so when rounding away from zero, correct answer is x - 1 ULP
+ if ((xbits.is_pos() && rounding == FE_UPWARD) ||
+ (xbits.is_neg() && rounding == FE_DOWNWARD))
+ return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
+ return x;
+ }
+
+ float sin_k, cos_k, sin_y, cosm1_y;
+ sincosf16_eval(xf, sin_k, cos_k, sin_y, cosm1_y);
+
+ using fputil::multiply_add;
+ return fputil::cast<bfloat16>(
+ multiply_add(sin_y, cos_k, multiply_add(cosm1_y, sin_k, sin_k)) /
+ multiply_add(sin_y, -sin_k, multiply_add(cosm1_y, cos_k, cos_k)));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_TANBF16_H
diff --git a/libc/src/__support/math/tanf16.h b/libc/src/__support/math/tanf16.h
index 6b9b9224fb84d..eda872ee7ab0a 100644
--- a/libc/src/__support/math/tanf16.h
+++ b/libc/src/__support/math/tanf16.h
@@ -76,7 +76,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
// tan(x) = x * 2^-11 + x
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD))
- return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
+ return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
return x;
}
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 730c0c06073e1..b5efbb59eed0f 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -584,6 +584,7 @@ add_math_entrypoint_object(sqrtf128)
add_math_entrypoint_object(sqrtbf16)
add_math_entrypoint_object(tan)
+add_math_entrypoint_object(tanbf16)
add_math_entrypoint_object(tanf)
add_math_entrypoint_object(tanf16)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 4c3eac4c3356c..0b8428f5cd622 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -415,6 +415,17 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ tanbf16
+ SRCS
+ tanbf16.cpp
+ HDRS
+ ../tanbf16.h
+ DEPENDS
+ libc.src.__support.math.tanbf16
+)
+
+
add_entrypoint_object(
tanf
SRCS
diff --git a/libc/src/math/generic/tanbf16.cpp b/libc/src/math/generic/tanbf16.cpp
new file mode 100644
index 0000000000000..40d0443a75fb1
--- /dev/null
+++ b/libc/src/math/generic/tanbf16.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation for tanbf16(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/tanbf16.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/math/tanbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, tanbf16, (bfloat16 x)) { return math::tanbf16(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/tanbf16.h b/libc/src/math/tanbf16.h
new file mode 100644
index 0000000000000..034167d3bb9c2
--- /dev/null
+++ b/libc/src/math/tanbf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for tanbf16 -----------------------*- 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_TANBF16_H
+#define LLVM_LIBC_SRC_MATH_TANBF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 tanbf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_TANBF16_H
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 7a5c3a369c2fc..7184d00cf1399 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -476,6 +476,7 @@ add_fp_unittest(
libc.src.__support.math.sqrtf
libc.src.__support.math.sqrtl
libc.src.__support.math.tan
+ libc.src.__support.math.tanbf16
libc.src.__support.math.tanf
libc.src.__support.math.tanf16
libc.src.__support.math.tanhf
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 571861ecbdfae..bdec3837d5a36 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -808,86 +808,5 @@ TEST(LlvmLibcSharedMathTest, AllBFloat16) {
EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::nextafterbf16(
bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(1.0), LIBC_NAMESPACE::shared::sqrtbf16(bfloat16(1.0)));
- // TODO: This test case just failed only when building with gcc-13 and only
- // for `ninja libc.test.shared.shared_math_test.__unit__.__NO_FMA_OPT
- // Other gcc versions or other sub-targets work fine.
- // https://github.com/llvm/llvm-project/issues/199332
- // #ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
- // EXPECT_FP_EQ(bfloat16(0.0),
- // LIBC_NAMESPACE::shared::nexttowardbf16(bfloat16(0.0),
- // 0.0L));
- // #endif // LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
-
- EXPECT_EQ(0, LIBC_NAMESPACE::shared::ilogbbf16(bfloat16(1.0)));
- EXPECT_EQ(0L, LIBC_NAMESPACE::shared::llogbbf16(bfloat16(1.0)));
-
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fmaximumbf16(
- bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fminimumbf16(
- bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::fminbf16(bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fmaximum_numbf16(
- bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fminimum_numbf16(
- bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::fromfpbf16(bfloat16(0.0), 0, 32));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::fromfpxbf16(bfloat16(0.0), 0, 32));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::ufromfpbf16(bfloat16(0.0), 0, 32));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::ufromfpxbf16(bfloat16(0.0), 0, 32));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fmaximum_magbf16(
- bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fminimum_magbf16(
- bfloat16(0.0), bfloat16(0.0)));
- bfloat16 totalorderbf16_x = bfloat16(0.0);
- bfloat16 totalorderbf16_y = bfloat16(0.0);
- EXPECT_EQ(1, LIBC_NAMESPACE::shared::totalorderbf16(&totalorderbf16_x,
- &totalorderbf16_y));
- bfloat16 totalordermagbf16_x = bfloat16(0.0);
- bfloat16 totalordermagbf16_y = bfloat16(0.0);
- EXPECT_EQ(1, LIBC_NAMESPACE::shared::totalordermagbf16(&totalordermagbf16_x,
- &totalordermagbf16_y));
- LIBC_NAMESPACE::shared::fmodbf16(bfloat16(1.0), bfloat16(1.0));
- bfloat16 modfbf16_iptr = bfloat16(0.0);
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::modfbf16(bfloat16(0.0), &modfbf16_iptr));
- EXPECT_FP_EQ(bfloat16(0.0), modfbf16_iptr);
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::fminimum_mag_numbf16(
- bfloat16(0.0), bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::remainderbf16(
- bfloat16(1.0), bfloat16(1.0)));
- int remquobf16_exp = 0;
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::remquobf16(bfloat16(1.0), bfloat16(1.0),
- &remquobf16_exp));
- EXPECT_EQ(1, remquobf16_exp);
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::ldexpbf16(bfloat16(0.0), 0));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::scalblnbf16(bfloat16(0.0), 0L));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::scalbnbf16(bfloat16(0.0), 0));
- int frexpbf16_exp = 0;
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::frexpbf16(
- bfloat16(0.0), &frexpbf16_exp));
- EXPECT_EQ(0, frexpbf16_exp);
- EXPECT_EQ(0L, LIBC_NAMESPACE::shared::lrintbf16(bfloat16(0.0)));
- EXPECT_EQ(0L, LIBC_NAMESPACE::shared::lroundbf16(bfloat16(0.0)));
- EXPECT_EQ(0LL, LIBC_NAMESPACE::shared::llrintbf16(bfloat16(0.0)));
- EXPECT_EQ(0LL, LIBC_NAMESPACE::shared::llroundbf16(bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::nearbyintbf16(bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::rintbf16(bfloat16(0.0)));
- EXPECT_EQ(1, LIBC_NAMESPACE::shared::iscanonicalbf16(bfloat16(0.0)));
- EXPECT_EQ(0, LIBC_NAMESPACE::shared::issignalingbf16(bfloat16(0.0)));
- EXPECT_TRUE(FPBits(LIBC_NAMESPACE::shared::nanbf16("")).is_nan());
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::roundbf16(bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0),
- LIBC_NAMESPACE::shared::roundevenbf16(bfloat16(0.0)));
- EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::truncbf16(bfloat16(0.0)));
+ EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::tanbf16(bfloat16(0.0)));
}
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 4213c11eca515..bfef01e584a38 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -201,6 +201,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ tanbf16_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ tanbf16_test.cpp
+ DEPENDS
+ libc.src.math.tanbf16
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
tanf_test
NEED_MPFR
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index bb462afb71b91..af0c5036dc11c 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -110,6 +110,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ tanbf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ tanbf16_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.src.math.tanbf16
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
tanf_test
SUITE
diff --git a/libc/test/src/math/smoke/tanbf16_test.cpp b/libc/test/src/math/smoke/tanbf16_test.cpp
new file mode 100644
index 0000000000000..4e760b4a747e4
--- /dev/null
+++ b/libc/test/src/math/smoke/tanbf16_test.cpp
@@ -0,0 +1,41 @@
+//===-- Unittests for tanbf16 ---------------------------------------------===//
+//
+//
+// 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 "src/__support/FPUtil/bfloat16.h"
+#include "src/math/tanbf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcTanBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+ DECLARE_SPECIAL_CONSTANTS(bfloat16)
+public:
+ void test_special_numbers() {
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::tanbf16(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+ aNaN, LIBC_NAMESPACE::tanbf16(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::tanbf16(zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::tanbf16(neg_zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::tanbf16(inf));
+ EXPECT_MATH_ERRNO(EDOM);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::tanbf16(neg_inf));
+ EXPECT_MATH_ERRNO(EDOM);
+ }
+};
+TEST_F(LlvmLibcTanBf16Test, SpecialNumbers) { test_special_numbers(); }
diff --git a/libc/test/src/math/tanbf16_test.cpp b/libc/test/src/math/tanbf16_test.cpp
new file mode 100644
index 0000000000000..b4e5f5a2fb12b
--- /dev/null
+++ b/libc/test/src/math/tanbf16_test.cpp
@@ -0,0 +1,76 @@
+//===-- Exhaustive test for tanbf16 ---------------------------------------===//
+//
+// 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/tanbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include <iostream>
+
+using LlvmLibcTanBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// Range: [-Inf, 0]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcTanBf16Test, PositiveRange) {
+ uint16_t last_equal = 0; // remove
+ for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+ bfloat16 x = FPBits(v).get_val();
+
+ bfloat16 result = LIBC_NAMESPACE::tanbf16(x);
+ // Check if tan(x) rounds to x itself
+ if (FPBits(result).uintval() == v) {
+ last_equal = v;
+ } else {
+ // First x where tan(x) != x — print and stop
+ bfloat16 prev = FPBits(last_equal).get_val();
+ std::cout << "Last x where tan(x)==x: "
+ << "hex=0x" << std::hex << last_equal << " value=" << std::dec
+ << (float)prev << "\n";
+ std::cout << "First x where tan(x)!=x: "
+ << "hex=0x" << std::hex << v << " value=" << std::dec
+ << (float)x << "\n";
+ std::cout << "tan(first_diff_x)=" << (float)result << "\n";
+ std::cout << "\n=== USE IN CODE ===\n"
+ << "if (x_abs <= 0x" << std::hex << last_equal
+ << "U) // tan(x)==x for bfloat16\n";
+ break;
+ }
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Tan, x,
+ LIBC_NAMESPACE::tanbf16(x), 0.5);
+ }
+}
+
+TEST_F(LlvmLibcTanBf16Test, NegativeRange) {
+ uint16_t last_equal = 0x8000; // remove
+ for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+ bfloat16 x = FPBits(v).get_val();
+
+ bfloat16 result = LIBC_NAMESPACE::tanbf16(x);
+ if (FPBits(result).uintval() == v) {
+ last_equal = v;
+ } else {
+ std::cout << "Negative — last equal: "
+ << "hex=0x" << std::hex << last_equal << " value=" << std::dec
+ << (float)FPBits(last_equal).get_val() << "\n";
+ break;
+ }
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Tan, x,
+ LIBC_NAMESPACE::tanbf16(x), 0.5);
+ }
+}
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 46da65b791918..7d56f8ea2ec87 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -8975,6 +8975,24 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_math_tanbf16",
+ hdrs = ["src/__support/math/tanbf16.h"],
+ deps = [
+ ":__support_fputil_cast",
+ ":__support_fputil_except_value_utils",
+ ":__support_fputil_fenv_impl",
+ ":__support_fputil_fp_bits",
+ ":__support_fputil_multiply_add",
+ ":__support_macros_optimization",
+ ":__support_macros_properties_types",
+ ":__support_math_sincosf16_utils",
+ ":hdr_errno_macros",
+ ":hdr_fenv_macros",
+ ":__support_fputil_bfloat16",
+ ],
+)
+
libc_support_library(
name = "__support_math_tanf",
hdrs = ["src/__support/math/tanf.h"],
@@ -12665,6 +12683,14 @@ libc_math_function(
additional_deps = [":__support_math_tan"],
)
+libc_math_function(
+ name = "tanbf16",
+ additional_deps = [
+ ":__support_math_tanbf16",
+ ],
+)
+
+
libc_math_function(
name = "tanf",
additional_deps = [":__support_math_tanf"],
>From 7b8af8e2a3fc414fe27943f2b63ba28912b29110 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 01:42:34 +0530
Subject: [PATCH 02/10] feat: added tests and corrections
---
libc/src/__support/math/CMakeLists.txt | 1 -
libc/src/__support/math/tanbf16.h | 24 +++++++++----------
.../llvm-project-overlay/libc/BUILD.bazel | 1 -
3 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 4f0f55f2b2a8c..3454365fbd5ec 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -5360,7 +5360,6 @@ add_header_library(
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.multiply_add
libc.src.__support.macros.optimization
libc.src.__support.FPUtil.bfloat16
diff --git a/libc/src/__support/math/tanbf16.h b/libc/src/__support/math/tanbf16.h
index 99d0369bc3dd5..57d3614e9de59 100644
--- a/libc/src/__support/math/tanbf16.h
+++ b/libc/src/__support/math/tanbf16.h
@@ -1,4 +1,4 @@
-//===-- Single-precision tanbf16 function ---------------------------------===//
+//===-- Implementation of tanbf16 function --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -14,11 +14,10 @@
#include "sincosf16_utils.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/macros/optimization.h"
-#include "src/__support/FPUtil/bfloat16.h"
namespace LIBC_NAMESPACE_DECL {
@@ -31,12 +30,13 @@ LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
uint16_t x_u = xbits.uintval();
uint16_t x_abs = x_u & 0x7fff;
+ float xf = x;
- //NaN or -/+ INF
- if(x_abs >= 0x7F80){
- //NaN
- if(xbits.is_nan()){
- if(xbits.is_signaling_nan()){
+ // NaN or -/+ INF
+ if (x_abs >= 0x7F80) {
+ // NaN
+ if (xbits.is_nan()) {
+ if (xbits.is_signaling_nan()) {
fputil::raise_except_if_required(FE_INVALID);
return FPBits::quiet_nan().get_val();
}
@@ -49,17 +49,15 @@ LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
}
// |x| = {0}
- if(LIBC_UNLIKELY(x_abs== 0)){
+ if (LIBC_UNLIKELY(x_abs == 0)) {
return x;
}
- float xf = x;
+
// Through Exhaustive testing
// The last value where tan(x) ~ x is 0x3db8
if (LIBC_UNLIKELY(x_abs <= 0x3db8)) {
int rounding = fputil::quick_get_round();
-
- // tan(x) is always slightly larger in magnitude than x
- // so when rounding away from zero, correct answer is x - 1 ULP
+ // separate case handles it with magnitude of 2^-13
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD))
return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 7d56f8ea2ec87..3c62e46c25827 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -8980,7 +8980,6 @@ libc_support_library(
hdrs = ["src/__support/math/tanbf16.h"],
deps = [
":__support_fputil_cast",
- ":__support_fputil_except_value_utils",
":__support_fputil_fenv_impl",
":__support_fputil_fp_bits",
":__support_fputil_multiply_add",
>From 81637f6daf9917296e412219dbb26067881cf130 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 01:44:14 +0530
Subject: [PATCH 03/10] chore: bazel
---
utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 3c62e46c25827..3c0bcafc7b097 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -8979,6 +8979,7 @@ libc_support_library(
name = "__support_math_tanbf16",
hdrs = ["src/__support/math/tanbf16.h"],
deps = [
+ ":__support_fputil_bfloat16",
":__support_fputil_cast",
":__support_fputil_fenv_impl",
":__support_fputil_fp_bits",
@@ -8988,7 +8989,6 @@ libc_support_library(
":__support_math_sincosf16_utils",
":hdr_errno_macros",
":hdr_fenv_macros",
- ":__support_fputil_bfloat16",
],
)
@@ -12689,7 +12689,6 @@ libc_math_function(
],
)
-
libc_math_function(
name = "tanf",
additional_deps = [":__support_math_tanf"],
>From 3784dfc45c820869aaaaea9b1b0a47de898e5d52 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 01:48:19 +0530
Subject: [PATCH 04/10] chore: nit
---
libc/src/__support/math/tanbf16.h | 2 +-
libc/src/__support/math/tanf16.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/math/tanbf16.h b/libc/src/__support/math/tanbf16.h
index 57d3614e9de59..ba182433c6932 100644
--- a/libc/src/__support/math/tanbf16.h
+++ b/libc/src/__support/math/tanbf16.h
@@ -60,7 +60,7 @@ LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
// separate case handles it with magnitude of 2^-13
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD))
- return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
+ return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
return x;
}
diff --git a/libc/src/__support/math/tanf16.h b/libc/src/__support/math/tanf16.h
index eda872ee7ab0a..6b9b9224fb84d 100644
--- a/libc/src/__support/math/tanf16.h
+++ b/libc/src/__support/math/tanf16.h
@@ -76,7 +76,7 @@ LIBC_INLINE float16 tanf16(float16 x) {
// tan(x) = x * 2^-11 + x
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD))
- return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
+ return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
return x;
}
>From 9bed1e6d59f0f15e254f63abf06ef8d046e1c865 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 01:56:08 +0530
Subject: [PATCH 05/10] chore: added in index.rst after exhaustive passes
---
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 a2465e1de2cc2..c2ca077c6cbdc 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -353,7 +353,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| sqrt | |check| | |check| | |check| | |check| | |check| | |check| | 7.12.7.10 | F.10.4.10 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| tan | |check| | |check| | | |check| | | | 7.12.4.7 | F.10.1.7 |
+| tan | |check| | |check| | | |check| | | |check| | 7.12.4.7 | F.10.1.7 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| tanh | |check| | | | |check| | | | 7.12.5.6 | F.10.2.6 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
>From b557a63a64fbc089e9ed944403c96aa6a8209c9c Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 01:58:54 +0530
Subject: [PATCH 06/10] chore: removed debug statements
---
libc/test/src/math/tanbf16_test.cpp | 33 -----------------------------
1 file changed, 33 deletions(-)
diff --git a/libc/test/src/math/tanbf16_test.cpp b/libc/test/src/math/tanbf16_test.cpp
index b4e5f5a2fb12b..848e07debe18d 100644
--- a/libc/test/src/math/tanbf16_test.cpp
+++ b/libc/test/src/math/tanbf16_test.cpp
@@ -11,7 +11,6 @@
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
-#include <iostream>
using LlvmLibcTanBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
@@ -26,50 +25,18 @@ static constexpr uint16_t NEG_START = 0x8000U;
static constexpr uint16_t NEG_STOP = 0xff80U;
TEST_F(LlvmLibcTanBf16Test, PositiveRange) {
- uint16_t last_equal = 0; // remove
for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
bfloat16 x = FPBits(v).get_val();
- bfloat16 result = LIBC_NAMESPACE::tanbf16(x);
- // Check if tan(x) rounds to x itself
- if (FPBits(result).uintval() == v) {
- last_equal = v;
- } else {
- // First x where tan(x) != x — print and stop
- bfloat16 prev = FPBits(last_equal).get_val();
- std::cout << "Last x where tan(x)==x: "
- << "hex=0x" << std::hex << last_equal << " value=" << std::dec
- << (float)prev << "\n";
- std::cout << "First x where tan(x)!=x: "
- << "hex=0x" << std::hex << v << " value=" << std::dec
- << (float)x << "\n";
- std::cout << "tan(first_diff_x)=" << (float)result << "\n";
- std::cout << "\n=== USE IN CODE ===\n"
- << "if (x_abs <= 0x" << std::hex << last_equal
- << "U) // tan(x)==x for bfloat16\n";
- break;
- }
-
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Tan, x,
LIBC_NAMESPACE::tanbf16(x), 0.5);
}
}
TEST_F(LlvmLibcTanBf16Test, NegativeRange) {
- uint16_t last_equal = 0x8000; // remove
for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
bfloat16 x = FPBits(v).get_val();
- bfloat16 result = LIBC_NAMESPACE::tanbf16(x);
- if (FPBits(result).uintval() == v) {
- last_equal = v;
- } else {
- std::cout << "Negative — last equal: "
- << "hex=0x" << std::hex << last_equal << " value=" << std::dec
- << (float)FPBits(last_equal).get_val() << "\n";
- break;
- }
-
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Tan, x,
LIBC_NAMESPACE::tanbf16(x), 0.5);
}
>From d96ac9b73248e8a55c8785bba03a8dd080580e00 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 02:14:10 +0530
Subject: [PATCH 07/10] fix: reverted magnitude
---
libc/src/__support/math/tanbf16.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/math/tanbf16.h b/libc/src/__support/math/tanbf16.h
index ba182433c6932..762feb1884190 100644
--- a/libc/src/__support/math/tanbf16.h
+++ b/libc/src/__support/math/tanbf16.h
@@ -57,10 +57,10 @@ LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
// The last value where tan(x) ~ x is 0x3db8
if (LIBC_UNLIKELY(x_abs <= 0x3db8)) {
int rounding = fputil::quick_get_round();
- // separate case handles it with magnitude of 2^-13
+ // separate case handles it with magnitude of 2^-11
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD))
- return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
+ return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
return x;
}
>From e5e53f45743468f27104fa0dced570031eba0b9d Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 10:59:03 +0530
Subject: [PATCH 08/10] fix: added double intermediate for sincoseval
test
test-handling larger separately
testing with double
chore: format and corrected cmake dependencies
chore: err
---
libc/src/__support/math/CMakeLists.txt | 2 +-
libc/src/__support/math/tanbf16.h | 20 +++++++++++--------
.../llvm-project-overlay/libc/BUILD.bazel | 2 +-
3 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 3454365fbd5ec..fa12a038d8ec7 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -5354,7 +5354,7 @@ add_header_library(
HDRS
tanbf16.h
DEPENDS
- .sincosf16_utils
+ .sincosf_utils
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.cast
diff --git a/libc/src/__support/math/tanbf16.h b/libc/src/__support/math/tanbf16.h
index 762feb1884190..69b275c4a9eb5 100644
--- a/libc/src/__support/math/tanbf16.h
+++ b/libc/src/__support/math/tanbf16.h
@@ -11,7 +11,7 @@
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
-#include "sincosf16_utils.h"
+#include "sincosf_utils.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/bfloat16.h"
@@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
- using namespace sincosf16_internal;
+ using namespace sincosf_utils_internal;
using FPBits = fputil::FPBits<bfloat16>;
FPBits xbits(x);
@@ -53,7 +53,7 @@ LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
return x;
}
- // Through Exhaustive testing
+ // Through Exhaustive testing -
// The last value where tan(x) ~ x is 0x3db8
if (LIBC_UNLIKELY(x_abs <= 0x3db8)) {
int rounding = fputil::quick_get_round();
@@ -64,13 +64,17 @@ LIBC_INLINE bfloat16 tanbf16(bfloat16 x) {
return x;
}
- float sin_k, cos_k, sin_y, cosm1_y;
- sincosf16_eval(xf, sin_k, cos_k, sin_y, cosm1_y);
+ double xd = static_cast<double>(xf);
+ uint32_t x_abs_d = fputil::FPBits<float>(xf).uintval() & 0x7fffffff;
+ double sin_k, cos_k, sin_y, cosm1_y;
+
+ sincosf_eval(xd, x_abs_d, sin_k, cos_k, sin_y, cosm1_y);
- using fputil::multiply_add;
return fputil::cast<bfloat16>(
- multiply_add(sin_y, cos_k, multiply_add(cosm1_y, sin_k, sin_k)) /
- multiply_add(sin_y, -sin_k, multiply_add(cosm1_y, cos_k, cos_k)));
+ fputil::multiply_add(sin_y, cos_k,
+ fputil::multiply_add(cosm1_y, sin_k, sin_k)) /
+ fputil::multiply_add(sin_y, -sin_k,
+ fputil::multiply_add(cosm1_y, cos_k, cos_k)));
}
} // namespace math
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 3c0bcafc7b097..d2b0f765b18fd 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -8986,7 +8986,7 @@ libc_support_library(
":__support_fputil_multiply_add",
":__support_macros_optimization",
":__support_macros_properties_types",
- ":__support_math_sincosf16_utils",
+ ":__support_math_sincosf_utils",
":hdr_errno_macros",
":hdr_fenv_macros",
],
>From c42d9b362e2c99eca48e95fd01881a26ac399690 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 7 Mar 2026 14:13:54 +0530
Subject: [PATCH 09/10] nit
---
libc/src/math/generic/CMakeLists.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 0b8428f5cd622..218b2bb043cbc 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -425,7 +425,6 @@ add_entrypoint_object(
libc.src.__support.math.tanbf16
)
-
add_entrypoint_object(
tanf
SRCS
>From ff111a3641ccf3623946b1f4f2882c358efa6912 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sun, 7 Jun 2026 16:04:58 +0530
Subject: [PATCH 10/10] add freebsd entrypoint
---
libc/config/freebsd/x86_64/entrypoints.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index 31d421555624d..79e8d11cf52df 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -624,6 +624,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
libc.src.math.setpayloadbf16
libc.src.math.setpayloadsigbf16
libc.src.math.sqrtbf16
+ libc.src.math.tanbf16
libc.src.math.truncbf16
libc.src.math.totalorderbf16
libc.src.math.totalordermagbf16
More information about the libc-commits
mailing list