1b8e8012aSKirill Okhotnikov //===-- Utility class to test FMod generic implementation -------*- C++ -*-===//
2b8e8012aSKirill Okhotnikov //
3b8e8012aSKirill Okhotnikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b8e8012aSKirill Okhotnikov // See https://llvm.org/LICENSE.txt for license information.
5b8e8012aSKirill Okhotnikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b8e8012aSKirill Okhotnikov //
7b8e8012aSKirill Okhotnikov //===----------------------------------------------------------------------===//
8f7226150SGuillaume Chatelet #include "src/__support/CPP/type_traits.h"
95d56b348SMichael Jones #include "src/__support/FPUtil/FPBits.h"
105d56b348SMichael Jones #include "src/__support/FPUtil/ManipulationFunctions.h" // ldexp
11b8e8012aSKirill Okhotnikov #include "src/__support/FPUtil/generic/FMod.h"
12*837dab96SRoland McGrath #include "test/UnitTest/FEnvSafeTest.h"
13af1315c2SSiva Chandra Reddy #include "test/UnitTest/FPMatcher.h"
14af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
15b8e8012aSKirill Okhotnikov #include "utils/MPFRWrapper/MPFRUtils.h"
16b8e8012aSKirill Okhotnikov
17b8e8012aSKirill Okhotnikov #include <array>
18b8e8012aSKirill Okhotnikov
19b6bc9d72SGuillaume Chatelet namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
20b8e8012aSKirill Okhotnikov
21b8e8012aSKirill Okhotnikov template <typename T, bool InverseMultiplication>
22*837dab96SRoland McGrath class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
23b8e8012aSKirill Okhotnikov
245d56b348SMichael Jones using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
255d56b348SMichael Jones using U = typename FPBits::StorageType;
26b6bc9d72SGuillaume Chatelet using DivisionHelper = LIBC_NAMESPACE::cpp::conditional_t<
27b8e8012aSKirill Okhotnikov InverseMultiplication,
284d21e752Slntue LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper<U>,
294d21e752Slntue LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper<U>>;
30b8e8012aSKirill Okhotnikov
315d56b348SMichael Jones static constexpr std::array<T, 11> TEST_BASES = {
32b8e8012aSKirill Okhotnikov T(0.0),
33b8e8012aSKirill Okhotnikov T(1.0),
34b8e8012aSKirill Okhotnikov T(3.0),
35b8e8012aSKirill Okhotnikov T(27.0),
36b8e8012aSKirill Okhotnikov T(11.0 / 8.0),
37b8e8012aSKirill Okhotnikov T(2.764443),
385d56b348SMichael Jones T(1.0) - T(0x1.0p-23) - T(0x1.0p-52) - T(0x1.0p-112),
395d56b348SMichael Jones T(1.0) + T(0x1.0p-23) + T(0x1.0p-52) + T(0x1.0p-112),
405d56b348SMichael Jones T(3.14159265),
415d56b348SMichael Jones T(1.41421356),
425d56b348SMichael Jones T(2.71828183)};
43b8e8012aSKirill Okhotnikov
44b8e8012aSKirill Okhotnikov public:
testExtensive()45b8e8012aSKirill Okhotnikov void testExtensive() {
464d21e752Slntue using FMod = LIBC_NAMESPACE::fputil::generic::FMod<T, U, DivisionHelper>;
475d56b348SMichael Jones int min2 = -(FPBits::MAX_BIASED_EXPONENT + FPBits::SIG_LEN) / 2;
485d56b348SMichael Jones int max2 = 3 + FPBits::MAX_BIASED_EXPONENT / 2;
495d56b348SMichael Jones for (T by : TEST_BASES) {
50b8e8012aSKirill Okhotnikov for (int iy = min2; iy < max2; iy++) {
515d56b348SMichael Jones T y = by * LIBC_NAMESPACE::fputil::ldexp(2.0, iy);
525d56b348SMichael Jones FPBits y_bits(y);
535d56b348SMichael Jones if (y_bits.is_zero() || !y_bits.is_finite())
54b8e8012aSKirill Okhotnikov continue;
555d56b348SMichael Jones for (T bx : TEST_BASES) {
56b8e8012aSKirill Okhotnikov for (int ix = min2; ix < max2; ix++) {
575d56b348SMichael Jones T x = bx * LIBC_NAMESPACE::fputil::ldexp(2.0, ix);
585d56b348SMichael Jones if (!FPBits(x).is_finite())
59b8e8012aSKirill Okhotnikov continue;
60b8e8012aSKirill Okhotnikov T result = FMod::eval(x, y);
61b8e8012aSKirill Okhotnikov mpfr::BinaryInput<T> input{x, y};
62b8e8012aSKirill Okhotnikov EXPECT_MPFR_MATCH(mpfr::Operation::Fmod, input, result, 0.0);
63b8e8012aSKirill Okhotnikov }
64b8e8012aSKirill Okhotnikov }
65b8e8012aSKirill Okhotnikov }
66b8e8012aSKirill Okhotnikov }
67b8e8012aSKirill Okhotnikov }
68b8e8012aSKirill Okhotnikov };
69b8e8012aSKirill Okhotnikov
70b8e8012aSKirill Okhotnikov using LlvmLibcFModFloatTest = LlvmLibcFModTest<float, false>;
TEST_F(LlvmLibcFModFloatTest,ExtensiveTest)71b8e8012aSKirill Okhotnikov TEST_F(LlvmLibcFModFloatTest, ExtensiveTest) { testExtensive(); }
72b8e8012aSKirill Okhotnikov
73b8e8012aSKirill Okhotnikov using LlvmLibcFModFloatInvTest = LlvmLibcFModTest<float, true>;
TEST_F(LlvmLibcFModFloatInvTest,ExtensiveTest)74b8e8012aSKirill Okhotnikov TEST_F(LlvmLibcFModFloatInvTest, ExtensiveTest) { testExtensive(); }
75b8e8012aSKirill Okhotnikov
76b8e8012aSKirill Okhotnikov using LlvmLibcFModDoubleTest = LlvmLibcFModTest<double, false>;
TEST_F(LlvmLibcFModDoubleTest,ExtensiveTest)77b8e8012aSKirill Okhotnikov TEST_F(LlvmLibcFModDoubleTest, ExtensiveTest) { testExtensive(); }
78b8e8012aSKirill Okhotnikov
79b8e8012aSKirill Okhotnikov using LlvmLibcFModDoubleInvTest = LlvmLibcFModTest<double, true>;
TEST_F(LlvmLibcFModDoubleInvTest,ExtensiveTest)80b8e8012aSKirill Okhotnikov TEST_F(LlvmLibcFModDoubleInvTest, ExtensiveTest) { testExtensive(); }
81