diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt index 9fa9744cf109..84600efc5e0d 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 e55407d340bb..902f6ed44179 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 654786b919c2..30f9bccd2221 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 d365708b950a..4d27e994323f 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 b0c247464c85..cad973f1ac06 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 98c27d300ad9..7aaf3470dcea 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 532fcda9ab3b..96c0902d729d 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 e6c903089884..d6569e59a3e5 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 91fa524cc0d6..9fd45329ad0f 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 ba97e5c2035b..fdfce36b824f 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 a58e68d47c1e..8cceaccc314d 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 a1803d65d1b4..ee8072a3465e 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 8692bf37c05b..202ef034b8ac 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 ef006c668f3a..3d81216f1bcf 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 000000000000..b3f6d280a70e --- /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 abac483e40fa..6266b26b81ba 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 000000000000..563b8325b842 --- /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; + 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(fputil::multiply_add(xf, -0x1p-9f, xf)); + + float result = atan_eval(x_sq); + return fputil::cast(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(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(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(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 98dba11f34c8..5bdb8d99eede 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 000000000000..571b436cb2d3 --- /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 8aaeea0565ee..fdc3fa777d1f 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 000000000000..fc2879b3a628 --- /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 bfacee9cecac..36262012ad0f 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 d958529d04fb..341b35a7b7e0 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; + 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 2710f4cbdbe3..ceed946e2386 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 000000000000..69d9b52d89a2 --- /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; + +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 d92e6b728b63..9d97c90cfaeb 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 000000000000..6e1595531694 --- /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 a73d64efae51..491e846cbe49 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"],