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/type_traits.h" |
9 | #include "src/__support/FPUtil/FPBits.h" |
10 | #include "src/__support/FPUtil/ManipulationFunctions.h" // ldexp |
11 | #include "src/__support/FPUtil/generic/FMod.h" |
12 | #include "test/UnitTest/FEnvSafeTest.h" |
13 | #include "test/UnitTest/FPMatcher.h" |
14 | #include "test/UnitTest/Test.h" |
15 | #include "utils/MPFRWrapper/MPFRUtils.h" |
16 | |
17 | #include <array> |
18 | |
19 | namespace mpfr = LIBC_NAMESPACE::testing::mpfr; |
20 | |
21 | template <typename T, bool InverseMultiplication> |
22 | class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { |
23 | |
24 | using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; |
25 | using U = typename FPBits::StorageType; |
26 | using DivisionHelper = LIBC_NAMESPACE::cpp::conditional_t< |
27 | InverseMultiplication, |
28 | LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper<U>, |
29 | LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper<U>>; |
30 | |
31 | static constexpr std::array<T, 11> TEST_BASES = { |
32 | T(0.0), |
33 | T(1.0), |
34 | T(3.0), |
35 | T(27.0), |
36 | T(11.0 / 8.0), |
37 | T(2.764443), |
38 | T(1.0) - T(0x1.0p-23) - T(0x1.0p-52) - T(0x1.0p-112), |
39 | T(1.0) + T(0x1.0p-23) + T(0x1.0p-52) + T(0x1.0p-112), |
40 | T(3.14159265), |
41 | T(1.41421356), |
42 | T(2.71828183)}; |
43 | |
44 | public: |
45 | void testExtensive() { |
46 | using FMod = LIBC_NAMESPACE::fputil::generic::FMod<T, U, DivisionHelper>; |
47 | int min2 = -(FPBits::MAX_BIASED_EXPONENT + FPBits::SIG_LEN) / 2; |
48 | int max2 = 3 + FPBits::MAX_BIASED_EXPONENT / 2; |
49 | for (T by : TEST_BASES) { |
50 | for (int iy = min2; iy < max2; iy++) { |
51 | T y = by * LIBC_NAMESPACE::fputil::ldexp(x: 2.0, exp: iy); |
52 | FPBits y_bits(y); |
53 | if (y_bits.is_zero() || !y_bits.is_finite()) |
54 | continue; |
55 | for (T bx : TEST_BASES) { |
56 | for (int ix = min2; ix < max2; ix++) { |
57 | T x = bx * LIBC_NAMESPACE::fputil::ldexp(x: 2.0, exp: ix); |
58 | if (!FPBits(x).is_finite()) |
59 | continue; |
60 | T result = FMod::eval(x, y); |
61 | mpfr::BinaryInput<T> input{x, y}; |
62 | EXPECT_MPFR_MATCH(mpfr::Operation::Fmod, input, result, 0.0); |
63 | } |
64 | } |
65 | } |
66 | } |
67 | } |
68 | }; |
69 | |
70 | using LlvmLibcFModFloatTest = LlvmLibcFModTest<float, false>; |
71 | TEST_F(LlvmLibcFModFloatTest, ExtensiveTest) { testExtensive(); } |
72 | |
73 | using LlvmLibcFModFloatInvTest = LlvmLibcFModTest<float, true>; |
74 | TEST_F(LlvmLibcFModFloatInvTest, ExtensiveTest) { testExtensive(); } |
75 | |
76 | using LlvmLibcFModDoubleTest = LlvmLibcFModTest<double, false>; |
77 | TEST_F(LlvmLibcFModDoubleTest, ExtensiveTest) { testExtensive(); } |
78 | |
79 | using LlvmLibcFModDoubleInvTest = LlvmLibcFModTest<double, true>; |
80 | TEST_F(LlvmLibcFModDoubleInvTest, ExtensiveTest) { testExtensive(); } |
81 | |