Skip to content

Commit abcf3bc

Browse files
committed
[libc][math] Refactor coshf16 implementation to header-only in src/__support/math folder.
1 parent 9ddc85f commit abcf3bc

File tree

18 files changed

+261
-164
lines changed

18 files changed

+261
-164
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "math/cosf.h"
3737
#include "math/cosf16.h"
3838
#include "math/coshf.h"
39+
#include "math/coshf16.h"
3940
#include "math/erff.h"
4041
#include "math/exp.h"
4142
#include "math/exp10.h"

libc/shared/math/coshf16.h

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

libc/src/__support/math/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,19 @@ add_header_library(
419419
libc.src.__support.macros.optimization
420420
)
421421

422+
add_header_library(
423+
coshf16
424+
HDRS
425+
coshf16.h
426+
DEPENDS
427+
.expxf16_utils
428+
libc.src.__support.FPUtil.except_value_utils
429+
libc.src.__support.FPUtil.fenv_impl
430+
libc.src.__support.FPUtil.fp_bits
431+
libc.src.__support.FPUtil.rounding_mode
432+
libc.src.__support.macros.optimization
433+
)
434+
422435
add_header_library(
423436
erff
424437
HDRS
@@ -489,6 +502,21 @@ add_header_library(
489502
libc.include.llvm-libc-macros.float16_macros
490503
)
491504

505+
add_header_library(
506+
expxf16_utils
507+
HDRS
508+
expxf16_utils.h
509+
DEPENDS
510+
libc.hdr.stdint_proxy
511+
libc.src.__support.FPUtil.fp_bits
512+
libc.src.__support.FPUtil.cast
513+
libc.src.__support.FPUtil.multiply_add
514+
libc.src.__support.FPUtil.nearest_integer
515+
libc.src.__support.macros.attributes
516+
libc.src.__support.math.expf16_utils
517+
libc.src.__support.math.exp10_float16_constants
518+
)
519+
492520
add_header_library(
493521
frexpf128
494522
HDRS

libc/src/__support/math/coshf16.h

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
//===-- Implementation header for coshf16 -----------------------*- 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_COSHF16_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_COSHF16_H
11+
12+
#include "include/llvm-libc-macros/float16-macros.h"
13+
14+
#ifdef LIBC_TYPES_HAS_FLOAT16
15+
16+
#include "expxf16_utils.h"
17+
#include "src/__support/FPUtil/FEnvImpl.h"
18+
#include "src/__support/FPUtil/FPBits.h"
19+
#include "src/__support/FPUtil/except_value_utils.h"
20+
#include "src/__support/FPUtil/rounding_mode.h"
21+
#include "src/__support/macros/config.h"
22+
#include "src/__support/macros/optimization.h"
23+
24+
namespace LIBC_NAMESPACE_DECL {
25+
26+
namespace math {
27+
28+
LIBC_INLINE static constexpr float16 coshf16(float16 x) {
29+
30+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
31+
constexpr fputil::ExceptValues<float16, 9> COSHF16_EXCEPTS_POS = {{
32+
// x = 0x1.6ap-5, coshf16(x) = 0x1p+0 (RZ)
33+
{0x29a8U, 0x3c00U, 1U, 0U, 1U},
34+
// x = 0x1.8c4p+0, coshf16(x) = 0x1.3a8p+1 (RZ)
35+
{0x3e31U, 0x40eaU, 1U, 0U, 0U},
36+
// x = 0x1.994p+0, coshf16(x) = 0x1.498p+1 (RZ)
37+
{0x3e65U, 0x4126U, 1U, 0U, 0U},
38+
// x = 0x1.b6p+0, coshf16(x) = 0x1.6d8p+1 (RZ)
39+
{0x3ed8U, 0x41b6U, 1U, 0U, 1U},
40+
// x = 0x1.aap+1, coshf16(x) = 0x1.be8p+3 (RZ)
41+
{0x42a8U, 0x4afaU, 1U, 0U, 1U},
42+
// x = 0x1.cc4p+1, coshf16(x) = 0x1.23cp+4 (RZ)
43+
{0x4331U, 0x4c8fU, 1U, 0U, 0U},
44+
// x = 0x1.288p+2, coshf16(x) = 0x1.9b4p+5 (RZ)
45+
{0x44a2U, 0x526dU, 1U, 0U, 0U},
46+
// x = 0x1.958p+2, coshf16(x) = 0x1.1a4p+8 (RZ)
47+
{0x4656U, 0x5c69U, 1U, 0U, 0U},
48+
// x = 0x1.5fp+3, coshf16(x) = 0x1.c54p+14 (RZ)
49+
{0x497cU, 0x7715U, 1U, 0U, 1U},
50+
}};
51+
52+
constexpr fputil::ExceptValues<float16, 6> COSHF16_EXCEPTS_NEG = {{
53+
// x = -0x1.6ap-5, coshf16(x) = 0x1p+0 (RZ)
54+
{0xa9a8U, 0x3c00U, 1U, 0U, 1U},
55+
// x = -0x1.b6p+0, coshf16(x) = 0x1.6d8p+1 (RZ)
56+
{0xbed8U, 0x41b6U, 1U, 0U, 1U},
57+
// x = -0x1.288p+2, coshf16(x) = 0x1.9b4p+5 (RZ)
58+
{0xc4a2U, 0x526dU, 1U, 0U, 0U},
59+
// x = -0x1.5fp+3, coshf16(x) = 0x1.c54p+14 (RZ)
60+
{0xc97cU, 0x7715U, 1U, 0U, 1U},
61+
// x = -0x1.8c4p+0, coshf16(x) = 0x1.3a8p+1 (RZ)
62+
{0xbe31U, 0x40eaU, 1U, 0U, 0U},
63+
// x = -0x1.994p+0, coshf16(x) = 0x1.498p+1 (RZ)
64+
{0xbe65U, 0x4126U, 1U, 0U, 0U},
65+
}};
66+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
67+
68+
using namespace expxf16_internal;
69+
using FPBits = fputil::FPBits<float16>;
70+
FPBits x_bits(x);
71+
72+
uint16_t x_u = x_bits.uintval();
73+
uint16_t x_abs = x_u & 0x7fffU;
74+
75+
// When |x| >= acosh(2^16), or x is NaN.
76+
if (LIBC_UNLIKELY(x_abs >= 0x49e5U)) {
77+
// cosh(NaN) = NaN
78+
if (x_bits.is_nan()) {
79+
if (x_bits.is_signaling_nan()) {
80+
fputil::raise_except_if_required(FE_INVALID);
81+
return FPBits::quiet_nan().get_val();
82+
}
83+
84+
return x;
85+
}
86+
87+
// When |x| >= acosh(2^16).
88+
if (x_abs >= 0x49e5U) {
89+
// cosh(+/-inf) = +inf
90+
if (x_bits.is_inf())
91+
return FPBits::inf().get_val();
92+
93+
switch (fputil::quick_get_round()) {
94+
case FE_TONEAREST:
95+
case FE_UPWARD:
96+
fputil::set_errno_if_required(ERANGE);
97+
fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
98+
return FPBits::inf().get_val();
99+
default:
100+
return FPBits::max_normal().get_val();
101+
}
102+
}
103+
}
104+
105+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
106+
if (x_bits.is_pos()) {
107+
if (auto r = COSHF16_EXCEPTS_POS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
108+
return r.value();
109+
} else {
110+
if (auto r = COSHF16_EXCEPTS_NEG.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
111+
return r.value();
112+
}
113+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
114+
115+
return eval_sinh_or_cosh</*IsSinh=*/false>(x);
116+
}
117+
118+
} // namespace math
119+
120+
} // namespace LIBC_NAMESPACE_DECL
121+
122+
#endif // LIBC_TYPES_HAS_FLOAT16
123+
124+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSHF16_H

libc/src/math/generic/expxf16.h renamed to libc/src/__support/math/expxf16_utils.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121

2222
namespace LIBC_NAMESPACE_DECL {
2323

24-
LIBC_INLINE ExpRangeReduction exp2_range_reduction(float16 x) {
24+
namespace math {
25+
26+
namespace expxf16_internal {
27+
28+
LIBC_INLINE static constexpr ExpRangeReduction exp2_range_reduction(float16 x) {
2529
// For -25 < x < 16, to compute 2^x, we perform the following range reduction:
2630
// find hi, mid, lo, such that:
2731
// x = hi + mid + lo, in which
@@ -117,7 +121,8 @@ static constexpr cpp::array<uint32_t, 32> EXP2_MID_5_BITS = {
117121
// The main point of these formulas is that the expensive part of calculating
118122
// the polynomials approximating lower parts of e^x and e^(-x) is shared and
119123
// only done once.
120-
template <bool IsSinh> LIBC_INLINE float16 eval_sinh_or_cosh(float16 x) {
124+
template <bool IsSinh>
125+
LIBC_INLINE static constexpr float16 eval_sinh_or_cosh(float16 x) {
121126
float xf = x;
122127
float kf = fputil::nearest_integer(xf * (LOG2F_E * 0x1.0p+5f));
123128
int x_hi_mid_p = static_cast<int>(kf);
@@ -174,7 +179,7 @@ template <bool IsSinh> LIBC_INLINE float16 eval_sinh_or_cosh(float16 x) {
174179
// Generated by Sollya with the following commands:
175180
// > display = hexadecimal;
176181
// > for i from 0 to 31 do print(round(log(1 + i * 2^-5), SG, RN));
177-
constexpr cpp::array<float, 32> LOGF_F = {
182+
static constexpr cpp::array<float, 32> LOGF_F = {
178183
0x0p+0f, 0x1.f829bp-6f, 0x1.f0a30cp-5f, 0x1.6f0d28p-4f,
179184
0x1.e27076p-4f, 0x1.29553p-3f, 0x1.5ff308p-3f, 0x1.9525aap-3f,
180185
0x1.c8ff7cp-3f, 0x1.fb9186p-3f, 0x1.1675cap-2f, 0x1.2e8e2cp-2f,
@@ -188,7 +193,7 @@ constexpr cpp::array<float, 32> LOGF_F = {
188193
// Generated by Sollya with the following commands:
189194
// > display = hexadecimal;
190195
// > for i from 0 to 31 do print(round(log2(1 + i * 2^-5), SG, RN));
191-
constexpr cpp::array<float, 32> LOG2F_F = {
196+
static constexpr cpp::array<float, 32> LOG2F_F = {
192197
0x0p+0f, 0x1.6bad38p-5f, 0x1.663f7p-4f, 0x1.08c588p-3f,
193198
0x1.5c01a4p-3f, 0x1.acf5e2p-3f, 0x1.fbc16cp-3f, 0x1.24407ap-2f,
194199
0x1.49a784p-2f, 0x1.6e221cp-2f, 0x1.91bba8p-2f, 0x1.b47ecp-2f,
@@ -202,7 +207,7 @@ constexpr cpp::array<float, 32> LOG2F_F = {
202207
// Generated by Sollya with the following commands:
203208
// > display = hexadecimal;
204209
// > for i from 0 to 31 do print(round(log10(1 + i * 2^-5), SG, RN));
205-
constexpr cpp::array<float, 32> LOG10F_F = {
210+
static constexpr cpp::array<float, 32> LOG10F_F = {
206211
0x0p+0f, 0x1.b5e908p-7f, 0x1.af5f92p-6f, 0x1.3ed11ap-5f,
207212
0x1.a30a9ep-5f, 0x1.02428cp-4f, 0x1.31b306p-4f, 0x1.5fe804p-4f,
208213
0x1.8cf184p-4f, 0x1.b8de4ep-4f, 0x1.e3bc1ap-4f, 0x1.06cbd6p-3f,
@@ -216,7 +221,7 @@ constexpr cpp::array<float, 32> LOG10F_F = {
216221
// Generated by Sollya with the following commands:
217222
// > display = hexadecimal;
218223
// > for i from 0 to 31 do print(round(1 / (1 + i * 2^-5), SG, RN));
219-
constexpr cpp::array<float, 32> ONE_OVER_F_F = {
224+
static constexpr cpp::array<float, 32> ONE_OVER_F_F = {
220225
0x1p+0f, 0x1.f07c2p-1f, 0x1.e1e1e2p-1f, 0x1.d41d42p-1f,
221226
0x1.c71c72p-1f, 0x1.bacf92p-1f, 0x1.af286cp-1f, 0x1.a41a42p-1f,
222227
0x1.99999ap-1f, 0x1.8f9c18p-1f, 0x1.861862p-1f, 0x1.7d05f4p-1f,
@@ -227,6 +232,10 @@ constexpr cpp::array<float, 32> ONE_OVER_F_F = {
227232
0x1.111112p-1f, 0x1.0c9714p-1f, 0x1.08421p-1f, 0x1.041042p-1f,
228233
};
229234

235+
} // namespace expxf16_internal
236+
237+
} // namespace math
238+
230239
} // namespace LIBC_NAMESPACE_DECL
231240

232241
#endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H

0 commit comments

Comments
 (0)