Skip to content

Commit 278b3ef

Browse files
committed
[libc][math][c23] Add f16subf C23 math function
1 parent f5e03f4 commit 278b3ef

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
@@ -510,6 +510,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
510510
libc.src.math.f16divf
511511
libc.src.math.f16fmaf
512512
libc.src.math.f16sqrtf
513+
libc.src.math.f16subf
513514
libc.src.math.fabsf16
514515
libc.src.math.fdimf16
515516
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
@@ -540,6 +540,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
540540
libc.src.math.f16divf
541541
libc.src.math.f16fmaf
542542
libc.src.math.f16sqrtf
543+
libc.src.math.f16subf
543544
libc.src.math.fabsf16
544545
libc.src.math.fdimf16
545546
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| | | | N/A | | 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
@@ -728,6 +728,8 @@ def StdC : StandardSpec<"stdc"> {
728728

729729
GuardedFunctionSpec<"f16addf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
730730

731+
GuardedFunctionSpec<"f16subf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
732+
731733
GuardedFunctionSpec<"f16divf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
732734

733735
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
@@ -47,9 +47,9 @@ add_header_library(
4747
)
4848

4949
add_header_library(
50-
add
50+
add_sub
5151
HDRS
52-
add.h
52+
add_sub.h
5353
DEPENDS
5454
libc.hdr.errno_macros
5555
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
@@ -107,6 +107,8 @@ add_math_entrypoint_object(f16fmaf)
107107

108108
add_math_entrypoint_object(f16sqrtf)
109109

110+
add_math_entrypoint_object(f16subf)
111+
110112
add_math_entrypoint_object(fabs)
111113
add_math_entrypoint_object(fabsf)
112114
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
@@ -3762,7 +3762,20 @@ add_entrypoint_object(
37623762
../f16addf.h
37633763
DEPENDS
37643764
libc.src.__support.macros.properties.types
3765-
libc.src.__support.FPUtil.generic.add
3765+
libc.src.__support.FPUtil.generic.add_sub
3766+
COMPILE_OPTIONS
3767+
-O3
3768+
)
3769+
3770+
add_entrypoint_object(
3771+
f16subf
3772+
SRCS
3773+
f16subf.cpp
3774+
HDRS
3775+
../f16subf.h
3776+
DEPENDS
3777+
libc.src.__support.macros.properties.types
3778+
libc.src.__support.FPUtil.generic.add_sub
37663779
COMPILE_OPTIONS
37673780
-O3
37683781
)

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
@@ -1903,6 +1903,19 @@ add_fp_unittest(
19031903
libc.src.math.f16addf
19041904
)
19051905

1906+
add_fp_unittest(
1907+
f16subf_test
1908+
NEED_MPFR
1909+
SUITE
1910+
libc-math-unittests
1911+
SRCS
1912+
f16subf_test.cpp
1913+
HDRS
1914+
SubTest.h
1915+
DEPENDS
1916+
libc.src.math.f16subf
1917+
)
1918+
19061919
add_fp_unittest(
19071920
f16divf_test
19081921
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
f16divf_test
36503664
SUITE

0 commit comments

Comments
 (0)