Skip to content

Commit 7be3b70

Browse files
committed
[libc][math] Refactor asinhf16 implementation to header-only in src/__support/math folder.
1 parent 37e1644 commit 7be3b70

File tree

10 files changed

+201
-107
lines changed

10 files changed

+201
-107
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "math/asinf.h"
2222
#include "math/asinf16.h"
2323
#include "math/asinhf.h"
24+
#include "math/asinhf16.h"
2425
#include "math/erff.h"
2526
#include "math/exp.h"
2627
#include "math/exp10.h"

libc/shared/math/asinf16.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ using math::asinf16;
2525

2626
#endif // LIBC_TYPES_HAS_FLOAT16
2727

28-
#endif // LLVM_LIBC_SHARED_MATH_ASINF_H
28+
#endif // LLVM_LIBC_SHARED_MATH_ASINF16_H

libc/shared/math/asinhf16.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===-- Shared asinhf16 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_ASINHF16_H
10+
#define LLVM_LIBC_SHARED_MATH_ASINHF16_H
11+
12+
#include "shared/libc_common.h"
13+
14+
#ifdef LIBC_TYPES_HAS_FLOAT16
15+
16+
#include "src/__support/math/asinhf16.h"
17+
18+
namespace LIBC_NAMESPACE_DECL {
19+
namespace shared {
20+
21+
using math::asinhf16;
22+
23+
} // namespace shared
24+
} // namespace LIBC_NAMESPACE_DECL
25+
26+
#endif // LIBC_TYPES_HAS_FLOAT16
27+
28+
#endif // LLVM_LIBC_SHARED_MATH_ASINHF16_H

libc/src/__support/math/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,24 @@ add_header_library(
154154
libc.src.__support.macros.optimization
155155
)
156156

157+
add_header_library(
158+
asinhf16
159+
HDRS
160+
asinhf16.h
161+
DEPENDS
162+
.acoshf_utils
163+
libc.src.__support.FPUtil.fenv_impl
164+
libc.src.__support.FPUtil.fp_bits
165+
libc.src.__support.FPUtil.polyeval
166+
libc.src.__support.FPUtil.cast
167+
libc.src.__support.FPUtil.except_value_utils
168+
libc.src.__support.FPUtil.multiply_add
169+
libc.src.__support.FPUtil.rounding_mode
170+
libc.src.__support.FPUtil.sqrt
171+
libc.src.__support.macros.config
172+
libc.src.__support.macros.optimization
173+
)
174+
157175
add_header_library(
158176
asinf
159177
HDRS

libc/src/__support/math/asinhf16.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//===-- Implementation header for asinhf16 ----------------------*- 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_ASINHF16_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF16_H
11+
12+
#include "include/llvm-libc-macros/float16-macros.h"
13+
14+
#ifdef LIBC_TYPES_HAS_FLOAT16
15+
16+
#include "acoshf_utils.h"
17+
#include "src/__support/FPUtil/FEnvImpl.h"
18+
#include "src/__support/FPUtil/FPBits.h"
19+
#include "src/__support/FPUtil/PolyEval.h"
20+
#include "src/__support/FPUtil/cast.h"
21+
#include "src/__support/FPUtil/except_value_utils.h"
22+
#include "src/__support/FPUtil/multiply_add.h"
23+
#include "src/__support/FPUtil/rounding_mode.h"
24+
#include "src/__support/FPUtil/sqrt.h"
25+
#include "src/__support/macros/config.h"
26+
#include "src/__support/macros/optimization.h"
27+
28+
namespace LIBC_NAMESPACE_DECL {
29+
30+
namespace math {
31+
32+
LIBC_INLINE static constexpr float16 asinhf16(float16 x) {
33+
34+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
35+
constexpr size_t N_EXCEPTS = 8;
36+
37+
constexpr fputil::ExceptValues<float16, N_EXCEPTS> ASINHF16_EXCEPTS{{
38+
// (input, RZ output, RU offset, RD offset, RN offset)
39+
40+
// x = 0x1.da4p-2, asinhf16(x) = 0x1.ca8p-2 (RZ)
41+
{0x3769, 0x372a, 1, 0, 1},
42+
// x = 0x1.d6cp-1, asinhf16(x) = 0x1.a58p-1 (RZ)
43+
{0x3b5b, 0x3a96, 1, 0, 0},
44+
// x = 0x1.c7cp+3, asinhf16(x) = 0x1.accp+1 (RZ)
45+
{0x4b1f, 0x42b3, 1, 0, 0},
46+
// x = 0x1.26cp+4, asinhf16(x) = 0x1.cd8p+1 (RZ)
47+
{0x4c9b, 0x4336, 1, 0, 1},
48+
// x = -0x1.da4p-2, asinhf16(x) = -0x1.ca8p-2 (RZ)
49+
{0xb769, 0xb72a, 0, 1, 1},
50+
// x = -0x1.d6cp-1, asinhf16(x) = -0x1.a58p-1 (RZ)
51+
{0xbb5b, 0xba96, 0, 1, 0},
52+
// x = -0x1.c7cp+3, asinhf16(x) = -0x1.accp+1 (RZ)
53+
{0xcb1f, 0xc2b3, 0, 1, 0},
54+
// x = -0x1.26cp+4, asinhf16(x) = -0x1.cd8p+1 (RZ)
55+
{0xcc9b, 0xc336, 0, 1, 1},
56+
}};
57+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
58+
59+
using namespace acoshf_internal;
60+
using FPBits = fputil::FPBits<float16>;
61+
FPBits xbits(x);
62+
63+
uint16_t x_u = xbits.uintval();
64+
uint16_t x_abs = x_u & 0x7fff;
65+
66+
if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
67+
if (xbits.is_signaling_nan()) {
68+
fputil::raise_except_if_required(FE_INVALID);
69+
return FPBits::quiet_nan().get_val();
70+
}
71+
72+
return x;
73+
}
74+
75+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
76+
// Handle exceptional values
77+
if (auto r = ASINHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
78+
return r.value();
79+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
80+
81+
float xf = x;
82+
const float SIGN[2] = {1.0f, -1.0f};
83+
float x_sign = SIGN[x_u >> 15];
84+
85+
// |x| <= 0.25
86+
if (LIBC_UNLIKELY(x_abs <= 0x3400)) {
87+
// when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
88+
// rounding types.
89+
if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
90+
int rounding = fputil::quick_get_round();
91+
if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
92+
return fputil::cast<float16>(xf + 0x1p-24f);
93+
if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
94+
return fputil::cast<float16>(xf - 0x1p-24f);
95+
return fputil::cast<float16>(xf);
96+
}
97+
98+
float x_sq = xf * xf;
99+
// Generated by Sollya with:
100+
// > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 2^-2]);
101+
// The last coefficient 0x1.bd114ep-6f has been changed to 0x1.bd114ep-5f
102+
// for better accuracy.
103+
float p = fputil::polyeval(x_sq, 1.0f, -0x1.555552p-3f, 0x1.332f6ap-4f,
104+
-0x1.6c53dep-5f, 0x1.bd114ep-5f);
105+
106+
return fputil::cast<float16>(xf * p);
107+
}
108+
109+
// General case: asinh(x) = ln(x + sqrt(x^2 + 1))
110+
float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, 1.0f));
111+
return fputil::cast<float16>(
112+
x_sign * log_eval(fputil::multiply_add(xf, x_sign, sqrt_term)));
113+
114+
115+
}
116+
117+
} // namespace math
118+
119+
} // namespace LIBC_NAMESPACE_DECL
120+
121+
#endif // LIBC_TYPES_HAS_FLOAT16
122+
123+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF16_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3899,18 +3899,7 @@ add_entrypoint_object(
38993899
HDRS
39003900
../asinhf16.h
39013901
DEPENDS
3902-
.explogxf
3903-
libc.hdr.fenv_macros
3904-
libc.src.__support.FPUtil.cast
3905-
libc.src.__support.FPUtil.except_value_utils
3906-
libc.src.__support.FPUtil.fenv_impl
3907-
libc.src.__support.FPUtil.fp_bits
3908-
libc.src.__support.FPUtil.multiply_add
3909-
libc.src.__support.FPUtil.polyeval
3910-
libc.src.__support.FPUtil.rounding_mode
3911-
libc.src.__support.FPUtil.sqrt
3912-
libc.src.__support.macros.optimization
3913-
libc.src.__support.macros.properties.types
3902+
libc.src.__support.math.asinhf16
39143903
)
39153904

39163905
add_entrypoint_object(

libc/src/math/generic/asinhf16.cpp

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

99
#include "src/math/asinhf16.h"
10-
#include "explogxf.h"
11-
#include "hdr/fenv_macros.h"
12-
#include "src/__support/FPUtil/FEnvImpl.h"
13-
#include "src/__support/FPUtil/FPBits.h"
14-
#include "src/__support/FPUtil/PolyEval.h"
15-
#include "src/__support/FPUtil/cast.h"
16-
#include "src/__support/FPUtil/except_value_utils.h"
17-
#include "src/__support/FPUtil/multiply_add.h"
18-
#include "src/__support/FPUtil/rounding_mode.h"
19-
#include "src/__support/FPUtil/sqrt.h"
20-
#include "src/__support/common.h"
21-
#include "src/__support/macros/config.h"
22-
#include "src/__support/macros/optimization.h"
10+
#include "src/__support/math/asinhf16.h"
2311

2412
namespace LIBC_NAMESPACE_DECL {
2513

26-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
27-
static constexpr size_t N_EXCEPTS = 8;
28-
29-
static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ASINHF16_EXCEPTS{{
30-
// (input, RZ output, RU offset, RD offset, RN offset)
31-
32-
// x = 0x1.da4p-2, asinhf16(x) = 0x1.ca8p-2 (RZ)
33-
{0x3769, 0x372a, 1, 0, 1},
34-
// x = 0x1.d6cp-1, asinhf16(x) = 0x1.a58p-1 (RZ)
35-
{0x3b5b, 0x3a96, 1, 0, 0},
36-
// x = 0x1.c7cp+3, asinhf16(x) = 0x1.accp+1 (RZ)
37-
{0x4b1f, 0x42b3, 1, 0, 0},
38-
// x = 0x1.26cp+4, asinhf16(x) = 0x1.cd8p+1 (RZ)
39-
{0x4c9b, 0x4336, 1, 0, 1},
40-
// x = -0x1.da4p-2, asinhf16(x) = -0x1.ca8p-2 (RZ)
41-
{0xb769, 0xb72a, 0, 1, 1},
42-
// x = -0x1.d6cp-1, asinhf16(x) = -0x1.a58p-1 (RZ)
43-
{0xbb5b, 0xba96, 0, 1, 0},
44-
// x = -0x1.c7cp+3, asinhf16(x) = -0x1.accp+1 (RZ)
45-
{0xcb1f, 0xc2b3, 0, 1, 0},
46-
// x = -0x1.26cp+4, asinhf16(x) = -0x1.cd8p+1 (RZ)
47-
{0xcc9b, 0xc336, 0, 1, 1},
48-
}};
49-
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
50-
51-
LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) {
52-
using namespace acoshf_internal;
53-
using FPBits = fputil::FPBits<float16>;
54-
FPBits xbits(x);
55-
56-
uint16_t x_u = xbits.uintval();
57-
uint16_t x_abs = x_u & 0x7fff;
58-
59-
if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
60-
if (xbits.is_signaling_nan()) {
61-
fputil::raise_except_if_required(FE_INVALID);
62-
return FPBits::quiet_nan().get_val();
63-
}
64-
65-
return x;
66-
}
67-
68-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
69-
// Handle exceptional values
70-
if (auto r = ASINHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
71-
return r.value();
72-
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
73-
74-
float xf = x;
75-
const float SIGN[2] = {1.0f, -1.0f};
76-
float x_sign = SIGN[x_u >> 15];
77-
78-
// |x| <= 0.25
79-
if (LIBC_UNLIKELY(x_abs <= 0x3400)) {
80-
// when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
81-
// rounding types.
82-
if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
83-
int rounding = fputil::quick_get_round();
84-
if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
85-
return fputil::cast<float16>(xf + 0x1p-24f);
86-
if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
87-
return fputil::cast<float16>(xf - 0x1p-24f);
88-
return fputil::cast<float16>(xf);
89-
}
90-
91-
float x_sq = xf * xf;
92-
// Generated by Sollya with:
93-
// > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 2^-2]);
94-
// The last coefficient 0x1.bd114ep-6f has been changed to 0x1.bd114ep-5f
95-
// for better accuracy.
96-
float p = fputil::polyeval(x_sq, 1.0f, -0x1.555552p-3f, 0x1.332f6ap-4f,
97-
-0x1.6c53dep-5f, 0x1.bd114ep-5f);
98-
99-
return fputil::cast<float16>(xf * p);
100-
}
101-
102-
// General case: asinh(x) = ln(x + sqrt(x^2 + 1))
103-
float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, 1.0f));
104-
return fputil::cast<float16>(
105-
x_sign * log_eval(fputil::multiply_add(xf, x_sign, sqrt_term)));
106-
}
14+
LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) { return math::asinhf16(x); }
10715

10816
} // namespace LIBC_NAMESPACE_DECL

libc/test/shared/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_fp_unittest(
1717
libc.src.__support.math.asinf
1818
libc.src.__support.math.asinf16
1919
libc.src.__support.math.asinhf
20+
libc.src.__support.math.asinhf16
2021
libc.src.__support.math.erff
2122
libc.src.__support.math.exp
2223
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
@@ -18,6 +18,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
1818
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::acoshf16(1.0f16));
1919
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::acospif16(1.0f16));
2020
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinf16(0.0f16));
21+
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinhf16(0.0f16));
2122

2223
EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16));
2324

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,6 +2245,24 @@ libc_support_library(
22452245
],
22462246
)
22472247

2248+
libc_support_library(
2249+
name = "__support_math_asinhf16",
2250+
hdrs = ["src/__support/math/asinhf16.h"],
2251+
deps = [
2252+
":__support_math_acoshf_utils",
2253+
":__support_fputil_fenv_impl",
2254+
":__support_fputil_fp_bits",
2255+
":__support_fputil_polyeval",
2256+
":__support_fputil_cast",
2257+
":__support_fputil_except_value_utils",
2258+
":__support_fputil_multiply_add",
2259+
":__support_fputil_rounding_mode",
2260+
":__support_fputil_sqrt",
2261+
":__support_macros_config",
2262+
":__support_macros_optimization",
2263+
],
2264+
)
2265+
22482266
libc_support_library(
22492267
name = "__support_math_asinf",
22502268
hdrs = ["src/__support/math/asinf.h"],
@@ -2847,6 +2865,13 @@ libc_math_function(
28472865
],
28482866
)
28492867

2868+
libc_math_function(
2869+
name = "asinhf16",
2870+
additional_deps = [
2871+
":__support_math_asinhf16",
2872+
],
2873+
)
2874+
28502875
libc_math_function(
28512876
name = "atanf",
28522877
additional_deps = [

0 commit comments

Comments
 (0)