123 lines · c
1//===-- Utility class to test different flavors of fma --------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_TEST_SRC_MATH_FMATEST_H10#define LLVM_LIBC_TEST_SRC_MATH_FMATEST_H11 12#include "src/__support/FPUtil/cast.h"13#include "test/UnitTest/FEnvSafeTest.h"14#include "test/UnitTest/FPMatcher.h"15#include "test/UnitTest/Test.h"16 17template <typename OutType, typename InType = OutType>18class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {19 20 struct OutConstants {21 DECLARE_SPECIAL_CONSTANTS(OutType)22 };23 24 struct InConstants {25 DECLARE_SPECIAL_CONSTANTS(InType)26 };27 28 using OutFPBits = typename OutConstants::FPBits;29 using OutStorageType = typename OutConstants::StorageType;30 using InFPBits = typename InConstants::FPBits;31 using InStorageType = typename InConstants::StorageType;32 33 static constexpr OutStorageType OUT_MIN_NORMAL_U =34 OutFPBits::min_normal().uintval();35 static constexpr InStorageType IN_MIN_NORMAL_U =36 InFPBits::min_normal().uintval();37 38 OutConstants out;39 InConstants in;40 41 const InType in_out_min_normal =42 LIBC_NAMESPACE::fputil::cast<InType>(out.min_normal);43 const InType in_out_min_denormal =44 LIBC_NAMESPACE::fputil::cast<InType>(out.min_denormal);45 46public:47 using FmaFunc = OutType (*)(InType, InType, InType);48 49 void test_special_numbers(FmaFunc func) {50 EXPECT_FP_EQ(out.zero, func(in.zero, in.zero, in.zero));51 EXPECT_FP_EQ(out.neg_zero, func(in.zero, in.neg_zero, in.neg_zero));52 EXPECT_FP_EQ(out.inf, func(in.inf, in.inf, in.zero));53 EXPECT_FP_EQ(out.neg_inf, func(in.neg_inf, in.inf, in.neg_inf));54 EXPECT_FP_EQ(out.aNaN, func(in.inf, in.zero, in.zero));55 EXPECT_FP_EQ(out.aNaN, func(in.inf, in.neg_inf, in.inf));56 EXPECT_FP_EQ(out.aNaN, func(in.aNaN, in.zero, in.inf));57 EXPECT_FP_EQ(out.aNaN, func(in.inf, in.neg_inf, in.aNaN));58 59 // Test underflow rounding up.60 EXPECT_FP_EQ(OutFPBits(OutStorageType(2)).get_val(),61 func(InType(0.5), in_out_min_denormal, in_out_min_denormal));62 63 if constexpr (sizeof(OutType) < sizeof(InType)) {64 EXPECT_FP_EQ(out.zero,65 func(InType(0.5), in.min_denormal, in.min_denormal));66 }67 68 // Test underflow rounding down.69 OutType v = OutFPBits(static_cast<OutStorageType>(OUT_MIN_NORMAL_U +70 OutStorageType(1)))71 .get_val();72 EXPECT_FP_EQ(v, func(InType(1) / InType(OUT_MIN_NORMAL_U << 1),73 LIBC_NAMESPACE::fputil::cast<InType>(v),74 in_out_min_normal));75 76 if constexpr (sizeof(OutType) < sizeof(InType)) {77 InFPBits tmp = InFPBits::one();78 tmp.set_biased_exponent(InFPBits::EXP_BIAS - InFPBits::FRACTION_LEN - 1);79 InType reciprocal_value = tmp.get_val();80 81 InType v = InFPBits(static_cast<InStorageType>(IN_MIN_NORMAL_U +82 InStorageType(1)))83 .get_val();84 EXPECT_FP_EQ(out.min_normal,85 func(reciprocal_value, v, in_out_min_normal));86 }87 88 // Test overflow.89 InType in_z = LIBC_NAMESPACE::fputil::cast<InType>(out.max_normal);90 EXPECT_FP_EQ_ALL_ROUNDING(func(InType(-0.25), in_z, in_z),91 func(InType(1.75), in_z, -in_z));92 93 // Exact cancellation.94 EXPECT_FP_EQ_ROUNDING_NEAREST(95 out.zero, func(InType(3.0), InType(5.0), InType(-15.0)));96 EXPECT_FP_EQ_ROUNDING_UPWARD(out.zero,97 func(InType(3.0), InType(5.0), InType(-15.0)));98 EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(99 out.zero, func(InType(3.0), InType(5.0), InType(-15.0)));100 EXPECT_FP_EQ_ROUNDING_DOWNWARD(101 out.neg_zero, func(InType(3.0), InType(5.0), InType(-15.0)));102 103 EXPECT_FP_EQ_ROUNDING_NEAREST(104 out.zero, func(InType(-3.0), InType(5.0), InType(15.0)));105 EXPECT_FP_EQ_ROUNDING_UPWARD(out.zero,106 func(InType(-3.0), InType(5.0), InType(15.0)));107 EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(108 out.zero, func(InType(-3.0), InType(5.0), InType(15.0)));109 EXPECT_FP_EQ_ROUNDING_DOWNWARD(110 out.neg_zero, func(InType(-3.0), InType(5.0), InType(15.0)));111 }112};113 114#define LIST_FMA_TESTS(T, func) \115 using LlvmLibcFmaTest = FmaTestTemplate<T>; \116 TEST_F(LlvmLibcFmaTest, SpecialNumbers) { test_special_numbers(&func); }117 118#define LIST_NARROWING_FMA_TESTS(OutType, InType, func) \119 using LlvmLibcFmaTest = FmaTestTemplate<OutType, InType>; \120 TEST_F(LlvmLibcFmaTest, SpecialNumbers) { test_special_numbers(&func); }121 122#endif // LLVM_LIBC_TEST_SRC_MATH_FMATEST_H123