Skip to content

Commit 8545827

Browse files
committed
[libc][math][c23] Add f16subf C23 math function
1 parent 096f017 commit 8545827

File tree

19 files changed

+396
-18
lines changed

19 files changed

+396
-18
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
512512
libc.src.math.f16divf
513513
libc.src.math.f16fmaf
514514
libc.src.math.f16sqrtf
515+
libc.src.math.f16subf
515516
libc.src.math.fabsf16
516517
libc.src.math.fdimf16
517518
libc.src.math.floorf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
545545
libc.src.math.f16fmaf
546546
libc.src.math.f16fmal
547547
libc.src.math.f16sqrtf
548+
libc.src.math.f16subf
548549
libc.src.math.fabsf16
549550
libc.src.math.fdimf16
550551
libc.src.math.floorf16

libc/docs/math/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ Basic Operations
130130
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
131131
| f16fma | |check| | |check| | |check| | N/A | |check| | 7.12.14.5 | F.10.11 |
132132
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
133+
| f16sub | |check| | | | N/A | | 7.12.14.2 | F.10.11 |
134+
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
133135
| fabs | |check| | |check| | |check| | |check| | |check| | 7.12.7.3 | F.10.4.3 |
134136
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
135137
| fadd | N/A | | | N/A | | 7.12.14.1 | F.10.11 |

libc/spec/stdc.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,8 @@ def StdC : StandardSpec<"stdc"> {
731731

732732
GuardedFunctionSpec<"f16addf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
733733

734+
GuardedFunctionSpec<"f16subf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
735+
734736
GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
735737

736738
GuardedFunctionSpec<"f16sqrtf", RetValSpec<Float16Type>, [ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,

libc/src/__support/FPUtil/generic/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ add_header_library(
4949
)
5050

5151
add_header_library(
52-
add
52+
add_sub
5353
HDRS
54-
add.h
54+
add_sub.h
5555
DEPENDS
5656
libc.hdr.errno_macros
5757
libc.hdr.fenv_macros

libc/src/__support/FPUtil/generic/add.h renamed to libc/src/__support/FPUtil/generic/add_sub.h

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
//===-- Addition of IEEE 754 floating-point numbers -------------*- C++ -*-===//
1+
//===-- Add and subtract IEEE 754 floating-point numbers --------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_H
10-
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_H
9+
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_SUB_H
10+
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_SUB_H
1111

1212
#include "hdr/errno_macros.h"
1313
#include "hdr/fenv_macros.h"
@@ -24,12 +24,12 @@
2424

2525
namespace LIBC_NAMESPACE::fputil::generic {
2626

27-
template <typename OutType, typename InType>
27+
template <bool IsSub, typename OutType, typename InType>
2828
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
2929
cpp::is_floating_point_v<InType> &&
3030
sizeof(OutType) <= sizeof(InType),
3131
OutType>
32-
add(InType x, InType y) {
32+
add_or_sub(InType x, InType y) {
3333
using OutFPBits = FPBits<OutType>;
3434
using OutStorageType = typename OutFPBits::StorageType;
3535
using InFPBits = FPBits<InType>;
@@ -45,6 +45,8 @@ add(InType x, InType y) {
4545
InFPBits x_bits(x);
4646
InFPBits y_bits(y);
4747

48+
bool is_effectively_add = (x_bits.sign() == y_bits.sign()) ^ IsSub;
49+
4850
if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
4951
x_bits.is_zero() || y_bits.is_zero())) {
5052
if (x_bits.is_nan() || y_bits.is_nan()) {
@@ -72,7 +74,7 @@ add(InType x, InType y) {
7274

7375
if (x_bits.is_inf()) {
7476
if (y_bits.is_inf()) {
75-
if (x_bits.sign() != y_bits.sign()) {
77+
if (!is_effectively_add) {
7678
raise_except_if_required(FE_INVALID);
7779
return OutFPBits::quiet_nan().get_val();
7880
}
@@ -106,7 +108,7 @@ add(InType x, InType y) {
106108
InType x_abs = x_bits.abs().get_val();
107109
InType y_abs = y_bits.abs().get_val();
108110

109-
if (x_abs == y_abs && x_bits.sign() != y_bits.sign()) {
111+
if (x_abs == y_abs && !is_effectively_add) {
110112
switch (quick_get_round()) {
111113
case FE_DOWNWARD:
112114
return OutFPBits::zero(Sign::NEG).get_val();
@@ -117,12 +119,16 @@ add(InType x, InType y) {
117119

118120
Sign result_sign = Sign::POS;
119121

120-
if (x_abs > y_abs)
122+
if (x_abs > y_abs) {
121123
result_sign = x_bits.sign();
122-
else if (x_abs < y_abs)
123-
result_sign = y_bits.sign();
124-
else if (x_bits.sign() == y_bits.sign())
124+
} else if (x_abs < y_abs) {
125+
if (is_effectively_add)
126+
result_sign = y_bits.sign();
127+
else if (y_bits.is_pos())
128+
result_sign = Sign::NEG;
129+
} else if (is_effectively_add) {
125130
result_sign = x_bits.sign();
131+
}
126132

127133
InFPBits max_bits(cpp::max(x_abs, y_abs));
128134
InFPBits min_bits(cpp::min(x_abs, y_abs));
@@ -131,7 +137,8 @@ add(InType x, InType y) {
131137

132138
if (max_bits.is_subnormal()) {
133139
// min_bits must be subnormal too.
134-
if (max_bits.sign() == min_bits.sign())
140+
141+
if (is_effectively_add)
135142
result_mant = max_bits.get_mantissa() + min_bits.get_mantissa();
136143
else
137144
result_mant = max_bits.get_mantissa() - min_bits.get_mantissa();
@@ -155,7 +162,7 @@ add(InType x, InType y) {
155162
else
156163
aligned_min_mant_sticky = true;
157164

158-
if (max_bits.sign() == min_bits.sign())
165+
if (is_effectively_add)
159166
result_mant = max_mant + (aligned_min_mant | aligned_min_mant_sticky);
160167
else
161168
result_mant = max_mant - (aligned_min_mant | aligned_min_mant_sticky);
@@ -166,6 +173,24 @@ add(InType x, InType y) {
166173
return result.template as<OutType, /*ShouldSignalExceptions=*/true>();
167174
}
168175

176+
template <typename OutType, typename InType>
177+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
178+
cpp::is_floating_point_v<InType> &&
179+
sizeof(OutType) <= sizeof(InType),
180+
OutType>
181+
add(InType x, InType y) {
182+
return add_or_sub</*IsSub=*/false, OutType>(x, y);
183+
}
184+
185+
template <typename OutType, typename InType>
186+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
187+
cpp::is_floating_point_v<InType> &&
188+
sizeof(OutType) <= sizeof(InType),
189+
OutType>
190+
sub(InType x, InType y) {
191+
return add_or_sub</*IsSub=*/true, OutType>(x, y);
192+
}
193+
169194
} // namespace LIBC_NAMESPACE::fputil::generic
170195

171-
#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_H
196+
#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_ADD_SUB_H

libc/src/math/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ add_math_entrypoint_object(f16fmaf128)
113113

114114
add_math_entrypoint_object(f16sqrtf)
115115

116+
add_math_entrypoint_object(f16subf)
117+
116118
add_math_entrypoint_object(fabs)
117119
add_math_entrypoint_object(fabsf)
118120
add_math_entrypoint_object(fabsl)

libc/src/math/f16subf.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for f16subf -----------------------*- 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_MATH_F16SUBF_H
10+
#define LLVM_LIBC_SRC_MATH_F16SUBF_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 f16subf(float x, float y);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_F16SUBF_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3784,7 +3784,20 @@ add_entrypoint_object(
37843784
../f16addf.h
37853785
DEPENDS
37863786
libc.src.__support.macros.properties.types
3787-
libc.src.__support.FPUtil.generic.add
3787+
libc.src.__support.FPUtil.generic.add_sub
3788+
COMPILE_OPTIONS
3789+
-O3
3790+
)
3791+
3792+
add_entrypoint_object(
3793+
f16subf
3794+
SRCS
3795+
f16subf.cpp
3796+
HDRS
3797+
../f16subf.h
3798+
DEPENDS
3799+
libc.src.__support.macros.properties.types
3800+
libc.src.__support.FPUtil.generic.add_sub
37883801
COMPILE_OPTIONS
37893802
-O3
37903803
)

libc/src/math/generic/f16addf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/math/f16addf.h"
10-
#include "src/__support/FPUtil/generic/add.h"
10+
#include "src/__support/FPUtil/generic/add_sub.h"
1111
#include "src/__support/common.h"
1212

1313
namespace LIBC_NAMESPACE {

libc/src/math/generic/f16subf.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of f16subf function --------------------------------===//
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+
#include "src/math/f16subf.h"
10+
#include "src/__support/FPUtil/generic/add_sub.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, f16subf, (float x, float y)) {
16+
return fputil::generic::sub<float16>(x, y);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/test/src/math/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,19 @@ add_fp_unittest(
19151915
libc.src.math.f16addf
19161916
)
19171917

1918+
add_fp_unittest(
1919+
f16subf_test
1920+
NEED_MPFR
1921+
SUITE
1922+
libc-math-unittests
1923+
SRCS
1924+
f16subf_test.cpp
1925+
HDRS
1926+
SubTest.h
1927+
DEPENDS
1928+
libc.src.math.f16subf
1929+
)
1930+
19181931
add_fp_unittest(
19191932
f16div_test
19201933
NEED_MPFR

libc/test/src/math/SubTest.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//===-- Utility class to test different flavors of float sub ----*- 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_TEST_SRC_MATH_SUBTEST_H
10+
#define LLVM_LIBC_TEST_SRC_MATH_SUBTEST_H
11+
12+
#include "test/UnitTest/FEnvSafeTest.h"
13+
#include "test/UnitTest/FPMatcher.h"
14+
#include "test/UnitTest/Test.h"
15+
#include "utils/MPFRWrapper/MPFRUtils.h"
16+
17+
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
18+
19+
template <typename OutType, typename InType>
20+
class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
21+
22+
struct InConstants {
23+
DECLARE_SPECIAL_CONSTANTS(InType)
24+
};
25+
26+
using InFPBits = typename InConstants::FPBits;
27+
using InStorageType = typename InConstants::StorageType;
28+
29+
static constexpr InStorageType IN_MAX_NORMAL_U =
30+
InFPBits::max_normal().uintval();
31+
static constexpr InStorageType IN_MIN_NORMAL_U =
32+
InFPBits::min_normal().uintval();
33+
static constexpr InStorageType IN_MAX_SUBNORMAL_U =
34+
InFPBits::max_subnormal().uintval();
35+
static constexpr InStorageType IN_MIN_SUBNORMAL_U =
36+
InFPBits::min_subnormal().uintval();
37+
38+
public:
39+
typedef OutType (*AddFunc)(InType, InType);
40+
41+
void test_subnormal_range(AddFunc func) {
42+
constexpr InStorageType STEP =
43+
(IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) / COUNT;
44+
for (InStorageType i = 0, v = 0, w = IN_MAX_SUBNORMAL_U; i <= COUNT;
45+
++i, v += STEP, w -= STEP) {
46+
InType x = InFPBits(v).get_val();
47+
InType y = InFPBits(w).get_val();
48+
mpfr::BinaryInput<InType> input{x, y};
49+
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sub, input, func(x, y),
50+
0.5);
51+
}
52+
}
53+
54+
void test_normal_range(AddFunc func) {
55+
constexpr InStorageType COUNT = 100'001;
56+
constexpr InStorageType STEP = (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT;
57+
for (InStorageType i = 0, v = 0, w = IN_MAX_NORMAL_U; i <= COUNT;
58+
++i, v += STEP, w -= STEP) {
59+
InType x = InFPBits(v).get_val();
60+
InType y = InFPBits(w).get_val();
61+
mpfr::BinaryInput<InType> input{x, y};
62+
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sub, input, func(x, y),
63+
0.5);
64+
}
65+
}
66+
};
67+
68+
#define LIST_SUB_TESTS(OutType, InType, func) \
69+
using LlvmLibcSubTest = SubTest<OutType, InType>; \
70+
TEST_F(LlvmLibcSubTest, SubnormalRange) { test_subnormal_range(&func); } \
71+
TEST_F(LlvmLibcSubTest, NormalRange) { test_normal_range(&func); }
72+
73+
#endif // LLVM_LIBC_TEST_SRC_MATH_ADDTEST_H

libc/test/src/math/f16subf_test.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for f16subf ---------------------------------------------===//
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+
#include "SubTest.h"
10+
11+
#include "src/math/f16subf.h"
12+
13+
LIST_SUB_TESTS(float16, float, LIBC_NAMESPACE::f16subf)

libc/test/src/math/smoke/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,20 @@ add_fp_unittest(
36453645
libc.src.math.f16addf
36463646
)
36473647

3648+
add_fp_unittest(
3649+
f16subf_test
3650+
SUITE
3651+
libc-math-smoke-tests
3652+
SRCS
3653+
f16subf_test.cpp
3654+
HDRS
3655+
SubTest.h
3656+
DEPENDS
3657+
libc.hdr.fenv_macros
3658+
libc.src.__support.FPUtil.basic_operations
3659+
libc.src.math.f16subf
3660+
)
3661+
36483662
add_fp_unittest(
36493663
f16div_test
36503664
SUITE

0 commit comments

Comments
 (0)