[libc-commits] [libc] [libc][math][c23] Add f16fmaf C23 math function (PR #95483)
via libc-commits
libc-commits at lists.llvm.org
Fri Jun 14 07:00:36 PDT 2024
================
@@ -19,85 +18,115 @@
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
-template <typename T>
+template <typename OutType, typename InType = OutType>
class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
-private:
- using Func = T (*)(T, T, T);
- using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
- using StorageType = typename FPBits::StorageType;
-
- const T min_subnormal = FPBits::min_subnormal(Sign::POS).get_val();
- const T min_normal = FPBits::min_normal(Sign::POS).get_val();
- const T max_normal = FPBits::max_normal(Sign::POS).get_val();
- const T inf = FPBits::inf(Sign::POS).get_val();
- const T neg_inf = FPBits::inf(Sign::NEG).get_val();
- const T zero = FPBits::zero(Sign::POS).get_val();
- const T neg_zero = FPBits::zero(Sign::NEG).get_val();
- const T nan = FPBits::quiet_nan().get_val();
-
- static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
- static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
- static constexpr StorageType MAX_SUBNORMAL =
- FPBits::max_subnormal().uintval();
- static constexpr StorageType MIN_SUBNORMAL =
- FPBits::min_subnormal().uintval();
-
- StorageType get_random_bit_pattern() {
- StorageType bits{0};
- for (StorageType i = 0; i < sizeof(StorageType) / 2; ++i) {
+
+ struct OutConstants {
+ DECLARE_SPECIAL_CONSTANTS(OutType)
+ };
+
+ struct InConstants {
+ DECLARE_SPECIAL_CONSTANTS(InType)
+ };
+
+ using OutFPBits = typename OutConstants::FPBits;
+ using OutStorageType = typename OutConstants::StorageType;
+ using InFPBits = typename InConstants::FPBits;
+ using InStorageType = typename InConstants::StorageType;
+
+ static constexpr OutStorageType OUT_MIN_NORMAL_U =
+ OutFPBits::min_normal().uintval();
+ static constexpr InStorageType IN_MAX_NORMAL_U =
+ InFPBits::max_normal().uintval();
+ static constexpr InStorageType IN_MIN_NORMAL_U =
+ InFPBits::min_normal().uintval();
+ static constexpr InStorageType IN_MAX_SUBNORMAL_U =
+ InFPBits::max_subnormal().uintval();
+ static constexpr InStorageType IN_MIN_SUBNORMAL_U =
+ InFPBits::min_subnormal().uintval();
+
+ OutConstants out;
+ InConstants in;
+
+ InStorageType get_random_bit_pattern() {
+ InStorageType bits{0};
+ for (InStorageType i = 0; i < sizeof(InStorageType) / 2; ++i) {
bits = (bits << 2) + static_cast<uint16_t>(LIBC_NAMESPACE::rand());
}
return bits;
}
public:
- void test_special_numbers(Func func) {
- EXPECT_FP_EQ(func(zero, zero, zero), zero);
- EXPECT_FP_EQ(func(zero, neg_zero, neg_zero), neg_zero);
- EXPECT_FP_EQ(func(inf, inf, zero), inf);
- EXPECT_FP_EQ(func(neg_inf, inf, neg_inf), neg_inf);
- EXPECT_FP_EQ(func(inf, zero, zero), nan);
- EXPECT_FP_EQ(func(inf, neg_inf, inf), nan);
- EXPECT_FP_EQ(func(nan, zero, inf), nan);
- EXPECT_FP_EQ(func(inf, neg_inf, nan), nan);
+ using FmaFunc = OutType (*)(InType, InType, InType);
+
+ void test_special_numbers(FmaFunc func) {
+ EXPECT_FP_EQ(out.zero, func(in.zero, in.zero, in.zero));
+ EXPECT_FP_EQ(out.neg_zero, func(in.zero, in.neg_zero, in.neg_zero));
+ EXPECT_FP_EQ(out.inf, func(in.inf, in.inf, in.zero));
+ EXPECT_FP_EQ(out.neg_inf, func(in.neg_inf, in.inf, in.neg_inf));
+ EXPECT_FP_EQ(out.aNaN, func(in.inf, in.zero, in.zero));
+ EXPECT_FP_EQ(out.aNaN, func(in.inf, in.neg_inf, in.inf));
+ EXPECT_FP_EQ(out.aNaN, func(in.aNaN, in.zero, in.inf));
+ EXPECT_FP_EQ(out.aNaN, func(in.inf, in.neg_inf, in.aNaN));
// Test underflow rounding up.
- EXPECT_FP_EQ(func(T(0.5), min_subnormal, min_subnormal),
- FPBits(StorageType(2)).get_val());
+ EXPECT_FP_EQ(OutFPBits(OutStorageType(2)).get_val(),
+ func(OutType(0.5), out.min_denormal, out.min_denormal));
+
+ if constexpr (sizeof(OutType) < sizeof(InType)) {
+ EXPECT_FP_EQ(out.zero,
+ func(InType(0.5), in.min_denormal, in.min_denormal));
+ }
// Test underflow rounding down.
- T v = FPBits(MIN_NORMAL + StorageType(1)).get_val();
- EXPECT_FP_EQ(func(T(1) / T(MIN_NORMAL << 1), v, min_normal), v);
+ OutType v = OutFPBits(static_cast<OutStorageType>(OUT_MIN_NORMAL_U +
+ OutStorageType(1)))
+ .get_val();
+ EXPECT_FP_EQ(v, func(OutType(1) / OutType(OUT_MIN_NORMAL_U << 1), v,
+ out.min_normal));
+
+ if constexpr (sizeof(OutType) < sizeof(InType)) {
+ InType v = InFPBits(static_cast<InStorageType>(IN_MIN_NORMAL_U +
+ InStorageType(1)))
+ .get_val();
+ EXPECT_FP_EQ(
+ out.min_normal,
+ func(InType(1) / InType(IN_MIN_NORMAL_U << 1), v, out.min_normal));
+ }
// Test overflow.
- T z = max_normal;
- EXPECT_FP_EQ(func(T(1.75), z, -z), T(0.75) * z);
+ OutType z = out.max_normal;
+ EXPECT_FP_EQ(OutType(0.75) * z, func(InType(1.75), z, -z));
----------------
overmighty wrote:
By the way, the whole `test_special_numbers` function is copied from the smoke test. Should we remove it from the MPFR unit test?
https://github.com/llvm/llvm-project/pull/95483
More information about the libc-commits
mailing list