[libc-commits] [libc] 7d7cd74 - [libc][math][c23] Add atanbf16 function (#184019)

via libc-commits libc-commits at lists.llvm.org
Sat Mar 21 08:09:16 PDT 2026


Author: Zorojuro
Date: 2026-03-21T11:09:11-04:00
New Revision: 7d7cd745af221c8690ea6deb2dfbf232658158cd

URL: https://github.com/llvm/llvm-project/commit/7d7cd745af221c8690ea6deb2dfbf232658158cd
DIFF: https://github.com/llvm/llvm-project/commit/7d7cd745af221c8690ea6deb2dfbf232658158cd.diff

LOG: [libc][math][c23] Add atanbf16 function (#184019)

This PR intends to add atanbf16 higher math function for BFloat16 type
along with the tests.

Added: 
    libc/shared/math/atanbf16.h
    libc/src/__support/math/atanbf16.h
    libc/src/math/atanbf16.h
    libc/src/math/generic/atanbf16.cpp
    libc/test/src/math/atanbf16_test.cpp
    libc/test/src/math/smoke/atanbf16_test.cpp

Modified: 
    libc/config/baremetal/aarch64/entrypoints.txt
    libc/config/baremetal/arm/entrypoints.txt
    libc/config/baremetal/riscv/entrypoints.txt
    libc/config/darwin/aarch64/entrypoints.txt
    libc/config/darwin/x86_64/entrypoints.txt
    libc/config/gpu/amdgpu/entrypoints.txt
    libc/config/gpu/nvptx/entrypoints.txt
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/arm/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/config/windows/entrypoints.txt
    libc/docs/headers/math/index.rst
    libc/shared/math.h
    libc/src/__support/math/CMakeLists.txt
    libc/src/math/CMakeLists.txt
    libc/src/math/generic/CMakeLists.txt
    libc/test/shared/CMakeLists.txt
    libc/test/shared/shared_math_test.cpp
    libc/test/src/math/CMakeLists.txt
    libc/test/src/math/smoke/CMakeLists.txt
    utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Removed: 
    


################################################################################
diff  --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 9fa9744cf109d..84600efc5e0d1 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -789,6 +789,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 e55407d340bb3..902f6ed44179b 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -799,6 +799,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 654786b919c2b..30f9bccd22214 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -795,6 +795,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 d365708b950ad..4d27e994323fd 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -608,6 +608,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 b0c247464c850..cad973f1ac069 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -234,6 +234,7 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 98c27d300ad9d..7aaf3470dceab 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -623,6 +623,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 532fcda9ab3be..96c0902d729dc 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -625,6 +625,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 e6c9030898841..d6569e59a3e5f 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -869,6 +869,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 91fa524cc0d6b..9fd45329ad0f9 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -475,6 +475,7 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 ba97e5c2035b3..fdfce36b824f0 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -890,6 +890,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 a58e68d47c1e1..8cceaccc314dc 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -945,6 +945,7 @@ endif()
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   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 a1803d65d1b49..ee8072a3465e5 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -321,6 +321,7 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
+  libc.src.math.atanbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl

diff  --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 8692bf37c05b1..202ef034b8ace 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -271,7 +271,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | asinpi    | |check|          |                 |                        | |check|              |                        |                        | 7.12.4.9               | F.10.1.9                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| atan      | |check|          | 1 ULP           |                        | |check|              |                        |                        | 7.12.4.3               | F.10.1.3                   |
+| atan      | |check|          | 1 ULP           |                        | |check|              |                        | |check|                | 7.12.4.3               | F.10.1.3                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | atan2     | |check|          | 1 ULP           |                        | |check|              | 1 ULP                  |                        | 7.12.4.4               | F.10.1.4                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+

diff  --git a/libc/shared/math.h b/libc/shared/math.h
index ef006c668f3ab..3d81216f1bcfb 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -30,6 +30,7 @@
 #include "math/atan2f.h"
 #include "math/atan2f128.h"
 #include "math/atan2f16.h"
+#include "math/atanbf16.h"
 #include "math/atanf.h"
 #include "math/atanf16.h"
 #include "math/atanhf.h"

diff  --git a/libc/shared/math/atanbf16.h b/libc/shared/math/atanbf16.h
new file mode 100644
index 0000000000000..b3f6d280a70e8
--- /dev/null
+++ b/libc/shared/math/atanbf16.h
@@ -0,0 +1,26 @@
+//===-- Shared atanbf16 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_ATANBF16_H
+#define LLVM_LIBC_SHARED_MATH_ATANBF16_H
+
+#include "shared/libc_common.h"
+
+#include "src/__support/math/atanbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace shared {
+
+using math::atanbf16;
+
+} // namespace shared
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ATANBF16_H

diff  --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index abac483e40fa9..6266b26b81ba8 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -289,6 +289,22 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  atanbf16
+  HDRS
+    atanbf16.h
+  DEPENDS
+    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(
   atanf
   HDRS

diff  --git a/libc/src/__support/math/atanbf16.h b/libc/src/__support/math/atanbf16.h
new file mode 100644
index 0000000000000..563b8325b8428
--- /dev/null
+++ b/libc/src/__support/math/atanbf16.h
@@ -0,0 +1,105 @@
+//===-- Implementation for atanbf16(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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ATANBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ATANBF16_H
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE bfloat16 atanbf16(bfloat16 x) {
+  // Generated by Sollya using the following command:
+  // > display = hexadecimal;
+  // > round(pi/2, SG, RN);
+  constexpr float PI_2 = 0x1.921fb6p0f;
+
+  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 -> [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)
+
+  // Degree 14 polynomial of atan(x) generated using Sollya with command :
+  // > display = hexadecimal ;
+  // > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|1, SG,
+  // SG..SG|], [0, 1]);
+  //
+  // relative error for the polynomial given by:
+  // > dirtyinfnorm(atan(x)/x - P(x), [0, 1]);
+  // gives error ~ 0x1.ee44001p-24
+  // worst case error for it being ~ 0x1.dcf750p-23
+  // satisfying -> error < worst_case
+  auto atan_eval = [](float x0) {
+    return fputil::polyeval(x0, -0x1.5552c4p-2f, 0x1.990f2p-3f, -0x1.1f7dccp-3f,
+                            0x1.97e49p-4f, -0x1.ebff34p-5f, 0x1.938e46p-6f,
+                            -0x1.3a28bcp-8f);
+  };
+
+  float xf = x;
+  float x_sq = xf * xf;
+
+  // |x| <= 1
+  if (x_abs <= 0x3f80) {
+    // atanbf16(+/-0) = +/-0
+    if (LIBC_UNLIKELY(x_abs == 0))
+      return x;
+
+    // For smaller x
+    if (LIBC_UNLIKELY(x_abs <= 0x3db8))
+      return fputil::cast<bfloat16>(fputil::multiply_add(xf, -0x1p-9f, xf));
+
+    float result = atan_eval(x_sq);
+    return fputil::cast<bfloat16>(fputil::multiply_add(xf * x_sq, result, xf));
+  }
+
+  // |x| is +/-inf or NaN
+  if (LIBC_UNLIKELY(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;
+    }
+    // atanbf16(+/-inf) = +/-pi/2
+    return fputil::cast<bfloat16>(sign * PI_2);
+  }
+
+  // If |x| > 1:
+  // atan(x) = sign(x) * (pi/2 - atan(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 = atan_eval(x_inv_sq);
+  float atan_inv = fputil::multiply_add(x_inv * x_inv_sq, result, x_inv);
+  return fputil::cast<bfloat16>(sign * (PI_2 - atan_inv));
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATANBF16_H

diff  --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 98dba11f34c86..5bdb8d99eedeb 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -63,6 +63,7 @@ add_math_entrypoint_object(asinpif)
 add_math_entrypoint_object(asinpif16)
 
 add_math_entrypoint_object(atan)
+add_math_entrypoint_object(atanbf16)
 add_math_entrypoint_object(atanf)
 add_math_entrypoint_object(atanf16)
 

diff  --git a/libc/src/math/atanbf16.h b/libc/src/math/atanbf16.h
new file mode 100644
index 0000000000000..571b436cb2d3d
--- /dev/null
+++ b/libc/src/math/atanbf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for atanbf16 ---------------------*- 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_ATANBF16_H
+#define LLVM_LIBC_SRC_MATH_ATANBF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 atanbf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ATANBF16_H

diff  --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 8aaeea0565eea..fdc3fa777d1fa 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4144,6 +4144,16 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  atanbf16
+  SRCS
+    atanbf16.cpp
+  HDRS
+    ../atanbf16.h
+  DEPENDS
+    libc.src.__support.math.atanbf16
+)
+
 add_entrypoint_object(
   atanf
   SRCS

diff  --git a/libc/src/math/generic/atanbf16.cpp b/libc/src/math/generic/atanbf16.cpp
new file mode 100644
index 0000000000000..fc2879b3a628c
--- /dev/null
+++ b/libc/src/math/generic/atanbf16.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation for atanbf16(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/atanbf16.h"
+#include "src/__support/math/atanbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, atanbf16, (bfloat16 x)) {
+  return math::atanbf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index bfacee9cecac4..36262012ad0f0 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -27,6 +27,7 @@ add_fp_unittest(
     libc.src.__support.math.atan2f
     libc.src.__support.math.atan2f128
     libc.src.__support.math.atan2f16
+    libc.src.__support.math.atanbf16
     libc.src.__support.math.atanf
     libc.src.__support.math.atanf16
     libc.src.__support.math.atanhf

diff  --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index d958529d04fba..341b35a7b7e0f 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -422,6 +422,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(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 2710f4cbdbe31..ceed946e2386e 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -69,7 +69,6 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
-
 add_fp_unittest(
   cospif16_test
   NEED_MPFR
@@ -2616,6 +2615,19 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  atanbf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    atanbf16_test.cpp
+  DEPENDS
+    libc.src.math.atanbf16
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   atanf16_test
   NEED_MPFR

diff  --git a/libc/test/src/math/atanbf16_test.cpp b/libc/test/src/math/atanbf16_test.cpp
new file mode 100644
index 0000000000000..69d9b52d89a22
--- /dev/null
+++ b/libc/test/src/math/atanbf16_test.cpp
@@ -0,0 +1,56 @@
+//===-- Unittests for atanbf16 --------------------------------------------===//
+//
+// 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/atanbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcAtanBf16Test = 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(LlvmLibcAtanBf16Test, NormalPositiveRange) {
+  for (uint16_t v1 = POS_START; v1 <= POS_STOP; v1++) {
+
+    bfloat16 x = FPBits(v1).get_val();
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan, x,
+                                   LIBC_NAMESPACE::atanbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcAtanBf16Test, NormalNegativeRange) {
+  for (uint16_t v1 = NEG_START; v1 <= NEG_STOP; v1++) {
+
+    bfloat16 x = FPBits(v1).get_val();
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan, x,
+                                   LIBC_NAMESPACE::atanbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcAtanBf16Test, SpecialNumbers) {
+  constexpr bfloat16 VALUES[] = {zero,    neg_zero,   inf,
+                                 neg_inf, min_normal, max_normal};
+  for (size_t i = 0; i < 6; ++i) {
+    bfloat16 x = VALUES[i];
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan, x,
+                                   LIBC_NAMESPACE::atanbf16(x), 0.5);
+  }
+}

diff  --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index d92e6b728b63e..9d97c90cfaeb9 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4904,6 +4904,20 @@ add_fp_unittest(
     libc.src.math.atan
 )
 
+add_fp_unittest(
+  atanbf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    atanbf16_test.cpp
+  DEPENDS
+    libc.src.math.atanbf16
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   atanf16_test
   SUITE

diff  --git a/libc/test/src/math/smoke/atanbf16_test.cpp b/libc/test/src/math/smoke/atanbf16_test.cpp
new file mode 100644
index 0000000000000..6e15955316946
--- /dev/null
+++ b/libc/test/src/math/smoke/atanbf16_test.cpp
@@ -0,0 +1,44 @@
+//===-- Unittests for atanbf16 --------------------------------------------===//
+//
+// 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/atanbf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+class LlvmLibcAtanBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(bfloat16)
+public:
+  void test_special_numbers() {
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanbf16(aNaN));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::atanbf16(sNaN), FE_INVALID);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::atanbf16(zero));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::atanbf16(neg_zero));
+    EXPECT_MATH_ERRNO(0);
+
+    bfloat16 VALUES[] = {inf, neg_inf, bfloat16(1.0f), bfloat16(-1.0)};
+    for (size_t i = 0; i < 4; ++i) {
+      bfloat16 x = VALUES[i];
+
+      EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan, x,
+                                     LIBC_NAMESPACE::atanbf16(x), 0.5);
+    }
+  }
+};
+TEST_F(LlvmLibcAtanBf16Test, 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 a73d64efae515..491e846cbe49a 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3096,6 +3096,21 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_atanbf16",
+    hdrs = ["src/__support/math/atanbf16.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",
+        ":__support_macros_optimization",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_atanf",
     hdrs = ["src/__support/math/atanf.h"],
@@ -6328,6 +6343,11 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "atanbf16",
+    additional_deps = [":__support_math_atanbf16"],
+)
+
 libc_math_function(
     name = "atanf",
     additional_deps = [":__support_math_atanf"],


        


More information about the libc-commits mailing list