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:
testExtensive()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>;
TEST_F(LlvmLibcFModFloatTest,ExtensiveTest)69 TEST_F(LlvmLibcFModFloatTest, ExtensiveTest) { testExtensive(); }
70 
71 using LlvmLibcFModFloatInvTest = LlvmLibcFModTest<float, true>;
TEST_F(LlvmLibcFModFloatInvTest,ExtensiveTest)72 TEST_F(LlvmLibcFModFloatInvTest, ExtensiveTest) { testExtensive(); }
73 
74 using LlvmLibcFModDoubleTest = LlvmLibcFModTest<double, false>;
TEST_F(LlvmLibcFModDoubleTest,ExtensiveTest)75 TEST_F(LlvmLibcFModDoubleTest, ExtensiveTest) { testExtensive(); }
76 
77 using LlvmLibcFModDoubleInvTest = LlvmLibcFModTest<double, true>;
TEST_F(LlvmLibcFModDoubleInvTest,ExtensiveTest)78 TEST_F(LlvmLibcFModDoubleInvTest, ExtensiveTest) { testExtensive(); }
79