diff --git a/libc/shared/math.h b/libc/shared/math.h index 6cb583c08dedd..ddf219ece8ff1 100644 --- a/libc/shared/math.h +++ b/libc/shared/math.h @@ -28,6 +28,7 @@ #include "math/atan2f128.h" #include "math/atanf.h" #include "math/atanf16.h" +#include "math/atanhf.h" #include "math/erff.h" #include "math/exp.h" #include "math/exp10.h" diff --git a/libc/shared/math/atanhf.h b/libc/shared/math/atanhf.h new file mode 100644 index 0000000000000..763fb3e00a659 --- /dev/null +++ b/libc/shared/math/atanhf.h @@ -0,0 +1,23 @@ +//===-- Shared atanhf 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_ATANHF_H +#define LLVM_LIBC_SHARED_MATH_ATANHF_H + +#include "shared/libc_common.h" +#include "src/__support/math/atanhf.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::atanhf; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_ATANHF_H diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index caafdc2cbf1d6..500dd9de2c555 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -275,6 +275,17 @@ add_header_library( libc.src.__support.macros.optimization ) +add_header_library( + atanhf + HDRS + atanhf.h + DEPENDS + .acoshf_utils + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.macros.optimization +) + add_header_library( asinf HDRS diff --git a/libc/src/__support/math/atanhf.h b/libc/src/__support/math/atanhf.h new file mode 100644 index 0000000000000..b3ee5bbb4d408 --- /dev/null +++ b/libc/src/__support/math/atanhf.h @@ -0,0 +1,76 @@ +//===-- Implementation header for atanhf ------------------------*- 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___SUPPORT_MATH_ATANHF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ATANHF_H + +#include "acoshf_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +LIBC_INLINE static constexpr float atanhf(float x) { + using namespace acoshf_internal; + using FPBits = typename fputil::FPBits; + + FPBits xbits(x); + Sign sign = xbits.sign(); + uint32_t x_abs = xbits.abs().uintval(); + + // |x| >= 1.0 + if (LIBC_UNLIKELY(x_abs >= 0x3F80'0000U)) { + if (xbits.is_nan()) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + return x; + } + // |x| == 1.0 + if (x_abs == 0x3F80'0000U) { + fputil::set_errno_if_required(ERANGE); + fputil::raise_except_if_required(FE_DIVBYZERO); + return FPBits::inf(sign).get_val(); + } else { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + } + + // |x| < ~0.10 + if (LIBC_UNLIKELY(x_abs <= 0x3dcc'0000U)) { + // |x| <= 2^-26 + if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) { + return static_cast(LIBC_UNLIKELY(x_abs == 0) + ? x + : (x + 0x1.5555555555555p-2 * x * x * x)); + } + + double xdbl = x; + double x2 = xdbl * xdbl; + // Pure Taylor series. + double pe = fputil::polyeval(x2, 0.0, 0x1.5555555555555p-2, + 0x1.999999999999ap-3, 0x1.2492492492492p-3, + 0x1.c71c71c71c71cp-4, 0x1.745d1745d1746p-4); + return static_cast(fputil::multiply_add(xdbl, pe, xdbl)); + } + double xdbl = x; + return static_cast(0.5 * log_eval((xdbl + 1.0) / (xdbl - 1.0))); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATANHF_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index dbab34bd9d5ed..bac043f1d7d00 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -3922,10 +3922,7 @@ add_entrypoint_object( HDRS ../atanhf.h DEPENDS - .explogxf - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.macros.optimization + libc.src.__support.math.atanhf ) add_entrypoint_object( diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp index 602a8f042f783..81706190383ed 100644 --- a/libc/src/math/generic/atanhf.cpp +++ b/libc/src/math/generic/atanhf.cpp @@ -7,62 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/atanhf.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/math/generic/explogxf.h" +#include "src/__support/math/atanhf.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { - using namespace acoshf_internal; - using FPBits = typename fputil::FPBits; - - FPBits xbits(x); - Sign sign = xbits.sign(); - uint32_t x_abs = xbits.abs().uintval(); - - // |x| >= 1.0 - if (LIBC_UNLIKELY(x_abs >= 0x3F80'0000U)) { - if (xbits.is_nan()) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - return x; - } - // |x| == 1.0 - if (x_abs == 0x3F80'0000U) { - fputil::set_errno_if_required(ERANGE); - fputil::raise_except_if_required(FE_DIVBYZERO); - return FPBits::inf(sign).get_val(); - } else { - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - } - - // |x| < ~0.10 - if (LIBC_UNLIKELY(x_abs <= 0x3dcc'0000U)) { - // |x| <= 2^-26 - if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) { - return static_cast(LIBC_UNLIKELY(x_abs == 0) - ? x - : (x + 0x1.5555555555555p-2 * x * x * x)); - } - - double xdbl = x; - double x2 = xdbl * xdbl; - // Pure Taylor series. - double pe = fputil::polyeval(x2, 0.0, 0x1.5555555555555p-2, - 0x1.999999999999ap-3, 0x1.2492492492492p-3, - 0x1.c71c71c71c71cp-4, 0x1.745d1745d1746p-4); - return static_cast(fputil::multiply_add(xdbl, pe, xdbl)); - } - double xdbl = x; - return static_cast(0.5 * log_eval((xdbl + 1.0) / (xdbl - 1.0))); -} +LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { return math::atanhf(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt index a2c9c824a443f..34236ad69473c 100644 --- a/libc/test/shared/CMakeLists.txt +++ b/libc/test/shared/CMakeLists.txt @@ -24,6 +24,7 @@ add_fp_unittest( libc.src.__support.math.atan2f128 libc.src.__support.math.atanf libc.src.__support.math.atanf16 + libc.src.__support.math.atanhf libc.src.__support.math.erff libc.src.__support.math.exp libc.src.__support.math.exp10 diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp index 8626c723b372a..ffe1a2495604e 100644 --- a/libc/test/shared/shared_math_test.cpp +++ b/libc/test/shared/shared_math_test.cpp @@ -47,6 +47,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) { EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinhf(0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::atan2f(0.0f, 0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::atanf(0.0f)); + EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::atanhf(0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::erff(0.0f)); EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::exp10f(0.0f)); EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::expf(0.0f)); diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index d530f7148ab96..aa635ac3800a3 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -2373,6 +2373,18 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_math_atanhf", + hdrs = ["src/__support/math/atanhf.h"], + deps = [ + ":__support_math_acoshf_utils", + ":__support_fputil_fenv_impl", + ":__support_fputil_fp_bits", + ":__support_macros_config", + ":__support_macros_optimization", + ], +) + libc_support_library( name = "__support_math_erff", hdrs = ["src/__support/math/erff.h"], @@ -2998,13 +3010,7 @@ libc_math_function( libc_math_function( name = "atanhf", additional_deps = [ - ":__support_fputil_fma", - ":__support_fputil_multiply_add", - ":__support_fputil_nearest_integer", - ":__support_fputil_polyeval", - ":__support_macros_optimization", - ":common_constants", - ":explogxf", + ":__support_math_atanhf", ], )