Skip to content

Commit ce1bed7

Browse files
committed
[libc][math] Refactor exp2f16 implementation to header-only in src/__support/math folder.
1 parent 93383ba commit ce1bed7

File tree

9 files changed

+177
-95
lines changed

9 files changed

+177
-95
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "math/exp10m1f16.h"
5050
#include "math/exp2.h"
5151
#include "math/exp2f.h"
52+
#include "math/exp2f16.h"
5253
#include "math/expf.h"
5354
#include "math/expf16.h"
5455
#include "math/frexpf.h"

libc/shared/math/exp2f16.h

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

libc/src/__support/math/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,20 @@ add_header_library(
753753
libc.src.errno.errno
754754
)
755755

756+
add_header_library(
757+
exp2f16
758+
HDRS
759+
exp2f16.h
760+
DEPENDS
761+
.expxf16_utils
762+
libc.src.__support.FPUtil.cast
763+
libc.src.__support.FPUtil.except_value_utils
764+
libc.src.__support.FPUtil.fenv_impl
765+
libc.src.__support.FPUtil.fp_bits
766+
libc.src.__support.FPUtil.rounding_mode
767+
libc.src.__support.macros.optimization
768+
)
769+
756770
add_header_library(
757771
exp10
758772
HDRS

libc/src/__support/math/exp2f16.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//===-- Implementation header for exp2f16 -----------------------*- 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_EXP2F16_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP2F16_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/cast.h"
20+
#include "src/__support/FPUtil/except_value_utils.h"
21+
#include "src/__support/FPUtil/rounding_mode.h"
22+
#include "src/__support/common.h"
23+
#include "src/__support/macros/config.h"
24+
#include "src/__support/macros/optimization.h"
25+
26+
namespace LIBC_NAMESPACE_DECL {
27+
28+
namespace math {
29+
30+
LIBC_INLINE static constexpr float16 exp2f16(float16 x) {
31+
32+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
33+
constexpr fputil::ExceptValues<float16, 3> EXP2F16_EXCEPTS = {{
34+
// (input, RZ output, RU offset, RD offset, RN offset)
35+
// x = 0x1.714p-11, exp2f16(x) = 0x1p+0 (RZ)
36+
{0x11c5U, 0x3c00U, 1U, 0U, 1U},
37+
// x = -0x1.558p-4, exp2f16(x) = 0x1.e34p-1 (RZ)
38+
{0xad56U, 0x3b8dU, 1U, 0U, 0U},
39+
// x = -0x1.d5cp-4, exp2f16(x) = 0x1.d8cp-1 (RZ)
40+
{0xaf57U, 0x3b63U, 1U, 0U, 0U},
41+
}};
42+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
43+
44+
using namespace math::expxf16_internal;
45+
using FPBits = fputil::FPBits<float16>;
46+
FPBits x_bits(x);
47+
48+
uint16_t x_u = x_bits.uintval();
49+
uint16_t x_abs = x_u & 0x7fffU;
50+
51+
// When |x| >= 16, or x is NaN.
52+
if (LIBC_UNLIKELY(x_abs >= 0x4c00U)) {
53+
// exp2(NaN) = NaN
54+
if (x_bits.is_nan()) {
55+
if (x_bits.is_signaling_nan()) {
56+
fputil::raise_except_if_required(FE_INVALID);
57+
return FPBits::quiet_nan().get_val();
58+
}
59+
60+
return x;
61+
}
62+
63+
// When x >= 16.
64+
if (x_bits.is_pos()) {
65+
// exp2(+inf) = +inf
66+
if (x_bits.is_inf())
67+
return FPBits::inf().get_val();
68+
69+
switch (fputil::quick_get_round()) {
70+
case FE_TONEAREST:
71+
case FE_UPWARD:
72+
fputil::set_errno_if_required(ERANGE);
73+
fputil::raise_except_if_required(FE_OVERFLOW);
74+
return FPBits::inf().get_val();
75+
default:
76+
return FPBits::max_normal().get_val();
77+
}
78+
}
79+
80+
// When x <= -25.
81+
if (x_u >= 0xce40U) {
82+
// exp2(-inf) = +0
83+
if (x_bits.is_inf())
84+
return FPBits::zero().get_val();
85+
86+
fputil::set_errno_if_required(ERANGE);
87+
fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
88+
89+
if (fputil::fenv_is_round_up())
90+
return FPBits::min_subnormal().get_val();
91+
return FPBits::zero().get_val();
92+
}
93+
}
94+
95+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
96+
if (auto r = EXP2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
97+
return r.value();
98+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
99+
100+
// exp2(x) = exp2(hi + mid) * exp2(lo)
101+
auto [exp2_hi_mid, exp2_lo] = exp2_range_reduction(x);
102+
return fputil::cast<float16>(exp2_hi_mid * exp2_lo);
103+
}
104+
105+
} // namespace math
106+
107+
} // namespace LIBC_NAMESPACE_DECL
108+
109+
#endif // LIBC_TYPES_HAS_FLOAT16
110+
111+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP2F16_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,15 +1468,7 @@ add_entrypoint_object(
14681468
HDRS
14691469
../exp2f16.h
14701470
DEPENDS
1471-
libc.hdr.errno_macros
1472-
libc.hdr.fenv_macros
1473-
libc.src.__support.FPUtil.cast
1474-
libc.src.__support.FPUtil.except_value_utils
1475-
libc.src.__support.FPUtil.fenv_impl
1476-
libc.src.__support.FPUtil.fp_bits
1477-
libc.src.__support.FPUtil.rounding_mode
1478-
libc.src.__support.macros.optimization
1479-
libc.src.__support.math.expxf16_utils
1471+
libc.src.__support.math.exp2f16
14801472
)
14811473

14821474
add_entrypoint_object(

libc/src/math/generic/exp2f16.cpp

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

99
#include "src/math/exp2f16.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/cast.h"
15-
#include "src/__support/FPUtil/except_value_utils.h"
16-
#include "src/__support/FPUtil/rounding_mode.h"
17-
#include "src/__support/common.h"
18-
#include "src/__support/macros/config.h"
19-
#include "src/__support/macros/optimization.h"
20-
#include "src/__support/math/expxf16_utils.h"
10+
#include "src/__support/math/exp2f16.h"
2111

2212
namespace LIBC_NAMESPACE_DECL {
2313

24-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
25-
static constexpr fputil::ExceptValues<float16, 3> EXP2F16_EXCEPTS = {{
26-
// (input, RZ output, RU offset, RD offset, RN offset)
27-
// x = 0x1.714p-11, exp2f16(x) = 0x1p+0 (RZ)
28-
{0x11c5U, 0x3c00U, 1U, 0U, 1U},
29-
// x = -0x1.558p-4, exp2f16(x) = 0x1.e34p-1 (RZ)
30-
{0xad56U, 0x3b8dU, 1U, 0U, 0U},
31-
// x = -0x1.d5cp-4, exp2f16(x) = 0x1.d8cp-1 (RZ)
32-
{0xaf57U, 0x3b63U, 1U, 0U, 0U},
33-
}};
34-
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
35-
36-
LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) {
37-
using namespace math::expxf16_internal;
38-
using FPBits = fputil::FPBits<float16>;
39-
FPBits x_bits(x);
40-
41-
uint16_t x_u = x_bits.uintval();
42-
uint16_t x_abs = x_u & 0x7fffU;
43-
44-
// When |x| >= 16, or x is NaN.
45-
if (LIBC_UNLIKELY(x_abs >= 0x4c00U)) {
46-
// exp2(NaN) = NaN
47-
if (x_bits.is_nan()) {
48-
if (x_bits.is_signaling_nan()) {
49-
fputil::raise_except_if_required(FE_INVALID);
50-
return FPBits::quiet_nan().get_val();
51-
}
52-
53-
return x;
54-
}
55-
56-
// When x >= 16.
57-
if (x_bits.is_pos()) {
58-
// exp2(+inf) = +inf
59-
if (x_bits.is_inf())
60-
return FPBits::inf().get_val();
61-
62-
switch (fputil::quick_get_round()) {
63-
case FE_TONEAREST:
64-
case FE_UPWARD:
65-
fputil::set_errno_if_required(ERANGE);
66-
fputil::raise_except_if_required(FE_OVERFLOW);
67-
return FPBits::inf().get_val();
68-
default:
69-
return FPBits::max_normal().get_val();
70-
}
71-
}
72-
73-
// When x <= -25.
74-
if (x_u >= 0xce40U) {
75-
// exp2(-inf) = +0
76-
if (x_bits.is_inf())
77-
return FPBits::zero().get_val();
78-
79-
fputil::set_errno_if_required(ERANGE);
80-
fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
81-
82-
if (fputil::fenv_is_round_up())
83-
return FPBits::min_subnormal().get_val();
84-
return FPBits::zero().get_val();
85-
}
86-
}
87-
88-
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
89-
if (auto r = EXP2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
90-
return r.value();
91-
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
92-
93-
// exp2(x) = exp2(hi + mid) * exp2(lo)
94-
auto [exp2_hi_mid, exp2_lo] = exp2_range_reduction(x);
95-
return fputil::cast<float16>(exp2_hi_mid * exp2_lo);
96-
}
14+
LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) { return math::exp2f16(x); }
9715

9816
} // namespace LIBC_NAMESPACE_DECL

libc/test/shared/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_fp_unittest(
4242
libc.src.__support.math.exp
4343
libc.src.__support.math.exp2
4444
libc.src.__support.math.exp2f
45+
libc.src.__support.math.exp2f16
4546
libc.src.__support.math.exp10
4647
libc.src.__support.math.exp10f
4748
libc.src.__support.math.exp10f16

libc/test/shared/shared_math_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
2828
EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::cospif16(0.0f16));
2929
EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16));
3030
EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::exp10m1f16(0.0f16));
31-
31+
EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp2f16(0.0f16));
3232
EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::expf16(0.0f16));
3333

3434
ASSERT_FP_EQ(float16(8 << 5), LIBC_NAMESPACE::shared::ldexpf16(8.0f16, 5));

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2895,6 +2895,22 @@ libc_support_library(
28952895
],
28962896
)
28972897

2898+
libc_support_library(
2899+
name = "__support_math_exp2f16",
2900+
hdrs = ["src/__support/math/exp2f16.h"],
2901+
deps = [
2902+
":__support_fputil_except_value_utils",
2903+
":__support_fputil_fma",
2904+
":__support_fputil_multiply_add",
2905+
":__support_fputil_nearest_integer",
2906+
":__support_fputil_polyeval",
2907+
":__support_fputil_rounding_mode",
2908+
":__support_macros_optimization",
2909+
":__support_math_common_constants",
2910+
":__support_math_expxf16_utils",
2911+
],
2912+
)
2913+
28982914
libc_support_library(
28992915
name = "__support_math_exp10",
29002916
hdrs = ["src/__support/math/exp10.h"],
@@ -3683,7 +3699,7 @@ libc_math_function(
36833699
libc_math_function(
36843700
name = "exp2f16",
36853701
additional_deps = [
3686-
":__support_math_expxf16_utils",
3702+
":__support_math_exp2f16",
36873703
],
36883704
)
36893705

0 commit comments

Comments
 (0)