96 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_TEST_SRC_MATH_MULTEST_H10#define LLVM_LIBC_TEST_SRC_MATH_MULTEST_H11 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 19namespace mpfr = LIBC_NAMESPACE::testing::mpfr;20 21template <typename OutType, typename InType>22class 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 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 47public:48 using MulFunc = OutType (*)(InType, InType);49 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_H96