aboutsummaryrefslogtreecommitdiff
path: root/libc/src/math/generic
diff options
context:
space:
mode:
Diffstat (limited to 'libc/src/math/generic')
-rw-r--r--libc/src/math/generic/CMakeLists.txt197
-rw-r--r--libc/src/math/generic/acosf.cpp121
-rw-r--r--libc/src/math/generic/acosf16.cpp138
-rw-r--r--libc/src/math/generic/acoshf.cpp68
-rw-r--r--libc/src/math/generic/acoshf16.cpp98
-rw-r--r--libc/src/math/generic/acospif16.cpp122
-rw-r--r--libc/src/math/generic/asin.cpp16
-rw-r--r--libc/src/math/generic/asinf.cpp154
-rw-r--r--libc/src/math/generic/asinf16.cpp121
-rw-r--r--libc/src/math/generic/asinhf.cpp105
-rw-r--r--libc/src/math/generic/asinhf16.cpp95
-rw-r--r--libc/src/math/generic/atan.cpp167
-rw-r--r--libc/src/math/generic/atan2.cpp186
-rw-r--r--libc/src/math/generic/atan2f.cpp3
-rw-r--r--libc/src/math/generic/atan2f128.cpp3
-rw-r--r--libc/src/math/generic/atan2l.cpp4
-rw-r--r--libc/src/math/generic/atan_utils.h241
-rw-r--r--libc/src/math/generic/atanf.cpp109
-rw-r--r--libc/src/math/generic/atanf16.cpp95
-rw-r--r--libc/src/math/generic/atanhf.cpp1
-rw-r--r--libc/src/math/generic/common_constants.cpp92
-rw-r--r--libc/src/math/generic/common_constants.h7
-rw-r--r--libc/src/math/generic/erff.cpp174
-rw-r--r--libc/src/math/generic/explogxf.h36
-rw-r--r--libc/src/math/generic/expxf16.h3
-rw-r--r--libc/src/math/generic/fabsbf16.cpp19
-rw-r--r--libc/src/math/generic/inv_trigf_utils.cpp86
-rw-r--r--libc/src/math/generic/inv_trigf_utils.h110
-rw-r--r--libc/src/math/generic/log1pf.cpp1
-rw-r--r--libc/src/math/generic/range_reduction_double_common.h2
30 files changed, 101 insertions, 2473 deletions
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 7e6a32b..6bcb1e2 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -698,6 +698,19 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ fabsbf16
+ SRCS
+ fabsbf16.cpp
+ HDRS
+ ../fabsbf16.h
+ DEPENDS
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.macros.config
+ libc.src.__support.macros.properties.types
+)
+
+add_entrypoint_object(
fadd
SRCS
fadd.cpp
@@ -1295,12 +1308,8 @@ add_entrypoint_object(
HDRS
../erff.h
DEPENDS
- .common_constants
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.macros.optimization
+ libc.src.__support.math.erff
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -1898,6 +1907,7 @@ add_object_library(
common_constants.cpp
DEPENDS
libc.src.__support.math.exp_constants
+ libc.src.__support.math.acosh_float_constants
libc.src.__support.number_pair
)
@@ -3761,7 +3771,7 @@ add_header_library(
DEPENDS
.common_constants
libc.src.__support.math.exp_utils
- libc.src.__support.math.exp10f_utils
+ libc.src.__support.math.acoshf_utils
libc.src.__support.macros.properties.cpu_features
libc.src.errno.errno
)
@@ -3871,12 +3881,7 @@ add_entrypoint_object(
../acoshf.h
DEPENDS
.explogxf
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
+ libc.src.__support.math.acoshf
)
add_entrypoint_object(
@@ -3886,18 +3891,8 @@ add_entrypoint_object(
HDRS
../acoshf16.h
DEPENDS
- .explogxf
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.cast
- 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.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
+ libc.src.__support.math.acoshf16
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -3907,12 +3902,7 @@ add_entrypoint_object(
HDRS
../asinhf.h
DEPENDS
- .explogxf
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
+ libc.src.__support.math.asinhf
)
add_entrypoint_object(
@@ -3922,18 +3912,7 @@ add_entrypoint_object(
HDRS
../asinhf16.h
DEPENDS
- .explogxf
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.cast
- 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.FPUtil.polyeval
- libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
+ libc.src.__support.math.asinhf16
)
add_entrypoint_object(
@@ -3969,18 +3948,6 @@ add_entrypoint_object(
libc.src.__support.macros.properties.types
)
-add_object_library(
- inv_trigf_utils
- HDRS
- inv_trigf_utils.h
- SRCS
- inv_trigf_utils.cpp
- DEPENDS
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.common
-)
-
add_entrypoint_object(
asinf
SRCS
@@ -3988,13 +3955,7 @@ add_entrypoint_object(
HDRS
../asinf.h
DEPENDS
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- .inv_trigf_utils
+ libc.src.__support.math.asinf
)
add_entrypoint_object(
@@ -4004,16 +3965,7 @@ add_entrypoint_object(
HDRS
../asinf16.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.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
+ libc.src.__support.math.asinf16
)
add_entrypoint_object(
@@ -4023,16 +3975,7 @@ add_entrypoint_object(
HDRS
../asin.h
DEPENDS
- libc.src.__support.math.asin_utils
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.dyadic_float
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.cpu_features
+ libc.src.__support.math.asin
)
add_entrypoint_object(
@@ -4042,13 +3985,7 @@ add_entrypoint_object(
HDRS
../acosf.h
DEPENDS
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- .inv_trigf_utils
+ libc.src.__support.math.acosf
)
add_entrypoint_object(
@@ -4058,17 +3995,8 @@ add_entrypoint_object(
HDRS
../acosf16.h
DEPENDS
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.cast
- 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.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
+ libc.src.__support.math.acosf16
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -4088,29 +4016,8 @@ add_entrypoint_object(
HDRS
../acospif16.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.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
-)
-
-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
+ libc.src.__support.math.acospif16
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -4120,14 +4027,7 @@ add_entrypoint_object(
HDRS
../atanf.h
DEPENDS
- .inv_trigf_utils
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.nearest_integer
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.macros.optimization
+ libc.src.__support.math.atanf
)
add_entrypoint_object(
@@ -4137,17 +4037,7 @@ add_entrypoint_object(
HDRS
../atanf16.h
DEPENDS
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.cast
- 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.FPUtil.polyeval
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
+ libc.src.__support.math.atanf16
)
add_entrypoint_object(
@@ -4159,13 +4049,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(
@@ -4176,7 +4060,6 @@ add_entrypoint_object(
../atan2f.h
atan2f_float.h
DEPENDS
- .inv_trigf_utils
libc.hdr.fenv_macros
libc.src.__support.FPUtil.double_double
libc.src.__support.FPUtil.fenv_impl
@@ -4186,6 +4069,7 @@ add_entrypoint_object(
libc.src.__support.FPUtil.polyeval
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.optimization
+ libc.src.__support.math.inv_trigf_utils
)
add_entrypoint_object(
@@ -4195,13 +4079,7 @@ add_entrypoint_object(
HDRS
../atan2.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
+ libc.src.__support.math.atan2
)
add_entrypoint_object(
@@ -4211,7 +4089,7 @@ add_entrypoint_object(
HDRS
../atan2l.h
DEPENDS
- .atan2
+ libc.src.__support.math.atan2
)
add_entrypoint_object(
@@ -4221,7 +4099,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
@@ -4987,6 +4865,7 @@ add_header_library(
HDRS
expxf16.h
DEPENDS
+ libc.hdr.stdint_proxy
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.multiply_add
diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp
index 8dd6de2..7afc7d6 100644
--- a/libc/src/math/generic/acosf.cpp
+++ b/libc/src/math/generic/acosf.cpp
@@ -7,127 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/acosf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-
-#include "inv_trigf_utils.h"
+#include "src/__support/math/acosf.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_EXCEPTS = 4;
-
-// Exceptional values when |x| <= 0.5
-static constexpr fputil::ExceptValues<float, N_EXCEPTS> ACOSF_EXCEPTS = {{
- // (inputs, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.110b46p-26, acosf(x) = 0x1.921fb4p0 (RZ)
- {0x328885a3, 0x3fc90fda, 1, 0, 1},
- // x = -0x1.110b46p-26, acosf(x) = 0x1.921fb4p0 (RZ)
- {0xb28885a3, 0x3fc90fda, 1, 0, 1},
- // x = 0x1.04c444p-12, acosf(x) = 0x1.920f68p0 (RZ)
- {0x39826222, 0x3fc907b4, 1, 0, 1},
- // x = -0x1.04c444p-12, acosf(x) = 0x1.923p0 (RZ)
- {0xb9826222, 0x3fc91800, 1, 0, 1},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
-
- FPBits xbits(x);
- uint32_t x_uint = xbits.uintval();
- uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU;
- uint32_t x_sign = x_uint >> 31;
-
- // |x| <= 0.5
- if (LIBC_UNLIKELY(x_abs <= 0x3f00'0000U)) {
- // |x| < 0x1p-10
- if (LIBC_UNLIKELY(x_abs < 0x3a80'0000U)) {
- // When |x| < 2^-10, we use the following approximation:
- // acos(x) = pi/2 - asin(x)
- // ~ pi/2 - x - x^3 / 6
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Check for exceptional values
- if (auto r = ACOSF_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- double xd = static_cast<double>(x);
- return static_cast<float>(fputil::multiply_add(
- -0x1.5555555555555p-3 * xd, xd * xd, M_MATH_PI_2 - xd));
- }
-
- // For |x| <= 0.5, we approximate acosf(x) by:
- // acos(x) = pi/2 - asin(x) = pi/2 - x * P(x^2)
- // Where P(X^2) = Q(X) is a degree-20 minimax even polynomial approximating
- // asin(x)/x on [0, 0.5] generated by Sollya with:
- // > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|],
- // [|1, D...|], [0, 0.5]);
- double xd = static_cast<double>(x);
- double xsq = xd * xd;
- double x3 = xd * xsq;
- double r = asin_eval(xsq);
- return static_cast<float>(fputil::multiply_add(-x3, r, M_MATH_PI_2 - xd));
- }
-
- // |x| >= 1, return 0, 2pi, or NaNs.
- if (LIBC_UNLIKELY(x_abs >= 0x3f80'0000U)) {
- if (x_abs == 0x3f80'0000U)
- return x_sign ? /* x == -1.0f */ fputil::round_result_slightly_down(
- 0x1.921fb6p+1f)
- : /* x == 1.0f */ 0.0f;
-
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- // |x| <= +/-inf
- 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();
- }
-
- // When 0.5 < |x| < 1, we perform range reduction as follow:
- //
- // Assume further that 0.5 < x <= 1, and let:
- // y = acos(x)
- // We use the double angle formula:
- // x = cos(y) = 1 - 2 sin^2(y/2)
- // So:
- // sin(y/2) = sqrt( (1 - x)/2 )
- // And hence:
- // y = 2 * asin( sqrt( (1 - x)/2 ) )
- // Let u = (1 - x)/2, then
- // acos(x) = 2 * asin( sqrt(u) )
- // Moreover, since 0.5 < x <= 1,
- // 0 <= u < 1/4, and 0 <= sqrt(u) < 0.5,
- // And hence we can reuse the same polynomial approximation of asin(x) when
- // |x| <= 0.5:
- // acos(x) ~ 2 * sqrt(u) * P(u).
- //
- // When -1 < x <= -0.5, we use the identity:
- // acos(x) = pi - acos(-x)
- // which is reduced to the postive case.
-
- xbits.set_sign(Sign::POS);
- double xd = static_cast<double>(xbits.get_val());
- double u = fputil::multiply_add(-0.5, xd, 0.5);
- double cv = 2 * fputil::sqrt<double>(u);
-
- double r3 = asin_eval(u);
- double r = fputil::multiply_add(cv * u, r3, cv);
- return static_cast<float>(x_sign ? M_MATH_PI - r : r);
-}
+LLVM_LIBC_FUNCTION(float, acosf, (float x)) { return math::acosf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/acosf16.cpp b/libc/src/math/generic/acosf16.cpp
index 202a950..0bf85f8 100644
--- a/libc/src/math/generic/acosf16.cpp
+++ b/libc/src/math/generic/acosf16.cpp
@@ -8,144 +8,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/acosf16.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/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/acosf16.h"
namespace LIBC_NAMESPACE_DECL {
-// Generated by Sollya using the following command:
-// > round(pi/2, SG, RN);
-// > round(pi, SG, RN);
-static constexpr float PI_OVER_2 = 0x1.921fb6p0f;
-static constexpr float PI = 0x1.921fb6p1f;
+LLVM_LIBC_FUNCTION(float16, acosf16, (float16 x)) { return math::acosf16(x); }
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_EXCEPTS = 2;
-
-static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ACOSF16_EXCEPTS{{
- // (input, RZ output, RU offset, RD offset, RN offset)
- {0xacaf, 0x3e93, 1, 0, 0},
- {0xb874, 0x4052, 1, 0, 1},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, acosf16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
-
- uint16_t x_u = xbits.uintval();
- uint16_t x_abs = x_u & 0x7fff;
- uint16_t x_sign = x_u >> 15;
-
- // |x| > 0x1p0, |x| > 1, or x is NaN.
- if (LIBC_UNLIKELY(x_abs > 0x3c00)) {
- // acosf16(NaN) = 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;
- }
-
- // 1 < |x| <= +/-inf
- fputil::raise_except_if_required(FE_INVALID);
- fputil::set_errno_if_required(EDOM);
-
- return FPBits::quiet_nan().get_val();
- }
-
- float xf = x;
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Handle exceptional values
- if (auto r = ACOSF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // |x| == 0x1p0, x is 1 or -1
- // if x is (-)1, return pi, else
- // if x is (+)1, return 0
- if (LIBC_UNLIKELY(x_abs == 0x3c00))
- return fputil::cast<float16>(x_sign ? PI : 0.0f);
-
- float xsq = xf * xf;
-
- // |x| <= 0x1p-1, |x| <= 0.5
- if (x_abs <= 0x3800) {
- // if x is 0, return pi/2
- if (LIBC_UNLIKELY(x_abs == 0))
- return fputil::cast<float16>(PI_OVER_2);
-
- // Note that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x)
- // Degree-6 minimax polynomial of asin(x) generated by Sollya with:
- // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]);
- float interm =
- fputil::polyeval(xsq, 0x1.000002p0f, 0x1.554c2ap-3f, 0x1.3541ccp-4f,
- 0x1.43b2d6p-5f, 0x1.a0d73ep-5f);
- return fputil::cast<float16>(fputil::multiply_add(-xf, interm, PI_OVER_2));
- }
-
- // When |x| > 0.5, assume that 0.5 < |x| <= 1
- //
- // Step-by-step range-reduction proof:
- // 1: Let y = asin(x), such that, x = sin(y)
- // 2: From complimentary angle identity:
- // x = sin(y) = cos(pi/2 - y)
- // 3: Let z = pi/2 - y, such that x = cos(z)
- // 4: From double angle formula; cos(2A) = 1 - 2 * sin^2(A):
- // z = 2A, z/2 = A
- // cos(z) = 1 - 2 * sin^2(z/2)
- // 5: Make sin(z/2) subject of the formula:
- // sin(z/2) = sqrt((1 - cos(z))/2)
- // 6: Recall [3]; x = cos(z). Therefore:
- // sin(z/2) = sqrt((1 - x)/2)
- // 7: Let u = (1 - x)/2
- // 8: Therefore:
- // asin(sqrt(u)) = z/2
- // 2 * asin(sqrt(u)) = z
- // 9: Recall [3]; z = pi/2 - y. Therefore:
- // y = pi/2 - z
- // y = pi/2 - 2 * asin(sqrt(u))
- // 10: Recall [1], y = asin(x). Therefore:
- // asin(x) = pi/2 - 2 * asin(sqrt(u))
- // 11: Recall that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x)
- // Therefore:
- // acos(x) = pi/2 - (pi/2 - 2 * asin(sqrt(u)))
- // acos(x) = 2 * asin(sqrt(u))
- //
- // THE RANGE REDUCTION, HOW?
- // 12: Recall [7], u = (1 - x)/2
- // 13: Since 0.5 < x <= 1, therefore:
- // 0 <= u <= 0.25 and 0 <= sqrt(u) <= 0.5
- //
- // Hence, we can reuse the same [0, 0.5] domain polynomial approximation for
- // Step [11] as `sqrt(u)` is in range.
- // When -1 < x <= -0.5, the identity:
- // acos(x) = pi - acos(-x)
- // allows us to compute for the negative x value (lhs)
- // with a positive x value instead (rhs).
-
- float xf_abs = (xf < 0 ? -xf : xf);
- float u = fputil::multiply_add(-0.5f, xf_abs, 0.5f);
- float sqrt_u = fputil::sqrt<float>(u);
-
- // Degree-6 minimax polynomial of asin(x) generated by Sollya with:
- // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]);
- float asin_sqrt_u =
- sqrt_u * fputil::polyeval(u, 0x1.000002p0f, 0x1.554c2ap-3f,
- 0x1.3541ccp-4f, 0x1.43b2d6p-5f, 0x1.a0d73ep-5f);
-
- return fputil::cast<float16>(
- x_sign ? fputil::multiply_add(-2.0f, asin_sqrt_u, PI) : 2 * asin_sqrt_u);
-}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/acoshf.cpp b/libc/src/math/generic/acoshf.cpp
index c4927fa..5c04583 100644
--- a/libc/src/math/generic/acoshf.cpp
+++ b/libc/src/math/generic/acoshf.cpp
@@ -7,73 +7,11 @@
//===----------------------------------------------------------------------===//
#include "src/math/acoshf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/math/generic/common_constants.h"
-#include "src/math/generic/explogxf.h"
-namespace LIBC_NAMESPACE_DECL {
-
-LLVM_LIBC_FUNCTION(float, acoshf, (float x)) {
- using FPBits_t = typename fputil::FPBits<float>;
- FPBits_t xbits(x);
-
- if (LIBC_UNLIKELY(x <= 1.0f)) {
- if (x == 1.0f)
- return 0.0f;
- // x < 1.
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits_t::quiet_nan().get_val();
- }
+#include "src/__support/math/acoshf.h"
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- uint32_t x_u = xbits.uintval();
- if (LIBC_UNLIKELY(x_u >= 0x4f8ffb03)) {
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
- return x;
-
- // Helper functions to set results for exceptional cases.
- auto round_result_slightly_down = [](float r) -> float {
- volatile float tmp = r;
- tmp = tmp - 0x1.0p-25f;
- return tmp;
- };
- auto round_result_slightly_up = [](float r) -> float {
- volatile float tmp = r;
- tmp = tmp + 0x1.0p-25f;
- return tmp;
- };
-
- switch (x_u) {
- case 0x4f8ffb03: // x = 0x1.1ff606p32f
- return round_result_slightly_up(0x1.6fdd34p4f);
- case 0x5c569e88: // x = 0x1.ad3d1p57f
- return round_result_slightly_up(0x1.45c146p5f);
- case 0x5e68984e: // x = 0x1.d1309cp61f
- return round_result_slightly_up(0x1.5c9442p5f);
- case 0x655890d3: // x = 0x1.b121a6p75f
- return round_result_slightly_down(0x1.a9a3f2p5f);
- case 0x6eb1a8ec: // x = 0x1.6351d8p94f
- return round_result_slightly_down(0x1.08b512p6f);
- case 0x7997f30a: // x = 0x1.2fe614p116f
- return round_result_slightly_up(0x1.451436p6f);
- }
- }
-#else
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
- return x;
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+namespace LIBC_NAMESPACE_DECL {
- double x_d = static_cast<double>(x);
- // acosh(x) = log(x + sqrt(x^2 - 1))
- return static_cast<float>(log_eval(
- x_d + fputil::sqrt<double>(fputil::multiply_add(x_d, x_d, -1.0))));
-}
+LLVM_LIBC_FUNCTION(float, acoshf, (float x)) { return math::acoshf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/acoshf16.cpp b/libc/src/math/generic/acoshf16.cpp
index 44783a8..bb3a91f 100644
--- a/libc/src/math/generic/acoshf16.cpp
+++ b/libc/src/math/generic/acoshf16.cpp
@@ -7,104 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/acoshf16.h"
-#include "explogxf.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/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/acoshf16.h"
namespace LIBC_NAMESPACE_DECL {
-static constexpr size_t N_EXCEPTS = 2;
-static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ACOSHF16_EXCEPTS{{
- // (input, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.6dcp+1, acoshf16(x) = 0x1.b6p+0 (RZ)
- {0x41B7, 0x3ED8, 1, 0, 0},
- // x = 0x1.39p+0, acoshf16(x) = 0x1.4f8p-1 (RZ)
- {0x3CE4, 0x393E, 1, 0, 1},
-}};
-
-LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
- uint16_t x_u = xbits.uintval();
-
- // Check for NaN input first.
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- if (xbits.is_neg()) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- return x;
- }
-
- // Domain error for inputs less than 1.0.
- if (LIBC_UNLIKELY(x <= 1.0f)) {
- if (x == 1.0f)
- return FPBits::zero().get_val();
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- if (auto r = ACOSHF16_EXCEPTS.lookup(xbits.uintval());
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
-
- float xf = x;
- // High-precision polynomial approximation for inputs close to 1.0
- // ([1, 1.25)).
- //
- // Brief derivation:
- // 1. Expand acosh(1 + delta) using Taylor series around delta=0:
- // acosh(1 + delta) ≈ sqrt(2 * delta) * [1 - delta/12 + 3*delta^2/160
- // - 5*delta^3/896 + 35*delta^4/18432 + ...]
- // 2. Truncate the series to fit accurately for delta in [0, 0.25].
- // 3. Polynomial coefficients (from sollya) used here are:
- // P(delta) ≈ 1 - 0x1.555556p-4 * delta + 0x1.333334p-6 * delta^2
- // - 0x1.6db6dcp-8 * delta^3 + 0x1.f1c71cp-10 * delta^4
- // 4. The Sollya commands used to generate these coefficients were:
- // > display = hexadecimal;
- // > round(1/12, SG, RN);
- // > round(3/160, SG, RN);
- // > round(5/896, SG, RN);
- // > round(35/18432, SG, RN);
- // With hexadecimal display mode enabled, the outputs were:
- // 0x1.555556p-4
- // 0x1.333334p-6
- // 0x1.6db6dcp-8
- // 0x1.f1c71cp-10
- // 5. The maximum absolute error, estimated using:
- // dirtyinfnorm(acosh(1 + x) - sqrt(2*x) * P(x), [0, 0.25])
- // is:
- // 0x1.d84281p-22
- if (LIBC_UNLIKELY(x_u < 0x3D00U)) {
- float delta = xf - 1.0f;
- float sqrt_2_delta = fputil::sqrt<float>(2.0 * delta);
- float pe = fputil::polyeval(delta, 0x1p+0f, -0x1.555556p-4f, 0x1.333334p-6f,
- -0x1.6db6dcp-8f, 0x1.f1c71cp-10f);
- float approx = sqrt_2_delta * pe;
- return fputil::cast<float16>(approx);
- }
-
- // acosh(x) = log(x + sqrt(x^2 - 1))
- float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, -1.0f));
- float result = static_cast<float>(log_eval(xf + sqrt_term));
-
- return fputil::cast<float16>(result);
-}
+LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) { return math::acoshf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/acospif16.cpp b/libc/src/math/generic/acospif16.cpp
index bfdf169..09cbd99 100644
--- a/libc/src/math/generic/acospif16.cpp
+++ b/libc/src/math/generic/acospif16.cpp
@@ -7,128 +7,12 @@
//===----------------------------------------------------------------------===//
#include "src/math/acospif16.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/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/acospif16.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, acospif16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
-
- uint16_t x_u = xbits.uintval();
- uint16_t x_abs = x_u & 0x7fff;
- uint16_t x_sign = x_u >> 15;
-
- // |x| > 0x1p0, |x| > 1, or x is NaN.
- if (LIBC_UNLIKELY(x_abs > 0x3c00)) {
- // acospif16(NaN) = 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;
- }
-
- // 1 < |x| <= +inf
- fputil::raise_except_if_required(FE_INVALID);
- fputil::set_errno_if_required(EDOM);
-
- return FPBits::quiet_nan().get_val();
- }
-
- // |x| == 0x1p0, x is 1 or -1
- // if x is (-)1, return 1
- // if x is (+)1, return 0
- if (LIBC_UNLIKELY(x_abs == 0x3c00))
- return fputil::cast<float16>(x_sign ? 1.0f : 0.0f);
-
- float xf = x;
- float xsq = xf * xf;
-
- // Degree-6 minimax polynomial coefficients of asin(x) generated by Sollya
- // with: > P = fpminimax(asin(x)/(pi * x), [|0, 2, 4, 6, 8|], [|SG...|], [0,
- // 0.5]);
- constexpr float POLY_COEFFS[5] = {0x1.45f308p-2f, 0x1.b2900cp-5f,
- 0x1.897e36p-6f, 0x1.9efafcp-7f,
- 0x1.06d884p-6f};
- // |x| <= 0x1p-1, |x| <= 0.5
- if (x_abs <= 0x3800) {
- // if x is 0, return 0.5
- if (LIBC_UNLIKELY(x_abs == 0))
- return fputil::cast<float16>(0.5f);
-
- // Note that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x), then
- // acospi(x) = 0.5 - asin(x)/pi
- float interm =
- fputil::polyeval(xsq, POLY_COEFFS[0], POLY_COEFFS[1], POLY_COEFFS[2],
- POLY_COEFFS[3], POLY_COEFFS[4]);
-
- return fputil::cast<float16>(fputil::multiply_add(-xf, interm, 0.5f));
- }
-
- // When |x| > 0.5, assume that 0.5 < |x| <= 1
- //
- // Step-by-step range-reduction proof:
- // 1: Let y = asin(x), such that, x = sin(y)
- // 2: From complimentary angle identity:
- // x = sin(y) = cos(pi/2 - y)
- // 3: Let z = pi/2 - y, such that x = cos(z)
- // 4: From double angle formula; cos(2A) = 1 - 2 * sin^2(A):
- // z = 2A, z/2 = A
- // cos(z) = 1 - 2 * sin^2(z/2)
- // 5: Make sin(z/2) subject of the formula:
- // sin(z/2) = sqrt((1 - cos(z))/2)
- // 6: Recall [3]; x = cos(z). Therefore:
- // sin(z/2) = sqrt((1 - x)/2)
- // 7: Let u = (1 - x)/2
- // 8: Therefore:
- // asin(sqrt(u)) = z/2
- // 2 * asin(sqrt(u)) = z
- // 9: Recall [3]; z = pi/2 - y. Therefore:
- // y = pi/2 - z
- // y = pi/2 - 2 * asin(sqrt(u))
- // 10: Recall [1], y = asin(x). Therefore:
- // asin(x) = pi/2 - 2 * asin(sqrt(u))
- // 11: Recall that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x)
- // Therefore:
- // acos(x) = pi/2 - (pi/2 - 2 * asin(sqrt(u)))
- // acos(x) = 2 * asin(sqrt(u))
- // acospi(x) = 2 * (asin(sqrt(u)) / pi)
- //
- // THE RANGE REDUCTION, HOW?
- // 12: Recall [7], u = (1 - x)/2
- // 13: Since 0.5 < x <= 1, therefore:
- // 0 <= u <= 0.25 and 0 <= sqrt(u) <= 0.5
- //
- // Hence, we can reuse the same [0, 0.5] domain polynomial approximation for
- // Step [11] as `sqrt(u)` is in range.
- // When -1 < x <= -0.5, the identity:
- // acos(x) = pi - acos(-x)
- // acospi(x) = 1 - acos(-x)/pi
- // allows us to compute for the negative x value (lhs)
- // with a positive x value instead (rhs).
-
- float xf_abs = (xf < 0 ? -xf : xf);
- float u = fputil::multiply_add(-0.5f, xf_abs, 0.5f);
- float sqrt_u = fputil::sqrt<float>(u);
-
- float asin_sqrt_u =
- sqrt_u * fputil::polyeval(u, POLY_COEFFS[0], POLY_COEFFS[1],
- POLY_COEFFS[2], POLY_COEFFS[3], POLY_COEFFS[4]);
-
- // Same as acos(x), but devided the expression with pi
- return fputil::cast<float16>(
- x_sign ? fputil::multiply_add(-2.0f, asin_sqrt_u, 1.0f)
- : 2.0f * asin_sqrt_u);
+ return math::acospif16(x);
}
+
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/asin.cpp b/libc/src/math/generic/asin.cpp
index c033597..b5ba9ea 100644
--- a/libc/src/math/generic/asin.cpp
+++ b/libc/src/math/generic/asin.cpp
@@ -7,24 +7,12 @@
//===----------------------------------------------------------------------===//
#include "src/math/asin.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/dyadic_float.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.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/asin_utils.h"
+#include "src/__support/math/asin.h"
namespace LIBC_NAMESPACE_DECL {
-using DoubleDouble = fputil::DoubleDouble;
-using Float128 = fputil::DyadicFloat<128>;
-
LLVM_LIBC_FUNCTION(double, asin, (double x)) {
+ using namespace asin_internal;
using FPBits = fputil::FPBits<double>;
FPBits xbits(x);
diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp
index 12383bf..9c6766f 100644
--- a/libc/src/math/generic/asinf.cpp
+++ b/libc/src/math/generic/asinf.cpp
@@ -7,160 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/asinf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.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 "inv_trigf_utils.h"
+#include "src/__support/math/asinf.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_EXCEPTS = 2;
-
-// Exceptional values when |x| <= 0.5
-static constexpr fputil::ExceptValues<float, N_EXCEPTS> ASINF_EXCEPTS_LO = {{
- // (inputs, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.137f0cp-5, asinf(x) = 0x1.138c58p-5 (RZ)
- {0x3d09bf86, 0x3d09c62c, 1, 0, 1},
- // x = 0x1.cbf43cp-4, asinf(x) = 0x1.cced1cp-4 (RZ)
- {0x3de5fa1e, 0x3de6768e, 1, 0, 0},
-}};
-
-// Exceptional values when 0.5 < |x| <= 1
-static constexpr fputil::ExceptValues<float, N_EXCEPTS> ASINF_EXCEPTS_HI = {{
- // (inputs, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.107434p-1, asinf(x) = 0x1.1f4b64p-1 (RZ)
- {0x3f083a1a, 0x3f0fa5b2, 1, 0, 0},
- // x = 0x1.ee836cp-1, asinf(x) = 0x1.4f0654p0 (RZ)
- {0x3f7741b6, 0x3fa7832a, 1, 0, 0},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float, asinf, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
-
- FPBits xbits(x);
- uint32_t x_uint = xbits.uintval();
- uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU;
- constexpr double SIGN[2] = {1.0, -1.0};
- uint32_t x_sign = x_uint >> 31;
-
- // |x| <= 0.5-ish
- if (x_abs < 0x3f04'471dU) {
- // |x| < 0x1.d12edp-12
- if (LIBC_UNLIKELY(x_abs < 0x39e8'9768U)) {
- // When |x| < 2^-12, the relative error of the approximation asin(x) ~ x
- // is:
- // |asin(x) - x| / |asin(x)| < |x^3| / (6|x|)
- // = x^2 / 6
- // < 2^-25
- // < epsilon(1)/2.
- // So the correctly rounded values of asin(x) are:
- // = x + sign(x)*eps(x) if rounding mode = FE_TOWARDZERO,
- // or (rounding mode = FE_UPWARD and x is
- // negative),
- // = x otherwise.
- // To simplify the rounding decision and make it more efficient, we use
- // fma(x, 2^-25, x) instead.
- // An exhaustive test shows that this formula work correctly for all
- // rounding modes up to |x| < 0x1.d12edp-12.
- // Note: to use the formula x + 2^-25*x to decide the correct rounding, we
- // do need fma(x, 2^-25, x) to prevent underflow caused by 2^-25*x when
- // |x| < 2^-125. For targets without FMA instructions, we simply use
- // double for intermediate results as it is more efficient than using an
- // emulated version of FMA.
-#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
- return fputil::multiply_add(x, 0x1.0p-25f, x);
-#else
- double xd = static_cast<double>(x);
- return static_cast<float>(fputil::multiply_add(xd, 0x1.0p-25, xd));
-#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Check for exceptional values
- if (auto r = ASINF_EXCEPTS_LO.lookup_odd(x_abs, x_sign);
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // For |x| <= 0.5, we approximate asinf(x) by:
- // asin(x) = x * P(x^2)
- // Where P(X^2) = Q(X) is a degree-20 minimax even polynomial approximating
- // asin(x)/x on [0, 0.5] generated by Sollya with:
- // > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|],
- // [|1, D...|], [0, 0.5]);
- // An exhaustive test shows that this approximation works well up to a
- // little more than 0.5.
- double xd = static_cast<double>(x);
- double xsq = xd * xd;
- double x3 = xd * xsq;
- double r = asin_eval(xsq);
- return static_cast<float>(fputil::multiply_add(x3, r, xd));
- }
-
- // |x| > 1, return NaNs.
- if (LIBC_UNLIKELY(x_abs > 0x3f80'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 FPBits::quiet_nan().get_val();
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Check for exceptional values
- if (auto r = ASINF_EXCEPTS_HI.lookup_odd(x_abs, x_sign);
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // When |x| > 0.5, we perform range reduction as follow:
- //
- // Assume further that 0.5 < x <= 1, and let:
- // y = asin(x)
- // We will use the double angle formula:
- // cos(2y) = 1 - 2 sin^2(y)
- // and the complement angle identity:
- // x = sin(y) = cos(pi/2 - y)
- // = 1 - 2 sin^2 (pi/4 - y/2)
- // So:
- // sin(pi/4 - y/2) = sqrt( (1 - x)/2 )
- // And hence:
- // pi/4 - y/2 = asin( sqrt( (1 - x)/2 ) )
- // Equivalently:
- // asin(x) = y = pi/2 - 2 * asin( sqrt( (1 - x)/2 ) )
- // Let u = (1 - x)/2, then:
- // asin(x) = pi/2 - 2 * asin( sqrt(u) )
- // Moreover, since 0.5 < x <= 1:
- // 0 <= u < 1/4, and 0 <= sqrt(u) < 0.5,
- // And hence we can reuse the same polynomial approximation of asin(x) when
- // |x| <= 0.5:
- // asin(x) ~ pi/2 - 2 * sqrt(u) * P(u),
-
- xbits.set_sign(Sign::POS);
- double sign = SIGN[x_sign];
- double xd = static_cast<double>(xbits.get_val());
- double u = fputil::multiply_add(-0.5, xd, 0.5);
- double c1 = sign * (-2 * fputil::sqrt<double>(u));
- double c2 = fputil::multiply_add(sign, M_MATH_PI_2, c1);
- double c3 = c1 * u;
-
- double r = asin_eval(u);
- return static_cast<float>(fputil::multiply_add(c3, r, c2));
-}
+LLVM_LIBC_FUNCTION(float, asinf, (float x)) { return math::asinf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/asinf16.cpp b/libc/src/math/generic/asinf16.cpp
index 518c384..af8dbfe 100644
--- a/libc/src/math/generic/asinf16.cpp
+++ b/libc/src/math/generic/asinf16.cpp
@@ -7,127 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/asinf16.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/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/asinf16.h"
namespace LIBC_NAMESPACE_DECL {
-// Generated by Sollya using the following command:
-// > round(pi/2, D, RN);
-static constexpr float PI_2 = 0x1.921fb54442d18p0f;
-
-LLVM_LIBC_FUNCTION(float16, asinf16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
-
- uint16_t x_u = xbits.uintval();
- uint16_t x_abs = x_u & 0x7fff;
- float xf = x;
-
- // |x| > 0x1p0, |x| > 1, or x is NaN.
- if (LIBC_UNLIKELY(x_abs > 0x3c00)) {
- // asinf16(NaN) = 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;
- }
-
- // 1 < |x| <= +/-inf
- fputil::raise_except_if_required(FE_INVALID);
- fputil::set_errno_if_required(EDOM);
-
- return FPBits::quiet_nan().get_val();
- }
-
- float xsq = xf * xf;
-
- // |x| <= 0x1p-1, |x| <= 0.5
- if (x_abs <= 0x3800) {
- // asinf16(+/-0) = +/-0
- if (LIBC_UNLIKELY(x_abs == 0))
- return x;
-
- // Exhaustive tests show that,
- // for |x| <= 0x1.878p-9, when:
- // x > 0, and rounding upward, or
- // x < 0, and rounding downward, then,
- // asin(x) = x * 2^-11 + x
- // else, in other rounding modes,
- // asin(x) = x
- if (LIBC_UNLIKELY(x_abs <= 0x1a1e)) {
- int rounding = fputil::quick_get_round();
-
- if ((xbits.is_pos() && rounding == FE_UPWARD) ||
- (xbits.is_neg() && rounding == FE_DOWNWARD))
- return fputil::cast<float16>(fputil::multiply_add(xf, 0x1.0p-11f, xf));
- return x;
- }
-
- // Degree-6 minimax odd polynomial of asin(x) generated by Sollya with:
- // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]);
- float result =
- fputil::polyeval(xsq, 0x1.000002p0f, 0x1.554c2ap-3f, 0x1.3541ccp-4f,
- 0x1.43b2d6p-5f, 0x1.a0d73ep-5f);
- return fputil::cast<float16>(xf * result);
- }
-
- // When |x| > 0.5, assume that 0.5 < |x| <= 1,
- //
- // Step-by-step range-reduction proof:
- // 1: Let y = asin(x), such that, x = sin(y)
- // 2: From complimentary angle identity:
- // x = sin(y) = cos(pi/2 - y)
- // 3: Let z = pi/2 - y, such that x = cos(z)
- // 4: From double angle formula; cos(2A) = 1 - sin^2(A):
- // z = 2A, z/2 = A
- // cos(z) = 1 - 2 * sin^2(z/2)
- // 5: Make sin(z/2) subject of the formula:
- // sin(z/2) = sqrt((1 - cos(z))/2)
- // 6: Recall [3]; x = cos(z). Therefore:
- // sin(z/2) = sqrt((1 - x)/2)
- // 7: Let u = (1 - x)/2
- // 8: Therefore:
- // asin(sqrt(u)) = z/2
- // 2 * asin(sqrt(u)) = z
- // 9: Recall [3], z = pi/2 - y. Therefore:
- // y = pi/2 - z
- // y = pi/2 - 2 * asin(sqrt(u))
- // 10: Recall [1], y = asin(x). Therefore:
- // asin(x) = pi/2 - 2 * asin(sqrt(u))
- //
- // WHY?
- // 11: Recall [7], u = (1 - x)/2
- // 12: Since 0.5 < x <= 1, therefore:
- // 0 <= u <= 0.25 and 0 <= sqrt(u) <= 0.5
- //
- // Hence, we can reuse the same [0, 0.5] domain polynomial approximation for
- // Step [10] as `sqrt(u)` is in range.
-
- // 0x1p-1 < |x| <= 0x1p0, 0.5 < |x| <= 1.0
- float xf_abs = (xf < 0 ? -xf : xf);
- float sign = (xbits.uintval() >> 15 == 1 ? -1.0 : 1.0);
- float u = fputil::multiply_add(-0.5f, xf_abs, 0.5f);
- float u_sqrt = fputil::sqrt<float>(u);
-
- // Degree-6 minimax odd polynomial of asin(x) generated by Sollya with:
- // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]);
- float asin_sqrt_u =
- u_sqrt * fputil::polyeval(u, 0x1.000002p0f, 0x1.554c2ap-3f,
- 0x1.3541ccp-4f, 0x1.43b2d6p-5f, 0x1.a0d73ep-5f);
-
- return fputil::cast<float16>(sign *
- fputil::multiply_add(-2.0f, asin_sqrt_u, PI_2));
-}
+LLVM_LIBC_FUNCTION(float16, asinf16, (float16 x)) { return math::asinf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/asinhf.cpp b/libc/src/math/generic/asinhf.cpp
index 0bb7065..45023c8 100644
--- a/libc/src/math/generic/asinhf.cpp
+++ b/libc/src/math/generic/asinhf.cpp
@@ -7,111 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/asinhf.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/math/generic/common_constants.h"
-#include "src/math/generic/explogxf.h"
+#include "src/__support/math/asinhf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, asinhf, (float x)) {
- using FPBits_t = typename fputil::FPBits<float>;
- FPBits_t xbits(x);
- uint32_t x_u = xbits.uintval();
- uint32_t x_abs = xbits.abs().uintval();
-
- // |x| <= 2^-3
- if (LIBC_UNLIKELY(x_abs <= 0x3e80'0000U)) {
- // |x| <= 2^-26
- if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
- return static_cast<float>(LIBC_UNLIKELY(x_abs == 0)
- ? x
- : (x - 0x1.5555555555555p-3 * x * x * x));
- }
-
- double x_d = x;
- double x_sq = x_d * x_d;
- // Generated by Sollya with:
- // > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16|], [|D...|],
- // [0, 2^-2]);
- double p = fputil::polyeval(
- x_sq, 0.0, -0x1.555555555551ep-3, 0x1.3333333325495p-4,
- -0x1.6db6db5a7622bp-5, 0x1.f1c70f82928c6p-6, -0x1.6e893934266b7p-6,
- 0x1.1c0b41d3fbe78p-6, -0x1.c0f47810b3c4fp-7, 0x1.2c8602690143dp-7);
- return static_cast<float>(fputil::multiply_add(x_d, p, x_d));
- }
-
- const double SIGN[2] = {1.0, -1.0};
- double x_sign = SIGN[x_u >> 31];
- double x_d = x;
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Helper functions to set results for exceptional cases.
- auto round_result_slightly_down = [x_sign](float r) -> float {
- return fputil::multiply_add(static_cast<float>(x_sign), r,
- static_cast<float>(x_sign) * (-0x1.0p-24f));
- };
- auto round_result_slightly_up = [x_sign](float r) -> float {
- return fputil::multiply_add(static_cast<float>(x_sign), r,
- static_cast<float>(x_sign) * 0x1.0p-24f);
- };
-
- if (LIBC_UNLIKELY(x_abs >= 0x4bdd'65a5U)) {
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits_t::quiet_nan().get_val();
- }
-
- return x;
- }
-
- // Exceptional cases when x > 2^24.
- switch (x_abs) {
- case 0x4bdd65a5: // |x| = 0x1.bacb4ap24f
- return round_result_slightly_down(0x1.1e0696p4f);
- case 0x4c803f2c: // |x| = 0x1.007e58p26f
- return round_result_slightly_down(0x1.2b786cp4f);
- case 0x4f8ffb03: // |x| = 0x1.1ff606p32f
- return round_result_slightly_up(0x1.6fdd34p4f);
- case 0x5c569e88: // |x| = 0x1.ad3d1p57f
- return round_result_slightly_up(0x1.45c146p5f);
- case 0x5e68984e: // |x| = 0x1.d1309cp61f
- return round_result_slightly_up(0x1.5c9442p5f);
- case 0x655890d3: // |x| = 0x1.b121a6p75f
- return round_result_slightly_down(0x1.a9a3f2p5f);
- case 0x65de7ca6: // |x| = 0x1.bcf94cp76f
- return round_result_slightly_up(0x1.af66cp5f);
- case 0x6eb1a8ec: // |x| = 0x1.6351d8p94f
- return round_result_slightly_down(0x1.08b512p6f);
- case 0x7997f30a: // |x| = 0x1.2fe614p116f
- return round_result_slightly_up(0x1.451436p6f);
- }
- } else {
- // Exceptional cases when x < 2^24.
- if (LIBC_UNLIKELY(x_abs == 0x45abaf26)) {
- // |x| = 0x1.575e4cp12f
- return round_result_slightly_down(0x1.29becap3f);
- }
- if (LIBC_UNLIKELY(x_abs == 0x49d29048)) {
- // |x| = 0x1.a5209p20f
- return round_result_slightly_down(0x1.e1b92p3f);
- }
- }
-#else
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
- return x;
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // asinh(x) = log(x + sqrt(x^2 + 1))
- return static_cast<float>(
- x_sign * log_eval(fputil::multiply_add(
- x_d, x_sign,
- fputil::sqrt<double>(fputil::multiply_add(x_d, x_d, 1.0)))));
-}
+LLVM_LIBC_FUNCTION(float, asinhf, (float x)) { return math::asinhf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/asinhf16.cpp b/libc/src/math/generic/asinhf16.cpp
index 7878632..d517e63 100644
--- a/libc/src/math/generic/asinhf16.cpp
+++ b/libc/src/math/generic/asinhf16.cpp
@@ -7,101 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/asinhf16.h"
-#include "explogxf.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/cast.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/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/asinhf16.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_EXCEPTS = 8;
-
-static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ASINHF16_EXCEPTS{{
- // (input, RZ output, RU offset, RD offset, RN offset)
-
- // x = 0x1.da4p-2, asinhf16(x) = 0x1.ca8p-2 (RZ)
- {0x3769, 0x372a, 1, 0, 1},
- // x = 0x1.d6cp-1, asinhf16(x) = 0x1.a58p-1 (RZ)
- {0x3b5b, 0x3a96, 1, 0, 0},
- // x = 0x1.c7cp+3, asinhf16(x) = 0x1.accp+1 (RZ)
- {0x4b1f, 0x42b3, 1, 0, 0},
- // x = 0x1.26cp+4, asinhf16(x) = 0x1.cd8p+1 (RZ)
- {0x4c9b, 0x4336, 1, 0, 1},
- // x = -0x1.da4p-2, asinhf16(x) = -0x1.ca8p-2 (RZ)
- {0xb769, 0xb72a, 0, 1, 1},
- // x = -0x1.d6cp-1, asinhf16(x) = -0x1.a58p-1 (RZ)
- {0xbb5b, 0xba96, 0, 1, 0},
- // x = -0x1.c7cp+3, asinhf16(x) = -0x1.accp+1 (RZ)
- {0xcb1f, 0xc2b3, 0, 1, 0},
- // x = -0x1.26cp+4, asinhf16(x) = -0x1.cd8p+1 (RZ)
- {0xcc9b, 0xc336, 0, 1, 1},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
-
- uint16_t x_u = xbits.uintval();
- uint16_t x_abs = x_u & 0x7fff;
-
- if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- return x;
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Handle exceptional values
- if (auto r = ASINHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- float xf = x;
- const float SIGN[2] = {1.0f, -1.0f};
- float x_sign = SIGN[x_u >> 15];
-
- // |x| <= 0.25
- if (LIBC_UNLIKELY(x_abs <= 0x3400)) {
- // when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
- // rounding types.
- if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
- int rounding = fputil::quick_get_round();
- if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
- return fputil::cast<float16>(xf + 0x1p-24f);
- if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
- return fputil::cast<float16>(xf - 0x1p-24f);
- return fputil::cast<float16>(xf);
- }
-
- float x_sq = xf * xf;
- // Generated by Sollya with:
- // > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 2^-2]);
- // The last coefficient 0x1.bd114ep-6f has been changed to 0x1.bd114ep-5f
- // for better accuracy.
- float p = fputil::polyeval(x_sq, 1.0f, -0x1.555552p-3f, 0x1.332f6ap-4f,
- -0x1.6c53dep-5f, 0x1.bd114ep-5f);
-
- return fputil::cast<float16>(xf * p);
- }
-
- // General case: asinh(x) = ln(x + sqrt(x^2 + 1))
- float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, 1.0f));
- return fputil::cast<float16>(
- x_sign * log_eval(fputil::multiply_add(xf, x_sign, sqrt_term)));
-}
+LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) { return math::asinhf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/atan.cpp b/libc/src/math/generic/atan.cpp
index cbca605..93bf2e1 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 aa770de..4aaa63d 100644
--- a/libc/src/math/generic/atan2.cpp
+++ b/libc/src/math/generic/atan2.cpp
@@ -7,194 +7,12 @@
//===----------------------------------------------------------------------===//
#include "src/math/atan2.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/atan2.h"
namespace LIBC_NAMESPACE_DECL {
-// There are several range reduction steps we can take for atan2(y, x) as
-// follow:
-
-// * Range reduction 1: signness
-// atan2(y, x) will return a number between -PI and PI representing the angle
-// forming by the 0x axis and the vector (x, y) on the 0xy-plane.
-// In particular, we have that:
-// atan2(y, x) = atan( y/x ) if x >= 0 and y >= 0 (I-quadrant)
-// = pi + atan( y/x ) if x < 0 and y >= 0 (II-quadrant)
-// = -pi + atan( y/x ) if x < 0 and y < 0 (III-quadrant)
-// = atan( y/x ) if x >= 0 and y < 0 (IV-quadrant)
-// Since atan function is odd, we can use the formula:
-// atan(-u) = -atan(u)
-// to adjust the above conditions a bit further:
-// atan2(y, x) = atan( |y|/|x| ) if x >= 0 and y >= 0 (I-quadrant)
-// = pi - atan( |y|/|x| ) if x < 0 and y >= 0 (II-quadrant)
-// = -pi + atan( |y|/|x| ) if x < 0 and y < 0 (III-quadrant)
-// = -atan( |y|/|x| ) if x >= 0 and y < 0 (IV-quadrant)
-// Which can be simplified to:
-// atan2(y, x) = sign(y) * atan( |y|/|x| ) if x >= 0
-// = sign(y) * (pi - atan( |y|/|x| )) if x < 0
-
-// * Range reduction 2: reciprocal
-// Now that the argument inside atan is positive, we can use the formula:
-// atan(1/x) = pi/2 - atan(x)
-// to make the argument inside atan <= 1 as follow:
-// atan2(y, x) = sign(y) * atan( |y|/|x|) if 0 <= |y| <= x
-// = sign(y) * (pi/2 - atan( |x|/|y| ) if 0 <= x < |y|
-// = sign(y) * (pi - atan( |y|/|x| )) if 0 <= |y| <= -x
-// = sign(y) * (pi/2 + atan( |x|/|y| )) if 0 <= -x < |y|
-
-// * Range reduction 3: look up table.
-// After the previous two range reduction steps, we reduce the problem to
-// compute atan(u) with 0 <= u <= 1, or to be precise:
-// atan( n / d ) where n = min(|x|, |y|) and d = max(|x|, |y|).
-// An accurate polynomial approximation for the whole [0, 1] input range will
-// require a very large degree. To make it more efficient, we reduce the input
-// range further by finding an integer idx such that:
-// | n/d - idx/64 | <= 1/128.
-// In particular,
-// idx := round(2^6 * n/d)
-// Then for the fast pass, we find a polynomial approximation for:
-// atan( n/d ) ~ atan( idx/64 ) + (n/d - idx/64) * Q(n/d - idx/64)
-// For the accurate pass, we use the addition formula:
-// atan( n/d ) - atan( idx/64 ) = atan( (n/d - idx/64)/(1 + (n*idx)/(64*d)) )
-// = atan( (n - d*(idx/64))/(d + n*(idx/64)) )
-// And for the fast pass, we use degree-9 Taylor polynomial to compute the RHS:
-// atan(u) ~ P(u) = u - u^3/3 + u^5/5 - u^7/7 + u^9/9
-// with absolute errors bounded by:
-// |atan(u) - P(u)| < |u|^11 / 11 < 2^-80
-// and relative errors bounded by:
-// |(atan(u) - P(u)) / P(u)| < u^10 / 11 < 2^-73.
-
LLVM_LIBC_FUNCTION(double, atan2, (double y, double x)) {
- using FPBits = fputil::FPBits<double>;
-
- constexpr double IS_NEG[2] = {1.0, -1.0};
- constexpr DoubleDouble ZERO = {0.0, 0.0};
- constexpr DoubleDouble MZERO = {-0.0, -0.0};
- constexpr DoubleDouble PI = {0x1.1a62633145c07p-53, 0x1.921fb54442d18p+1};
- constexpr DoubleDouble MPI = {-0x1.1a62633145c07p-53, -0x1.921fb54442d18p+1};
- constexpr DoubleDouble PI_OVER_2 = {0x1.1a62633145c07p-54,
- 0x1.921fb54442d18p0};
- constexpr DoubleDouble MPI_OVER_2 = {-0x1.1a62633145c07p-54,
- -0x1.921fb54442d18p0};
- constexpr DoubleDouble PI_OVER_4 = {0x1.1a62633145c07p-55,
- 0x1.921fb54442d18p-1};
- constexpr DoubleDouble THREE_PI_OVER_4 = {0x1.a79394c9e8a0ap-54,
- 0x1.2d97c7f3321d2p+1};
- // Adjustment for constant term:
- // CONST_ADJ[x_sign][y_sign][recip]
- constexpr DoubleDouble CONST_ADJ[2][2][2] = {
- {{ZERO, MPI_OVER_2}, {MZERO, MPI_OVER_2}},
- {{MPI, PI_OVER_2}, {MPI, PI_OVER_2}}};
-
- FPBits x_bits(x), y_bits(y);
- bool x_sign = x_bits.sign().is_neg();
- bool y_sign = y_bits.sign().is_neg();
- x_bits = x_bits.abs();
- y_bits = y_bits.abs();
- uint64_t x_abs = x_bits.uintval();
- uint64_t y_abs = y_bits.uintval();
- bool recip = x_abs < y_abs;
- uint64_t min_abs = recip ? x_abs : y_abs;
- uint64_t max_abs = !recip ? x_abs : y_abs;
- unsigned min_exp = static_cast<unsigned>(min_abs >> FPBits::FRACTION_LEN);
- unsigned max_exp = static_cast<unsigned>(max_abs >> FPBits::FRACTION_LEN);
-
- double num = FPBits(min_abs).get_val();
- double den = FPBits(max_abs).get_val();
-
- // Check for exceptional cases, whether inputs are 0, inf, nan, or close to
- // overflow, or close to underflow.
- if (LIBC_UNLIKELY(max_exp > 0x7ffU - 128U || min_exp < 128U)) {
- if (x_bits.is_nan() || y_bits.is_nan()) {
- if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- unsigned x_except = x == 0.0 ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1);
- unsigned y_except = y == 0.0 ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1);
-
- // Exceptional cases:
- // EXCEPT[y_except][x_except][x_is_neg]
- // with x_except & y_except:
- // 0: zero
- // 1: finite, non-zero
- // 2: infinity
- constexpr DoubleDouble EXCEPTS[3][3][2] = {
- {{ZERO, PI}, {ZERO, PI}, {ZERO, PI}},
- {{PI_OVER_2, PI_OVER_2}, {ZERO, ZERO}, {ZERO, PI}},
- {{PI_OVER_2, PI_OVER_2},
- {PI_OVER_2, PI_OVER_2},
- {PI_OVER_4, THREE_PI_OVER_4}},
- };
-
- if ((x_except != 1) || (y_except != 1)) {
- DoubleDouble r = EXCEPTS[y_except][x_except][x_sign];
- return fputil::multiply_add(IS_NEG[y_sign], r.hi, IS_NEG[y_sign] * r.lo);
- }
- bool scale_up = min_exp < 128U;
- bool scale_down = max_exp > 0x7ffU - 128U;
- // At least one input is denormal, multiply both numerator and denominator
- // by some large enough power of 2 to normalize denormal inputs.
- if (scale_up) {
- num *= 0x1.0p64;
- if (!scale_down)
- den *= 0x1.0p64;
- } else if (scale_down) {
- den *= 0x1.0p-64;
- if (!scale_up)
- num *= 0x1.0p-64;
- }
-
- min_abs = FPBits(num).uintval();
- max_abs = FPBits(den).uintval();
- min_exp = static_cast<unsigned>(min_abs >> FPBits::FRACTION_LEN);
- max_exp = static_cast<unsigned>(max_abs >> FPBits::FRACTION_LEN);
- }
-
- double final_sign = IS_NEG[(x_sign != y_sign) != recip];
- DoubleDouble const_term = CONST_ADJ[x_sign][y_sign][recip];
- unsigned exp_diff = max_exp - min_exp;
- // We have the following bound for normalized n and d:
- // 2^(-exp_diff - 1) < n/d < 2^(-exp_diff + 1).
- if (LIBC_UNLIKELY(exp_diff > 54)) {
- return fputil::multiply_add(final_sign, const_term.hi,
- final_sign * (const_term.lo + num / den));
- }
-
- double k = fputil::nearest_integer(64.0 * num / den);
- unsigned idx = static_cast<unsigned>(k);
- // k = idx / 64
- k *= 0x1.0p-6;
-
- // Range reduction:
- // atan(n/d) - atan(k/64) = atan((n/d - k/64) / (1 + (n/d) * (k/64)))
- // = atan((n - d * k/64)) / (d + n * k/64))
- DoubleDouble num_k = fputil::exact_mult(num, k);
- DoubleDouble den_k = fputil::exact_mult(den, k);
-
- // num_dd = n - d * k
- DoubleDouble num_dd = fputil::exact_add(num - den_k.hi, -den_k.lo);
- // den_dd = d + n * k
- DoubleDouble den_dd = fputil::exact_add(den, num_k.hi);
- den_dd.lo += num_k.lo;
-
- // q = (n - d * k) / (d + n * k)
- DoubleDouble q = fputil::div(num_dd, den_dd);
- // p ~ atan(q)
- DoubleDouble p = atan_eval(q);
-
- DoubleDouble r = fputil::add(const_term, fputil::add(ATAN_I[idx], p));
- r.hi *= final_sign;
- r.lo *= final_sign;
-
- return r.hi + r.lo;
+ return math::atan2(y, x);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/atan2f.cpp b/libc/src/math/generic/atan2f.cpp
index c04b0eb..32b977f 100644
--- a/libc/src/math/generic/atan2f.cpp
+++ b/libc/src/math/generic/atan2f.cpp
@@ -8,7 +8,6 @@
#include "src/math/atan2f.h"
#include "hdr/fenv_macros.h"
-#include "inv_trigf_utils.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
@@ -18,6 +17,7 @@
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/math/inv_trigf_utils.h"
#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) && \
defined(LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT)
@@ -236,6 +236,7 @@ float atan2f_double_double(double num_d, double den_d, double q_d, int idx,
// which is about rounding errors of double-double (2^-104).
LLVM_LIBC_FUNCTION(float, atan2f, (float y, float x)) {
+ using namespace inv_trigf_utils_internal;
using FPBits = typename fputil::FPBits<float>;
constexpr double IS_NEG[2] = {1.0, -1.0};
constexpr double PI = 0x1.921fb54442d18p1;
diff --git a/libc/src/math/generic/atan2f128.cpp b/libc/src/math/generic/atan2f128.cpp
index a3aba0b..8838d94 100644
--- a/libc/src/math/generic/atan2f128.cpp
+++ b/libc/src/math/generic/atan2f128.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "src/math/atan2f128.h"
-#include "atan_utils.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/dyadic_float.h"
#include "src/__support/FPUtil/multiply_add.h"
@@ -16,6 +15,7 @@
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/macros/properties/types.h"
+#include "src/__support/math/atan_utils.h"
#include "src/__support/uint128.h"
namespace LIBC_NAMESPACE_DECL {
@@ -103,6 +103,7 @@ static constexpr Float128 CONST_ADJ[2][2][2] = {
// |(atan(u) - P(u)) / P(u)| < 2^-114.
LLVM_LIBC_FUNCTION(float128, atan2f128, (float128 y, float128 x)) {
+ using namespace atan_internal;
using FPBits = fputil::FPBits<float128>;
using Float128 = fputil::DyadicFloat<128>;
diff --git a/libc/src/math/generic/atan2l.cpp b/libc/src/math/generic/atan2l.cpp
index 47a2e985..a7824c6 100644
--- a/libc/src/math/generic/atan2l.cpp
+++ b/libc/src/math/generic/atan2l.cpp
@@ -9,7 +9,7 @@
#include "src/math/atan2l.h"
#include "src/__support/common.h"
#include "src/__support/macros/properties/types.h"
-#include "src/math/atan2.h"
+#include "src/__support/math/atan2.h"
namespace LIBC_NAMESPACE_DECL {
@@ -17,7 +17,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(long double, atan2l, (long double y, long double x)) {
#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
return static_cast<long double>(
- atan2(static_cast<double>(y), static_cast<double>(x)));
+ math::atan2(static_cast<double>(y), static_cast<double>(x)));
#else
#error "Extended precision is not yet supported"
#endif
diff --git a/libc/src/math/generic/atan_utils.h b/libc/src/math/generic/atan_utils.h
deleted file mode 100644
index 24c7271..0000000
--- a/libc/src/math/generic/atan_utils.h
+++ /dev/null
@@ -1,241 +0,0 @@
-//===-- Collection of utils for atan/atan2 ----------------------*- 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_MATH_GENERIC_ATAN_UTILS_H
-#define LLVM_LIBC_SRC_MATH_GENERIC_ATAN_UTILS_H
-
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/dyadic_float.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/integer_literals.h"
-#include "src/__support/macros/config.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-namespace {
-
-using DoubleDouble = fputil::DoubleDouble;
-using Float128 = fputil::DyadicFloat<128>;
-
-// atan(i/64) with i = 0..64, generated by Sollya with:
-// > for i from 0 to 64 do {
-// a = round(atan(i/64), D, RN);
-// b = round(atan(i/64) - a, D, RN);
-// print("{", b, ",", a, "},");
-// };
-constexpr DoubleDouble ATAN_I[65] = {
- {0.0, 0.0},
- {-0x1.220c39d4dff5p-61, 0x1.fff555bbb729bp-7},
- {-0x1.5ec431444912cp-60, 0x1.ffd55bba97625p-6},
- {-0x1.86ef8f794f105p-63, 0x1.7fb818430da2ap-5},
- {-0x1.c934d86d23f1dp-60, 0x1.ff55bb72cfdeap-5},
- {0x1.ac4ce285df847p-58, 0x1.3f59f0e7c559dp-4},
- {-0x1.cfb654c0c3d98p-58, 0x1.7ee182602f10fp-4},
- {0x1.f7b8f29a05987p-58, 0x1.be39ebe6f07c3p-4},
- {-0x1.cd37686760c17p-59, 0x1.fd5ba9aac2f6ep-4},
- {-0x1.b485914dacf8cp-59, 0x1.1e1fafb043727p-3},
- {0x1.61a3b0ce9281bp-57, 0x1.3d6eee8c6626cp-3},
- {-0x1.054ab2c010f3dp-58, 0x1.5c9811e3ec26ap-3},
- {0x1.347b0b4f881cap-58, 0x1.7b97b4bce5b02p-3},
- {0x1.cf601e7b4348ep-59, 0x1.9a6a8e96c8626p-3},
- {0x1.17b10d2e0e5abp-61, 0x1.b90d7529260a2p-3},
- {0x1.c648d1534597ep-57, 0x1.d77d5df205736p-3},
- {0x1.8ab6e3cf7afbdp-57, 0x1.f5b75f92c80ddp-3},
- {0x1.62e47390cb865p-56, 0x1.09dc597d86362p-2},
- {0x1.30ca4748b1bf9p-57, 0x1.18bf5a30bf178p-2},
- {-0x1.077cdd36dfc81p-56, 0x1.278372057ef46p-2},
- {-0x1.963a544b672d8p-57, 0x1.362773707ebccp-2},
- {-0x1.5d5e43c55b3bap-56, 0x1.44aa436c2af0ap-2},
- {-0x1.2566480884082p-57, 0x1.530ad9951cd4ap-2},
- {-0x1.a725715711fp-56, 0x1.614840309cfe2p-2},
- {-0x1.c63aae6f6e918p-56, 0x1.6f61941e4def1p-2},
- {0x1.69c885c2b249ap-56, 0x1.7d5604b63b3f7p-2},
- {0x1.b6d0ba3748fa8p-56, 0x1.8b24d394a1b25p-2},
- {0x1.9e6c988fd0a77p-56, 0x1.98cd5454d6b18p-2},
- {-0x1.24dec1b50b7ffp-56, 0x1.a64eec3cc23fdp-2},
- {0x1.ae187b1ca504p-56, 0x1.b3a911da65c6cp-2},
- {-0x1.cc1ce70934c34p-56, 0x1.c0db4c94ec9fp-2},
- {-0x1.a2cfa4418f1adp-56, 0x1.cde53432c1351p-2},
- {0x1.a2b7f222f65e2p-56, 0x1.dac670561bb4fp-2},
- {0x1.0e53dc1bf3435p-56, 0x1.e77eb7f175a34p-2},
- {-0x1.a3992dc382a23p-57, 0x1.f40dd0b541418p-2},
- {-0x1.b32c949c9d593p-55, 0x1.0039c73c1a40cp-1},
- {-0x1.d5b495f6349e6p-56, 0x1.0657e94db30dp-1},
- {0x1.974fa13b5404fp-58, 0x1.0c6145b5b43dap-1},
- {-0x1.2bdaee1c0ee35p-58, 0x1.1255d9bfbd2a9p-1},
- {0x1.c621cec00c301p-55, 0x1.1835a88be7c13p-1},
- {-0x1.928df287a668fp-58, 0x1.1e00babdefeb4p-1},
- {0x1.c421c9f38224ep-57, 0x1.23b71e2cc9e6ap-1},
- {-0x1.09e73b0c6c087p-56, 0x1.2958e59308e31p-1},
- {0x1.c5d5e9ff0cf8dp-55, 0x1.2ee628406cbcap-1},
- {0x1.1021137c71102p-55, 0x1.345f01cce37bbp-1},
- {-0x1.2304331d8bf46p-55, 0x1.39c391cd4171ap-1},
- {0x1.ecf8b492644fp-56, 0x1.3f13fb89e96f4p-1},
- {-0x1.f76d0163f79c8p-56, 0x1.445065b795b56p-1},
- {0x1.2419a87f2a458p-56, 0x1.4978fa3269ee1p-1},
- {0x1.4a33dbeb3796cp-55, 0x1.4e8de5bb6ec04p-1},
- {-0x1.1bb74abda520cp-55, 0x1.538f57b89061fp-1},
- {-0x1.5e5c9d8c5a95p-56, 0x1.587d81f732fbbp-1},
- {0x1.0028e4bc5e7cap-57, 0x1.5d58987169b18p-1},
- {-0x1.2b785350ee8c1p-57, 0x1.6220d115d7b8ep-1},
- {-0x1.6ea6febe8bbbap-56, 0x1.66d663923e087p-1},
- {-0x1.a80386188c50ep-55, 0x1.6b798920b3d99p-1},
- {-0x1.8c34d25aadef6p-56, 0x1.700a7c5784634p-1},
- {0x1.7b2a6165884a1p-59, 0x1.748978fba8e0fp-1},
- {0x1.406a08980374p-55, 0x1.78f6bbd5d315ep-1},
- {0x1.560821e2f3aa9p-55, 0x1.7d528289fa093p-1},
- {-0x1.bf76229d3b917p-56, 0x1.819d0b7158a4dp-1},
- {0x1.6b66e7fc8b8c3p-57, 0x1.85d69576cc2c5p-1},
- {-0x1.55b9a5e177a1bp-55, 0x1.89ff5ff57f1f8p-1},
- {-0x1.ec182ab042f61p-56, 0x1.8e17aa99cc05ep-1},
- {0x1.1a62633145c07p-55, 0x1.921fb54442d18p-1},
-};
-
-// Approximate atan(x) for |x| <= 2^-7.
-// Using degree-9 Taylor polynomial:
-// P = x - x^3/3 + x^5/5 -x^7/7 + x^9/9;
-// Then the absolute error is bounded by:
-// |atan(x) - P(x)| < |x|^11/11 < 2^(-7*11) / 11 < 2^-80.
-// And the relative error is bounded by:
-// |(atan(x) - P(x))/atan(x)| < |x|^10 / 10 < 2^-73.
-// For x = x_hi + x_lo, fully expand the polynomial and drop any terms less than
-// ulp(x_hi^3 / 3) gives us:
-// P(x) ~ x_hi - x_hi^3/3 + x_hi^5/5 - x_hi^7/7 + x_hi^9/9 +
-// + 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) {
- DoubleDouble p;
- p.hi = x.hi;
- double x_hi_sq = x.hi * x.hi;
- // c0 ~ x_hi^2 * 1/5 - 1/3
- double c0 = fputil::multiply_add(x_hi_sq, 0x1.999999999999ap-3,
- -0x1.5555555555555p-2);
- // c1 ~ x_hi^2 * 1/9 - 1/7
- double c1 = fputil::multiply_add(x_hi_sq, 0x1.c71c71c71c71cp-4,
- -0x1.2492492492492p-3);
- // x_hi^3
- double x_hi_3 = x_hi_sq * x.hi;
- // x_hi^4
- double x_hi_4 = x_hi_sq * x_hi_sq;
- // d0 ~ 1/3 - x_hi^2 / 5 + x_hi^4 / 7 - x_hi^6 / 9
- double d0 = fputil::multiply_add(x_hi_4, c1, c0);
- // x_lo - x_lo * x_hi^2 + x_lo * x_hi^4
- double d1 = fputil::multiply_add(x_hi_4 - x_hi_sq, x.lo, x.lo);
- // p.lo ~ -x_hi^3/3 + x_hi^5/5 - x_hi^7/7 + x_hi^9/9 +
- // + x_lo * (1 - x_hi^2 + x_hi^4)
- p.lo = fputil::multiply_add(x_hi_3, d0, d1);
- return p;
-}
-
-// Float128 versions.
-// atan(i/64) with i = 0..64, generated by Sollya with:
-// > for i from 1 to 64 do {
-// a = round(atan(i/64), 128, RN);
-// ll = ceil(log2(a));
-// b = 2^ll + a;
-// print("{Sign::POS, ", 2^(ll - 128), ",", b, "},");
-// };
-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},
- {Sign::POS, -132, 0xbfdc0c21'86d14fcf'220e10d6'1df56ec7_u128},
- {Sign::POS, -132, 0xffaaddb9'67ef4e36'cb2792dc'0e2e0d51_u128},
- {Sign::POS, -131, 0x9facf873'e2aceb58'99c50bbf'08e6cdf6_u128},
- {Sign::POS, -131, 0xbf70c130'17887460'93567e78'4cf83676_u128},
- {Sign::POS, -131, 0xdf1cf5f3'783e1bef'71e5340b'30e5d9ef_u128},
- {Sign::POS, -131, 0xfeadd4d5'617b6e32'c897989f'3e888ef8_u128},
- {Sign::POS, -130, 0x8f0fd7d8'21b93725'bd375929'83a0af9a_u128},
- {Sign::POS, -130, 0x9eb77746'331362c3'47619d25'0360fe85_u128},
- {Sign::POS, -130, 0xae4c08f1'f6134efa'b54d3fef'0c2de994_u128},
- {Sign::POS, -130, 0xbdcbda5e'72d81134'7b0b4f88'1c9c7488_u128},
- {Sign::POS, -130, 0xcd35474b'643130e7'b00f3da1'a46eeb3b_u128},
- {Sign::POS, -130, 0xdc86ba94'93051022'f621a5c1'cb552f03_u128},
- {Sign::POS, -130, 0xebbeaef9'02b9b38c'91a2a68b'2fbd78e8_u128},
- {Sign::POS, -130, 0xfadbafc9'6406eb15'6dc79ef5'f7a217e6_u128},
- {Sign::POS, -129, 0x84ee2cbe'c31b12c5'c8e72197'0cabd3a3_u128},
- {Sign::POS, -129, 0x8c5fad18'5f8bc130'ca4748b1'bf88298d_u128},
- {Sign::POS, -129, 0x93c1b902'bf7a2df1'06459240'6fe1447a_u128},
- {Sign::POS, -129, 0x9b13b9b8'3f5e5e69'c5abb498'd27af328_u128},
- {Sign::POS, -129, 0xa25521b6'15784d45'43787549'88b8d9e3_u128},
- {Sign::POS, -129, 0xa9856cca'8e6a4eda'99b7f77b'f7d9e8c1_u128},
- {Sign::POS, -129, 0xb0a42018'4e7f0cb1'b51d51dc'200a0fc3_u128},
- {Sign::POS, -129, 0xb7b0ca0f'26f78473'8aa32122'dcfe4483_u128},
- {Sign::POS, -129, 0xbeab025b'1d9fbad3'910b8564'93411026_u128},
- {Sign::POS, -129, 0xc59269ca'50d92b6d'a1746e91'f50a28de_u128},
- {Sign::POS, -129, 0xcc66aa2a'6b58c33c'd9311fa1'4ed9b7c4_u128},
- {Sign::POS, -129, 0xd327761e'611fe5b6'427c95e9'001e7136_u128},
- {Sign::POS, -129, 0xd9d488ed'32e3635c'30f6394a'0806345d_u128},
- {Sign::POS, -129, 0xe06da64a'764f7c67'c631ed96'798cb804_u128},
- {Sign::POS, -129, 0xe6f29a19'609a84ba'60b77ce1'ca6dc2c8_u128},
- {Sign::POS, -129, 0xed63382b'0dda7b45'6fe445ec'bc3a8d03_u128},
- {Sign::POS, -129, 0xf3bf5bf8'bad1a21c'a7b837e6'86adf3fa_u128},
- {Sign::POS, -129, 0xfa06e85a'a0a0be5c'66d23c7d'5dc8ecc2_u128},
- {Sign::POS, -128, 0x801ce39e'0d205c99'a6d6c6c5'4d938596_u128},
- {Sign::POS, -128, 0x832bf4a6'd9867e2a'4b6a09cb'61a515c1_u128},
- {Sign::POS, -128, 0x8630a2da'da1ed065'd3e84ed5'013ca37e_u128},
- {Sign::POS, -128, 0x892aecdf'de9547b5'094478fc'472b4afc_u128},
- {Sign::POS, -128, 0x8c1ad445'f3e09b8c'439d8018'60205921_u128},
- {Sign::POS, -128, 0x8f005d5e'f7f59f9b'5c835e16'65c43748_u128},
- {Sign::POS, -128, 0x91db8f16'64f350e2'10e4f9c1'126e0220_u128},
- {Sign::POS, -128, 0x94ac72c9'847186f6'18c4f393'f78a32f9_u128},
- {Sign::POS, -128, 0x97731420'365e538b'abd3fe19'f1aeb6b3_u128},
- {Sign::POS, -128, 0x9a2f80e6'71bdda20'4226f8e2'204ff3bd_u128},
- {Sign::POS, -128, 0x9ce1c8e6'a0b8cdb9'f799c4e8'174cf11c_u128},
- {Sign::POS, -128, 0x9f89fdc4'f4b7a1ec'f8b49264'4f0701e0_u128},
- {Sign::POS, -128, 0xa22832db'cadaae08'92fe9c08'637af0e6_u128},
- {Sign::POS, -128, 0xa4bc7d19'34f70924'19a87f2a'457dac9f_u128},
- {Sign::POS, -128, 0xa746f2dd'b7602294'67b7d66f'2d74e019_u128},
- {Sign::POS, -128, 0xa9c7abdc'4830f5c8'916a84b5'be7933f6_u128},
- {Sign::POS, -128, 0xac3ec0fb'997dd6a1'a36273a5'6afa8ef4_u128},
- {Sign::POS, -128, 0xaeac4c38'b4d8c080'14725e2f'3e52070a_u128},
- {Sign::POS, -128, 0xb110688a'ebdc6f6a'43d65788'b9f6a7b5_u128},
- {Sign::POS, -128, 0xb36b31c9'1f043691'59014174'4462f93a_u128},
- {Sign::POS, -128, 0xb5bcc490'59ecc4af'f8f3cee7'5e3907d5_u128},
- {Sign::POS, -128, 0xb8053e2b'c2319e73'cb2da552'10a4443d_u128},
- {Sign::POS, -128, 0xba44bc7d'd470782f'654c2cb1'0942e386_u128},
- {Sign::POS, -128, 0xbc7b5dea'e98af280'd4113006'e80fb290_u128},
- {Sign::POS, -128, 0xbea94144'fd049aac'1043c5e7'55282e7d_u128},
- {Sign::POS, -128, 0xc0ce85b8'ac526640'89dd62c4'6e92fa25_u128},
- {Sign::POS, -128, 0xc2eb4abb'661628b5'b373fe45'c61bb9fb_u128},
- {Sign::POS, -128, 0xc4ffaffa'bf8fbd54'8cb43d10'bc9e0221_u128},
- {Sign::POS, -128, 0xc70bd54c'e602ee13'e7d54fbd'09f2be38_u128},
- {Sign::POS, -128, 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128},
-};
-
-// Degree-13 minimax polynomial generated by Sollya with:
-// > P = fpminimax(atan(x), [|1, 3, 5, 7, 9, 11, 13|], [|1, 128...|],
-// [0, 2^-7]);
-// > dirtyinfnorm(atan(x) - P, [0, 2^-7]);
-// 0x1.26016ad97f323875760f869684c0898d7b7bb8bep-122
-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},
- {Sign::POS, -131, 0xe38e38e3'8dce3d96'626a1643'f8eb68f3_u128},
- {Sign::NEG, -131, 0xba2e8b7a'ea4ad00f'005a35c7'6ef609b1_u128},
- {Sign::POS, -131, 0x9d82765e'd22a7d92'ac09c405'c0a69214_u128},
-};
-
-// Approximate atan for |x| <= 2^-7.
-[[maybe_unused]] 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],
- ATAN_POLY_F128[2], ATAN_POLY_F128[3],
- ATAN_POLY_F128[4], ATAN_POLY_F128[5]);
- return fputil::multiply_add(x3, p, x);
-}
-
-} // anonymous namespace
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_MATH_GENERIC_ATAN_UTILS_H
diff --git a/libc/src/math/generic/atanf.cpp b/libc/src/math/generic/atanf.cpp
index 46196dbe..acd32f0 100644
--- a/libc/src/math/generic/atanf.cpp
+++ b/libc/src/math/generic/atanf.cpp
@@ -7,115 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/atanf.h"
-#include "inv_trigf_utils.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/nearest_integer.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/math/atanf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, atanf, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
-
- constexpr double FINAL_SIGN[2] = {1.0, -1.0};
- constexpr double SIGNED_PI_OVER_2[2] = {0x1.921fb54442d18p0,
- -0x1.921fb54442d18p0};
-
- FPBits x_bits(x);
- Sign sign = x_bits.sign();
- x_bits.set_sign(Sign::POS);
- uint32_t x_abs = x_bits.uintval();
-
- // x is inf or nan, |x| < 2^-4 or |x|= > 16.
- if (LIBC_UNLIKELY(x_abs <= 0x3d80'0000U || x_abs >= 0x4180'0000U)) {
- double x_d = static_cast<double>(x);
- double const_term = 0.0;
- if (LIBC_UNLIKELY(x_abs >= 0x4180'0000)) {
- // atan(+-Inf) = +-pi/2.
- if (x_bits.is_inf()) {
- volatile double sign_pi_over_2 = SIGNED_PI_OVER_2[sign.is_neg()];
- return static_cast<float>(sign_pi_over_2);
- }
- if (x_bits.is_nan())
- return x;
- // x >= 16
- x_d = -1.0 / x_d;
- const_term = SIGNED_PI_OVER_2[sign.is_neg()];
- }
- // 0 <= x < 1/16;
- if (LIBC_UNLIKELY(x_bits.is_zero()))
- return x;
- // x <= 2^-12;
- if (LIBC_UNLIKELY(x_abs < 0x3980'0000)) {
-#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
- return fputil::multiply_add(x, -0x1.0p-25f, x);
-#else
- double x_d = static_cast<double>(x);
- return static_cast<float>(fputil::multiply_add(x_d, -0x1.0p-25, x_d));
-#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
- }
- // Use Taylor polynomial:
- // atan(x) ~ x * (1 - x^2 / 3 + x^4 / 5 - x^6 / 7 + x^8 / 9 - x^10 / 11).
- constexpr double ATAN_TAYLOR[6] = {
- 0x1.0000000000000p+0, -0x1.5555555555555p-2, 0x1.999999999999ap-3,
- -0x1.2492492492492p-3, 0x1.c71c71c71c71cp-4, -0x1.745d1745d1746p-4,
- };
- double x2 = x_d * x_d;
- double x4 = x2 * x2;
- double c0 = fputil::multiply_add(x2, ATAN_TAYLOR[1], ATAN_TAYLOR[0]);
- double c1 = fputil::multiply_add(x2, ATAN_TAYLOR[3], ATAN_TAYLOR[2]);
- double c2 = fputil::multiply_add(x2, ATAN_TAYLOR[5], ATAN_TAYLOR[4]);
- double p = fputil::polyeval(x4, c0, c1, c2);
- double r = fputil::multiply_add(x_d, p, const_term);
- return static_cast<float>(r);
- }
-
- // Range reduction steps:
- // 1) atan(x) = sign(x) * atan(|x|)
- // 2) If |x| > 1, atan(|x|) = pi/2 - atan(1/|x|)
- // 3) For 1/16 < x <= 1, we find k such that: |x - k/16| <= 1/32.
- // 4) Then we use polynomial approximation:
- // atan(x) ~ atan((k/16) + (x - (k/16)) * Q(x - k/16)
- // = P(x - k/16)
- double x_d, const_term, final_sign;
- int idx;
-
- if (x_abs > 0x3f80'0000U) {
- // |x| > 1, we need to invert x, so we will perform range reduction in
- // double precision.
- x_d = 1.0 / static_cast<double>(x_bits.get_val());
- double k_d = fputil::nearest_integer(x_d * 0x1.0p4);
- x_d = fputil::multiply_add(k_d, -0x1.0p-4, x_d);
- idx = static_cast<int>(k_d);
- final_sign = FINAL_SIGN[sign.is_pos()];
- // Adjust constant term of the polynomial by +- pi/2.
- const_term = fputil::multiply_add(final_sign, ATAN_COEFFS[idx][0],
- SIGNED_PI_OVER_2[sign.is_neg()]);
- } else {
- // Exceptional value:
- if (LIBC_UNLIKELY(x_abs == 0x3d8d'6b23U)) { // |x| = 0x1.1ad646p-4
- return sign.is_pos() ? fputil::round_result_slightly_down(0x1.1a6386p-4f)
- : fputil::round_result_slightly_up(-0x1.1a6386p-4f);
- }
- // Perform range reduction in single precision.
- float x_f = x_bits.get_val();
- float k_f = fputil::nearest_integer(x_f * 0x1.0p4f);
- x_f = fputil::multiply_add(k_f, -0x1.0p-4f, x_f);
- x_d = static_cast<double>(x_f);
- idx = static_cast<int>(k_f);
- final_sign = FINAL_SIGN[sign.is_neg()];
- const_term = final_sign * ATAN_COEFFS[idx][0];
- }
-
- double p = atan_eval(x_d, idx);
- double r = fputil::multiply_add(final_sign * x_d, p, const_term);
-
- return static_cast<float>(r);
-}
+LLVM_LIBC_FUNCTION(float, atanf, (float x)) { return math::atanf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/atanf16.cpp b/libc/src/math/generic/atanf16.cpp
index 9b6ec65..7191c42 100644
--- a/libc/src/math/generic/atanf16.cpp
+++ b/libc/src/math/generic/atanf16.cpp
@@ -7,101 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/atanf16.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/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/atanf16.h"
namespace LIBC_NAMESPACE_DECL {
-// Generated by Solly using the following command:
-// > round(pi/2, SG, RN);
-static constexpr float PI_2 = 0x1.921fb6p0;
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_EXCEPTS = 6;
-
-static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ATANF16_EXCEPTS{{
- // (input, RZ output, RU offset, RD offset, RN offset)
- {0x2745, 0x2744, 1, 0, 1},
- {0x3099, 0x3090, 1, 0, 1},
- {0x3c6c, 0x3aae, 1, 0, 1},
- {0x466e, 0x3daa, 1, 0, 1},
- {0x48ae, 0x3ddb, 1, 0, 0},
- {0x5619, 0x3e3d, 1, 0, 1},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, atanf16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
-
- uint16_t x_u = xbits.uintval();
- uint16_t x_abs = x_u & 0x7fff;
- bool x_sign = x_u >> 15;
- float sign = (x_sign ? -1.0 : 1.0);
-
- // |x| >= +/-inf
- if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
- if (xbits.is_nan()) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- return x;
- }
-
- // atanf16(+/-inf) = +/-pi/2
- return fputil::cast<float16>(sign * PI_2);
- }
-
- float xf = x;
- float xsq = xf * xf;
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Handle exceptional values
- if (auto r = ATANF16_EXCEPTS.lookup_odd(x_abs, x_sign);
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif
-
- // |x| <= 0x1p0, |x| <= 1
- if (x_abs <= 0x3c00) {
- // atanf16(+/-0) = +/-0
- if (LIBC_UNLIKELY(x_abs == 0))
- return x;
-
- // Degree-14 minimax odd polynomial of atan(x) generated by Sollya with:
- // > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|SG...|],
- // [0, 1]);
- float result = fputil::polyeval(
- xsq, 0x1.fffffcp-1f, -0x1.55519ep-2f, 0x1.98f6a8p-3f, -0x1.1f0a92p-3f,
- 0x1.95b654p-4f, -0x1.e65492p-5f, 0x1.8c0c36p-6f, -0x1.32316ep-8f);
- return fputil::cast<float16>(xf * result);
- }
-
- // If |x| > 1
- // y = atan(x) = sign(x) * atan(|x|)
- // atan(|x|) = pi/2 - atan(1/|x|)
- // Recall, 1/|x| < 1
- float x_inv_sq = 1.0f / xsq;
- float x_inv = fputil::sqrt<float>(x_inv_sq);
-
- // Degree-14 minimax odd polynomial of atan(x) generated by Sollya with:
- // > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|SG...|],
- // [0, 1]);
- float interm =
- fputil::polyeval(x_inv_sq, 0x1.fffffcp-1f, -0x1.55519ep-2f,
- 0x1.98f6a8p-3f, -0x1.1f0a92p-3f, 0x1.95b654p-4f,
- -0x1.e65492p-5f, 0x1.8c0c36p-6f, -0x1.32316ep-8f);
-
- return fputil::cast<float16>(sign *
- fputil::multiply_add(x_inv, -interm, PI_2));
-}
+LLVM_LIBC_FUNCTION(float16, atanf16, (float16 x)) { return math::atanf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp
index f6fde76..602a8f0 100644
--- a/libc/src/math/generic/atanhf.cpp
+++ b/libc/src/math/generic/atanhf.cpp
@@ -16,6 +16,7 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, atanhf, (float x)) {
+ using namespace acoshf_internal;
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/math/generic/common_constants.cpp b/libc/src/math/generic/common_constants.cpp
index 4dcf84d..42e3ff0 100644
--- a/libc/src/math/generic/common_constants.cpp
+++ b/libc/src/math/generic/common_constants.cpp
@@ -51,52 +51,6 @@ const float ONE_OVER_F_FLOAT[128] = {
0x1.08421p-1f, 0x1.07326p-1f, 0x1.0624dep-1f, 0x1.05198p-1f,
0x1.041042p-1f, 0x1.03091cp-1f, 0x1.020408p-1f, 0x1.010102p-1f};
-// Lookup table for (1/f) where f = 1 + n*2^(-7), n = 0..127.
-const double ONE_OVER_F[128] = {
- 0x1.0000000000000p+0, 0x1.fc07f01fc07f0p-1, 0x1.f81f81f81f820p-1,
- 0x1.f44659e4a4271p-1, 0x1.f07c1f07c1f08p-1, 0x1.ecc07b301ecc0p-1,
- 0x1.e9131abf0b767p-1, 0x1.e573ac901e574p-1, 0x1.e1e1e1e1e1e1ep-1,
- 0x1.de5d6e3f8868ap-1, 0x1.dae6076b981dbp-1, 0x1.d77b654b82c34p-1,
- 0x1.d41d41d41d41dp-1, 0x1.d0cb58f6ec074p-1, 0x1.cd85689039b0bp-1,
- 0x1.ca4b3055ee191p-1, 0x1.c71c71c71c71cp-1, 0x1.c3f8f01c3f8f0p-1,
- 0x1.c0e070381c0e0p-1, 0x1.bdd2b899406f7p-1, 0x1.bacf914c1bad0p-1,
- 0x1.b7d6c3dda338bp-1, 0x1.b4e81b4e81b4fp-1, 0x1.b2036406c80d9p-1,
- 0x1.af286bca1af28p-1, 0x1.ac5701ac5701bp-1, 0x1.a98ef606a63bep-1,
- 0x1.a6d01a6d01a6dp-1, 0x1.a41a41a41a41ap-1, 0x1.a16d3f97a4b02p-1,
- 0x1.9ec8e951033d9p-1, 0x1.9c2d14ee4a102p-1, 0x1.999999999999ap-1,
- 0x1.970e4f80cb872p-1, 0x1.948b0fcd6e9e0p-1, 0x1.920fb49d0e229p-1,
- 0x1.8f9c18f9c18fap-1, 0x1.8d3018d3018d3p-1, 0x1.8acb90f6bf3aap-1,
- 0x1.886e5f0abb04ap-1, 0x1.8618618618618p-1, 0x1.83c977ab2beddp-1,
- 0x1.8181818181818p-1, 0x1.7f405fd017f40p-1, 0x1.7d05f417d05f4p-1,
- 0x1.7ad2208e0ecc3p-1, 0x1.78a4c8178a4c8p-1, 0x1.767dce434a9b1p-1,
- 0x1.745d1745d1746p-1, 0x1.724287f46debcp-1, 0x1.702e05c0b8170p-1,
- 0x1.6e1f76b4337c7p-1, 0x1.6c16c16c16c17p-1, 0x1.6a13cd1537290p-1,
- 0x1.6816816816817p-1, 0x1.661ec6a5122f9p-1, 0x1.642c8590b2164p-1,
- 0x1.623fa77016240p-1, 0x1.6058160581606p-1, 0x1.5e75bb8d015e7p-1,
- 0x1.5c9882b931057p-1, 0x1.5ac056b015ac0p-1, 0x1.58ed2308158edp-1,
- 0x1.571ed3c506b3ap-1, 0x1.5555555555555p-1, 0x1.5390948f40febp-1,
- 0x1.51d07eae2f815p-1, 0x1.5015015015015p-1, 0x1.4e5e0a72f0539p-1,
- 0x1.4cab88725af6ep-1, 0x1.4afd6a052bf5bp-1, 0x1.49539e3b2d067p-1,
- 0x1.47ae147ae147bp-1, 0x1.460cbc7f5cf9ap-1, 0x1.446f86562d9fbp-1,
- 0x1.42d6625d51f87p-1, 0x1.4141414141414p-1, 0x1.3fb013fb013fbp-1,
- 0x1.3e22cbce4a902p-1, 0x1.3c995a47babe7p-1, 0x1.3b13b13b13b14p-1,
- 0x1.3991c2c187f63p-1, 0x1.3813813813814p-1, 0x1.3698df3de0748p-1,
- 0x1.3521cfb2b78c1p-1, 0x1.33ae45b57bcb2p-1, 0x1.323e34a2b10bfp-1,
- 0x1.30d190130d190p-1, 0x1.2f684bda12f68p-1, 0x1.2e025c04b8097p-1,
- 0x1.2c9fb4d812ca0p-1, 0x1.2b404ad012b40p-1, 0x1.29e4129e4129ep-1,
- 0x1.288b01288b013p-1, 0x1.27350b8812735p-1, 0x1.25e22708092f1p-1,
- 0x1.2492492492492p-1, 0x1.23456789abcdfp-1, 0x1.21fb78121fb78p-1,
- 0x1.20b470c67c0d9p-1, 0x1.1f7047dc11f70p-1, 0x1.1e2ef3b3fb874p-1,
- 0x1.1cf06ada2811dp-1, 0x1.1bb4a4046ed29p-1, 0x1.1a7b9611a7b96p-1,
- 0x1.19453808ca29cp-1, 0x1.1811811811812p-1, 0x1.16e0689427379p-1,
- 0x1.15b1e5f75270dp-1, 0x1.1485f0e0acd3bp-1, 0x1.135c81135c811p-1,
- 0x1.12358e75d3033p-1, 0x1.1111111111111p-1, 0x1.0fef010fef011p-1,
- 0x1.0ecf56be69c90p-1, 0x1.0db20a88f4696p-1, 0x1.0c9714fbcda3bp-1,
- 0x1.0b7e6ec259dc8p-1, 0x1.0a6810a6810a7p-1, 0x1.0953f39010954p-1,
- 0x1.0842108421084p-1, 0x1.073260a47f7c6p-1, 0x1.0624dd2f1a9fcp-1,
- 0x1.05197f7d73404p-1, 0x1.0410410410410p-1, 0x1.03091b51f5e1ap-1,
- 0x1.0204081020408p-1, 0x1.0101010101010p-1};
-
// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127,
// computed and stored as float precision constants.
// Generated by Sollya with the following commands:
@@ -136,52 +90,6 @@ const float LOG_F_FLOAT[128] = {
0x1.52a2d2p-1f, 0x1.54b246p-1f, 0x1.56bf9ep-1f, 0x1.58cadcp-1f,
0x1.5ad404p-1f, 0x1.5cdb1ep-1f, 0x1.5ee02ap-1f, 0x1.60e33p-1f};
-// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127.
-const double LOG_F[128] = {
- 0x0.0000000000000p+0, 0x1.fe02a6b106788p-8, 0x1.fc0a8b0fc03e3p-7,
- 0x1.7b91b07d5b11ap-6, 0x1.f829b0e783300p-6, 0x1.39e87b9febd5fp-5,
- 0x1.77458f632dcfcp-5, 0x1.b42dd711971bep-5, 0x1.f0a30c01162a6p-5,
- 0x1.16536eea37ae0p-4, 0x1.341d7961bd1d0p-4, 0x1.51b073f06183fp-4,
- 0x1.6f0d28ae56b4bp-4, 0x1.8c345d6319b20p-4, 0x1.a926d3a4ad563p-4,
- 0x1.c5e548f5bc743p-4, 0x1.e27076e2af2e5p-4, 0x1.fec9131dbeabap-4,
- 0x1.0d77e7cd08e59p-3, 0x1.1b72ad52f67a0p-3, 0x1.29552f81ff523p-3,
- 0x1.371fc201e8f74p-3, 0x1.44d2b6ccb7d1ep-3, 0x1.526e5e3a1b437p-3,
- 0x1.5ff3070a793d3p-3, 0x1.6d60fe719d21cp-3, 0x1.7ab890210d909p-3,
- 0x1.87fa06520c910p-3, 0x1.9525a9cf456b4p-3, 0x1.a23bc1fe2b563p-3,
- 0x1.af3c94e80bff2p-3, 0x1.bc286742d8cd6p-3, 0x1.c8ff7c79a9a21p-3,
- 0x1.d5c216b4fbb91p-3, 0x1.e27076e2af2e5p-3, 0x1.ef0adcbdc5936p-3,
- 0x1.fb9186d5e3e2ap-3, 0x1.0402594b4d040p-2, 0x1.0a324e27390e3p-2,
- 0x1.1058bf9ae4ad5p-2, 0x1.1675cababa60ep-2, 0x1.1c898c16999fap-2,
- 0x1.22941fbcf7965p-2, 0x1.2895a13de86a3p-2, 0x1.2e8e2bae11d30p-2,
- 0x1.347dd9a987d54p-2, 0x1.3a64c556945e9p-2, 0x1.404308686a7e3p-2,
- 0x1.4618bc21c5ec2p-2, 0x1.4be5f957778a0p-2, 0x1.51aad872df82dp-2,
- 0x1.5767717455a6cp-2, 0x1.5d1bdbf5809cap-2, 0x1.62c82f2b9c795p-2,
- 0x1.686c81e9b14aep-2, 0x1.6e08eaa2ba1e3p-2, 0x1.739d7f6bbd006p-2,
- 0x1.792a55fdd47a2p-2, 0x1.7eaf83b82afc3p-2, 0x1.842d1da1e8b17p-2,
- 0x1.89a3386c1425ap-2, 0x1.8f11e873662c7p-2, 0x1.947941c2116fap-2,
- 0x1.99d958117e08ap-2, 0x1.9f323ecbf984bp-2, 0x1.a484090e5bb0ap-2,
- 0x1.a9cec9a9a0849p-2, 0x1.af1293247786bp-2, 0x1.b44f77bcc8f62p-2,
- 0x1.b9858969310fbp-2, 0x1.beb4d9da71b7bp-2, 0x1.c3dd7a7cdad4dp-2,
- 0x1.c8ff7c79a9a21p-2, 0x1.ce1af0b85f3ebp-2, 0x1.d32fe7e00ebd5p-2,
- 0x1.d83e7258a2f3ep-2, 0x1.dd46a04c1c4a0p-2, 0x1.e24881a7c6c26p-2,
- 0x1.e744261d68787p-2, 0x1.ec399d2468cc0p-2, 0x1.f128f5faf06ecp-2,
- 0x1.f6123fa7028acp-2, 0x1.faf588f78f31ep-2, 0x1.ffd2e0857f498p-2,
- 0x1.02552a5a5d0fep-1, 0x1.04bdf9da926d2p-1, 0x1.0723e5c1cdf40p-1,
- 0x1.0986f4f573520p-1, 0x1.0be72e4252a82p-1, 0x1.0e44985d1cc8bp-1,
- 0x1.109f39e2d4c96p-1, 0x1.12f719593efbcp-1, 0x1.154c3d2f4d5e9p-1,
- 0x1.179eabbd899a0p-1, 0x1.19ee6b467c96ep-1, 0x1.1c3b81f713c24p-1,
- 0x1.1e85f5e7040d0p-1, 0x1.20cdcd192ab6dp-1, 0x1.23130d7bebf42p-1,
- 0x1.2555bce98f7cbp-1, 0x1.2795e1289b11ap-1, 0x1.29d37fec2b08ap-1,
- 0x1.2c0e9ed448e8bp-1, 0x1.2e47436e40268p-1, 0x1.307d7334f10bep-1,
- 0x1.32b1339121d71p-1, 0x1.34e289d9ce1d3p-1, 0x1.37117b54747b5p-1,
- 0x1.393e0d3562a19p-1, 0x1.3b68449fffc22p-1, 0x1.3d9026a7156fap-1,
- 0x1.3fb5b84d16f42p-1, 0x1.41d8fe84672aep-1, 0x1.43f9fe2f9ce67p-1,
- 0x1.4618bc21c5ec2p-1, 0x1.48353d1ea88dfp-1, 0x1.4a4f85db03ebbp-1,
- 0x1.4c679afccee39p-1, 0x1.4e7d811b75bb0p-1, 0x1.50913cc01686bp-1,
- 0x1.52a2d265bc5aap-1, 0x1.54b2467999497p-1, 0x1.56bf9d5b3f399p-1,
- 0x1.58cadb5cd7989p-1, 0x1.5ad404c359f2cp-1, 0x1.5cdb1dc6c1764p-1,
- 0x1.5ee02a9241675p-1, 0x1.60e32f44788d8p-1};
-
// Range reduction constants for logarithms.
// r(0) = 1, r(127) = 0.5
// r(k) = 2^-8 * ceil(2^8 * (1 - 2^-8) / (1 + k*2^-7))
diff --git a/libc/src/math/generic/common_constants.h b/libc/src/math/generic/common_constants.h
index 291816a..72b1d564 100644
--- a/libc/src/math/generic/common_constants.h
+++ b/libc/src/math/generic/common_constants.h
@@ -11,6 +11,7 @@
#include "src/__support/FPUtil/triple_double.h"
#include "src/__support/macros/config.h"
+#include "src/__support/math/acosh_float_constants.h"
#include "src/__support/math/exp_constants.h"
#include "src/__support/number_pair.h"
@@ -20,16 +21,10 @@ namespace LIBC_NAMESPACE_DECL {
// computed and stored as float precision constants.
extern const float ONE_OVER_F_FLOAT[128];
-// Lookup table for (1/f) where f = 1 + n*2^(-7), n = 0..127.
-extern const double ONE_OVER_F[128];
-
// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127,
// computed and stored as float precision constants.
extern const float LOG_F_FLOAT[128];
-// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127.
-extern const double LOG_F[128];
-
// Lookup table for range reduction constants r for logarithms.
extern const float R[128];
diff --git a/libc/src/math/generic/erff.cpp b/libc/src/math/generic/erff.cpp
index 44607a5..003b346 100644
--- a/libc/src/math/generic/erff.cpp
+++ b/libc/src/math/generic/erff.cpp
@@ -7,180 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/erff.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.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/math/erff.h"
namespace LIBC_NAMESPACE_DECL {
-// Polynomials approximating erf(x)/x on ( k/8, (k + 1)/8 ) generated by Sollya
-// with:
-// > P = fpminimax(erf(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|D...|],
-// [k/8, (k + 1)/8]);
-// for k = 0..31.
-constexpr double COEFFS[32][8] = {
- {0x1.20dd750429b6dp0, -0x1.812746b037753p-2, 0x1.ce2f219e8596ap-4,
- -0x1.b82cdacb78fdap-6, 0x1.56479297dfda5p-8, -0x1.8b3ac5455ef02p-11,
- -0x1.126fcac367e3bp-8, 0x1.2d0bdb3ba4984p-4},
- {0x1.20dd750429b6dp0, -0x1.812746b0379a8p-2, 0x1.ce2f21a03cf2ap-4,
- -0x1.b82ce30de083ep-6, 0x1.565bcad3eb60fp-8, -0x1.c02c66f659256p-11,
- 0x1.f92f673385229p-14, -0x1.def402648ae9p-17},
- {0x1.20dd750429b34p0, -0x1.812746b032dcep-2, 0x1.ce2f219d84aaep-4,
- -0x1.b82ce22dcf139p-6, 0x1.565b9efcd4af1p-8, -0x1.c021f1af414bcp-11,
- 0x1.f7c6d177eff82p-14, -0x1.c9e4410dcf865p-17},
- {0x1.20dd750426eabp0, -0x1.812746ae592c7p-2, 0x1.ce2f211525f14p-4,
- -0x1.b82ccc125e63fp-6, 0x1.56596f261cfd3p-8, -0x1.bfde1ff8eeecfp-11,
- 0x1.f31a9d15dc5d8p-14, -0x1.a5a4362844b3cp-17},
- {0x1.20dd75039c705p0, -0x1.812746777e74dp-2, 0x1.ce2f17af98a1bp-4,
- -0x1.b82be4b817cbep-6, 0x1.564bec2e2962ep-8, -0x1.bee86f9da3558p-11,
- 0x1.e9443689dc0ccp-14, -0x1.79c0f230805d8p-17},
- {0x1.20dd74f811211p0, -0x1.81274371a3e8fp-2, 0x1.ce2ec038262e5p-4,
- -0x1.b8265b82c5e1fp-6, 0x1.5615a2e239267p-8, -0x1.bc63ae023dcebp-11,
- 0x1.d87c2102f7e06p-14, -0x1.49584bea41d62p-17},
- {0x1.20dd746d063e3p0, -0x1.812729a8a950fp-2, 0x1.ce2cb0a2df232p-4,
- -0x1.b80eca1f51278p-6, 0x1.5572e26c46815p-8, -0x1.b715e5638b65ep-11,
- 0x1.bfbb195484968p-14, -0x1.177a565c15c52p-17},
- {0x1.20dd701b44486p0, -0x1.812691145f237p-2, 0x1.ce23a06b8cfd9p-4,
- -0x1.b7c1dc7245288p-6, 0x1.53e92f7f397ddp-8, -0x1.ad97cc4acf0b2p-11,
- 0x1.9f028b2b09b71p-14, -0x1.cdc4da08da8c1p-18},
- {0x1.20dd5715ac332p0, -0x1.8123e680bd0ebp-2, 0x1.ce0457aded691p-4,
- -0x1.b6f52d52bed4p-6, 0x1.50c291b84414cp-8, -0x1.9ea246b1ad4a9p-11,
- 0x1.77654674e0cap-14, -0x1.737c11a1bcebbp-18},
- {0x1.20dce6593e114p0, -0x1.811a59c02eadcp-2, 0x1.cdab53c7cd7d5p-4,
- -0x1.b526d2e321eedp-6, 0x1.4b1d32cd8b994p-8, -0x1.8963143ec0a1ep-11,
- 0x1.4ad5700e4db91p-14, -0x1.231e100e43ef2p-18},
- {0x1.20db48bfd5a62p0, -0x1.80fdd84f9e308p-2, 0x1.ccd340d462983p-4,
- -0x1.b196a2928768p-6, 0x1.4210c2c13a0f7p-8, -0x1.6dbdfb4ff71aep-11,
- 0x1.1bca2d17fbd71p-14, -0x1.bca36f90c7cf5p-19},
- {0x1.20d64b2f8f508p0, -0x1.80b4d4f19fa8bp-2, 0x1.cb088197262e3p-4,
- -0x1.ab51fd02e5b99p-6, 0x1.34e1e5e81a632p-8, -0x1.4c66377b502cep-11,
- 0x1.d9ad25066213cp-15, -0x1.4b0df7dd0cfa1p-19},
- {0x1.20c8fc1243576p0, -0x1.8010cb2009e27p-2, 0x1.c7a47e9299315p-4,
- -0x1.a155be5683654p-6, 0x1.233502694997bp-8, -0x1.26c94b7d813p-11,
- 0x1.8094f1de25fb9p-15, -0x1.e0e3d776c6eefp-20},
- {0x1.20a9bd1611bc1p0, -0x1.7ec7fbce83f9p-2, 0x1.c1d757d7317b7p-4,
- -0x1.92c160cd589fp-6, 0x1.0d307269cc5c2p-8, -0x1.fda5b0d2d1879p-12,
- 0x1.2fdd7b3b14a7fp-15, -0x1.54eed4a26af5ap-20},
- {0x1.20682834f943dp0, -0x1.7c73f747bf5a9p-2, 0x1.b8c2db4a9ffd1p-4,
- -0x1.7f0e4ffe989ecp-6, 0x1.e7061eae4166ep-9, -0x1.ad36e873fff2dp-12,
- 0x1.d39222396128ep-16, -0x1.d83dacec5ea6bp-21},
- {0x1.1feb8d12676d7p0, -0x1.7898347284afep-2, 0x1.aba3466b34451p-4,
- -0x1.663adc573e2f9p-6, 0x1.ae99fb17c3e08p-9, -0x1.602f950ad5535p-12,
- 0x1.5e9717490609dp-16, -0x1.3fca107bbc8d5p-21},
- {0x1.1f12fe3c536fap0, -0x1.72b1d1f22e6d3p-2, 0x1.99fc0eed4a896p-4,
- -0x1.48db0a87bd8c6p-6, 0x1.73e368895aa61p-9, -0x1.19b35d5301fc8p-12,
- 0x1.007987e4bb033p-16, -0x1.a7edcd4c2dc7p-22},
- {0x1.1db7b0df84d5dp0, -0x1.6a4e4a41cde02p-2, 0x1.83bbded16455dp-4,
- -0x1.2809b3b36977ep-6, 0x1.39c08bab44679p-9, -0x1.b7b45a70ed119p-13,
- 0x1.6e99b36410e7bp-17, -0x1.13619bb7ebc0cp-22},
- {0x1.1bb1c85c4a527p0, -0x1.5f23b99a249a3p-2, 0x1.694c91fa0d12cp-4,
- -0x1.053e1ce11c72dp-6, 0x1.02bf72c50ea78p-9, -0x1.4f478fb56cb02p-13,
- 0x1.005f80ecbe213p-17, -0x1.5f2446bde7f5bp-23},
- {0x1.18dec3bd51f9dp0, -0x1.5123f58346186p-2, 0x1.4b8a1ca536ab4p-4,
- -0x1.c4243015cc723p-7, 0x1.a1a8a01d351efp-10, -0x1.f466b34f1d86bp-14,
- 0x1.5f835eea0bf6ap-18, -0x1.b83165b939234p-24},
- {0x1.152804c3369f4p0, -0x1.4084cd4afd4bcp-2, 0x1.2ba2e836e47aap-4,
- -0x1.800f2dfc6904bp-7, 0x1.4a6daf0669c59p-10, -0x1.6e326ab872317p-14,
- 0x1.d9761a6a755a5p-19, -0x1.0fca33f9dd4b5p-24},
- {0x1.1087ad68356aap0, -0x1.2dbb044707459p-2, 0x1.0aea8ceaa0384p-4,
- -0x1.40b516d52b3d2p-7, 0x1.00c9e05f01d22p-10, -0x1.076afb0dc0ff7p-14,
- 0x1.39fadec400657p-19, -0x1.4b5761352e7e3p-25},
- {0x1.0b0a7a8ba4a22p0, -0x1.196990d22d4a1p-2, 0x1.d5551e6ac0c4dp-5,
- -0x1.07cce1770bd1ap-7, 0x1.890347b8848bfp-11, -0x1.757ec96750b6ap-15,
- 0x1.9b258a1e06bcep-20, -0x1.8fc6d22da7572p-26},
- {0x1.04ce2be70fb47p0, -0x1.0449e4b0b9cacp-2, 0x1.97f7424f4b0e7p-5,
- -0x1.ac825439c42f4p-8, 0x1.28f5f65426dfbp-11, -0x1.05b699a90f90fp-15,
- 0x1.0a888eecf4593p-20, -0x1.deace2b32bb31p-27},
- {0x1.fbf9fb0e11cc8p-1, -0x1.de2640856545ap-3, 0x1.5f5b1f47f851p-5,
- -0x1.588bc71eb41b9p-8, 0x1.bc6a0a772f56dp-12, -0x1.6b9fad1f1657ap-16,
- 0x1.573204ba66504p-21, -0x1.1d38065c94e44p-27},
- {0x1.ed8f18c99e031p-1, -0x1.b4cb6acd903b4p-3, 0x1.2c7f3dddd6fc1p-5,
- -0x1.13052067df4ep-8, 0x1.4a5027444082fp-12, -0x1.f672bab0e2554p-17,
- 0x1.b83c756348cc9p-22, -0x1.534f1a1079499p-28},
- {0x1.debd33044166dp-1, -0x1.8d7cd9053f7d8p-3, 0x1.ff9957fb3d6e7p-6,
- -0x1.b50be55de0f36p-9, 0x1.e92c8ec53a628p-13, -0x1.5a4b88d508007p-17,
- 0x1.1a27737559e26p-22, -0x1.942ae62cb2c14p-29},
- {0x1.cfdbf0386f3bdp-1, -0x1.68e33d93b0dc4p-3, 0x1.b2683d58f53dep-6,
- -0x1.5a9174e70d26fp-9, 0x1.69ddd326d49cdp-13, -0x1.dd8f397a8219cp-18,
- 0x1.6a755016ad4ddp-23, -0x1.e366e0139187dp-30},
- {0x1.c132adb8d7464p-1, -0x1.475a899f61b46p-3, 0x1.70a431397a77cp-6,
- -0x1.12e3d35beeee2p-9, 0x1.0c16b05738333p-13, -0x1.4a47f873e144ep-18,
- 0x1.d3d494c698c02p-24, -0x1.2302c59547fe5p-30},
- {0x1.b2f5fd05555e7p-1, -0x1.28feefbe03ec7p-3, 0x1.3923acbb3a676p-6,
- -0x1.b4ff793cd6358p-10, 0x1.8ea0eb8c913bcp-14, -0x1.cb31ec2baceb1p-19,
- 0x1.30011e7e80c04p-24, -0x1.617710635cb1dp-31},
- {0x1.a54853cd9593ep-1, -0x1.0dbdbaea4dc8ep-3, 0x1.0a93e2c20a0fdp-6,
- -0x1.5c969ff401ea8p-10, 0x1.29e0cc64fe627p-14, -0x1.4160d8e9d3c2ap-19,
- 0x1.8e7b67594624ap-25, -0x1.b1cf2c975b09bp-32},
- {0x1.983ceece09ff8p-1, -0x1.eacc78f7a2dp-4, 0x1.c74418410655fp-7,
- -0x1.1756a050e441ep-10, 0x1.bff3650f7f548p-15, -0x1.c56c0217d3adap-20,
- 0x1.07b4918d0b489p-25, -0x1.0d4be8c1c50f8p-32},
-};
-
-LLVM_LIBC_FUNCTION(float, erff, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
- FPBits xbits(x);
-
- uint32_t x_u = xbits.uintval();
- uint32_t x_abs = x_u & 0x7fff'ffffU;
-
- if (LIBC_UNLIKELY(x_abs >= 0x4080'0000U)) {
- const float ONE[2] = {1.0f, -1.0f};
- const float SMALL[2] = {-0x1.0p-25f, 0x1.0p-25f};
-
- int sign = xbits.is_neg() ? 1 : 0;
-
- 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();
- }
- return (x_abs > 0x7f80'0000) ? x : ONE[sign];
- }
-
- return ONE[sign] + SMALL[sign];
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Exceptional mask = common 0 bits of 2 exceptional values.
- constexpr uint32_t EXCEPT_MASK = 0x809a'6184U;
-
- if (LIBC_UNLIKELY((x_abs & EXCEPT_MASK) == 0)) {
- // Exceptional values
- if (LIBC_UNLIKELY(x_abs == 0x3f65'9229U)) // |x| = 0x1.cb2452p-1f
- return x < 0.0f ? fputil::round_result_slightly_down(-0x1.972ea8p-1f)
- : fputil::round_result_slightly_up(0x1.972ea8p-1f);
- if (LIBC_UNLIKELY(x_abs == 0x4004'1e6aU)) // |x| = 0x1.083cd4p+1f
- return x < 0.0f ? fputil::round_result_slightly_down(-0x1.fe3462p-1f)
- : fputil::round_result_slightly_up(0x1.fe3462p-1f);
- if (x_abs == 0U)
- return x;
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // Polynomial approximation:
- // erf(x) ~ x * (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14)
- double xd = static_cast<double>(x);
- double xsq = xd * xd;
-
- const uint32_t EIGHT = 3 << FPBits::FRACTION_LEN;
- int idx = static_cast<int>(FPBits(x_abs + EIGHT).get_val());
-
- double x4 = xsq * xsq;
- double c0 = fputil::multiply_add(xsq, COEFFS[idx][1], COEFFS[idx][0]);
- double c1 = fputil::multiply_add(xsq, COEFFS[idx][3], COEFFS[idx][2]);
- double c2 = fputil::multiply_add(xsq, COEFFS[idx][5], COEFFS[idx][4]);
- double c3 = fputil::multiply_add(xsq, COEFFS[idx][7], COEFFS[idx][6]);
-
- double x8 = x4 * x4;
- double p0 = fputil::multiply_add(x4, c1, c0);
- double p1 = fputil::multiply_add(x4, c3, c2);
-
- return static_cast<float>(xd * fputil::multiply_add(x8, p1, p0));
-}
+LLVM_LIBC_FUNCTION(float, erff, (float x)) { return math::erff(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/explogxf.h b/libc/src/math/generic/explogxf.h
index be4328a..a2a6d60 100644
--- a/libc/src/math/generic/explogxf.h
+++ b/libc/src/math/generic/explogxf.h
@@ -13,6 +13,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/math/acoshf_utils.h"
#include "src/__support/math/exp10f_utils.h"
#include "src/__support/math/exp_utils.h"
@@ -163,41 +164,6 @@ LIBC_INLINE static float log_eval_f(float x) {
return result;
}
-// x should be positive, normal finite value
-LIBC_INLINE static double log_eval(double x) {
- // For x = 2^ex * (1 + mx)
- // log(x) = ex * log(2) + log(1 + mx)
- using FPB = fputil::FPBits<double>;
- FPB bs(x);
-
- double ex = static_cast<double>(bs.get_exponent());
-
- // p1 is the leading 7 bits of mx, i.e.
- // p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7).
- int p1 = static_cast<int>(bs.get_mantissa() >> (FPB::FRACTION_LEN - 7));
-
- // Set bs to (1 + (mx - p1*2^(-7))
- bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> 7));
- bs.set_biased_exponent(FPB::EXP_BIAS);
- // dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)).
- double dx = (bs.get_val() - 1.0) * ONE_OVER_F[p1];
-
- // Minimax polynomial of log(1 + dx) generated by Sollya with:
- // > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]);
- const double COEFFS[6] = {-0x1.ffffffffffffcp-2, 0x1.5555555552ddep-2,
- -0x1.ffffffefe562dp-3, 0x1.9999817d3a50fp-3,
- -0x1.554317b3f67a5p-3, 0x1.1dc5c45e09c18p-3};
- double dx2 = dx * dx;
- double c1 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
- double c2 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
- double c3 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
-
- double p = fputil::polyeval(dx2, dx, c1, c2, c3);
- double result =
- fputil::multiply_add(ex, /*log(2)*/ 0x1.62e42fefa39efp-1, LOG_F[p1] + p);
- return result;
-}
-
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPLOGXF_H
diff --git a/libc/src/math/generic/expxf16.h b/libc/src/math/generic/expxf16.h
index b17b14f..562a427 100644
--- a/libc/src/math/generic/expxf16.h
+++ b/libc/src/math/generic/expxf16.h
@@ -9,14 +9,13 @@
#ifndef LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H
#define LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H
+#include "hdr/stdint_proxy.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
-#include <stdint.h>
-
#include "src/__support/math/exp10_float16_constants.h"
#include "src/__support/math/expf16_utils.h"
diff --git a/libc/src/math/generic/fabsbf16.cpp b/libc/src/math/generic/fabsbf16.cpp
new file mode 100644
index 0000000..ea39719
--- /dev/null
+++ b/libc/src/math/generic/fabsbf16.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fabsbf16 function -------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/fabsbf16.h"
+
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, fabsbf16, (bfloat16 x)) { return fputil::abs(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/inv_trigf_utils.cpp b/libc/src/math/generic/inv_trigf_utils.cpp
deleted file mode 100644
index f23028b..0000000
--- a/libc/src/math/generic/inv_trigf_utils.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===-- Single-precision general exp/log functions ------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "inv_trigf_utils.h"
-#include "src/__support/macros/config.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-// Polynomial approximation for 0 <= x <= 1:
-// atan(x) ~ atan((i/16) + (x - (i/16)) * Q(x - i/16)
-// = P(x - i/16)
-// Generated by Sollya with:
-// > for i from 1 to 16 do {
-// mid_point = i/16;
-// P = fpminimax(atan(mid_point + x), 8, [|D...|], [-1/32, 1/32]);
-// print("{", coeff(P, 0), ",", coeff(P, 1), ",", coeff(P, 2), ",",
-// coeff(P, 3), ",", coeff(P, 4), ",", coeff(P, 5), ",", coeff(P, 6),
-// ",", coeff(P, 7), ",", coeff(P, 8), "},");
-// };
-// For i = 0, the polynomial is generated by:
-// > P = fpminimax(atan(x)/x, 7, [|1, D...|], [0, 1/32]);
-// > dirtyinfnorm((atan(x) - x*P)/x, [0, 1/32]);
-// 0x1.feb2fcdba66447ccbe28a1a0f935b51678a718fb1p-59
-// Notice that degree-7 is good enough for atanf, but degree-8 helps reduce the
-// error bounds for atan2f's fast pass 16 times, and it does not affect the
-// performance of atanf much.
-double ATAN_COEFFS[17][9] = {
- {0.0, 1.0, 0x1.3f8d76d26d61bp-47, -0x1.5555555574cd8p-2,
- 0x1.0dde5d06878eap-29, 0x1.99997738acc77p-3, 0x1.2c43eac9797cap-16,
- -0x1.25fb020007dbdp-3, 0x1.c1b6c31d7b0aep-7},
- {0x1.ff55bb72cfde9p-5, 0x1.fe01fe01fe007p-1, -0x1.fc05f809ed8dap-5,
- -0x1.4d69303afe04ep-2, 0x1.f61bc3e8349cp-5, 0x1.820839278756bp-3,
- -0x1.eda4de1c6bf3fp-5, -0x1.0514d42d64a63p-3, 0x1.db3746a442dcbp-5},
- {0x1.fd5ba9aac2f6ep-4, 0x1.f81f81f81f813p-1, -0x1.f05e09d0dc378p-4,
- -0x1.368c3aa719215p-2, 0x1.d9b16b33ff9c9p-4, 0x1.40488f9c6262ap-3,
- -0x1.ba55933e62ea5p-4, -0x1.64c6a15cd9116p-4, 0x1.9273d5939a75ap-4},
- {0x1.7b97b4bce5b02p-3, 0x1.ee9c7f8458e05p-1, -0x1.665c226d6961p-3,
- -0x1.1344bb7391703p-2, 0x1.42aca8b0081b9p-3, 0x1.c32d9381d7c03p-4,
- -0x1.13e970672e246p-3, -0x1.181ed934dd733p-5, 0x1.bad81ea190c08p-4},
- {0x1.f5b75f92c80ddp-3, 0x1.e1e1e1e1e1e2cp-1, -0x1.c5894d10d363dp-3,
- -0x1.ce6de025f9f5ep-3, 0x1.78a3a07c8dd7fp-3, 0x1.dd5f5180f386ep-5,
- -0x1.1b1f513c4536bp-3, 0x1.0df852e58c43cp-6, 0x1.722e7a7e42505p-4},
- {0x1.362773707ebccp-2, 0x1.d272ca3fc5b2ep-1, -0x1.0997e8aeca8fbp-2,
- -0x1.6cf6666e5e693p-3, 0x1.8dd1e907e88adp-3, 0x1.24849ac0caa5dp-7,
- -0x1.f496be486229dp-4, 0x1.b7d54b8e759ecp-5, 0x1.d39c0d39c3922p-5},
- {0x1.6f61941e4def1p-2, 0x1.c0e070381c0f2p-1, -0x1.2726dd135d9eep-2,
- -0x1.09f37b39b70e4p-3, 0x1.85eacdaadd712p-3, -0x1.04d66340d5b9p-5,
- -0x1.8056b15a22b98p-4, 0x1.29baf494ad3ddp-4, 0x1.52d5881322a7ap-6},
- {0x1.a64eec3cc23fdp-2, 0x1.adbe87f94906ap-1, -0x1.3b9d8eab55addp-2,
- -0x1.57c09646eb7p-4, 0x1.6795319e3b8dfp-3, -0x1.f2d89b5ef31bep-5,
- -0x1.f38aac26203cap-5, 0x1.3262802235e3fp-4, -0x1.2afd6b9a57d66p-7},
- {0x1.dac670561bb4fp-2, 0x1.99999999999ap-1, -0x1.47ae147adff11p-2,
- -0x1.5d867c40188b7p-5, 0x1.3a92a2df85e7ap-3, -0x1.3ec457c46e851p-4,
- -0x1.ec1b9777e2e5bp-6, 0x1.0a542992a821ep-4, -0x1.ccffbe2f0d945p-6},
- {0x1.0657e94db30dp-1, 0x1.84f00c2780615p-1, -0x1.4c62cb562defap-2,
- -0x1.e6495b3c14e03p-8, 0x1.063c2fa617bfcp-3, -0x1.58b782d9907aap-4,
- -0x1.41e6ff524b7fp-8, 0x1.937dfff3205a7p-5, -0x1.0fb1fd1c729dp-5},
- {0x1.1e00babdefeb4p-1, 0x1.702e05c0b816ep-1, -0x1.4af2b78215fbep-2,
- 0x1.5d0b7e9f36997p-6, 0x1.a1247cb978debp-4, -0x1.519e1457734cap-4,
- 0x1.a755cf86b5bfbp-7, 0x1.096d174284564p-5, -0x1.081adf539ad58p-5},
- {0x1.345f01cce37bbp-1, 0x1.5babcc647fa8ep-1, -0x1.449db09426a6dp-2,
- 0x1.655caac5896dap-5, 0x1.3bbbd22d05a61p-4, -0x1.34a2febee042fp-4,
- 0x1.84df9c8269e34p-6, 0x1.200e8176c899ap-6, -0x1.c00b23c3ce222p-6},
- {0x1.4978fa3269ee1p-1, 0x1.47ae147ae1477p-1, -0x1.3a92a3055231ap-2,
- 0x1.ec21b515a4a2p-5, 0x1.c2f8b81f9a0d2p-5, -0x1.0ba9964125453p-4,
- 0x1.d7b5614777a05p-6, 0x1.971e91ed73595p-8, -0x1.3fc375a78dc74p-6},
- {0x1.5d58987169b18p-1, 0x1.34679ace01343p-1, -0x1.2ddfb039136e5p-2,
- 0x1.2491307b9fb73p-4, 0x1.29c7e4886dc22p-5, -0x1.bca78bcca83ap-5,
- 0x1.e63efd7cbe1ddp-6, -0x1.8ea6c4f03b42dp-10, -0x1.9385b5c3a6997p-7},
- {0x1.700a7c5784634p-1, 0x1.21fb78121fb76p-1, -0x1.1f6a8499e5d1ap-2,
- 0x1.41b15e5e29423p-4, 0x1.59bc953163345p-6, -0x1.63b54b13184ddp-5,
- 0x1.c9086666d213p-6, -0x1.90c3b4ad8d4bcp-8, -0x1.80f08ed9f6f57p-8},
- {0x1.819d0b7158a4dp-1, 0x1.107fbbe01107ep-1, -0x1.0feeb4089670ep-2,
- 0x1.50e5afb93f5cbp-4, 0x1.2a7c2adffeffbp-7, -0x1.12bd29b4f1b43p-5,
- 0x1.93f71f0eb00eap-6, -0x1.10ece5ad30e28p-7, -0x1.db1a76bcd2b9cp-10},
- {0x1.921fb54442d18p-1, 0x1.ffffffffffffep-2, -0x1.fffffffffc51cp-3,
- 0x1.555555557002ep-4, -0x1.a88260c338e75p-30, -0x1.99999f9a7614fp-6,
- 0x1.555e31a1e15e9p-6, -0x1.245240d65e629p-7, -0x1.fa9ba66478903p-11},
-};
-
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/inv_trigf_utils.h b/libc/src/math/generic/inv_trigf_utils.h
deleted file mode 100644
index 8b47aba..0000000
--- a/libc/src/math/generic/inv_trigf_utils.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//===-- Single-precision general inverse trigonometric functions ----------===//
-//
-// 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_MATH_GENERIC_INV_TRIGF_UTILS_H
-#define LLVM_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H
-
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-// PI and PI / 2
-static constexpr double M_MATH_PI = 0x1.921fb54442d18p+1;
-static constexpr double M_MATH_PI_2 = 0x1.921fb54442d18p+0;
-
-extern double ATAN_COEFFS[17][9];
-
-// Look-up table for atan(k/16) with k = 0..16.
-static constexpr double ATAN_K_OVER_16[17] = {
- 0.0,
- 0x1.ff55bb72cfdeap-5,
- 0x1.fd5ba9aac2f6ep-4,
- 0x1.7b97b4bce5b02p-3,
- 0x1.f5b75f92c80ddp-3,
- 0x1.362773707ebccp-2,
- 0x1.6f61941e4def1p-2,
- 0x1.a64eec3cc23fdp-2,
- 0x1.dac670561bb4fp-2,
- 0x1.0657e94db30dp-1,
- 0x1.1e00babdefeb4p-1,
- 0x1.345f01cce37bbp-1,
- 0x1.4978fa3269ee1p-1,
- 0x1.5d58987169b18p-1,
- 0x1.700a7c5784634p-1,
- 0x1.819d0b7158a4dp-1,
- 0x1.921fb54442d18p-1,
-};
-
-// For |x| <= 1/32 and 0 <= i <= 16, return Q(x) such that:
-// Q(x) ~ (atan(x + i/16) - atan(i/16)) / x.
-LIBC_INLINE static double atan_eval(double x, unsigned i) {
- double x2 = x * x;
-
- double c0 = fputil::multiply_add(x, ATAN_COEFFS[i][2], ATAN_COEFFS[i][1]);
- double c1 = fputil::multiply_add(x, ATAN_COEFFS[i][4], ATAN_COEFFS[i][3]);
- double c2 = fputil::multiply_add(x, ATAN_COEFFS[i][6], ATAN_COEFFS[i][5]);
- double c3 = fputil::multiply_add(x, ATAN_COEFFS[i][8], ATAN_COEFFS[i][7]);
-
- double x4 = x2 * x2;
- double d1 = fputil::multiply_add(x2, c1, c0);
- double d2 = fputil::multiply_add(x2, c3, c2);
- double p = fputil::multiply_add(x4, d2, d1);
- return p;
-}
-
-// Evaluate atan without big lookup table.
-// atan(n/d) - atan(k/16) = atan((n/d - k/16) / (1 + (n/d) * (k/16)))
-// = atan((n - d * k/16)) / (d + n * k/16))
-// So we let q = (n - d * k/16) / (d + n * k/16),
-// and approximate with Taylor polynomial:
-// atan(q) ~ q - q^3/3 + q^5/5 - q^7/7 + q^9/9
-LIBC_INLINE static double atan_eval_no_table(double num, double den,
- double k_over_16) {
- double num_r = fputil::multiply_add(den, -k_over_16, num);
- double den_r = fputil::multiply_add(num, k_over_16, den);
- double q = num_r / den_r;
-
- constexpr double ATAN_TAYLOR[] = {
- -0x1.5555555555555p-2,
- 0x1.999999999999ap-3,
- -0x1.2492492492492p-3,
- 0x1.c71c71c71c71cp-4,
- };
- double q2 = q * q;
- double q3 = q2 * q;
- double q4 = q2 * q2;
- double c0 = fputil::multiply_add(q2, ATAN_TAYLOR[1], ATAN_TAYLOR[0]);
- double c1 = fputil::multiply_add(q2, ATAN_TAYLOR[3], ATAN_TAYLOR[2]);
- double d = fputil::multiply_add(q4, c1, c0);
- return fputil::multiply_add(q3, d, q);
-}
-
-// > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|],
-// [|1, D...|], [0, 0.5]);
-static constexpr double ASIN_COEFFS[10] = {
- 0x1.5555555540fa1p-3, 0x1.333333512edc2p-4, 0x1.6db6cc1541b31p-5,
- 0x1.f1caff324770ep-6, 0x1.6e43899f5f4f4p-6, 0x1.1f847cf652577p-6,
- 0x1.9b60f47f87146p-7, 0x1.259e2634c494fp-6, -0x1.df946fa875ddp-8,
- 0x1.02311ecf99c28p-5};
-
-// Evaluate P(x^2) - 1, where P(x^2) ~ asin(x)/x
-LIBC_INLINE static double asin_eval(double xsq) {
- double x4 = xsq * xsq;
- double r1 = fputil::polyeval(x4, ASIN_COEFFS[0], ASIN_COEFFS[2],
- ASIN_COEFFS[4], ASIN_COEFFS[6], ASIN_COEFFS[8]);
- double r2 = fputil::polyeval(x4, ASIN_COEFFS[1], ASIN_COEFFS[3],
- ASIN_COEFFS[5], ASIN_COEFFS[7], ASIN_COEFFS[9]);
- return fputil::multiply_add(xsq, r2, r1);
-}
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H
diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp
index 7f61429..16b1b34 100644
--- a/libc/src/math/generic/log1pf.cpp
+++ b/libc/src/math/generic/log1pf.cpp
@@ -37,6 +37,7 @@ namespace internal {
// We don't need to treat denormal and 0
LIBC_INLINE float log(double x) {
+ using namespace acoshf_internal;
constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
using FPBits = typename fputil::FPBits<double>;
diff --git a/libc/src/math/generic/range_reduction_double_common.h b/libc/src/math/generic/range_reduction_double_common.h
index f3dcdb9..a93ee25 100644
--- a/libc/src/math/generic/range_reduction_double_common.h
+++ b/libc/src/math/generic/range_reduction_double_common.h
@@ -278,7 +278,7 @@ private:
};
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static Float128 range_reduction_small_f128(double x) {
+LIBC_INLINE static Float128 range_reduction_small_f128(double x) {
constexpr Float128 PI_OVER_128_F128 = {
Sign::POS, -133, 0xc90f'daa2'2168'c234'c4c6'628b'80dc'1cd1_u128};
constexpr double ONE_TWENTY_EIGHT_OVER_PI_D = 0x1.45f306dc9c883p5;