-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[libc][math] Refactor atan implementation to header-only in src/__support/math folder. #150852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libc Author: Muhammad Bassiouni (bassiounix) ChangesPart of #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 Patch is 24.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150852.diff 12 Files Affected:
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 26e33ecd45d73..70b1b7b0bef09 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -22,6 +22,7 @@
#include "math/asinf16.h"
#include "math/asinhf.h"
#include "math/asinhf16.h"
+#include "math/atan.h"
#include "math/erff.h"
#include "math/exp.h"
#include "math/exp10.h"
diff --git a/libc/shared/math/atan.h b/libc/shared/math/atan.h
new file mode 100644
index 0000000000000..b9ba89b7e6225
--- /dev/null
+++ b/libc/shared/math/atan.h
@@ -0,0 +1,23 @@
+//===-- Shared atan 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_ATAN_H
+#define LLVM_LIBC_SHARED_MATH_ATAN_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/atan.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::atan;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ATAN_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index be208f946024a..cc02920c2a1ef 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -172,6 +172,33 @@ DEPENDS
libc.src.__support.macros.optimization
)
+add_header_library(
+ atan_utils
+ HDRS
+ atan_utils.h
+DEPENDS
+ libc.src.__support.integer_literals
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.dyadic_float
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ atan
+ HDRS
+ atan.h
+DEPENDS
+ .atan_utils
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.nearest_integer
+ libc.src.__support.macros.optimization
+)
+
add_header_library(
asinf
HDRS
diff --git a/libc/src/__support/math/atan.h b/libc/src/__support/math/atan.h
new file mode 100644
index 0000000000000..4f42b2948aea8
--- /dev/null
+++ b/libc/src/__support/math/atan.h
@@ -0,0 +1,190 @@
+//===-- Implementation header for atan --------------------------*- 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_ATAN_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ATAN_H
+
+#include "atan_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/double_double.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+// To compute atan(x), we divided it into the following cases:
+// * |x| < 2^-26:
+// Since |x| > atan(|x|) > |x| - |x|^3/3, and |x|^3/3 < ulp(x)/2, we simply
+// return atan(x) = x - sign(x) * epsilon.
+// * 2^-26 <= |x| < 1:
+// We perform range reduction mod 2^-6 = 1/64 as follow:
+// Let k = 2^(-6) * round(|x| * 2^6), then
+// atan(x) = sign(x) * atan(|x|)
+// = sign(x) * (atan(k) + atan((|x| - k) / (1 + |x|*k)).
+// We store atan(k) in a look up table, and perform intermediate steps in
+// double-double.
+// * 1 < |x| < 2^53:
+// First we perform the transformation y = 1/|x|:
+// atan(x) = sign(x) * (pi/2 - atan(1/|x|))
+// = sign(x) * (pi/2 - atan(y)).
+// Then we compute atan(y) using range reduction mod 2^-6 = 1/64 as the
+// previous case:
+// Let k = 2^(-6) * round(y * 2^6), then
+// atan(y) = atan(k) + atan((y - k) / (1 + y*k))
+// = atan(k) + atan((1/|x| - k) / (1 + k/|x|)
+// = atan(k) + atan((1 - k*|x|) / (|x| + k)).
+// * |x| >= 2^53:
+// Using the reciprocal transformation:
+// atan(x) = sign(x) * (pi/2 - atan(1/|x|)).
+// We have that:
+// atan(1/|x|) <= 1/|x| <= 2^-53,
+// which is smaller than ulp(pi/2) / 2.
+// So we can return:
+// atan(x) = sign(x) * (pi/2 - epsilon)
+
+LIBC_INLINE static constexpr double atan(double x) {
+
+ using namespace atan_internal;
+ using FPBits = fputil::FPBits<double>;
+
+ constexpr double IS_NEG[2] = {1.0, -1.0};
+ constexpr DoubleDouble PI_OVER_2 = {0x1.1a62633145c07p-54,
+ 0x1.921fb54442d18p0};
+ constexpr DoubleDouble MPI_OVER_2 = {-0x1.1a62633145c07p-54,
+ -0x1.921fb54442d18p0};
+
+ FPBits xbits(x);
+ bool x_sign = xbits.is_neg();
+ xbits = xbits.abs();
+ uint64_t x_abs = xbits.uintval();
+ int x_exp =
+ static_cast<int>(x_abs >> FPBits::FRACTION_LEN) - FPBits::EXP_BIAS;
+
+ // |x| < 1.
+ if (x_exp < 0) {
+ if (LIBC_UNLIKELY(x_exp < -26)) {
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ return x;
+#else
+ if (x == 0.0)
+ return x;
+ // |x| < 2^-26
+ return fputil::multiply_add(-0x1.0p-54, x, x);
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ }
+
+ double x_d = xbits.get_val();
+ // k = 2^-6 * round(2^6 * |x|)
+ double k = fputil::nearest_integer(0x1.0p6 * x_d);
+ unsigned idx = static_cast<unsigned>(k);
+ k *= 0x1.0p-6;
+
+ // numerator = |x| - k
+ DoubleDouble num, den;
+ num.lo = 0.0;
+ num.hi = x_d - k;
+
+ // denominator = 1 - k * |x|
+ den.hi = fputil::multiply_add(x_d, k, 1.0);
+ DoubleDouble prod = fputil::exact_mult(x_d, k);
+ // Using Dekker's 2SUM algorithm to compute the lower part.
+ den.lo = ((1.0 - den.hi) + prod.hi) + prod.lo;
+
+ // x_r = (|x| - k) / (1 + k * |x|)
+ DoubleDouble x_r = fputil::div(num, den);
+
+ // Approximating atan(x_r) using Taylor polynomial.
+ DoubleDouble p = atan_eval(x_r);
+
+ // atan(x) = sign(x) * (atan(k) + atan(x_r))
+ // = sign(x) * (atan(k) + atan( (|x| - k) / (1 + k * |x|) ))
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ return IS_NEG[x_sign] * (ATAN_I[idx].hi + (p.hi + (p.lo + ATAN_I[idx].lo)));
+#else
+
+ DoubleDouble c0 = fputil::exact_add(ATAN_I[idx].hi, p.hi);
+ double c1 = c0.lo + (ATAN_I[idx].lo + p.lo);
+ double r = IS_NEG[x_sign] * (c0.hi + c1);
+
+ return r;
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ }
+
+ // |x| >= 2^53 or x is NaN.
+ if (LIBC_UNLIKELY(x_exp >= 53)) {
+ // x is 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;
+ }
+ // |x| >= 2^53
+ // atan(x) ~ sign(x) * pi/2.
+ if (x_exp >= 53)
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ return IS_NEG[x_sign] * PI_OVER_2.hi;
+#else
+ return fputil::multiply_add(IS_NEG[x_sign], PI_OVER_2.hi,
+ IS_NEG[x_sign] * PI_OVER_2.lo);
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ }
+
+ double x_d = xbits.get_val();
+ double y = 1.0 / x_d;
+
+ // k = 2^-6 * round(2^6 / |x|)
+ double k = fputil::nearest_integer(0x1.0p6 * y);
+ unsigned idx = static_cast<unsigned>(k);
+ k *= 0x1.0p-6;
+
+ // denominator = |x| + k
+ DoubleDouble den = fputil::exact_add(x_d, k);
+ // numerator = 1 - k * |x|
+ DoubleDouble num;
+ num.hi = fputil::multiply_add(-x_d, k, 1.0);
+ DoubleDouble prod = fputil::exact_mult(x_d, k);
+ // Using Dekker's 2SUM algorithm to compute the lower part.
+ num.lo = ((1.0 - num.hi) - prod.hi) - prod.lo;
+
+ // x_r = (1/|x| - k) / (1 - k/|x|)
+ // = (1 - k * |x|) / (|x| - k)
+ DoubleDouble x_r = fputil::div(num, den);
+
+ // Approximating atan(x_r) using Taylor polynomial.
+ DoubleDouble p = atan_eval(x_r);
+
+ // atan(x) = sign(x) * (pi/2 - atan(1/|x|))
+ // = sign(x) * (pi/2 - atan(k) - atan(x_r))
+ // = (-sign(x)) * (-pi/2 + atan(k) + atan((1 - k*|x|)/(|x| - k)))
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ double lo_part = p.lo + ATAN_I[idx].lo + MPI_OVER_2.lo;
+ return IS_NEG[!x_sign] * (MPI_OVER_2.hi + ATAN_I[idx].hi + (p.hi + lo_part));
+#else
+ DoubleDouble c0 = fputil::exact_add(MPI_OVER_2.hi, ATAN_I[idx].hi);
+ DoubleDouble c1 = fputil::exact_add(c0.hi, p.hi);
+ double c2 = c1.lo + (c0.lo + p.lo) + (ATAN_I[idx].lo + MPI_OVER_2.lo);
+
+ double r = IS_NEG[!x_sign] * (c1.hi + c2);
+
+ return r;
+#endif
+
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATAN_H
diff --git a/libc/src/math/generic/atan_utils.h b/libc/src/__support/math/atan_utils.h
similarity index 96%
rename from libc/src/math/generic/atan_utils.h
rename to libc/src/__support/math/atan_utils.h
index 24c7271b7e4ec..95613d38c413e 100644
--- a/libc/src/math/generic/atan_utils.h
+++ b/libc/src/__support/math/atan_utils.h
@@ -18,7 +18,7 @@
namespace LIBC_NAMESPACE_DECL {
-namespace {
+namespace atan_internal {
using DoubleDouble = fputil::DoubleDouble;
using Float128 = fputil::DyadicFloat<128>;
@@ -29,7 +29,7 @@ using Float128 = fputil::DyadicFloat<128>;
// b = round(atan(i/64) - a, D, RN);
// print("{", b, ",", a, "},");
// };
-constexpr DoubleDouble ATAN_I[65] = {
+static constexpr DoubleDouble ATAN_I[65] = {
{0.0, 0.0},
{-0x1.220c39d4dff5p-61, 0x1.fff555bbb729bp-7},
{-0x1.5ec431444912cp-60, 0x1.ffd55bba97625p-6},
@@ -110,7 +110,7 @@ constexpr DoubleDouble ATAN_I[65] = {
// + x_lo * (1 - x_hi^2 + x_hi^4)
// Since p.lo is ~ x^3/3, the relative error from rounding is bounded by:
// |(atan(x) - P(x))/atan(x)| < ulp(x^2) <= 2^(-14-52) = 2^-66.
-[[maybe_unused]] DoubleDouble atan_eval(const DoubleDouble &x) {
+[[maybe_unused]] LIBC_INLINE static DoubleDouble atan_eval(const DoubleDouble &x) {
DoubleDouble p;
p.hi = x.hi;
double x_hi_sq = x.hi * x.hi;
@@ -142,7 +142,7 @@ constexpr DoubleDouble ATAN_I[65] = {
// b = 2^ll + a;
// print("{Sign::POS, ", 2^(ll - 128), ",", b, "},");
// };
-constexpr Float128 ATAN_I_F128[65] = {
+static constexpr Float128 ATAN_I_F128[65] = {
{Sign::POS, 0, 0_u128},
{Sign::POS, -134, 0xfffaaadd'db94d5bb'e78c5640'15f76048_u128},
{Sign::POS, -133, 0xffeaaddd'4bb12542'779d776d'da8c6214_u128},
@@ -215,7 +215,7 @@ constexpr Float128 ATAN_I_F128[65] = {
// [0, 2^-7]);
// > dirtyinfnorm(atan(x) - P, [0, 2^-7]);
// 0x1.26016ad97f323875760f869684c0898d7b7bb8bep-122
-constexpr Float128 ATAN_POLY_F128[] = {
+static constexpr Float128 ATAN_POLY_F128[] = {
{Sign::NEG, -129, 0xaaaaaaaa'aaaaaaaa'aaaaaaa6'003c5d1d_u128},
{Sign::POS, -130, 0xcccccccc'cccccccc'cca00232'8776b063_u128},
{Sign::NEG, -130, 0x92492492'49249201'27f5268a'cb24aec0_u128},
@@ -225,7 +225,7 @@ constexpr Float128 ATAN_POLY_F128[] = {
};
// Approximate atan for |x| <= 2^-7.
-[[maybe_unused]] Float128 atan_eval(const Float128 &x) {
+[[maybe_unused]] LIBC_INLINE static constexpr Float128 atan_eval(const Float128 &x) {
Float128 x_sq = fputil::quick_mul(x, x);
Float128 x3 = fputil::quick_mul(x, x_sq);
Float128 p = fputil::polyeval(x_sq, ATAN_POLY_F128[0], ATAN_POLY_F128[1],
@@ -234,7 +234,7 @@ constexpr Float128 ATAN_POLY_F128[] = {
return fputil::multiply_add(x3, p, x);
}
-} // anonymous namespace
+} // namespace atan_internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 025b0290bfe70..ffb0d06c434fc 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4007,19 +4007,6 @@ add_entrypoint_object(
libc.src.errno.errno
)
-add_header_library(
- atan_utils
- HDRS
- atan_utils.h
- DEPENDS
- libc.src.__support.integer_literals
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.dyadic_float
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.macros.optimization
-)
-
add_entrypoint_object(
atanf
SRCS
@@ -4066,13 +4053,7 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
DEPENDS
- .atan_utils
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.nearest_integer
- libc.src.__support.macros.optimization
+ libc.src.__support.math.atan
)
add_entrypoint_object(
@@ -4102,7 +4083,7 @@ add_entrypoint_object(
HDRS
../atan2.h
DEPENDS
- .atan_utils
+ libc.src.__support.math.atan_utils
libc.src.__support.FPUtil.double_double
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
@@ -4128,7 +4109,7 @@ add_entrypoint_object(
HDRS
../atan2f128.h
DEPENDS
- .atan_utils
+ libc.src.__support.math.atan_utils
libc.src.__support.integer_literals
libc.src.__support.uint128
libc.src.__support.FPUtil.dyadic_float
diff --git a/libc/src/math/generic/atan.cpp b/libc/src/math/generic/atan.cpp
index cbca60536a3fd..93bf2e108e361 100644
--- a/libc/src/math/generic/atan.cpp
+++ b/libc/src/math/generic/atan.cpp
@@ -7,173 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/atan.h"
-#include "atan_utils.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/nearest_integer.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/math/atan.h"
namespace LIBC_NAMESPACE_DECL {
-// To compute atan(x), we divided it into the following cases:
-// * |x| < 2^-26:
-// Since |x| > atan(|x|) > |x| - |x|^3/3, and |x|^3/3 < ulp(x)/2, we simply
-// return atan(x) = x - sign(x) * epsilon.
-// * 2^-26 <= |x| < 1:
-// We perform range reduction mod 2^-6 = 1/64 as follow:
-// Let k = 2^(-6) * round(|x| * 2^6), then
-// atan(x) = sign(x) * atan(|x|)
-// = sign(x) * (atan(k) + atan((|x| - k) / (1 + |x|*k)).
-// We store atan(k) in a look up table, and perform intermediate steps in
-// double-double.
-// * 1 < |x| < 2^53:
-// First we perform the transformation y = 1/|x|:
-// atan(x) = sign(x) * (pi/2 - atan(1/|x|))
-// = sign(x) * (pi/2 - atan(y)).
-// Then we compute atan(y) using range reduction mod 2^-6 = 1/64 as the
-// previous case:
-// Let k = 2^(-6) * round(y * 2^6), then
-// atan(y) = atan(k) + atan((y - k) / (1 + y*k))
-// = atan(k) + atan((1/|x| - k) / (1 + k/|x|)
-// = atan(k) + atan((1 - k*|x|) / (|x| + k)).
-// * |x| >= 2^53:
-// Using the reciprocal transformation:
-// atan(x) = sign(x) * (pi/2 - atan(1/|x|)).
-// We have that:
-// atan(1/|x|) <= 1/|x| <= 2^-53,
-// which is smaller than ulp(pi/2) / 2.
-// So we can return:
-// atan(x) = sign(x) * (pi/2 - epsilon)
-
-LLVM_LIBC_FUNCTION(double, atan, (double x)) {
- using FPBits = fputil::FPBits<double>;
-
- constexpr double IS_NEG[2] = {1.0, -1.0};
- constexpr DoubleDouble PI_OVER_2 = {0x1.1a62633145c07p-54,
- 0x1.921fb54442d18p0};
- constexpr DoubleDouble MPI_OVER_2 = {-0x1.1a62633145c07p-54,
- -0x1.921fb54442d18p0};
-
- FPBits xbits(x);
- bool x_sign = xbits.is_neg();
- xbits = xbits.abs();
- uint64_t x_abs = xbits.uintval();
- int x_exp =
- static_cast<int>(x_abs >> FPBits::FRACTION_LEN) - FPBits::EXP_BIAS;
-
- // |x| < 1.
- if (x_exp < 0) {
- if (LIBC_UNLIKELY(x_exp < -26)) {
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return x;
-#else
- if (x == 0.0)
- return x;
- // |x| < 2^-26
- return fputil::multiply_add(-0x1.0p-54, x, x);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- }
-
- double x_d = xbits.get_val();
- // k = 2^-6 * round(2^6 * |x|)
- double k = fputil::nearest_integer(0x1.0p6 * x_d);
- unsigned idx = static_cast<unsigned>(k);
- k *= 0x1.0p-6;
-
- // numerator = |x| - k
- DoubleDouble num, den;
- num.lo = 0.0;
- num.hi = x_d - k;
-
- // denominator = 1 - k * |x|
- den.hi = fputil::multiply_add(x_d, k, 1.0);
- DoubleDouble prod = fputil::exact_mult(x_d, k);
- // Using Dekker's 2SUM algorithm to compute the lower part.
- den.lo = ((1.0 - den.hi) + prod.hi) + prod.lo;
-
- // x_r = (|x| - k) / (1 + k * |x|)
- DoubleDouble x_r = fputil::div(num, den);
-
- // Approximating atan(x_r) using Taylor polynomial.
- DoubleDouble p = atan_eval(x_r);
-
- // atan(x) = sign(x) * (atan(k) + atan(x_r))
- // = sign(x) * (atan(k) + atan( (|x| - k) / (1 + k * |x|) ))
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return IS_NEG[x_sign] * (ATAN_I[idx].hi + (p.hi + (p.lo + ATAN_I[idx].lo)));
-#else
-
- DoubleDouble c0 = fputil::exact_add(ATAN_I[idx].hi, p.hi);
- double c1 = c0.lo + (ATAN_I[idx].lo + p.lo);
- double r = IS_NEG[x_sign] * (c0.hi + c1);
-
- return r;
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- }
-
- // |x| >= 2^53 or x is NaN.
- if (LIBC_UNLIKELY(x_exp >= 53)) {
- // x is 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;
- }
- // |x| >= 2^53
- // atan(x) ~ sign(x) * pi/2.
- if (x_exp >= 53)
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return IS_NEG[x_sign] * PI_OVER_2.hi;
-#else
- return fputil::multiply_add(IS_NEG[x_sign], PI_OVER_2.hi,
- IS_NEG[x_sign] * PI_OVER_2.lo);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- }
-
- double x_d = xbits.get_val();
- double y = 1.0 / x_d;
-
- // k = 2^-6 * round(2^6 / |x|)
- double k = fputil::nearest_integer(0x1.0p6 * y);
- unsigned idx = static_cast<unsigned>(k);
- k *= 0x1.0p-6;
-
- // denominator = |x| + k
- DoubleDouble den = fputil::exact_add(x_d, k);
- // numerator = 1 - k * |x|
- DoubleDouble num;
- num.hi = fputil::multiply_add(-x_d, k, 1.0);
- DoubleDouble prod = fputil::exact_mult(x_d, k);
- // Using Dekker's 2SUM algorithm to compute the lower part.
- num.lo = ((1.0 - num.hi) - prod.hi) - prod.lo;
-
- // x_r = (1/|x| - k) / (1 - k/|x|)
- // = (1 - k * |x|) / (|x| - k)
- DoubleDouble x_r = fputil::div(num, den);
-
- // Approximating atan(x_r) using Taylor polynomial.
- DoubleDouble p = atan_eval(x_r);
-
- // atan(x) = sign(x) * (pi/2 - atan(1/|x|))
- // = sign(x) * (pi/2 - atan(k) - atan(x_r))
- // = (-sign(x)) * (-pi/2 + atan(k) + atan((1 - k*|x|)/(|x| - k)))
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- double lo_part = p.lo + ATAN_I[idx].lo + MPI_OVER_2.lo;
- return IS_NEG[!x_sign] * (MPI_OVER_2.hi + ATAN_I[idx].hi + (p.hi + lo_part));
-#else
- DoubleDouble c0 = fputil::exact_add(MPI_OVER_2.hi, ATAN_I[idx].hi);
- DoubleDouble c1 = fputil::exact_add(c0.hi, p.hi);
- double c2 = c1.lo + (c0.lo + p.lo) + (ATAN_I[idx].lo + MPI_OVER_2.lo);
-
- double r = IS_NEG[!x_sign] * (c1.hi + c2);
-
- return r;
-#endif
-}
+LLVM_LIBC_FUNCTION(double, atan, (double x)) { return math::atan(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/atan2.cpp b/libc/src/math/generic/atan2.cpp
index aa770de33fb1f..f60c30fc288aa 100644
--- a/libc/src/math/generic/atan2.cpp
+++ b/libc/src/math/generic/atan2.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/math/atan2.h"
-#include "atan_utils.h"
+#include "src/__support/math/atan_utils.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/double_double.h"
@@ -72,6 +72,7 @@ namespace LIBC_NAMESP...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
5c60818
to
da6cf0f
Compare
408c7a4
to
ef0a9ce
Compare
ef0a9ce
to
cae5d05
Compare
41e35b0
to
8c60f83
Compare
cae5d05
to
0138846
Compare
8c60f83
to
10fe025
Compare
0138846
to
66a1b22
Compare
10fe025
to
ee67fee
Compare
2aac58c
to
041abc3
Compare
e60e02e
to
e03587c
Compare
Merge activity
|
…port/math folder.
e03587c
to
884f616
Compare
Part of #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