1 //===-- Utility class to test different flavors of float mul ----*- 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_MULTEST_H 10 #define LLVM_LIBC_TEST_SRC_MATH_MULTEST_H 11 12 #include "src/stdlib/rand.h" 13 #include "src/stdlib/srand.h" 14 #include "test/UnitTest/FEnvSafeTest.h" 15 #include "test/UnitTest/FPMatcher.h" 16 #include "test/UnitTest/Test.h" 17 #include "utils/MPFRWrapper/MPFRUtils.h" 18 19 namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 20 21 template <typename OutType, typename InType> 22 class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 23 24 struct InConstants { 25 DECLARE_SPECIAL_CONSTANTS(InType) 26 }; 27 28 using InFPBits = typename InConstants::FPBits; 29 using InStorageType = typename InConstants::StorageType; 30 31 static constexpr InStorageType IN_MAX_NORMAL_U = 32 InFPBits::max_normal().uintval(); 33 static constexpr InStorageType IN_MIN_NORMAL_U = 34 InFPBits::min_normal().uintval(); 35 static constexpr InStorageType IN_MAX_SUBNORMAL_U = 36 InFPBits::max_subnormal().uintval(); 37 static constexpr InStorageType IN_MIN_SUBNORMAL_U = 38 InFPBits::min_subnormal().uintval(); 39 get_random_bit_pattern()40 InStorageType get_random_bit_pattern() { 41 InStorageType bits{0}; 42 for (InStorageType i = 0; i < sizeof(InStorageType) / 2; ++i) 43 bits = (bits << 2) + static_cast<uint16_t>(LIBC_NAMESPACE::rand()); 44 return bits; 45 } 46 47 public: 48 using MulFunc = OutType (*)(InType, InType); 49 test_subnormal_range(MulFunc func)50 void test_subnormal_range(MulFunc func) { 51 constexpr InStorageType COUNT = 10'001; 52 constexpr InStorageType STEP = 53 (IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) / COUNT; 54 LIBC_NAMESPACE::srand(1); 55 for (int signs = 0; signs < 4; signs++) { 56 for (InStorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) { 57 InType x = InFPBits(get_random_bit_pattern()).get_val(); 58 InType y = InFPBits(v).get_val(); 59 if ((signs & 1) != 0) 60 x = -x; 61 if ((signs & 2) != 0) 62 y = -y; 63 mpfr::BinaryInput<InType> input{x, y}; 64 EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, func(x, y), 65 0.5); 66 } 67 } 68 } 69 70 void test_normal_range(MulFunc func) { 71 constexpr InStorageType COUNT = 10'001; 72 constexpr InStorageType STEP = (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT; 73 LIBC_NAMESPACE::srand(1); 74 for (int signs = 0; signs < 4; signs++) { 75 for (InStorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) { 76 InType x = InFPBits(get_random_bit_pattern()).get_val(); 77 InType y = InFPBits(v).get_val(); 78 if ((signs & 1) != 0) 79 x = -x; 80 if ((signs & 2) != 0) 81 y = -y; 82 mpfr::BinaryInput<InType> input{x, y}; 83 EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, func(x, y), 84 0.5); 85 } 86 } 87 } 88 }; 89 90 #define LIST_MUL_TESTS(OutType, InType, func) \ 91 using LlvmLibcMulTest = MulTest<OutType, InType>; \ 92 TEST_F(LlvmLibcMulTest, SubnormalRange) { test_subnormal_range(&func); } \ 93 TEST_F(LlvmLibcMulTest, NormalRange) { test_normal_range(&func); } 94 95 #endif // LLVM_LIBC_TEST_SRC_MATH_MULTEST_H 96