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