diff options
author | OverMighty <its.overmighty@gmail.com> | 2024-06-20 19:33:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 13:33:34 -0400 |
commit | 1107575c95577f32678ad60a96be6eaf29cf0f65 (patch) | |
tree | c0b395399cb7bc243ced228a5dfab3e7dd9de92c | |
parent | f1edc0459a4cc8cd4d00331c2a5cb318955318b2 (diff) | |
download | llvm-1107575c95577f32678ad60a96be6eaf29cf0f65.zip llvm-1107575c95577f32678ad60a96be6eaf29cf0f65.tar.gz llvm-1107575c95577f32678ad60a96be6eaf29cf0f65.tar.bz2 |
[libc][math][c23] Add {getpayload,setpayload,setpayloadsig}f16 C23 math functions (#95159)
Part of #93566.
21 files changed, 519 insertions, 2 deletions
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index dfed6ac..aa223a6 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -522,6 +522,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.frexpf16 libc.src.math.fromfpf16 libc.src.math.fromfpxf16 + libc.src.math.getpayloadf16 libc.src.math.ilogbf16 libc.src.math.llogbf16 libc.src.math.llrintf16 @@ -544,6 +545,8 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.rintf16 libc.src.math.roundf16 libc.src.math.roundevenf16 + libc.src.math.setpayloadf16 + libc.src.math.setpayloadsigf16 libc.src.math.totalorderf16 libc.src.math.totalordermagf16 libc.src.math.truncf16 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index cfe3516..ab7f572 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -555,6 +555,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.frexpf16 libc.src.math.fromfpf16 libc.src.math.fromfpxf16 + libc.src.math.getpayloadf16 libc.src.math.ilogbf16 libc.src.math.llogbf16 libc.src.math.llrintf16 @@ -574,6 +575,8 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.rintf16 libc.src.math.roundf16 libc.src.math.roundevenf16 + libc.src.math.setpayloadf16 + libc.src.math.setpayloadsigf16 libc.src.math.totalorderf16 libc.src.math.totalordermagf16 libc.src.math.truncf16 diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst index 4134bef..b9a2424 100644 --- a/libc/docs/c23.rst +++ b/libc/docs/c23.rst @@ -44,8 +44,9 @@ Additions: * compoundn* * totalorder* |check| * totalordermag* |check| - * getpayload* - * setpayload* + * getpayload* |check| + * setpayload* |check| + * setpayloadsig* |check| * iscannonical * issignaling * issubnormal diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 293edd1..c9b1238 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -170,6 +170,8 @@ Basic Operations +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | fsub | N/A | | | N/A | | 7.12.14.2 | F.10.11 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ +| getpayload | | | | |check| | | F.10.13.1 | N/A | ++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | ilogb | |check| | |check| | |check| | |check| | |check| | 7.12.6.8 | F.10.3.8 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | ldexp | |check| | |check| | |check| | | |check| | 7.12.6.9 | F.10.3.9 | @@ -212,6 +214,10 @@ Basic Operations +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | scalbn | |check| | |check| | |check| | | |check| | 7.12.6.19 | F.10.3.19 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ +| setpayload | | | | |check| | | F.10.13.2 | N/A | ++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ +| setpayloadsig | | | | |check| | | F.10.13.3 | N/A | ++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | totalorder | | | | |check| | | F.10.12.1 | N/A | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | totalordermag | | | | |check| | | F.10.12.2 | N/A | diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index f9c79ee..f0b36f82 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -716,6 +716,12 @@ def StdC : StandardSpec<"stdc"> { GuardedFunctionSpec<"totalordermagf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">, + GuardedFunctionSpec<"getpayloadf16", RetValSpec<Float16Type>, [ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">, + + GuardedFunctionSpec<"setpayloadf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">, + + GuardedFunctionSpec<"setpayloadsigf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">, + GuardedFunctionSpec<"f16sqrtf", RetValSpec<Float16Type>, [ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">, ] >; diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index beb8e48..17eee7b 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -265,6 +265,48 @@ totalordermag(T x, T y) { return FPBits<T>(x).abs().uintval() <= FPBits<T>(y).abs().uintval(); } +template <typename T> +LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> getpayload(T x) { + using FPBits = FPBits<T>; + FPBits x_bits(x); + + if (!x_bits.is_nan()) + return T(-1.0); + + return T(x_bits.uintval() & (FPBits::FRACTION_MASK >> 1)); +} + +template <bool IsSignaling, typename T> +LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> +setpayload(T &res, T pl) { + using FPBits = FPBits<T>; + FPBits pl_bits(pl); + + // Signaling NaNs don't have the mantissa's MSB set to 1, so they need a + // non-zero payload to distinguish them from infinities. + if (!IsSignaling && pl_bits.is_zero()) { + res = FPBits::quiet_nan(Sign::POS).get_val(); + return false; + } + + int pl_exp = pl_bits.get_exponent(); + + if (pl_bits.is_neg() || pl_exp < 0 || pl_exp >= FPBits::FRACTION_LEN - 1 || + ((pl_bits.get_mantissa() << pl_exp) & FPBits::FRACTION_MASK) != 0) { + res = T(0.0); + return true; + } + + using StorageType = typename FPBits::StorageType; + StorageType v(pl_bits.get_explicit_mantissa() >> (FPBits::SIG_LEN - pl_exp)); + + if constexpr (IsSignaling) + res = FPBits::signaling_nan(Sign::POS, v).get_val(); + else + res = FPBits::quiet_nan(Sign::POS, v).get_val(); + return false; +} + } // namespace fputil } // namespace LIBC_NAMESPACE diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 4472367..92e0cd2 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -210,6 +210,8 @@ add_math_entrypoint_object(fromfpxl) add_math_entrypoint_object(fromfpxf16) add_math_entrypoint_object(fromfpxf128) +add_math_entrypoint_object(getpayloadf16) + add_math_entrypoint_object(hypot) add_math_entrypoint_object(hypotf) @@ -350,6 +352,10 @@ add_math_entrypoint_object(scalbnf) add_math_entrypoint_object(scalbnl) add_math_entrypoint_object(scalbnf128) +add_math_entrypoint_object(setpayloadf16) + +add_math_entrypoint_object(setpayloadsigf16) + add_math_entrypoint_object(sincos) add_math_entrypoint_object(sincosf) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index aa0069d..f509b97 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -3603,6 +3603,45 @@ add_entrypoint_object( ) add_entrypoint_object( + getpayloadf16 + SRCS + getpayloadf16.cpp + HDRS + ../getpayloadf16.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + setpayloadf16 + SRCS + setpayloadf16.cpp + HDRS + ../setpayloadf16.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + setpayloadsigf16 + SRCS + setpayloadsigf16.cpp + HDRS + ../setpayloadsigf16.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( f16fmaf SRCS f16fmaf.cpp diff --git a/libc/src/math/generic/getpayloadf16.cpp b/libc/src/math/generic/getpayloadf16.cpp new file mode 100644 index 0000000..0923226 --- /dev/null +++ b/libc/src/math/generic/getpayloadf16.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of getpayloadf16 function --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/getpayloadf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float16, getpayloadf16, (const float16 *x)) { + return fputil::getpayload(*x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/setpayloadf16.cpp b/libc/src/math/generic/setpayloadf16.cpp new file mode 100644 index 0000000..98fc239 --- /dev/null +++ b/libc/src/math/generic/setpayloadf16.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of setpayloadf16 function --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/setpayloadf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, setpayloadf16, (float16 * res, float16 pl)) { + return static_cast<int>(fputil::setpayload</*IsSignaling=*/false>(*res, pl)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/setpayloadsigf16.cpp b/libc/src/math/generic/setpayloadsigf16.cpp new file mode 100644 index 0000000..c79620f --- /dev/null +++ b/libc/src/math/generic/setpayloadsigf16.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of setpayloadsigf16 function -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/setpayloadsigf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, setpayloadsigf16, (float16 * res, float16 pl)) { + return static_cast<int>(fputil::setpayload</*IsSignaling=*/true>(*res, pl)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/getpayloadf16.h b/libc/src/math/getpayloadf16.h new file mode 100644 index 0000000..1349dfd --- /dev/null +++ b/libc/src/math/getpayloadf16.h @@ -0,0 +1,20 @@ +//===-- Implementation header for getpayloadf16 -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_GETPAYLOADF16_H +#define LLVM_LIBC_SRC_MATH_GETPAYLOADF16_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float16 getpayloadf16(const float16 *x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_GETPAYLOADF16_H diff --git a/libc/src/math/setpayloadf16.h b/libc/src/math/setpayloadf16.h new file mode 100644 index 0000000..8705e28 --- /dev/null +++ b/libc/src/math/setpayloadf16.h @@ -0,0 +1,20 @@ +//===-- Implementation header for setpayloadf16 -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_SETPAYLOADF16_H +#define LLVM_LIBC_SRC_MATH_SETPAYLOADF16_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +int setpayloadf16(float16 *res, float16 pl); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_SETPAYLOADF16_H diff --git a/libc/src/math/setpayloadsigf16.h b/libc/src/math/setpayloadsigf16.h new file mode 100644 index 0000000..ee9bc38 --- /dev/null +++ b/libc/src/math/setpayloadsigf16.h @@ -0,0 +1,20 @@ +//===-- Implementation header for setpayloadsigf16 --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_SETPAYLOADSIGF16_H +#define LLVM_LIBC_SRC_MATH_SETPAYLOADSIGF16_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +int setpayloadsigf16(float16 *res, float16 pl); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_SETPAYLOADSIGF16_H diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index a67d043..bd8de18 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -3554,6 +3554,42 @@ add_fp_unittest( ) add_fp_unittest( + getpayloadf16_test + SUITE + libc-math-smoke-tests + SRCS + getpayloadf16_test.cpp + HDRS + GetPayloadTest.h + DEPENDS + libc.src.math.getpayloadf16 +) + +add_fp_unittest( + setpayloadf16_test + SUITE + libc-math-smoke-tests + SRCS + setpayloadf16_test.cpp + HDRS + SetPayloadTest.h + DEPENDS + libc.src.math.setpayloadf16 +) + +add_fp_unittest( + setpayloadsigf16_test + SUITE + libc-math-smoke-tests + SRCS + setpayloadsigf16_test.cpp + HDRS + SetPayloadSigTest.h + DEPENDS + libc.src.math.setpayloadsigf16 +) + +add_fp_unittest( f16fmaf_test SUITE libc-math-smoke-tests diff --git a/libc/test/src/math/smoke/GetPayloadTest.h b/libc/test/src/math/smoke/GetPayloadTest.h new file mode 100644 index 0000000..6e30de7 --- /dev/null +++ b/libc/test/src/math/smoke/GetPayloadTest.h @@ -0,0 +1,70 @@ +//===-- Utility class to test different flavors of getpayload ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LIBC_TEST_SRC_MATH_SMOKE_GETPAYLOADTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_GETPAYLOADTEST_H + +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class GetPayloadTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*GetPayloadFunc)(const T *); + + T funcWrapper(GetPayloadFunc func, T x) { return func(&x); } + + void testNonNaNs(GetPayloadFunc func) { + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, T(0.0))); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, T(-0.0))); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, T(0.1))); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, T(-0.1))); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, T(123.38))); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, T(-123.38))); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, inf)); + EXPECT_FP_EQ(T(-1.0), funcWrapper(func, neg_inf)); + } + + void testNaNs(GetPayloadFunc func) { + EXPECT_FP_EQ(T(0.0), funcWrapper(func, aNaN)); + EXPECT_FP_EQ(T(0.0), funcWrapper(func, neg_aNaN)); + + T default_snan_payload = StorageType(1) << (FPBits::SIG_LEN - 2); + EXPECT_FP_EQ(default_snan_payload, funcWrapper(func, sNaN)); + EXPECT_FP_EQ(default_snan_payload, funcWrapper(func, neg_sNaN)); + + T qnan_42 = FPBits::quiet_nan(Sign::POS, 0x42).get_val(); + T neg_qnan_42 = FPBits::quiet_nan(Sign::NEG, 0x42).get_val(); + T snan_42 = FPBits::signaling_nan(Sign::POS, 0x42).get_val(); + T neg_snan_42 = FPBits::signaling_nan(Sign::NEG, 0x42).get_val(); + EXPECT_FP_EQ(T(0x42.0p+0), funcWrapper(func, qnan_42)); + EXPECT_FP_EQ(T(0x42.0p+0), funcWrapper(func, neg_qnan_42)); + EXPECT_FP_EQ(T(0x42.0p+0), funcWrapper(func, snan_42)); + EXPECT_FP_EQ(T(0x42.0p+0), funcWrapper(func, neg_snan_42)); + + T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val(); + T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val(); + T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val(); + T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val(); + EXPECT_FP_EQ(T(0x123.0p+0), funcWrapper(func, qnan_123)); + EXPECT_FP_EQ(T(0x123.0p+0), funcWrapper(func, neg_qnan_123)); + EXPECT_FP_EQ(T(0x123.0p+0), funcWrapper(func, snan_123)); + EXPECT_FP_EQ(T(0x123.0p+0), funcWrapper(func, neg_snan_123)); + } +}; + +#define LIST_GETPAYLOAD_TESTS(T, func) \ + using LlvmLibcGetPayloadTest = GetPayloadTestTemplate<T>; \ + TEST_F(LlvmLibcGetPayloadTest, NonNaNs) { testNonNaNs(&func); } \ + TEST_F(LlvmLibcGetPayloadTest, NaNs) { testNaNs(&func); } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_GETPAYLOADTEST_H diff --git a/libc/test/src/math/smoke/SetPayloadSigTest.h b/libc/test/src/math/smoke/SetPayloadSigTest.h new file mode 100644 index 0000000..7ec3ac0 --- /dev/null +++ b/libc/test/src/math/smoke/SetPayloadSigTest.h @@ -0,0 +1,74 @@ +//===-- Utility class to test flavors of setpayloadsig ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADSIGTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADSIGTEST_H + +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class SetPayloadSigTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef int (*SetPayloadSigFunc)(T *, T); + + void testInvalidPayloads(SetPayloadSigFunc func) { + T res; + + EXPECT_EQ(1, func(&res, T(aNaN))); + EXPECT_EQ(1, func(&res, T(neg_aNaN))); + EXPECT_EQ(1, func(&res, T(inf))); + EXPECT_EQ(1, func(&res, T(neg_inf))); + EXPECT_EQ(1, func(&res, T(0.0))); + EXPECT_EQ(1, func(&res, T(-0.0))); + EXPECT_EQ(1, func(&res, T(0.1))); + EXPECT_EQ(1, func(&res, T(-0.1))); + EXPECT_EQ(1, func(&res, T(-1.0))); + EXPECT_EQ(1, func(&res, T(0x42.1p+0))); + EXPECT_EQ(1, func(&res, T(-0x42.1p+0))); + EXPECT_EQ(1, func(&res, T(StorageType(1) << (FPBits::FRACTION_LEN - 1)))); + } + + void testValidPayloads(SetPayloadSigFunc func) { + T res; + + EXPECT_EQ(0, func(&res, T(1.0))); + EXPECT_TRUE(FPBits(res).is_signaling_nan()); + EXPECT_EQ(FPBits::signaling_nan(Sign::POS, 1).uintval(), + FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(0x42.0p+0))); + EXPECT_TRUE(FPBits(res).is_signaling_nan()); + EXPECT_EQ(FPBits::signaling_nan(Sign::POS, 0x42).uintval(), + FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(0x123.0p+0))); + EXPECT_TRUE(FPBits(res).is_signaling_nan()); + EXPECT_EQ(FPBits::signaling_nan(Sign::POS, 0x123).uintval(), + FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(FPBits::FRACTION_MASK >> 1))); + EXPECT_TRUE(FPBits(res).is_signaling_nan()); + EXPECT_EQ( + FPBits::signaling_nan(Sign::POS, FPBits::FRACTION_MASK >> 1).uintval(), + FPBits(res).uintval()); + } +}; + +#define LIST_SETPAYLOADSIG_TESTS(T, func) \ + using LlvmLibcSetPayloadSigTest = SetPayloadSigTestTemplate<T>; \ + TEST_F(LlvmLibcSetPayloadSigTest, InvalidPayloads) { \ + testInvalidPayloads(&func); \ + } \ + TEST_F(LlvmLibcSetPayloadSigTest, ValidPayloads) { testValidPayloads(&func); } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADSIGTEST_H diff --git a/libc/test/src/math/smoke/SetPayloadTest.h b/libc/test/src/math/smoke/SetPayloadTest.h new file mode 100644 index 0000000..4b0dacf --- /dev/null +++ b/libc/test/src/math/smoke/SetPayloadTest.h @@ -0,0 +1,75 @@ +//===-- Utility class to test different flavors of setpayload ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADTEST_H + +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class SetPayloadTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef int (*SetPayloadFunc)(T *, T); + + void testInvalidPayloads(SetPayloadFunc func) { + T res; + + EXPECT_EQ(1, func(&res, T(aNaN))); + EXPECT_EQ(1, func(&res, T(neg_aNaN))); + EXPECT_EQ(1, func(&res, T(inf))); + EXPECT_EQ(1, func(&res, T(neg_inf))); + EXPECT_EQ(1, func(&res, T(0.1))); + EXPECT_EQ(1, func(&res, T(-0.1))); + EXPECT_EQ(1, func(&res, T(-1.0))); + EXPECT_EQ(1, func(&res, T(0x42.1p+0))); + EXPECT_EQ(1, func(&res, T(-0x42.1p+0))); + EXPECT_EQ(1, func(&res, T(StorageType(1) << (FPBits::FRACTION_LEN - 1)))); + } + + void testValidPayloads(SetPayloadFunc func) { + T res; + + EXPECT_EQ(0, func(&res, T(0.0))); + EXPECT_TRUE(FPBits(res).is_quiet_nan()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(1.0))); + EXPECT_TRUE(FPBits(res).is_quiet_nan()); + EXPECT_EQ(FPBits::quiet_nan(Sign::POS, 1).uintval(), FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(0x42.0p+0))); + EXPECT_TRUE(FPBits(res).is_quiet_nan()); + EXPECT_EQ(FPBits::quiet_nan(Sign::POS, 0x42).uintval(), + FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(0x123.0p+0))); + EXPECT_TRUE(FPBits(res).is_quiet_nan()); + EXPECT_EQ(FPBits::quiet_nan(Sign::POS, 0x123).uintval(), + FPBits(res).uintval()); + + EXPECT_EQ(0, func(&res, T(FPBits::FRACTION_MASK >> 1))); + EXPECT_TRUE(FPBits(res).is_quiet_nan()); + EXPECT_EQ( + FPBits::quiet_nan(Sign::POS, FPBits::FRACTION_MASK >> 1).uintval(), + FPBits(res).uintval()); + } +}; + +#define LIST_SETPAYLOAD_TESTS(T, func) \ + using LlvmLibcSetPayloadTest = SetPayloadTestTemplate<T>; \ + TEST_F(LlvmLibcSetPayloadTest, InvalidPayloads) { \ + testInvalidPayloads(&func); \ + } \ + TEST_F(LlvmLibcSetPayloadTest, ValidPayloads) { testValidPayloads(&func); } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_SETPAYLOADTEST_H diff --git a/libc/test/src/math/smoke/getpayloadf16_test.cpp b/libc/test/src/math/smoke/getpayloadf16_test.cpp new file mode 100644 index 0000000..385b047 --- /dev/null +++ b/libc/test/src/math/smoke/getpayloadf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for getpayloadf16 ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "GetPayloadTest.h" + +#include "src/math/getpayloadf16.h" + +LIST_GETPAYLOAD_TESTS(float16, LIBC_NAMESPACE::getpayloadf16) diff --git a/libc/test/src/math/smoke/setpayloadf16_test.cpp b/libc/test/src/math/smoke/setpayloadf16_test.cpp new file mode 100644 index 0000000..ccf5370 --- /dev/null +++ b/libc/test/src/math/smoke/setpayloadf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for setpayloadf16 ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SetPayloadTest.h" + +#include "src/math/setpayloadf16.h" + +LIST_SETPAYLOAD_TESTS(float16, LIBC_NAMESPACE::setpayloadf16) diff --git a/libc/test/src/math/smoke/setpayloadsigf16_test.cpp b/libc/test/src/math/smoke/setpayloadsigf16_test.cpp new file mode 100644 index 0000000..9f786e6 --- /dev/null +++ b/libc/test/src/math/smoke/setpayloadsigf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for setpayloadsigf16 ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SetPayloadSigTest.h" + +#include "src/math/setpayloadsigf16.h" + +LIST_SETPAYLOADSIG_TESTS(float16, LIBC_NAMESPACE::setpayloadsigf16) |