Skip to content

Commit b06c93e

Browse files
committed
[libc][math] Refactor asinhf implementation to header-only in src/__support/math folder.
1 parent 83cb8b7 commit b06c93e

File tree

9 files changed

+183
-118
lines changed

9 files changed

+183
-118
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "math/asin.h"
2121
#include "math/asinf.h"
2222
#include "math/asinf16.h"
23+
#include "math/asinhf.h"
2324
#include "math/erff.h"
2425
#include "math/exp.h"
2526
#include "math/exp10.h"

libc/shared/math/asinhf.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Shared asinhf function ----------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SHARED_MATH_ASINHF_H
10+
#define LLVM_LIBC_SHARED_MATH_ASINHF_H
11+
12+
#include "shared/libc_common.h"
13+
#include "src/__support/math/asinhf.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
namespace shared {
17+
18+
using math::asinhf;
19+
20+
} // namespace shared
21+
} // namespace LIBC_NAMESPACE_DECL
22+
23+
#endif // LLVM_LIBC_SHARED_MATH_ASINHF_H

libc/src/__support/math/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,20 @@ add_header_library(
140140
libc.src.__support.macros.properties.cpu_features
141141
)
142142

143+
add_header_library(
144+
asinhf
145+
HDRS
146+
asinhf.h
147+
DEPENDS
148+
.acoshf_utils
149+
libc.src.__support.FPUtil.fp_bits
150+
libc.src.__support.FPUtil.polyeval
151+
libc.src.__support.FPUtil.multiply_add
152+
libc.src.__support.FPUtil.sqrt
153+
libc.src.__support.macros.config
154+
libc.src.__support.macros.optimization
155+
)
156+
143157
add_header_library(
144158
asinf
145159
HDRS

libc/src/__support/math/asinhf.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//===-- Implementation header for asinf -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF_H
11+
12+
#include "acoshf_utils.h"
13+
#include "src/__support/FPUtil/FPBits.h"
14+
#include "src/__support/FPUtil/PolyEval.h"
15+
#include "src/__support/FPUtil/multiply_add.h"
16+
#include "src/__support/FPUtil/sqrt.h"
17+
#include "src/__support/macros/config.h"
18+
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
22+
namespace math {
23+
24+
LIBC_INLINE static constexpr float asinhf(float x) {
25+
using namespace acoshf_internal;
26+
using FPBits_t = typename fputil::FPBits<float>;
27+
FPBits_t xbits(x);
28+
uint32_t x_u = xbits.uintval();
29+
uint32_t x_abs = xbits.abs().uintval();
30+
31+
// |x| <= 2^-3
32+
if (LIBC_UNLIKELY(x_abs <= 0x3e80'0000U)) {
33+
// |x| <= 2^-26
34+
if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
35+
return static_cast<float>(LIBC_UNLIKELY(x_abs == 0)
36+
? x
37+
: (x - 0x1.5555555555555p-3 * x * x * x));
38+
}
39+
40+
double x_d = x;
41+
double x_sq = x_d * x_d;
42+
// Generated by Sollya with:
43+
// > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16|], [|D...|],
44+
// [0, 2^-2]);
45+
double p = fputil::polyeval(
46+
x_sq, 0.0, -0x1.555555555551ep-3, 0x1.3333333325495p-4,
47+
-0x1.6db6db5a7622bp-5, 0x1.f1c70f82928c6p-6, -0x1.6e893934266b7p-6,
48+
0x1.1c0b41d3fbe78p-6, -0x1.c0f47810b3c4fp-7, 0x1.2c8602690143dp-7);
49+
return static_cast<float>(fputil::multiply_add(x_d, p, x_d));
50+
}
51+
52+
const double SIGN[2] = {1.0, -1.0};
53+
double x_sign = SIGN[x_u >> 31];
54+
double x_d = x;
55+
56+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
57+
// Helper functions to set results for exceptional cases.
58+
auto round_result_slightly_down = [x_sign](float r) -> float {
59+
return fputil::multiply_add(static_cast<float>(x_sign), r,
60+
static_cast<float>(x_sign) * (-0x1.0p-24f));
61+
};
62+
auto round_result_slightly_up = [x_sign](float r) -> float {
63+
return fputil::multiply_add(static_cast<float>(x_sign), r,
64+
static_cast<float>(x_sign) * 0x1.0p-24f);
65+
};
66+
67+
if (LIBC_UNLIKELY(x_abs >= 0x4bdd'65a5U)) {
68+
if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
69+
if (xbits.is_signaling_nan()) {
70+
fputil::raise_except_if_required(FE_INVALID);
71+
return FPBits_t::quiet_nan().get_val();
72+
}
73+
74+
return x;
75+
}
76+
77+
// Exceptional cases when x > 2^24.
78+
switch (x_abs) {
79+
case 0x4bdd65a5: // |x| = 0x1.bacb4ap24f
80+
return round_result_slightly_down(0x1.1e0696p4f);
81+
case 0x4c803f2c: // |x| = 0x1.007e58p26f
82+
return round_result_slightly_down(0x1.2b786cp4f);
83+
case 0x4f8ffb03: // |x| = 0x1.1ff606p32f
84+
return round_result_slightly_up(0x1.6fdd34p4f);
85+
case 0x5c569e88: // |x| = 0x1.ad3d1p57f
86+
return round_result_slightly_up(0x1.45c146p5f);
87+
case 0x5e68984e: // |x| = 0x1.d1309cp61f
88+
return round_result_slightly_up(0x1.5c9442p5f);
89+
case 0x655890d3: // |x| = 0x1.b121a6p75f
90+
return round_result_slightly_down(0x1.a9a3f2p5f);
91+
case 0x65de7ca6: // |x| = 0x1.bcf94cp76f
92+
return round_result_slightly_up(0x1.af66cp5f);
93+
case 0x6eb1a8ec: // |x| = 0x1.6351d8p94f
94+
return round_result_slightly_down(0x1.08b512p6f);
95+
case 0x7997f30a: // |x| = 0x1.2fe614p116f
96+
return round_result_slightly_up(0x1.451436p6f);
97+
}
98+
} else {
99+
// Exceptional cases when x < 2^24.
100+
if (LIBC_UNLIKELY(x_abs == 0x45abaf26)) {
101+
// |x| = 0x1.575e4cp12f
102+
return round_result_slightly_down(0x1.29becap3f);
103+
}
104+
if (LIBC_UNLIKELY(x_abs == 0x49d29048)) {
105+
// |x| = 0x1.a5209p20f
106+
return round_result_slightly_down(0x1.e1b92p3f);
107+
}
108+
}
109+
#else
110+
if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
111+
return x;
112+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
113+
114+
// asinh(x) = log(x + sqrt(x^2 + 1))
115+
return static_cast<float>(
116+
x_sign * log_eval(fputil::multiply_add(
117+
x_d, x_sign,
118+
fputil::sqrt<double>(fputil::multiply_add(x_d, x_d, 1.0)))));
119+
}
120+
121+
} // namespace math
122+
123+
} // namespace LIBC_NAMESPACE_DECL
124+
125+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,12 +3889,7 @@ add_entrypoint_object(
38893889
HDRS
38903890
../asinhf.h
38913891
DEPENDS
3892-
.explogxf
3893-
libc.src.__support.FPUtil.fp_bits
3894-
libc.src.__support.FPUtil.multiply_add
3895-
libc.src.__support.FPUtil.polyeval
3896-
libc.src.__support.FPUtil.sqrt
3897-
libc.src.__support.macros.optimization
3892+
libc.src.__support.math.asinhf
38983893
)
38993894

39003895
add_entrypoint_object(

libc/src/math/generic/asinhf.cpp

Lines changed: 2 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -7,112 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/math/asinhf.h"
10-
#include "src/__support/FPUtil/FPBits.h"
11-
#include "src/__support/FPUtil/PolyEval.h"
12-
#include "src/__support/FPUtil/multiply_add.h"
13-
#include "src/__support/FPUtil/sqrt.h"
14-
#include "src/__support/macros/config.h"
15-
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
16-
#include "src/math/generic/common_constants.h"
17-
#include "src/math/generic/explogxf.h"
10+
#include "src/__support/math/asinhf.h"
1811

1912
namespace LIBC_NAMESPACE_DECL {
2013

21-
LLVM_LIBC_FUNCTION(float, asinhf, (float x)) {
22-
using namespace acoshf_internal;
23-
using FPBits_t = typename fputil::FPBits<float>;
24-
FPBits_t xbits(x);
25-
uint32_t x_u = xbits.uintval();
26-
uint32_t x_abs = xbits.abs().uintval();
27-
28-
// |x| <= 2^-3
29-
if (LIBC_UNLIKELY(x_abs <= 0x3e80'0000U)) {
30-
// |x| <= 2^-26
31-
if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
32-
return static_cast<float>(LIBC_UNLIKELY(x_abs == 0)
33-
? x
34-
: (x - 0x1.5555555555555p-3 * x * x * x));
35-
}
36-
37-
double x_d = x;
38-
double x_sq = x_d * x_d;
39-
// Generated by Sollya with:
40-
// > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16|], [|D...|],
41-
// [0, 2^-2]);
42-
double p = fputil::polyeval(
43-
x_sq, 0.0, -0x1.555555555551ep-3, 0x1.3333333325495p-4,
44-
-0x1.6db6db5a7622bp-5, 0x1.f1c70f82928c6p-6, -0x1.6e893934266b7p-6,
45-
0x1.1c0b41d3fbe78p-6, -0x1.c0f47810b3c4fp-7, 0x1.2c8602690143dp-7);
46-
return static_cast<float>(fputil::multiply_add(x_d, p, x_d));
47-
}
48-
49-
const double SIGN[2] = {1.0, -1.0};
50-
double x_sign = SIGN[x_u >> 31];
51-
double x_d = x;
52-
53-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
54-
// Helper functions to set results for exceptional cases.
55-
auto round_result_slightly_down = [x_sign](float r) -> float {
56-
return fputil::multiply_add(static_cast<float>(x_sign), r,
57-
static_cast<float>(x_sign) * (-0x1.0p-24f));
58-
};
59-
auto round_result_slightly_up = [x_sign](float r) -> float {
60-
return fputil::multiply_add(static_cast<float>(x_sign), r,
61-
static_cast<float>(x_sign) * 0x1.0p-24f);
62-
};
63-
64-
if (LIBC_UNLIKELY(x_abs >= 0x4bdd'65a5U)) {
65-
if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
66-
if (xbits.is_signaling_nan()) {
67-
fputil::raise_except_if_required(FE_INVALID);
68-
return FPBits_t::quiet_nan().get_val();
69-
}
70-
71-
return x;
72-
}
73-
74-
// Exceptional cases when x > 2^24.
75-
switch (x_abs) {
76-
case 0x4bdd65a5: // |x| = 0x1.bacb4ap24f
77-
return round_result_slightly_down(0x1.1e0696p4f);
78-
case 0x4c803f2c: // |x| = 0x1.007e58p26f
79-
return round_result_slightly_down(0x1.2b786cp4f);
80-
case 0x4f8ffb03: // |x| = 0x1.1ff606p32f
81-
return round_result_slightly_up(0x1.6fdd34p4f);
82-
case 0x5c569e88: // |x| = 0x1.ad3d1p57f
83-
return round_result_slightly_up(0x1.45c146p5f);
84-
case 0x5e68984e: // |x| = 0x1.d1309cp61f
85-
return round_result_slightly_up(0x1.5c9442p5f);
86-
case 0x655890d3: // |x| = 0x1.b121a6p75f
87-
return round_result_slightly_down(0x1.a9a3f2p5f);
88-
case 0x65de7ca6: // |x| = 0x1.bcf94cp76f
89-
return round_result_slightly_up(0x1.af66cp5f);
90-
case 0x6eb1a8ec: // |x| = 0x1.6351d8p94f
91-
return round_result_slightly_down(0x1.08b512p6f);
92-
case 0x7997f30a: // |x| = 0x1.2fe614p116f
93-
return round_result_slightly_up(0x1.451436p6f);
94-
}
95-
} else {
96-
// Exceptional cases when x < 2^24.
97-
if (LIBC_UNLIKELY(x_abs == 0x45abaf26)) {
98-
// |x| = 0x1.575e4cp12f
99-
return round_result_slightly_down(0x1.29becap3f);
100-
}
101-
if (LIBC_UNLIKELY(x_abs == 0x49d29048)) {
102-
// |x| = 0x1.a5209p20f
103-
return round_result_slightly_down(0x1.e1b92p3f);
104-
}
105-
}
106-
#else
107-
if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
108-
return x;
109-
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
110-
111-
// asinh(x) = log(x + sqrt(x^2 + 1))
112-
return static_cast<float>(
113-
x_sign * log_eval(fputil::multiply_add(
114-
x_d, x_sign,
115-
fputil::sqrt<double>(fputil::multiply_add(x_d, x_d, 1.0)))));
116-
}
14+
LLVM_LIBC_FUNCTION(float, asinhf, (float x)) { return math::asinhf(x); }
11715

11816
} // namespace LIBC_NAMESPACE_DECL

libc/test/shared/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_fp_unittest(
1616
libc.src.__support.math.asin
1717
libc.src.__support.math.asinf
1818
libc.src.__support.math.asinf16
19+
libc.src.__support.math.asinhf
1920
libc.src.__support.math.erff
2021
libc.src.__support.math.exp
2122
libc.src.__support.math.exp10

libc/test/shared/shared_math_test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
4242
EXPECT_FP_EQ(0x1.921fb6p+0, LIBC_NAMESPACE::shared::acosf(0.0f));
4343
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acoshf(1.0f));
4444
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinf(0.0f));
45+
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinhf(0.0f));
4546
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::erff(0.0f));
4647
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::exp10f(0.0f));
4748
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::expf(0.0f));

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,6 +2231,20 @@ libc_support_library(
22312231
],
22322232
)
22332233

2234+
libc_support_library(
2235+
name = "__support_math_asinhf",
2236+
hdrs = ["src/__support/math/asinhf.h"],
2237+
deps = [
2238+
":__support_math_acoshf_utils",
2239+
":__support_fputil_fp_bits",
2240+
":__support_fputil_polyeval",
2241+
":__support_fputil_multiply_add",
2242+
":__support_fputil_sqrt",
2243+
":__support_macros_config",
2244+
":__support_macros_optimization",
2245+
],
2246+
)
2247+
22342248
libc_support_library(
22352249
name = "__support_math_asinf",
22362250
hdrs = ["src/__support/math/asinf.h"],
@@ -2829,14 +2843,7 @@ libc_math_function(
28292843
libc_math_function(
28302844
name = "asinhf",
28312845
additional_deps = [
2832-
":__support_fputil_fma",
2833-
":__support_fputil_multiply_add",
2834-
":__support_fputil_nearest_integer",
2835-
":__support_fputil_polyeval",
2836-
":__support_fputil_sqrt",
2837-
":__support_macros_optimization",
2838-
":common_constants",
2839-
":explogxf",
2846+
":__support_math_asinhf",
28402847
],
28412848
)
28422849

0 commit comments

Comments
 (0)