Skip to content

Commit 0f24379

Browse files
committed
[libc][math] Refactor atanf16 implementation to header-only in src/__support/math folder.
1 parent 26d6828 commit 0f24379

File tree

9 files changed

+190
-104
lines changed

9 files changed

+190
-104
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "math/asinhf16.h"
2525
#include "math/atan.h"
2626
#include "math/atanf.h"
27+
#include "math/atanf16.h"
2728
#include "math/erff.h"
2829
#include "math/exp.h"
2930
#include "math/exp10.h"

libc/shared/math/atanf16.h

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

libc/src/__support/math/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,21 @@ add_header_library(
214214
libc.src.__support.macros.optimization
215215
)
216216

217+
add_header_library(
218+
atanf16
219+
HDRS
220+
atanf16.h
221+
DEPENDS
222+
libc.src.__support.FPUtil.cast
223+
libc.src.__support.FPUtil.except_value_utils
224+
libc.src.__support.FPUtil.fenv_impl
225+
libc.src.__support.FPUtil.fp_bits
226+
libc.src.__support.FPUtil.multiply_add
227+
libc.src.__support.FPUtil.polyeval
228+
libc.src.__support.FPUtil.sqrt
229+
libc.src.__support.macros.optimization
230+
)
231+
217232
add_header_library(
218233
asinf
219234
HDRS

libc/src/__support/math/atanf16.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//===-- Implementation header for atanf16 -----------------------*- 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_ATANF16_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_ATANF16_H
11+
12+
#include "include/llvm-libc-macros/float16-macros.h"
13+
14+
#ifdef LIBC_TYPES_HAS_FLOAT16
15+
16+
#include "src/__support/FPUtil/FEnvImpl.h"
17+
#include "src/__support/FPUtil/FPBits.h"
18+
#include "src/__support/FPUtil/PolyEval.h"
19+
#include "src/__support/FPUtil/cast.h"
20+
#include "src/__support/FPUtil/except_value_utils.h"
21+
#include "src/__support/FPUtil/multiply_add.h"
22+
#include "src/__support/FPUtil/sqrt.h"
23+
#include "src/__support/macros/optimization.h"
24+
25+
namespace LIBC_NAMESPACE_DECL {
26+
27+
namespace math {
28+
29+
LIBC_INLINE static constexpr float16 atanf16(float16 x) {
30+
// Generated by Solly using the following command:
31+
// > round(pi/2, SG, RN);
32+
constexpr float PI_2 = 0x1.921fb6p0;
33+
34+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
35+
constexpr size_t N_EXCEPTS = 6;
36+
37+
constexpr fputil::ExceptValues<float16, N_EXCEPTS> ATANF16_EXCEPTS{{
38+
// (input, RZ output, RU offset, RD offset, RN offset)
39+
{0x2745, 0x2744, 1, 0, 1},
40+
{0x3099, 0x3090, 1, 0, 1},
41+
{0x3c6c, 0x3aae, 1, 0, 1},
42+
{0x466e, 0x3daa, 1, 0, 1},
43+
{0x48ae, 0x3ddb, 1, 0, 0},
44+
{0x5619, 0x3e3d, 1, 0, 1},
45+
}};
46+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
47+
48+
using FPBits = fputil::FPBits<float16>;
49+
FPBits xbits(x);
50+
51+
uint16_t x_u = xbits.uintval();
52+
uint16_t x_abs = x_u & 0x7fff;
53+
bool x_sign = x_u >> 15;
54+
float sign = (x_sign ? -1.0 : 1.0);
55+
56+
// |x| >= +/-inf
57+
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
58+
if (xbits.is_nan()) {
59+
if (xbits.is_signaling_nan()) {
60+
fputil::raise_except_if_required(FE_INVALID);
61+
return FPBits::quiet_nan().get_val();
62+
}
63+
return x;
64+
}
65+
66+
// atanf16(+/-inf) = +/-pi/2
67+
return fputil::cast<float16>(sign * PI_2);
68+
}
69+
70+
float xf = x;
71+
float xsq = xf * xf;
72+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
73+
// Handle exceptional values
74+
if (auto r = ATANF16_EXCEPTS.lookup_odd(x_abs, x_sign);
75+
LIBC_UNLIKELY(r.has_value()))
76+
return r.value();
77+
#endif
78+
79+
// |x| <= 0x1p0, |x| <= 1
80+
if (x_abs <= 0x3c00) {
81+
// atanf16(+/-0) = +/-0
82+
if (LIBC_UNLIKELY(x_abs == 0))
83+
return x;
84+
85+
// Degree-14 minimax odd polynomial of atan(x) generated by Sollya with:
86+
// > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|SG...|],
87+
// [0, 1]);
88+
float result = fputil::polyeval(
89+
xsq, 0x1.fffffcp-1f, -0x1.55519ep-2f, 0x1.98f6a8p-3f, -0x1.1f0a92p-3f,
90+
0x1.95b654p-4f, -0x1.e65492p-5f, 0x1.8c0c36p-6f, -0x1.32316ep-8f);
91+
return fputil::cast<float16>(xf * result);
92+
}
93+
94+
// If |x| > 1
95+
// y = atan(x) = sign(x) * atan(|x|)
96+
// atan(|x|) = pi/2 - atan(1/|x|)
97+
// Recall, 1/|x| < 1
98+
float x_inv_sq = 1.0f / xsq;
99+
float x_inv = fputil::sqrt<float>(x_inv_sq);
100+
101+
// Degree-14 minimax odd polynomial of atan(x) generated by Sollya with:
102+
// > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|SG...|],
103+
// [0, 1]);
104+
float interm =
105+
fputil::polyeval(x_inv_sq, 0x1.fffffcp-1f, -0x1.55519ep-2f,
106+
0x1.98f6a8p-3f, -0x1.1f0a92p-3f, 0x1.95b654p-4f,
107+
-0x1.e65492p-5f, 0x1.8c0c36p-6f, -0x1.32316ep-8f);
108+
109+
return fputil::cast<float16>(sign *
110+
fputil::multiply_add(x_inv, -interm, PI_2));
111+
}
112+
113+
} // namespace math
114+
115+
} // namespace LIBC_NAMESPACE_DECL
116+
117+
#endif // LIBC_TYPES_HAS_FLOAT16
118+
119+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATANF16_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4037,17 +4037,7 @@ add_entrypoint_object(
40374037
HDRS
40384038
../atanf16.h
40394039
DEPENDS
4040-
libc.hdr.errno_macros
4041-
libc.hdr.fenv_macros
4042-
libc.src.__support.FPUtil.cast
4043-
libc.src.__support.FPUtil.except_value_utils
4044-
libc.src.__support.FPUtil.fenv_impl
4045-
libc.src.__support.FPUtil.fp_bits
4046-
libc.src.__support.FPUtil.multiply_add
4047-
libc.src.__support.FPUtil.polyeval
4048-
libc.src.__support.FPUtil.sqrt
4049-
libc.src.__support.macros.optimization
4050-
libc.src.__support.macros.properties.types
4040+
libc.src.__support.math.atanf16
40514041
)
40524042

40534043
add_entrypoint_object(

libc/src/math/generic/atanf16.cpp

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

99
#include "src/math/atanf16.h"
10-
#include "hdr/errno_macros.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/sqrt.h"
19-
#include "src/__support/macros/optimization.h"
10+
#include "src/__support/math/atanf16.h"
2011

2112
namespace LIBC_NAMESPACE_DECL {
2213

23-
// Generated by Solly using the following command:
24-
// > round(pi/2, SG, RN);
25-
static constexpr float PI_2 = 0x1.921fb6p0;
26-
27-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
28-
static constexpr size_t N_EXCEPTS = 6;
29-
30-
static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ATANF16_EXCEPTS{{
31-
// (input, RZ output, RU offset, RD offset, RN offset)
32-
{0x2745, 0x2744, 1, 0, 1},
33-
{0x3099, 0x3090, 1, 0, 1},
34-
{0x3c6c, 0x3aae, 1, 0, 1},
35-
{0x466e, 0x3daa, 1, 0, 1},
36-
{0x48ae, 0x3ddb, 1, 0, 0},
37-
{0x5619, 0x3e3d, 1, 0, 1},
38-
}};
39-
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
40-
41-
LLVM_LIBC_FUNCTION(float16, atanf16, (float16 x)) {
42-
using FPBits = fputil::FPBits<float16>;
43-
FPBits xbits(x);
44-
45-
uint16_t x_u = xbits.uintval();
46-
uint16_t x_abs = x_u & 0x7fff;
47-
bool x_sign = x_u >> 15;
48-
float sign = (x_sign ? -1.0 : 1.0);
49-
50-
// |x| >= +/-inf
51-
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
52-
if (xbits.is_nan()) {
53-
if (xbits.is_signaling_nan()) {
54-
fputil::raise_except_if_required(FE_INVALID);
55-
return FPBits::quiet_nan().get_val();
56-
}
57-
return x;
58-
}
59-
60-
// atanf16(+/-inf) = +/-pi/2
61-
return fputil::cast<float16>(sign * PI_2);
62-
}
63-
64-
float xf = x;
65-
float xsq = xf * xf;
66-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
67-
// Handle exceptional values
68-
if (auto r = ATANF16_EXCEPTS.lookup_odd(x_abs, x_sign);
69-
LIBC_UNLIKELY(r.has_value()))
70-
return r.value();
71-
#endif
72-
73-
// |x| <= 0x1p0, |x| <= 1
74-
if (x_abs <= 0x3c00) {
75-
// atanf16(+/-0) = +/-0
76-
if (LIBC_UNLIKELY(x_abs == 0))
77-
return x;
78-
79-
// Degree-14 minimax odd polynomial of atan(x) generated by Sollya with:
80-
// > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|SG...|],
81-
// [0, 1]);
82-
float result = fputil::polyeval(
83-
xsq, 0x1.fffffcp-1f, -0x1.55519ep-2f, 0x1.98f6a8p-3f, -0x1.1f0a92p-3f,
84-
0x1.95b654p-4f, -0x1.e65492p-5f, 0x1.8c0c36p-6f, -0x1.32316ep-8f);
85-
return fputil::cast<float16>(xf * result);
86-
}
87-
88-
// If |x| > 1
89-
// y = atan(x) = sign(x) * atan(|x|)
90-
// atan(|x|) = pi/2 - atan(1/|x|)
91-
// Recall, 1/|x| < 1
92-
float x_inv_sq = 1.0f / xsq;
93-
float x_inv = fputil::sqrt<float>(x_inv_sq);
94-
95-
// Degree-14 minimax odd polynomial of atan(x) generated by Sollya with:
96-
// > P = fpminimax(atan(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|SG...|],
97-
// [0, 1]);
98-
float interm =
99-
fputil::polyeval(x_inv_sq, 0x1.fffffcp-1f, -0x1.55519ep-2f,
100-
0x1.98f6a8p-3f, -0x1.1f0a92p-3f, 0x1.95b654p-4f,
101-
-0x1.e65492p-5f, 0x1.8c0c36p-6f, -0x1.32316ep-8f);
102-
103-
return fputil::cast<float16>(sign *
104-
fputil::multiply_add(x_inv, -interm, PI_2));
105-
}
14+
LLVM_LIBC_FUNCTION(float16, atanf16, (float16 x)) { return math::atanf16(x); }
10615

10716
} // namespace LIBC_NAMESPACE_DECL

libc/test/shared/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_fp_unittest(
2020
libc.src.__support.math.asinhf16
2121
libc.src.__support.math.atan
2222
libc.src.__support.math.atanf
23+
libc.src.__support.math.atanf16
2324
libc.src.__support.math.erff
2425
libc.src.__support.math.exp
2526
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
@@ -19,6 +19,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
1919
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::acospif16(1.0f16));
2020
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinf16(0.0f16));
2121
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinhf16(0.0f16));
22+
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::atanf16(0.0f16));
2223

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

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,6 +2288,21 @@ libc_support_library(
22882288
],
22892289
)
22902290

2291+
libc_support_library(
2292+
name = "__support_math_atanf16",
2293+
hdrs = ["src/__support/math/atanf16.h"],
2294+
deps = [
2295+
":__support_fputil_cast",
2296+
":__support_fputil_except_value_utils",
2297+
":__support_fputil_fenv_impl",
2298+
":__support_fputil_fp_bits",
2299+
":__support_fputil_polyeval",
2300+
":__support_fputil_multiply_add",
2301+
":__support_fputil_sqrt",
2302+
":__support_macros_optimization",
2303+
],
2304+
)
2305+
22912306
libc_support_library(
22922307
name = "__support_math_asinf",
22932308
hdrs = ["src/__support/math/asinf.h"],
@@ -2904,6 +2919,13 @@ libc_math_function(
29042919
],
29052920
)
29062921

2922+
libc_math_function(
2923+
name = "atanf16",
2924+
additional_deps = [
2925+
":__support_math_atanf16"
2926+
],
2927+
)
2928+
29072929
libc_math_function(
29082930
name = "atan",
29092931
additional_deps = [

0 commit comments

Comments
 (0)