Skip to content

Commit 6879c2a

Browse files
committed
[libc][math][c23] Add f16subf C23 math function
1 parent 513826a commit 6879c2a

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
@@ -514,6 +514,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
514514
libc.src.math.f16fmaf
515515
libc.src.math.f16sqrt
516516
libc.src.math.f16sqrtf
517+
libc.src.math.f16subf
517518
libc.src.math.fabsf16
518519
libc.src.math.fdimf16
519520
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
@@ -548,6 +548,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
548548
libc.src.math.f16sqrt
549549
libc.src.math.f16sqrtf
550550
libc.src.math.f16sqrtl
551+
libc.src.math.f16subf
551552
libc.src.math.fabsf16
552553
libc.src.math.fdimf16
553554
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<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,

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

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

5252
add_header_library(
53-
add
53+
add_sub
5454
HDRS
55-
add.h
55+
add_sub.h
5656
DEPENDS
5757
libc.hdr.errno_macros
5858
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
@@ -116,6 +116,8 @@ add_math_entrypoint_object(f16sqrtf)
116116
add_math_entrypoint_object(f16sqrtl)
117117
add_math_entrypoint_object(f16sqrtf128)
118118

119+
add_math_entrypoint_object(f16subf)
120+
119121
add_math_entrypoint_object(fabs)
120122
add_math_entrypoint_object(fabsf)
121123
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
@@ -3803,7 +3803,20 @@ add_entrypoint_object(
38033803
../f16addf.h
38043804
DEPENDS
38053805
libc.src.__support.macros.properties.types
3806-
libc.src.__support.FPUtil.generic.add
3806+
libc.src.__support.FPUtil.generic.add_sub
3807+
COMPILE_OPTIONS
3808+
-O3
3809+
)
3810+
3811+
add_entrypoint_object(
3812+
f16subf
3813+
SRCS
3814+
f16subf.cpp
3815+
HDRS
3816+
../f16subf.h
3817+
DEPENDS
3818+
libc.src.__support.macros.properties.types
3819+
libc.src.__support.FPUtil.generic.add_sub
38073820
COMPILE_OPTIONS
38083821
-O3
38093822
)

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
@@ -2009,6 +2009,19 @@ add_fp_unittest(
20092009
libc.src.math.f16addf
20102010
)
20112011

2012+
add_fp_unittest(
2013+
f16subf_test
2014+
NEED_MPFR
2015+
SUITE
2016+
libc-math-unittests
2017+
SRCS
2018+
f16subf_test.cpp
2019+
HDRS
2020+
SubTest.h
2021+
DEPENDS
2022+
libc.src.math.f16subf
2023+
)
2024+
20122025
add_fp_unittest(
20132026
f16div_test
20142027
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
@@ -3658,6 +3658,20 @@ add_fp_unittest(
36583658
libc.src.math.f16addf
36593659
)
36603660

3661+
add_fp_unittest(
3662+
f16subf_test
3663+
SUITE
3664+
libc-math-smoke-tests
3665+
SRCS
3666+
f16subf_test.cpp
3667+
HDRS
3668+
SubTest.h
3669+
DEPENDS
3670+
libc.hdr.fenv_macros
3671+
libc.src.__support.FPUtil.basic_operations
3672+
libc.src.math.f16subf
3673+
)
3674+
36613675
add_fp_unittest(
36623676
f16div_test
36633677
SUITE

0 commit comments

Comments
 (0)