diff --git a/libc/shared/math.h b/libc/shared/math.h index 6ab5df103bfb3..69d785b3e0291 100644 --- a/libc/shared/math.h +++ b/libc/shared/math.h @@ -38,6 +38,7 @@ #include "math/coshf.h" #include "math/coshf16.h" #include "math/cospif.h" +#include "math/cospif16.h" #include "math/erff.h" #include "math/exp.h" #include "math/exp10.h" diff --git a/libc/shared/math/cospif16.h b/libc/shared/math/cospif16.h new file mode 100644 index 0000000000000..a1680b00d0b5b --- /dev/null +++ b/libc/shared/math/cospif16.h @@ -0,0 +1,28 @@ +//===-- Shared cospif16 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_COSPIF16_H +#define LLVM_LIBC_SHARED_MATH_COSPIF16_H + +#include "shared/libc_common.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "src/__support/math/cospif16.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::cospif16; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SHARED_MATH_COSPIF_H diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index 8ce6cef732d76..39dc0e57f4472 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -444,6 +444,19 @@ add_header_library( libc.src.__support.macros.optimization ) +add_header_library( + cospif16 + HDRS + cospif16.h + DEPENDS + .sincosf16_utils + 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.macros.optimization +) + add_header_library( erff HDRS diff --git a/libc/src/__support/math/cospif16.h b/libc/src/__support/math/cospif16.h new file mode 100644 index 0000000000000..d07236cccac75 --- /dev/null +++ b/libc/src/__support/math/cospif16.h @@ -0,0 +1,99 @@ +//===-- Implementation header for cospif16 ----------------------*- 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_COSPIF16_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_COSPIF16_H + +#include "include/llvm-libc-macros/float16-macros.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "sincosf16_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/macros/optimization.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +LIBC_INLINE static constexpr float16 cospif16(float16 x) { + + using namespace sincosf16_internal; + using FPBits = typename fputil::FPBits; + FPBits xbits(x); + + uint16_t x_u = xbits.uintval(); + uint16_t x_abs = x_u & 0x7fff; + float xf = x; + + // Range reduction: + // For |x| > 1/32, we perform range reduction as follows: + // Find k and y such that: + // x = (k + y) * 1/32 + // k is an integer + // |y| < 0.5 + // + // This is done by performing: + // k = round(x * 32) + // y = x * 32 - k + // + // Once k and y are computed, we then deduce the answer by the cosine of sum + // formula: + // cos(x * pi) = cos((k + y) * pi/32) + // = cos(k * pi/32) * cos(y * pi/32) + + // sin(y * pi/32) * sin(k * pi/32) + + // For signed zeros + if (LIBC_UNLIKELY(x_abs == 0U)) + return fputil::cast(1.0f); + + // Numbers greater or equal to 2^10 are integers, or infinity, or NaN + if (LIBC_UNLIKELY(x_abs >= 0x6400)) { + if (LIBC_UNLIKELY(x_abs <= 0x67FF)) + return fputil::cast((x_abs & 0x1) ? -1.0f : 1.0f); + + // Check for NaN or infintiy values + if (LIBC_UNLIKELY(x_abs >= 0x7c00)) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + // If value is equal to infinity + if (x_abs == 0x7c00) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + } + + return x + FPBits::quiet_nan().get_val(); + } + + return fputil::cast(1.0f); + } + + float sin_k = 0, cos_k = 0, sin_y = 0, cosm1_y = 0; + sincospif16_eval(xf, sin_k, cos_k, sin_y, cosm1_y); + + if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) + return fputil::cast(0.0f); + + // Since, cosm1_y = cos_y - 1, therefore: + // cos(x * pi) = cos_k(cosm1_y) + cos_k - sin_k * sin_y + return fputil::cast(fputil::multiply_add( + cos_k, cosm1_y, fputil::multiply_add(-sin_k, sin_y, cos_k))); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSHF16_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index b377d56e96d1d..018d73d6b4722 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -325,14 +325,7 @@ add_entrypoint_object( HDRS ../cospif16.h DEPENDS - libc.hdr.errno_macros - 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.macros.optimization - libc.src.__support.math.sincosf16_utils + libc.src.__support.math.cospif16 ) add_entrypoint_object( diff --git a/libc/src/math/generic/cospif16.cpp b/libc/src/math/generic/cospif16.cpp index c99285b25c106..a4bae8e13eac8 100644 --- a/libc/src/math/generic/cospif16.cpp +++ b/libc/src/math/generic/cospif16.cpp @@ -7,80 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/cospif16.h" -#include "hdr/errno_macros.h" -#include "hdr/fenv_macros.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/cast.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/macros/optimization.h" -#include "src/__support/math/sincosf16_utils.h" +#include "src/__support/math/cospif16.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float16, cospif16, (float16 x)) { - using namespace sincosf16_internal; - using FPBits = typename fputil::FPBits; - FPBits xbits(x); - - uint16_t x_u = xbits.uintval(); - uint16_t x_abs = x_u & 0x7fff; - float xf = x; - - // Range reduction: - // For |x| > 1/32, we perform range reduction as follows: - // Find k and y such that: - // x = (k + y) * 1/32 - // k is an integer - // |y| < 0.5 - // - // This is done by performing: - // k = round(x * 32) - // y = x * 32 - k - // - // Once k and y are computed, we then deduce the answer by the cosine of sum - // formula: - // cos(x * pi) = cos((k + y) * pi/32) - // = cos(k * pi/32) * cos(y * pi/32) + - // sin(y * pi/32) * sin(k * pi/32) - - // For signed zeros - if (LIBC_UNLIKELY(x_abs == 0U)) - return fputil::cast(1.0f); - - // Numbers greater or equal to 2^10 are integers, or infinity, or NaN - if (LIBC_UNLIKELY(x_abs >= 0x6400)) { - if (LIBC_UNLIKELY(x_abs <= 0x67FF)) - return fputil::cast((x_abs & 0x1) ? -1.0f : 1.0f); - - // Check for NaN or infintiy values - if (LIBC_UNLIKELY(x_abs >= 0x7c00)) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - // If value is equal to infinity - if (x_abs == 0x7c00) { - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - } - - return x + FPBits::quiet_nan().get_val(); - } - - return fputil::cast(1.0f); - } - - float sin_k, cos_k, sin_y, cosm1_y; - sincospif16_eval(xf, sin_k, cos_k, sin_y, cosm1_y); - - if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) - return fputil::cast(0.0f); - - // Since, cosm1_y = cos_y - 1, therefore: - // cos(x * pi) = cos_k(cosm1_y) + cos_k - sin_k * sin_y - return fputil::cast(fputil::multiply_add( - cos_k, cosm1_y, fputil::multiply_add(-sin_k, sin_y, cos_k))); -} +LLVM_LIBC_FUNCTION(float16, cospif16, (float16 x)) { return math::cospif16(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt index 89d5b243b20a3..48241d3f55287 100644 --- a/libc/test/shared/CMakeLists.txt +++ b/libc/test/shared/CMakeLists.txt @@ -34,6 +34,7 @@ add_fp_unittest( libc.src.__support.math.coshf libc.src.__support.math.coshf16 libc.src.__support.math.cospif + libc.src.__support.math.cospif16 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 c22543d3337ab..2e5a2d51146d4 100644 --- a/libc/test/shared/shared_math_test.cpp +++ b/libc/test/shared/shared_math_test.cpp @@ -23,6 +23,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) { EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::atanhf16(0.0f16)); EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::cosf16(0.0f16)); EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::coshf16(0.0f16)); + EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::cospif16(0.0f16)); EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16)); EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::expf16(0.0f16)); diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index d698e15317c84..a4a2e39c74fe0 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -2407,6 +2407,18 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_math_cospif16", + hdrs = ["src/__support/math/cospif16.h"], + deps = [ + ":__support_fputil_cast", + ":__support_fputil_fenv_impl", + ":__support_fputil_multiply_add", + ":__support_macros_optimization", + ":__support_math_sincosf16_utils", + ], +) + libc_support_library( name = "__support_math_erff", hdrs = ["src/__support/math/erff.h"], @@ -3242,9 +3254,7 @@ libc_math_function( libc_math_function( name = "cospif16", additional_deps = [ - ":__support_fputil_multiply_add", - ":__support_macros_optimization", - ":__support_math_sincosf16_utils", + ":__support_math_cospif16", ], )