From cc5909b3e3de5470b31592eec6b22da88ca82df2 Mon Sep 17 00:00:00 2001 From: Ash <97464181+tnuha@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:57:05 +0000 Subject: [PATCH] [libc][math] Refactor sincos implementation to header only (#177522) Part of llvm#147386 in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450 Closes #177638 --- libc/shared/math.h | 1 + libc/shared/math/sincos.h | 23 ++ libc/src/__support/math/CMakeLists.txt | 21 ++ libc/src/__support/math/sincos.h | 229 ++++++++++++++++++ libc/src/math/generic/CMakeLists.txt | 11 +- libc/src/math/generic/sincos.cpp | 210 +--------------- libc/test/shared/CMakeLists.txt | 1 + libc/test/shared/shared_math_test.cpp | 4 + .../llvm-project-overlay/libc/BUILD.bazel | 27 ++- 9 files changed, 304 insertions(+), 223 deletions(-) create mode 100644 libc/shared/math/sincos.h create mode 100644 libc/src/__support/math/sincos.h diff --git a/libc/shared/math.h b/libc/shared/math.h index 1138e1189636..1b7bf1b93e05 100644 --- a/libc/shared/math.h +++ b/libc/shared/math.h @@ -119,6 +119,7 @@ #include "math/rsqrtf.h" #include "math/rsqrtf16.h" #include "math/sin.h" +#include "math/sincos.h" #include "math/sincosf.h" #include "math/sinf.h" #include "math/sinf16.h" diff --git a/libc/shared/math/sincos.h b/libc/shared/math/sincos.h new file mode 100644 index 000000000000..fec49a02feb1 --- /dev/null +++ b/libc/shared/math/sincos.h @@ -0,0 +1,23 @@ +//===-- Shared sincos 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_SINCOS_H +#define LLVM_LIBC_SHARED_MATH_SINCOS_H + +#include "shared/libc_common.h" +#include "src/__support/math/sincos.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::sincos; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_SINCOS_H diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index bb07ddaeb193..64be1d98493d 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -1344,6 +1344,27 @@ add_header_library( libc.include.llvm-libc-macros.float16_macros ) +add_header_library( + sincos + HDRS + sincos.h + DEPENDS + .range_reduction_double + .sincos_eval + libc.hdr.errno_macros + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.double_double + libc.src.__support.FPUtil.dyadic_float + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.rounding_mode + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.cpu_features +) + add_header_library( sincos_eval HDRS diff --git a/libc/src/__support/math/sincos.h b/libc/src/__support/math/sincos.h new file mode 100644 index 000000000000..11727c3bf380 --- /dev/null +++ b/libc/src/__support/math/sincos.h @@ -0,0 +1,229 @@ +//===-- Implementation header for sincos ------------------------*- 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_SINCOS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_SINCOS_H + +#include "hdr/errno_macros.h" +#include "range_reduction_double_common.h" +#include "sincos_eval.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/double_double.h" +#include "src/__support/FPUtil/dyadic_float.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/rounding_mode.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 + +#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE +#include "range_reduction_double_fma.h" +#else +#include "range_reduction_double_nofma.h" +#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +LIBC_INLINE void sincos(double x, double *sin_x, double *cos_x) { + using DoubleDouble = fputil::DoubleDouble; + using namespace math::range_reduction_double_internal; + using FPBits = typename fputil::FPBits; + FPBits xbits(x); + + uint16_t x_e = xbits.get_biased_exponent(); + + DoubleDouble y; + unsigned k = 0; + LargeRangeReduction range_reduction_large{}; + + // |x| < 2^16 + if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT)) { + // |x| < 2^-7 + if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 7)) { + // |x| < 2^-27 + if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 27)) { + // Signed zeros. + if (LIBC_UNLIKELY(x == 0.0)) { + *sin_x = x; + *cos_x = 1.0; + return; + } + + // For |x| < 2^-27, max(|sin(x) - x|, |cos(x) - 1|) < ulp(x)/2. +#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE + *sin_x = fputil::multiply_add(x, -0x1.0p-54, x); + *cos_x = fputil::multiply_add(x, -x, 1.0); +#else + *cos_x = fputil::round_result_slightly_down(1.0); + + if (LIBC_UNLIKELY(x_e < 4)) { + int rounding_mode = fputil::quick_get_round(); + if (rounding_mode == FE_TOWARDZERO || + (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) || + (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD)) + *sin_x = FPBits(xbits.uintval() - 1).get_val(); + } + *sin_x = fputil::multiply_add(x, -0x1.0p-54, x); +#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE + return; + } + // No range reduction needed. + k = 0; + y.lo = 0.0; + y.hi = x; + } else { + // Small range reduction. + k = range_reduction_small(x, y); + } + } else { + // Inf or NaN + if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + *sin_x = *cos_x = FPBits::quiet_nan().get_val(); + return; + } + + // sin(+-Inf) = NaN + if (xbits.get_mantissa() == 0) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + } + *sin_x = *cos_x = x + FPBits::quiet_nan().get_val(); + return; + } + + // Large range reduction. + k = range_reduction_large.fast(x, y); + } + + DoubleDouble sin_y, cos_y; + + [[maybe_unused]] double err = + math::sincos_eval_internal::sincos_eval(y, sin_y, cos_y); + + // Look up sin(k * pi/128) and cos(k * pi/128) +#ifdef LIBC_MATH_HAS_SMALL_TABLES + // Memory saving versions. Use 65-entry table. + auto get_idx_dd = [](unsigned kk) -> DoubleDouble { + unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63); + DoubleDouble ans = SIN_K_PI_OVER_128[idx]; + if (kk & 128) { + ans.hi = -ans.hi; + ans.lo = -ans.lo; + } + return ans; + }; + DoubleDouble sin_k = get_idx_dd(k); + DoubleDouble cos_k = get_idx_dd(k + 64); +#else + // Fast look up version, but needs 256-entry table. + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + DoubleDouble sin_k = SIN_K_PI_OVER_128[k & 255]; + DoubleDouble cos_k = SIN_K_PI_OVER_128[(k + 64) & 255]; +#endif // LIBC_MATH_HAS_SMALL_TABLES + + DoubleDouble msin_k{-sin_k.lo, -sin_k.hi}; + + // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128). + // So k is an integer and -pi / 256 <= y <= pi / 256. + // Then sin(x) = sin((k * pi/128 + y) + // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) + DoubleDouble sin_k_cos_y = fputil::quick_mult(cos_y, sin_k); + DoubleDouble cos_k_sin_y = fputil::quick_mult(sin_y, cos_k); + // cos(x) = cos((k * pi/128 + y) + // = cos(y) * cos(k*pi/128) - sin(y) * sin(k*pi/128) + DoubleDouble cos_k_cos_y = fputil::quick_mult(cos_y, cos_k); + DoubleDouble msin_k_sin_y = fputil::quick_mult(sin_y, msin_k); + + DoubleDouble sin_dd = + fputil::exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); + DoubleDouble cos_dd = + fputil::exact_add(cos_k_cos_y.hi, msin_k_sin_y.hi); + sin_dd.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; + cos_dd.lo += msin_k_sin_y.lo + cos_k_cos_y.lo; + +#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + *sin_x = sin_dd.hi + sin_dd.lo; + *cos_x = cos_dd.hi + cos_dd.lo; + return; +#else + // Accurate test and pass for correctly rounded implementation. + + double sin_lp = sin_dd.lo + err; + double sin_lm = sin_dd.lo - err; + double cos_lp = cos_dd.lo + err; + double cos_lm = cos_dd.lo - err; + + double sin_upper = sin_dd.hi + sin_lp; + double sin_lower = sin_dd.hi + sin_lm; + double cos_upper = cos_dd.hi + cos_lp; + double cos_lower = cos_dd.hi + cos_lm; + + // Ziv's rounding test. + if (LIBC_LIKELY(sin_upper == sin_lower && cos_upper == cos_lower)) { + *sin_x = sin_upper; + *cos_x = cos_upper; + return; + } + + Float128 u_f128, sin_u, cos_u; + if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT)) + u_f128 = range_reduction_small_f128(x); + else + u_f128 = range_reduction_large.accurate(); + + math::sincos_eval_internal::sincos_eval(u_f128, sin_u, cos_u); + + auto get_sin_k = [](unsigned kk) -> Float128 { + unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63); + Float128 ans = SIN_K_PI_OVER_128_F128[idx]; + if (kk & 128) + ans.sign = Sign::NEG; + return ans; + }; + + // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). + Float128 sin_k_f128 = get_sin_k(k); + Float128 cos_k_f128 = get_sin_k(k + 64); + Float128 msin_k_f128 = get_sin_k(k + 128); + + // TODO: Add assertion if Ziv's accuracy tests fail in debug mode. + // https://github.com/llvm/llvm-project/issues/96452. + + if (sin_upper == sin_lower) + *sin_x = sin_upper; + else + // sin(x) = sin((k * pi/128 + u) + // = sin(u) * cos(k*pi/128) + cos(u) * sin(k*pi/128) + *sin_x = static_cast( + fputil::quick_add(fputil::quick_mul(sin_k_f128, cos_u), + fputil::quick_mul(cos_k_f128, sin_u))); + + if (cos_upper == cos_lower) + *cos_x = cos_upper; + else + // cos(x) = cos((k * pi/128 + u) + // = cos(u) * cos(k*pi/128) - sin(u) * sin(k*pi/128) + *cos_x = static_cast( + fputil::quick_add(fputil::quick_mul(cos_k_f128, cos_u), + fputil::quick_mul(msin_k_f128, sin_u))); + +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINCOS_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 7ee4aa509976..35eb74360ab4 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -389,17 +389,8 @@ add_entrypoint_object( HDRS ../sincos.h DEPENDS - libc.src.__support.math.range_reduction_double - libc.src.__support.math.sincos_eval - libc.hdr.errno_macros + libc.src.__support.math.sincos libc.src.errno.errno - libc.src.__support.FPUtil.double_double - libc.src.__support.FPUtil.dyadic_float - libc.src.__support.FPUtil.except_value_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_entrypoint_object( diff --git a/libc/src/math/generic/sincos.cpp b/libc/src/math/generic/sincos.cpp index 38661deaa886..730618865016 100644 --- a/libc/src/math/generic/sincos.cpp +++ b/libc/src/math/generic/sincos.cpp @@ -7,217 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/math/sincos.h" -#include "hdr/errno_macros.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/double_double.h" -#include "src/__support/FPUtil/dyadic_float.h" -#include "src/__support/FPUtil/except_value_utils.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/rounding_mode.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/range_reduction_double_common.h" -#include "src/__support/math/sincos_eval.h" - -#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE -#include "src/__support/math/range_reduction_double_fma.h" -#else -#include "src/__support/math/range_reduction_double_nofma.h" -#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE +#include "src/__support/math/sincos.h" namespace LIBC_NAMESPACE_DECL { - -using DoubleDouble = fputil::DoubleDouble; -using Float128 = typename fputil::DyadicFloat<128>; - LLVM_LIBC_FUNCTION(void, sincos, (double x, double *sin_x, double *cos_x)) { - using namespace math::range_reduction_double_internal; - using FPBits = typename fputil::FPBits; - FPBits xbits(x); - - uint16_t x_e = xbits.get_biased_exponent(); - - DoubleDouble y; - unsigned k; - LargeRangeReduction range_reduction_large{}; - - // |x| < 2^16 - if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT)) { - // |x| < 2^-7 - if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 7)) { - // |x| < 2^-27 - if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 27)) { - // Signed zeros. - if (LIBC_UNLIKELY(x == 0.0)) { - *sin_x = x; - *cos_x = 1.0; - return; - } - - // For |x| < 2^-27, max(|sin(x) - x|, |cos(x) - 1|) < ulp(x)/2. -#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE - *sin_x = fputil::multiply_add(x, -0x1.0p-54, x); - *cos_x = fputil::multiply_add(x, -x, 1.0); -#else - *cos_x = fputil::round_result_slightly_down(1.0); - - if (LIBC_UNLIKELY(x_e < 4)) { - int rounding_mode = fputil::quick_get_round(); - if (rounding_mode == FE_TOWARDZERO || - (xbits.sign() == Sign::POS && rounding_mode == FE_DOWNWARD) || - (xbits.sign() == Sign::NEG && rounding_mode == FE_UPWARD)) - *sin_x = FPBits(xbits.uintval() - 1).get_val(); - } - *sin_x = fputil::multiply_add(x, -0x1.0p-54, x); -#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE - return; - } - // No range reduction needed. - k = 0; - y.lo = 0.0; - y.hi = x; - } else { - // Small range reduction. - k = range_reduction_small(x, y); - } - } else { - // Inf or NaN - if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - *sin_x = *cos_x = FPBits::quiet_nan().get_val(); - return; - } - - // sin(+-Inf) = NaN - if (xbits.get_mantissa() == 0) { - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - } - *sin_x = *cos_x = x + FPBits::quiet_nan().get_val(); - return; - } - - // Large range reduction. - k = range_reduction_large.fast(x, y); - } - - DoubleDouble sin_y, cos_y; - - [[maybe_unused]] double err = - math::sincos_eval_internal::sincos_eval(y, sin_y, cos_y); - - // Look up sin(k * pi/128) and cos(k * pi/128) -#ifdef LIBC_MATH_HAS_SMALL_TABLES - // Memory saving versions. Use 65-entry table. - auto get_idx_dd = [](unsigned kk) -> DoubleDouble { - unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63); - DoubleDouble ans = SIN_K_PI_OVER_128[idx]; - if (kk & 128) { - ans.hi = -ans.hi; - ans.lo = -ans.lo; - } - return ans; - }; - DoubleDouble sin_k = get_idx_dd(k); - DoubleDouble cos_k = get_idx_dd(k + 64); -#else - // Fast look up version, but needs 256-entry table. - // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). - DoubleDouble sin_k = SIN_K_PI_OVER_128[k & 255]; - DoubleDouble cos_k = SIN_K_PI_OVER_128[(k + 64) & 255]; -#endif // LIBC_MATH_HAS_SMALL_TABLES - - DoubleDouble msin_k{-sin_k.lo, -sin_k.hi}; - - // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128). - // So k is an integer and -pi / 256 <= y <= pi / 256. - // Then sin(x) = sin((k * pi/128 + y) - // = sin(y) * cos(k*pi/128) + cos(y) * sin(k*pi/128) - DoubleDouble sin_k_cos_y = fputil::quick_mult(cos_y, sin_k); - DoubleDouble cos_k_sin_y = fputil::quick_mult(sin_y, cos_k); - // cos(x) = cos((k * pi/128 + y) - // = cos(y) * cos(k*pi/128) - sin(y) * sin(k*pi/128) - DoubleDouble cos_k_cos_y = fputil::quick_mult(cos_y, cos_k); - DoubleDouble msin_k_sin_y = fputil::quick_mult(sin_y, msin_k); - - DoubleDouble sin_dd = - fputil::exact_add(sin_k_cos_y.hi, cos_k_sin_y.hi); - DoubleDouble cos_dd = - fputil::exact_add(cos_k_cos_y.hi, msin_k_sin_y.hi); - sin_dd.lo += sin_k_cos_y.lo + cos_k_sin_y.lo; - cos_dd.lo += msin_k_sin_y.lo + cos_k_cos_y.lo; - -#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - *sin_x = sin_dd.hi + sin_dd.lo; - *cos_x = cos_dd.hi + cos_dd.lo; - return; -#else - // Accurate test and pass for correctly rounded implementation. - - double sin_lp = sin_dd.lo + err; - double sin_lm = sin_dd.lo - err; - double cos_lp = cos_dd.lo + err; - double cos_lm = cos_dd.lo - err; - - double sin_upper = sin_dd.hi + sin_lp; - double sin_lower = sin_dd.hi + sin_lm; - double cos_upper = cos_dd.hi + cos_lp; - double cos_lower = cos_dd.hi + cos_lm; - - // Ziv's rounding test. - if (LIBC_LIKELY(sin_upper == sin_lower && cos_upper == cos_lower)) { - *sin_x = sin_upper; - *cos_x = cos_upper; - return; - } - - Float128 u_f128, sin_u, cos_u; - if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT)) - u_f128 = range_reduction_small_f128(x); - else - u_f128 = range_reduction_large.accurate(); - - math::sincos_eval_internal::sincos_eval(u_f128, sin_u, cos_u); - - auto get_sin_k = [](unsigned kk) -> Float128 { - unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63); - Float128 ans = SIN_K_PI_OVER_128_F128[idx]; - if (kk & 128) - ans.sign = Sign::NEG; - return ans; - }; - - // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128). - Float128 sin_k_f128 = get_sin_k(k); - Float128 cos_k_f128 = get_sin_k(k + 64); - Float128 msin_k_f128 = get_sin_k(k + 128); - - // TODO: Add assertion if Ziv's accuracy tests fail in debug mode. - // https://github.com/llvm/llvm-project/issues/96452. - - if (sin_upper == sin_lower) - *sin_x = sin_upper; - else - // sin(x) = sin((k * pi/128 + u) - // = sin(u) * cos(k*pi/128) + cos(u) * sin(k*pi/128) - *sin_x = static_cast( - fputil::quick_add(fputil::quick_mul(sin_k_f128, cos_u), - fputil::quick_mul(cos_k_f128, sin_u))); - - if (cos_upper == cos_lower) - *cos_x = cos_upper; - else - // cos(x) = cos((k * pi/128 + u) - // = cos(u) * cos(k*pi/128) - sin(u) * sin(k*pi/128) - *cos_x = static_cast( - fputil::quick_add(fputil::quick_mul(cos_k_f128, cos_u), - fputil::quick_mul(msin_k_f128, sin_u))); - -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + return math::sincos(x, sin_x, cos_x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt index 5dfbadfdcc85..20efee227256 100644 --- a/libc/test/shared/CMakeLists.txt +++ b/libc/test/shared/CMakeLists.txt @@ -117,6 +117,7 @@ add_fp_unittest( libc.src.__support.math.rsqrtf16 libc.src.__support.math.sqrtf16 libc.src.__support.math.sin + libc.src.__support.math.sincos libc.src.__support.math.sincosf libc.src.__support.math.sinf libc.src.__support.math.sinf16 diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp index 0c12d1b4b6f0..b8ccacd9bc71 100644 --- a/libc/test/shared/shared_math_test.cpp +++ b/libc/test/shared/shared_math_test.cpp @@ -145,6 +145,8 @@ TEST(LlvmLibcSharedMathTest, AllFloat) { } TEST(LlvmLibcSharedMathTest, AllDouble) { + double sin, cos; + LIBC_NAMESPACE::shared::sincos(0.0, &sin, &cos); EXPECT_FP_EQ(0x1.921fb54442d18p+0, LIBC_NAMESPACE::shared::acos(0.0)); EXPECT_FP_EQ(0x0p+0, LIBC_NAMESPACE::shared::asin(0.0)); EXPECT_FP_EQ(0x0p+0, LIBC_NAMESPACE::shared::atan(0.0)); @@ -164,6 +166,8 @@ TEST(LlvmLibcSharedMathTest, AllDouble) { EXPECT_FP_EQ(0x0p+0, LIBC_NAMESPACE::shared::log2(1.0)); EXPECT_FP_EQ(1.0, LIBC_NAMESPACE::shared::pow(0.0, 0.0)); EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::shared::sin(0.0)); + EXPECT_FP_EQ(1.0, cos); + EXPECT_FP_EQ(0.0, sin); EXPECT_FP_EQ(0x0p+0, LIBC_NAMESPACE::shared::sqrt(0.0)); EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::shared::tan(0.0)); EXPECT_EQ(0, LIBC_NAMESPACE::shared::ilogb(1.0)); diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index b4a48319a03c..0984aef75660 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -3805,6 +3805,26 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_math_sincos", + hdrs = ["src/__support/math/sincos.h"], + deps = [ + ":__support_common", + ":__support_fputil_double_double", + ":__support_fputil_dyadic_float", + ":__support_fputil_except_value_utils", + ":__support_fputil_fenv_impl", + ":__support_fputil_fp_bits", + ":__support_fputil_multiply_add", + ":__support_fputil_rounding_mode", + ":__support_macros_config", + ":__support_macros_optimization", + ":__support_macros_properties_cpu_features", + ":__support_range_reduction_double", + ":__support_sincos_eval", + ], +) + libc_support_library( name = "__support_sincos_eval", hdrs = ["src/__support/math/sincos_eval.h"], @@ -5546,11 +5566,8 @@ libc_math_function( libc_math_function( name = "sincos", additional_deps = [ - ":__support_fputil_multiply_add", - ":__support_macros_optimization", - ":__support_macros_properties_cpu_features", - ":__support_range_reduction_double", - ":__support_sincos_eval", + ":__support_math_sincos", + ":errno", ], )