From bb73a0a4c223b260f525d4b12b073de15fd09354 Mon Sep 17 00:00:00 2001 From: bassiounix Date: Tue, 19 Aug 2025 01:28:06 +0300 Subject: [PATCH] [libc][math] Refactor cospif implementation to header-only in src/__support/math folder. --- libc/shared/math.h | 1 + libc/shared/math/cospif.h | 23 ++++ libc/src/__support/math/CMakeLists.txt | 12 ++ libc/src/__support/math/cospif.h | 109 ++++++++++++++++++ libc/src/math/generic/CMakeLists.txt | 7 +- libc/src/math/generic/cospif.cpp | 89 +------------- libc/test/shared/CMakeLists.txt | 1 + libc/test/shared/shared_math_test.cpp | 1 + .../llvm-project-overlay/libc/BUILD.bazel | 24 ++-- 9 files changed, 166 insertions(+), 101 deletions(-) create mode 100644 libc/shared/math/cospif.h create mode 100644 libc/src/__support/math/cospif.h diff --git a/libc/shared/math.h b/libc/shared/math.h index a89aa90ee1ef8..6ab5df103bfb3 100644 --- a/libc/shared/math.h +++ b/libc/shared/math.h @@ -37,6 +37,7 @@ #include "math/cosf16.h" #include "math/coshf.h" #include "math/coshf16.h" +#include "math/cospif.h" #include "math/erff.h" #include "math/exp.h" #include "math/exp10.h" diff --git a/libc/shared/math/cospif.h b/libc/shared/math/cospif.h new file mode 100644 index 0000000000000..ce664e9c54859 --- /dev/null +++ b/libc/shared/math/cospif.h @@ -0,0 +1,23 @@ +//===-- Shared cospif 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_COSPIF_H +#define LLVM_LIBC_SHARED_MATH_COSPIF_H + +#include "shared/libc_common.h" +#include "src/__support/math/cospif.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::cospif; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_COSPIF_H diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index cddf336369973..8ce6cef732d76 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -432,6 +432,18 @@ add_header_library( libc.src.__support.macros.optimization ) +add_header_library( + cospif + HDRS + cospif.h + DEPENDS + .sincosf_utils + 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/cospif.h b/libc/src/__support/math/cospif.h new file mode 100644 index 0000000000000..e921090459769 --- /dev/null +++ b/libc/src/__support/math/cospif.h @@ -0,0 +1,109 @@ +//===-- Implementation header for cospif ------------------------*- 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_COSPIF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_COSPIF_H + +#include "sincosf_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +LIBC_INLINE static constexpr float cospif(float x) { + using FPBits = typename fputil::FPBits; + + FPBits xbits(x); + xbits.set_sign(Sign::POS); + + uint32_t x_abs = xbits.uintval(); + double xd = static_cast(xbits.get_val()); + + // 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: + // cospi(x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed + // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are + // computed using degree-7 and degree-6 minimax polynomials generated by + // Sollya respectively. + + // The exhautive test passes for smaller values + if (LIBC_UNLIKELY(x_abs < 0x38A2'F984U)) { + +#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT) + return fputil::multiply_add(xbits.get_val(), -0x1.0p-25f, 1.0f); +#else + return static_cast(fputil::multiply_add(xd, -0x1.0p-25, 1.0)); +#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT + } + + // Numbers greater or equal to 2^23 are always integers or NaN + if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) { + + if (LIBC_UNLIKELY(x_abs < 0x4B80'0000)) { + return (x_abs & 0x1) ? -1.0f : 1.0f; + } + + // x is inf or nan. + if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + if (x_abs == 0x7f80'0000U) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + } + return x + FPBits::quiet_nan().get_val(); + } + + return 1.0f; + } + + // Combine the results with the sine of sum formula: + // cos(pi * x) = cos((k + y)*pi/32) + // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) + // = (cosm1_y + 1) * cos_k - sin_y * sin_k + // = (cosm1_y * cos_k + cos_k) - sin_y * sin_k + double sin_k = 0, cos_k = 0, sin_y = 0, cosm1_y = 0; + + sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y); + + if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) { + return 0.0f; + } + + return static_cast(fputil::multiply_add( + sin_y, -sin_k, fputil::multiply_add(cosm1_y, cos_k, cos_k))); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSHF_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 2bb4d44eddb8d..b377d56e96d1d 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -315,12 +315,7 @@ add_entrypoint_object( HDRS ../cospif.h DEPENDS - libc.src.__support.math.sincosf_utils - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.fma - libc.src.__support.FPUtil.multiply_add - libc.src.__support.macros.optimization + libc.src.__support.math.cospif ) add_entrypoint_object( diff --git a/libc/src/math/generic/cospif.cpp b/libc/src/math/generic/cospif.cpp index 6b524a2cace7e..b9a4637da2ef4 100644 --- a/libc/src/math/generic/cospif.cpp +++ b/libc/src/math/generic/cospif.cpp @@ -7,95 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/cospif.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA -#include "src/__support/math/sincosf_utils.h" +#include "src/__support/math/cospif.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, cospif, (float x)) { - using FPBits = typename fputil::FPBits; - - FPBits xbits(x); - xbits.set_sign(Sign::POS); - - uint32_t x_abs = xbits.uintval(); - double xd = static_cast(xbits.get_val()); - - // 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: - // cospi(x) = cos((k + y)*pi/32) - // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) - // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed - // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are - // computed using degree-7 and degree-6 minimax polynomials generated by - // Sollya respectively. - - // The exhautive test passes for smaller values - if (LIBC_UNLIKELY(x_abs < 0x38A2'F984U)) { - -#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT) - return fputil::multiply_add(xbits.get_val(), -0x1.0p-25f, 1.0f); -#else - return static_cast(fputil::multiply_add(xd, -0x1.0p-25, 1.0)); -#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT - } - - // Numbers greater or equal to 2^23 are always integers or NaN - if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) { - - if (LIBC_UNLIKELY(x_abs < 0x4B80'0000)) { - return (x_abs & 0x1) ? -1.0f : 1.0f; - } - - // x is inf or nan. - if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - - if (x_abs == 0x7f80'0000U) { - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - } - return x + FPBits::quiet_nan().get_val(); - } - - return 1.0f; - } - - // Combine the results with the sine of sum formula: - // cos(pi * x) = cos((k + y)*pi/32) - // = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32) - // = (cosm1_y + 1) * cos_k - sin_y * sin_k - // = (cosm1_y * cos_k + cos_k) - sin_y * sin_k - double sin_k, cos_k, sin_y, cosm1_y; - - sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y); - - if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) { - return 0.0f; - } - - return static_cast(fputil::multiply_add( - sin_y, -sin_k, fputil::multiply_add(cosm1_y, cos_k, cos_k))); -} +LLVM_LIBC_FUNCTION(float, cospif, (float x)) { return math::cospif(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt index 3865fd8bcacc5..89d5b243b20a3 100644 --- a/libc/test/shared/CMakeLists.txt +++ b/libc/test/shared/CMakeLists.txt @@ -33,6 +33,7 @@ add_fp_unittest( libc.src.__support.math.cosf16 libc.src.__support.math.coshf libc.src.__support.math.coshf16 + libc.src.__support.math.cospif 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 048ff025cd1fb..c22543d3337ab 100644 --- a/libc/test/shared/shared_math_test.cpp +++ b/libc/test/shared/shared_math_test.cpp @@ -53,6 +53,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) { EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::cbrtf(0.0f)); EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::cosf(0.0f)); EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::coshf(0.0f)); + EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::cospif(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 830042a400f33..d698e15317c84 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -2392,6 +2392,21 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_math_cospif", + hdrs = ["src/__support/math/cospif.h"], + deps = [ + ":__support_fputil_fma", + ":__support_fputil_multiply_add", + ":__support_fputil_nearest_integer", + ":__support_fputil_polyeval", + ":__support_fputil_rounding_mode", + ":__support_macros_optimization", + ":__support_sincosf_utils", + ":common_constants", + ], +) + libc_support_library( name = "__support_math_erff", hdrs = ["src/__support/math/erff.h"], @@ -3220,14 +3235,7 @@ libc_math_function( libc_math_function( name = "cospif", additional_deps = [ - ":__support_fputil_fma", - ":__support_fputil_multiply_add", - ":__support_fputil_nearest_integer", - ":__support_fputil_polyeval", - ":__support_fputil_rounding_mode", - ":__support_macros_optimization", - ":__support_sincosf_utils", - ":common_constants", + ":__support_math_cospif", ], )