[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