[libc-commits] [libc] [llvm] [libc][math][c23] Add atanpibf16 math function (PR #189151)
via libc-commits
libc-commits at lists.llvm.org
Sat Mar 28 01:34:39 PDT 2026
https://github.com/Sukumarsawant created https://github.com/llvm/llvm-project/pull/189151
This PR intends to add atanpi math function for bfloat16 type, along with exhaustive tests for it.
>From ad78bad1f088dda28d530ddfd1232acd159cfe0e Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 24 Mar 2026 19:05:35 +0530
Subject: [PATCH 1/3] intial commit
feat: added entrypoints
intial commit
feat: raw implementation
temp commit
err
err
passes exhaustive
tests
entrypoints fixed
comments
not verified
26/3 rem
unoptimized which passes
---
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/atanpibf16.h | 23 ++++
libc/src/__support/math/CMakeLists.txt | 17 ++-
libc/src/__support/math/atanpibf16.h | 110 ++++++++++++++++++
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/atanpibf16.h | 21 ++++
libc/src/math/generic/CMakeLists.txt | 10 ++
libc/src/math/generic/atanpibf16.cpp | 18 +++
libc/test/shared/CMakeLists.txt | 1 +
libc/test/shared/shared_math_test.cpp | 1 +
libc/test/src/math/CMakeLists.txt | 13 +++
libc/test/src/math/atanpibf16_test.cpp | 45 +++++++
libc/test/src/math/smoke/CMakeLists.txt | 13 +++
libc/test/src/math/smoke/atanpibf16_test.cpp | 40 +++++++
.../llvm-project-overlay/libc/BUILD.bazel | 21 ++++
27 files changed, 346 insertions(+), 1 deletion(-)
create mode 100644 libc/shared/math/atanpibf16.h
create mode 100644 libc/src/__support/math/atanpibf16.h
create mode 100644 libc/src/math/atanpibf16.h
create mode 100644 libc/src/math/generic/atanpibf16.cpp
create mode 100644 libc/test/src/math/atanpibf16_test.cpp
create mode 100644 libc/test/src/math/smoke/atanpibf16_test.cpp
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 84600efc5e0d1..e1fbcdbb352a9 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -790,6 +790,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 902f6ed44179b..3c536b1d89073 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -800,6 +800,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 30f9bccd22214..e5c6fc203bd40 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -796,6 +796,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 4d27e994323fd..1b090d9dd58aa 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -609,6 +609,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index cad973f1ac069..3d5f5af62c0ba 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -235,6 +235,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 7aaf3470dceab..ed7299127ac0f 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -624,6 +624,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index 96c0902d729dc..4eecdb0844e6c 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -626,6 +626,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index d6569e59a3e5f..3eb45fc134966 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -870,6 +870,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 9fd45329ad0f9..e42a57e7fc3eb 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -476,6 +476,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index fdfce36b824f0..a4666f38c8210 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -891,6 +891,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8cceaccc314dc..f26e0cafbc112 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -946,6 +946,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index ee8072a3465e5..cee7ca319ee52 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -322,6 +322,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.atanpibf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 6add9628cabdd..bd6e0e9820355 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -36,6 +36,7 @@
#include "math/atanhf.h"
#include "math/atanhf16.h"
#include "math/atanpif16.h"
+#include "math/atanpibf16.h"
#include "math/bf16add.h"
#include "math/bf16addf.h"
#include "math/bf16addf128.h"
diff --git a/libc/shared/math/atanpibf16.h b/libc/shared/math/atanpibf16.h
new file mode 100644
index 0000000000000..69c55accda3cc
--- /dev/null
+++ b/libc/shared/math/atanpibf16.h
@@ -0,0 +1,23 @@
+//===-- Shared atanpibf16 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_ATANPIBF16_H
+#define LLVM_LIBC_SHARED_MATH_ATANPIBF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/atanpibf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::atanpibf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ATANPIBF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index c3ffa2f79dd3e..67cb6e4368aff 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -304,7 +304,6 @@ add_header_library(
libc.src.__support.FPUtil.sqrt
libc.src.__support.macros.optimization
libc.src.__support.FPUtil.bfloat16
-
)
add_header_library(
@@ -364,6 +363,22 @@ add_header_library(
libc.src.__support.macros.optimization
)
+add_header_library(
+ atanpibf16
+ HDRS
+ atanpibf16.h
+ DEPENDS
+ 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.multiply_add
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_header_library(
atanpif16
HDRS
diff --git a/libc/src/__support/math/atanpibf16.h b/libc/src/__support/math/atanpibf16.h
new file mode 100644
index 0000000000000..ebe540df1bb43
--- /dev/null
+++ b/libc/src/__support/math/atanpibf16.h
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ATANPIBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ATANPIBF16_H
+
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/FPUtil/bfloat16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE bfloat16 atanpibf16(bfloat16 x) {
+
+ using FPBits = fputil::FPBits<bfloat16>;
+ FPBits xbits(x);
+
+ uint16_t x_u = xbits.uintval();
+ uint16_t x_abs = x_u & 0x7fff;
+ bool x_sign = x_u >> 15;
+ float sign = (x_sign ? -1.0f : 1.0f);
+
+ // Taylor series for atan-> [x - x^3/3 + x^5/5 - x^7/7 ...]
+ // x * [1 - x^2/3 + x^4/5 - x^6/7...] -> x * P(x)
+ // atan(x) = x * poly(x^2)
+ // atan(x)/x = poly(x^2)
+ // atan(x)/(x*pi) =
+ //
+ // Degree 14 polynomial of atan(x) generated using Sollya with command :
+ // > display = hexadecimal ;
+ // > P = fpminimax(atan(x)/(x*pi), [|0, 2, 4, 6, 8, 10, 12, 14|], [|1,SG,SG,SG,SG,SG,SG,SG|], [0, 1]);
+ //
+ // relative error for the polynomial given by:
+ // > dirtyinfnorm(atan(x)/(x*pi) - P(x), [0, 1]);
+ // error - 0x1.6e4e44p-25
+ // worst case error for it being ~
+ // satisfying -> error < worst_case
+ auto atanpi_eval = [](float x0) {
+return fputil::polyeval(
+ x0,
+ 0x1.45f304p-2f,
+ -0x1.b29476p-4f,
+ 0x1.0458d4p-4f,
+ -0x1.6d6784p-5f,
+ 0x1.021eep-5f,
+ -0x1.352efap-6f,
+ 0x1.f724c8p-8f,
+ -0x1.84ac1ep-10f
+);
+ };
+
+ float xf = x;
+ float x_sq = xf * xf ;
+
+ // Case 1: |x| <= 1
+ if (x_abs <= 0x3f80) {
+ // atanpibf16(±0) = ±0
+ if (LIBC_UNLIKELY(x_abs == 0))
+ return x;
+ // atanpibf16(±1) = ±0.25
+ if (LIBC_UNLIKELY(x_abs == 0x3f80))
+ return fputil::cast<bfloat16>(sign * 0.25f);
+
+
+ float result = atanpi_eval(x_sq);
+ return fputil::cast<bfloat16>(xf *result );
+ }
+
+ // Case 2: |x| > 1 ( But not too large )
+ if(x_abs < 0x43a3){
+ // atan(x) = sign(x) * (pi/2 - atan(1/|x|))
+ // atan(x)/pi = sign(x) * ((pi/2)/pi) - ((atan(1/|x|))/pi))
+ // atanpi(x) = sign(x) * ((0.5) - atanpi(1/|x|))
+ // Since 1/|x| < 1, we can use the same polynomial.
+ float x_inv_sq = 1.0f / x_sq;
+ float x_inv = fputil::sqrt<float>(x_inv_sq);
+
+ float result = atanpi_eval(x_inv_sq);
+ float atan_inv = (x_inv * result);
+ return fputil::cast<bfloat16>(sign * (0.5 - atan_inv));
+ }
+
+ // Case 3: For Large x in bfloat16 the value is close to 0.5 but not exactly 0.5
+ if (LIBC_UNLIKELY(x_abs < 0x7F80))
+ return fputil::cast<bfloat16>(sign * 0x1.fffffep-2f);
+
+ // Case 4: |x| is ±inf or 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;
+ }
+ // atanpibf16( ±inf )/pi = ±((pi/2)/pi) = ± 1/2
+ return fputil::cast<bfloat16>(sign * 0.5f);
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATANPIBF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 5bdb8d99eedeb..7d88e0cfeb77d 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -77,6 +77,7 @@ add_math_entrypoint_object(atanh)
add_math_entrypoint_object(atanhf)
add_math_entrypoint_object(atanhf16)
+add_math_entrypoint_object(atanpibf16)
add_math_entrypoint_object(atanpif16)
add_math_entrypoint_object(canonicalize)
diff --git a/libc/src/math/atanpibf16.h b/libc/src/math/atanpibf16.h
new file mode 100644
index 0000000000000..0ae3e4d371fea
--- /dev/null
+++ b/libc/src/math/atanpibf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for atanpibf16 ---------------------*- 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_ATANPIBF16_H
+#define LLVM_LIBC_SRC_MATH_ATANPIBF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 atanpibf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ATANPIBF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 40d21ffaaa524..69a4ac973b36e 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4058,6 +4058,16 @@ add_entrypoint_object(
libc.src.__support.math.atanhf16
)
+add_entrypoint_object(
+ atanpibf16
+ SRCS
+ atanpibf16.cpp
+ HDRS
+ ../atanpibf16.h
+ DEPENDS
+ libc.src.__support.math.atanpibf16
+)
+
add_entrypoint_object(
atanpif16
SRCS
diff --git a/libc/src/math/generic/atanpibf16.cpp b/libc/src/math/generic/atanpibf16.cpp
new file mode 100644
index 0000000000000..35830810c5c75
--- /dev/null
+++ b/libc/src/math/generic/atanpibf16.cpp
@@ -0,0 +1,18 @@
+//===-- Bfloat16 atanpi 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/atanpibf16.h"
+#include "src/__support/math/atanpibf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, atanpibf16, (bfloat16 x)) {
+ return math::atanpibf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 9ea5d1bd359c7..29fa1216d4953 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -32,6 +32,7 @@ add_fp_unittest(
libc.src.__support.math.atanf16
libc.src.__support.math.atanhf
libc.src.__support.math.atanhf16
+ libc.src.__support.math.atanpibf16
libc.src.__support.math.atanpif16
libc.src.__support.math.bf16add
libc.src.__support.math.bf16addf
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 5afb982dd57ed..4c3fa3531797b 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -423,6 +423,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
TEST(LlvmLibcSharedMathTest, AllBFloat16) {
using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::atanbf16(bfloat16(0.0)));
+ EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::atanpibf16(bfloat16(0.0)));
EXPECT_FP_EQ(bfloat16(5.0), LIBC_NAMESPACE::shared::bf16add(2.0, 3.0));
EXPECT_FP_EQ(bfloat16(2.0f), LIBC_NAMESPACE::shared::bf16divf(4.0f, 2.0f));
EXPECT_FP_EQ(bfloat16(2.0), LIBC_NAMESPACE::shared::bf16divl(6.0L, 3.0L));
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index ceed946e2386e..028e65bf6402c 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2389,6 +2389,19 @@ add_fp_unittest(
libc.src.math.atanhf16
)
+add_fp_unittest(
+ atanpibf16_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ atanpibf16_test.cpp
+ DEPENDS
+ libc.src.math.atanpibf16
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
atanpif16_test
NEED_MPFR
diff --git a/libc/test/src/math/atanpibf16_test.cpp b/libc/test/src/math/atanpibf16_test.cpp
new file mode 100644
index 0000000000000..2b4586fc6f3fe
--- /dev/null
+++ b/libc/test/src/math/atanpibf16_test.cpp
@@ -0,0 +1,45 @@
+//===-- Exhaustive test for atanpibf16 -------------------------------------===//
+//
+// 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/atanpibf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcAtanpiBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Normal range: [+0, +int]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// Normal range: [-0, -int]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcAtanpiBf16Test, NormalPositiveRange) {
+ for (uint16_t v1 = POS_START; v1 <= POS_STOP; v1++) {
+
+ bfloat16 x = FPBits(v1).get_val();
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atanpi, x,
+ LIBC_NAMESPACE::atanpibf16(x), 0.5);
+ }
+}
+
+TEST_F(LlvmLibcAtanpiBf16Test, NormalNegativeRange) {
+ for (uint16_t v1 = NEG_START; v1 <= NEG_STOP; v1++) {
+
+ bfloat16 x = FPBits(v1).get_val();
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atanpi, x,
+ LIBC_NAMESPACE::atanpibf16(x), 0.5);
+ }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 9d97c90cfaeb9..89a22812e47d7 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4710,6 +4710,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.cast
)
+add_fp_unittest(
+ atanpibf16_test
+ SUITE
+ libc-math-unittests
+ SRCS
+ atanpibf16_test.cpp
+ DEPENDS
+ libc.src.math.atanpibf16
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
atanpif16_test
NEED_MPFR
diff --git a/libc/test/src/math/smoke/atanpibf16_test.cpp b/libc/test/src/math/smoke/atanpibf16_test.cpp
new file mode 100644
index 0000000000000..ee8b26789d132
--- /dev/null
+++ b/libc/test/src/math/smoke/atanpibf16_test.cpp
@@ -0,0 +1,40 @@
+//===-- Unittests for atanpibf16 ------------------------------------------===//
+//
+// 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/atanpibf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcAtanpiBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+ DECLARE_SPECIAL_CONSTANTS(bfloat16)
+public:
+ void test_special_numbers() {
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::atanpibf16(zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::atanpibf16(neg_zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanpibf16(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+ aNaN, LIBC_NAMESPACE::atanpibf16(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(0.5), LIBC_NAMESPACE::atanpibf16(inf));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(bfloat16(-0.5), LIBC_NAMESPACE::atanpibf16(neg_inf));
+ EXPECT_MATH_ERRNO(0);
+ }
+};
+
+TEST_F(LlvmLibcAtanpiBf16Test, SpecialNumbers) { test_special_numbers(); }
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index fa435eefaaed9..8be709b25f7fb 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3204,6 +3204,22 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_math_atanpibf16",
+ hdrs = ["src/__support/math/atanpibf16.h"],
+ deps = [
+ ":__support_fputil_bfloat16",
+ ":__support_fputil_cast",
+ ":__support_fputil_fenv_impl",
+ ":__support_fputil_fp_bits",
+ ":__support_fputil_multiply_add",
+ ":__support_fputil_polyeval",
+ ":__support_fputil_sqrt",
+ ":hdr_fenv_macros",
+ ":__support_macros_optimization",
+ ],
+)
+
libc_support_library(
name = "__support_math_atanpif16",
hdrs = ["src/__support/math/atanpif16.h"],
@@ -6412,6 +6428,11 @@ libc_math_function(
],
)
+libc_math_function(
+ name = "atanpibf16",
+ additional_deps = [":__support_math_atanpibf16"],
+)
+
libc_math_function(
name = "atanpif16",
additional_deps = [":__support_math_atanpif16"],
>From 3a57ce6088ae46a89cf052a8647611eb27b9f756 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 13:54:32 +0530
Subject: [PATCH 2/3] Implement atanpibf16 function with exahaustive tests
---
libc/src/__support/math/atanpibf16.h | 56 +++++++++----------
.../llvm-project-overlay/libc/BUILD.bazel | 2 +-
2 files changed, 26 insertions(+), 32 deletions(-)
diff --git a/libc/src/__support/math/atanpibf16.h b/libc/src/__support/math/atanpibf16.h
index ebe540df1bb43..01b2ad915e959 100644
--- a/libc/src/__support/math/atanpibf16.h
+++ b/libc/src/__support/math/atanpibf16.h
@@ -28,34 +28,27 @@ LIBC_INLINE bfloat16 atanpibf16(bfloat16 x) {
bool x_sign = x_u >> 15;
float sign = (x_sign ? -1.0f : 1.0f);
- // Taylor series for atan-> [x - x^3/3 + x^5/5 - x^7/7 ...]
- // x * [1 - x^2/3 + x^4/5 - x^6/7...] -> x * P(x)
- // atan(x) = x * poly(x^2)
- // atan(x)/x = poly(x^2)
- // atan(x)/(x*pi) =
+ // Taylor series for atan
+ // atan(x) = [x - x^3/3 + x^5/5 - x^7/7 ...]
+ // = x * [1 - x^2/3 + x^4/5 - x^6/7...]
+ // = x * P(x^2)
//
- // Degree 14 polynomial of atan(x) generated using Sollya with command :
+ // atan(x) = x * P(x^2)
+ //
+ // since atanpi(x) = atan(x)/pi
+ // atanpi(x) = x * poly(x^2)/pi
+ // where [poly(x^2)/pi] <= atan(x)/(x*pi)
+ //
+ // Degree 12 polynomial of atanpi(x) generated using Sollya with command :
// > display = hexadecimal ;
- // > P = fpminimax(atan(x)/(x*pi), [|0, 2, 4, 6, 8, 10, 12, 14|], [|1,SG,SG,SG,SG,SG,SG,SG|], [0, 1]);
+ // > P = fpminimax(atan(x)/(x*pi), [|0, 2, 4, 6, 8, 10, 12|], [|SG,SG,SG,SG,SG,SG,SG|], [0, 1]);
//
// relative error for the polynomial given by:
- // > dirtyinfnorm(atan(x)/(x*pi) - P(x), [0, 1]);
- // error - 0x1.6e4e44p-25
- // worst case error for it being ~
- // satisfying -> error < worst_case
- auto atanpi_eval = [](float x0) {
-return fputil::polyeval(
- x0,
- 0x1.45f304p-2f,
- -0x1.b29476p-4f,
- 0x1.0458d4p-4f,
- -0x1.6d6784p-5f,
- 0x1.021eep-5f,
- -0x1.352efap-6f,
- 0x1.f724c8p-8f,
- -0x1.84ac1ep-10f
-);
- };
+ // > dirtyinfnorm(atan(x)/(x*pi) - P(x^2), [0, 1]);
+ // error - 0x1.db939p-23
+auto atanpi_eval = [](float x0) {
+ return fputil::polyeval(x0, 0x1.45f2f8p-2f, -0x1.b28236p-4f, 0x1.0333bp-4f, -0x1.5f9b92p-5f, 0x1.b520c4p-6f, -0x1.819ef4p-7f, 0x1.4789p-9f);
+};
float xf = x;
float x_sq = xf * xf ;
@@ -74,8 +67,13 @@ return fputil::polyeval(
return fputil::cast<bfloat16>(xf *result );
}
- // Case 2: |x| > 1 ( But not too large )
- if(x_abs < 0x43a3){
+ // Case 2: |x| > 1 ( uses range reduction )
+ if(x_abs < 0x7F80){
+
+ // For Large x in bfloat16 the value is close to 0.5 but not exactly 0.5
+ if (LIBC_UNLIKELY(x_abs >= 0x43a3))
+ return fputil::cast<bfloat16>(sign * 0x1.fffffep-2f);
+
// atan(x) = sign(x) * (pi/2 - atan(1/|x|))
// atan(x)/pi = sign(x) * ((pi/2)/pi) - ((atan(1/|x|))/pi))
// atanpi(x) = sign(x) * ((0.5) - atanpi(1/|x|))
@@ -88,11 +86,7 @@ return fputil::polyeval(
return fputil::cast<bfloat16>(sign * (0.5 - atan_inv));
}
- // Case 3: For Large x in bfloat16 the value is close to 0.5 but not exactly 0.5
- if (LIBC_UNLIKELY(x_abs < 0x7F80))
- return fputil::cast<bfloat16>(sign * 0x1.fffffep-2f);
-
- // Case 4: |x| is ±inf or NaN
+ // Case 3: |x| is ±inf or NaN
if (xbits.is_nan()) {
if (xbits.is_signaling_nan()) {
fputil::raise_except_if_required(FE_INVALID);
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 8be709b25f7fb..d1162391e3a55 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3215,8 +3215,8 @@ libc_support_library(
":__support_fputil_multiply_add",
":__support_fputil_polyeval",
":__support_fputil_sqrt",
- ":hdr_fenv_macros",
":__support_macros_optimization",
+ ":hdr_fenv_macros",
],
)
>From cc21b30c43eec77ffe511240627fbd3b815f5aff Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 14:01:45 +0530
Subject: [PATCH 3/3] marked
---
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 202ef034b8ace..1556982cf48b2 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -279,7 +279,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| atanh | |check| | | | |check| | | | 7.12.5.3 | F.10.2.3 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| atanpi | | | | |check| | | | 7.12.4.10 | F.10.1.10 |
+| atanpi | | | | |check| | | |check| | 7.12.4.10 | F.10.1.10 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| cbrt | |check| | |check| | | | | |check| | 7.12.7.1 | F.10.4.1 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
More information about the libc-commits
mailing list