Skip to content

Commit f9fb6c9

Browse files
committed
[libc][math][c23] Add setpayloadsigf16 C23 math function
1 parent 846a5fb commit f9fb6c9

File tree

15 files changed

+178
-4
lines changed

15 files changed

+178
-4
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
543543
libc.src.math.roundf16
544544
libc.src.math.roundevenf16
545545
libc.src.math.setpayloadf16
546+
libc.src.math.setpayloadsigf16
546547
libc.src.math.totalorderf16
547548
libc.src.math.totalordermagf16
548549
libc.src.math.truncf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
573573
libc.src.math.roundf16
574574
libc.src.math.roundevenf16
575575
libc.src.math.setpayloadf16
576+
libc.src.math.setpayloadsigf16
576577
libc.src.math.totalorderf16
577578
libc.src.math.totalordermagf16
578579
libc.src.math.truncf16

libc/docs/c23.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Additions:
4646
* totalordermag* |check|
4747
* getpayload* |check|
4848
* setpayload* |check|
49+
* setpayloadsig* |check|
4950
* iscannonical
5051
* issignaling
5152
* issubnormal

libc/docs/math/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ Basic Operations
214214
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
215215
| setpayload | | | | |check| | | F.10.13.2 | N/A |
216216
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
217+
| setpayloadsig | | | | |check| | | F.10.13.3 | N/A |
218+
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
217219
| totalorder | | | | |check| | | F.10.12.1 | N/A |
218220
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
219221
| totalordermag | | | | |check| | | F.10.12.2 | N/A |

libc/spec/stdc.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,8 @@ def StdC : StandardSpec<"stdc"> {
718718
GuardedFunctionSpec<"getpayloadf16", RetValSpec<Float16Type>, [ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
719719

720720
GuardedFunctionSpec<"setpayloadf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
721+
722+
GuardedFunctionSpec<"setpayloadsigf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
721723
]
722724
>;
723725

libc/src/__support/FPUtil/BasicOperations.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,15 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> getpayload(T x) {
276276
return T(x_bits.uintval() & (FPBits::FRACTION_MASK >> 1));
277277
}
278278

279-
template <typename T>
279+
template <bool IsSignaling, typename T>
280280
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
281281
setpayload(T *res, T pl) {
282282
using FPBits = FPBits<T>;
283283
FPBits pl_bits(pl);
284284

285-
if (pl_bits.is_zero()) {
285+
// Signaling NaNs don't have the mantissa's MSB set to 1, so they need a
286+
// non-zero payload to distinguish them from infinities.
287+
if (!IsSignaling && pl_bits.is_zero()) {
286288
*res = FPBits::quiet_nan(Sign::POS).get_val();
287289
return false;
288290
}
@@ -297,7 +299,11 @@ setpayload(T *res, T pl) {
297299

298300
using StorageType = typename FPBits::StorageType;
299301
StorageType v(pl_bits.get_explicit_mantissa() >> (FPBits::SIG_LEN - pl_exp));
300-
*res = FPBits::quiet_nan(Sign::POS, v).get_val();
302+
303+
if constexpr (IsSignaling)
304+
*res = FPBits::signaling_nan(Sign::POS, v).get_val();
305+
else
306+
*res = FPBits::quiet_nan(Sign::POS, v).get_val();
301307
return false;
302308
}
303309

libc/src/math/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ add_math_entrypoint_object(scalbnf128)
350350

351351
add_math_entrypoint_object(setpayloadf16)
352352

353+
add_math_entrypoint_object(setpayloadsigf16)
354+
353355
add_math_entrypoint_object(sincos)
354356
add_math_entrypoint_object(sincosf)
355357

libc/src/math/generic/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3625,3 +3625,15 @@ add_entrypoint_object(
36253625
COMPILE_OPTIONS
36263626
-O3
36273627
)
3628+
3629+
add_entrypoint_object(
3630+
setpayloadsigf16
3631+
SRCS
3632+
setpayloadsigf16.cpp
3633+
HDRS
3634+
../setpayloadsigf16.h
3635+
DEPENDS
3636+
libc.src.__support.FPUtil.basic_operations
3637+
COMPILE_OPTIONS
3638+
-O3
3639+
)

libc/src/math/generic/setpayloadf16.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
namespace LIBC_NAMESPACE {
1414

1515
LLVM_LIBC_FUNCTION(int, setpayloadf16, (float16 * res, float16 pl)) {
16-
return static_cast<int>(fputil::setpayload(res, pl));
16+
return static_cast<int>(fputil::setpayload</*IsSignaling=*/false>(res, pl));
1717
}
1818

1919
} // namespace LIBC_NAMESPACE
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of setpayloadsigf16 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/setpayloadsigf16.h"
10+
#include "src/__support/FPUtil/BasicOperations.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(int, setpayloadsigf16, (float16 * res, float16 pl)) {
16+
return static_cast<int>(fputil::setpayload</*IsSignaling=*/true>(res, pl));
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/math/setpayloadsigf16.h

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

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3567,3 +3567,15 @@ add_fp_unittest(
35673567
DEPENDS
35683568
libc.src.math.setpayloadf16
35693569
)
3570+
3571+
add_fp_unittest(
3572+
setpayloadsigf16_test
3573+
SUITE
3574+
libc-math-smoke-tests
3575+
SRCS
3576+
setpayloadsigf16_test.cpp
3577+
HDRS
3578+
SetPayloadSigTest.h
3579+
DEPENDS
3580+
libc.src.math.setpayloadsigf16
3581+
)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===-- Utility class to test flavors of setpayloadsig ----------*- 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 LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADSIGTEST_H
10+
#define LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADSIGTEST_H
11+
12+
#include "test/UnitTest/FEnvSafeTest.h"
13+
#include "test/UnitTest/FPMatcher.h"
14+
#include "test/UnitTest/Test.h"
15+
16+
template <typename T>
17+
class SetPayloadSigTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
18+
19+
DECLARE_SPECIAL_CONSTANTS(T)
20+
21+
public:
22+
typedef int (*SetPayloadSigFunc)(T *, T);
23+
24+
void testInvalidPayloads(SetPayloadSigFunc func) {
25+
T res;
26+
27+
EXPECT_EQ(1, func(&res, T(aNaN)));
28+
EXPECT_EQ(1, func(&res, T(neg_aNaN)));
29+
EXPECT_EQ(1, func(&res, T(inf)));
30+
EXPECT_EQ(1, func(&res, T(neg_inf)));
31+
EXPECT_EQ(1, func(&res, T(0.0)));
32+
EXPECT_EQ(1, func(&res, T(-0.0)));
33+
EXPECT_EQ(1, func(&res, T(0.1)));
34+
EXPECT_EQ(1, func(&res, T(-0.1)));
35+
EXPECT_EQ(1, func(&res, T(-1.0)));
36+
EXPECT_EQ(1, func(&res, T(0x42.1p+0)));
37+
EXPECT_EQ(1, func(&res, T(-0x42.1p+0)));
38+
EXPECT_EQ(1, func(&res, T(StorageType(1) << (FPBits::FRACTION_LEN - 1))));
39+
}
40+
41+
void testValidPayloads(SetPayloadSigFunc func) {
42+
T res;
43+
44+
EXPECT_EQ(0, func(&res, T(1.0)));
45+
EXPECT_TRUE(FPBits(res).is_signaling_nan());
46+
EXPECT_EQ(FPBits::signaling_nan(Sign::POS, 1).uintval(),
47+
FPBits(res).uintval());
48+
49+
EXPECT_EQ(0, func(&res, T(0x42.0p+0)));
50+
EXPECT_TRUE(FPBits(res).is_signaling_nan());
51+
EXPECT_EQ(FPBits::signaling_nan(Sign::POS, 0x42).uintval(),
52+
FPBits(res).uintval());
53+
54+
EXPECT_EQ(0, func(&res, T(0x123.0p+0)));
55+
EXPECT_TRUE(FPBits(res).is_signaling_nan());
56+
EXPECT_EQ(FPBits::signaling_nan(Sign::POS, 0x123).uintval(),
57+
FPBits(res).uintval());
58+
59+
EXPECT_EQ(0, func(&res, T(FPBits::FRACTION_MASK >> 1)));
60+
EXPECT_TRUE(FPBits(res).is_signaling_nan());
61+
EXPECT_EQ(
62+
FPBits::signaling_nan(Sign::POS, FPBits::FRACTION_MASK >> 1).uintval(),
63+
FPBits(res).uintval());
64+
}
65+
};
66+
67+
#define LIST_SETPAYLOADSIG_TESTS(T, func) \
68+
using LlvmLibcSetPayloadSigTest = SetPayloadSigTestTemplate<T>; \
69+
TEST_F(LlvmLibcSetPayloadSigTest, InvalidPayloads) { \
70+
testInvalidPayloads(&func); \
71+
} \
72+
TEST_F(LlvmLibcSetPayloadSigTest, ValidPayloads) { testValidPayloads(&func); }
73+
74+
#endif // LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADSIGTEST_H

libc/test/src/math/smoke/SetPayloadTest.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,25 @@ class SetPayloadTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
4040
T res;
4141

4242
EXPECT_EQ(0, func(&res, T(0.0)));
43+
EXPECT_TRUE(FPBits(res).is_quiet_nan());
4344
EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(res).uintval());
45+
4446
EXPECT_EQ(0, func(&res, T(1.0)));
47+
EXPECT_TRUE(FPBits(res).is_quiet_nan());
4548
EXPECT_EQ(FPBits::quiet_nan(Sign::POS, 1).uintval(), FPBits(res).uintval());
49+
4650
EXPECT_EQ(0, func(&res, T(0x42.0p+0)));
51+
EXPECT_TRUE(FPBits(res).is_quiet_nan());
4752
EXPECT_EQ(FPBits::quiet_nan(Sign::POS, 0x42).uintval(),
4853
FPBits(res).uintval());
54+
4955
EXPECT_EQ(0, func(&res, T(0x123.0p+0)));
56+
EXPECT_TRUE(FPBits(res).is_quiet_nan());
5057
EXPECT_EQ(FPBits::quiet_nan(Sign::POS, 0x123).uintval(),
5158
FPBits(res).uintval());
59+
5260
EXPECT_EQ(0, func(&res, T(FPBits::FRACTION_MASK >> 1)));
61+
EXPECT_TRUE(FPBits(res).is_quiet_nan());
5362
EXPECT_EQ(
5463
FPBits::quiet_nan(Sign::POS, FPBits::FRACTION_MASK >> 1).uintval(),
5564
FPBits(res).uintval());
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for setpayloadsigf16 ------------------------------------===//
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 "SetPayloadSigTest.h"
10+
11+
#include "src/math/setpayloadsigf16.h"
12+
13+
LIST_SETPAYLOADSIG_TESTS(float16, LIBC_NAMESPACE::setpayloadsigf16)

0 commit comments

Comments
 (0)