1 //===-- Utility class to test FMod generic implementation -------*- 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 #include "src/__support/CPP/TypeTraits.h" 9 #include "src/__support/FPUtil/generic/FMod.h" 10 #include "utils/MPFRWrapper/MPFRUtils.h" 11 #include "utils/UnitTest/FPMatcher.h" 12 #include "utils/UnitTest/Test.h" 13 14 #include <array> 15 #include <limits> 16 17 namespace mpfr = __llvm_libc::testing::mpfr; 18 19 template <typename T, bool InverseMultiplication> 20 class LlvmLibcFModTest : public __llvm_libc::testing::Test { 21 22 using DivisionHelper = __llvm_libc::cpp::ConditionalType< 23 InverseMultiplication, 24 __llvm_libc::fputil::generic::FModDivisionInvMultHelper<T>, 25 __llvm_libc::fputil::generic::FModDivisionSimpleHelper<T>>; 26 27 static constexpr std::array<T, 11> test_bases = { 28 T(0.0), 29 T(1.0), 30 T(3.0), 31 T(27.0), 32 T(11.0 / 8.0), 33 T(2.764443), 34 T(1.0) - std::numeric_limits<T>::epsilon(), 35 T(1.0) + std::numeric_limits<T>::epsilon(), 36 T(M_PI), 37 T(M_SQRT2), 38 T(M_E)}; 39 40 public: 41 void testExtensive() { 42 using FMod = __llvm_libc::fputil::generic::FMod< 43 T, __llvm_libc::fputil::generic::FModFastMathWrapper<T>, 44 DivisionHelper>; 45 using nl = std::numeric_limits<T>; 46 int min2 = nl::min_exponent - nl::digits - 5; 47 int max2 = nl::max_exponent + 3; 48 for (T by : test_bases) { 49 for (int iy = min2; iy < max2; iy++) { 50 T y = by * std::ldexp(2, iy); 51 if (y == 0 || !std::isfinite(y)) 52 continue; 53 for (T bx : test_bases) { 54 for (int ix = min2; ix < max2; ix++) { 55 T x = bx * std::ldexp(2, ix); 56 if (!std::isfinite(x)) 57 continue; 58 T result = FMod::eval(x, y); 59 mpfr::BinaryInput<T> input{x, y}; 60 EXPECT_MPFR_MATCH(mpfr::Operation::Fmod, input, result, 0.0); 61 } 62 } 63 } 64 } 65 } 66 }; 67 68 using LlvmLibcFModFloatTest = LlvmLibcFModTest<float, false>; 69 TEST_F(LlvmLibcFModFloatTest, ExtensiveTest) { testExtensive(); } 70 71 using LlvmLibcFModFloatInvTest = LlvmLibcFModTest<float, true>; 72 TEST_F(LlvmLibcFModFloatInvTest, ExtensiveTest) { testExtensive(); } 73 74 using LlvmLibcFModDoubleTest = LlvmLibcFModTest<double, false>; 75 TEST_F(LlvmLibcFModDoubleTest, ExtensiveTest) { testExtensive(); } 76 77 using LlvmLibcFModDoubleInvTest = LlvmLibcFModTest<double, true>; 78 TEST_F(LlvmLibcFModDoubleInvTest, ExtensiveTest) { testExtensive(); } 79