1*71db0c75SAndroid Build Coastguard Worker //===-- Utility class to test different flavors of remquo -------*- C++ -*-===// 2*71db0c75SAndroid Build Coastguard Worker // 3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*71db0c75SAndroid Build Coastguard Worker // 7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 8*71db0c75SAndroid Build Coastguard Worker 9*71db0c75SAndroid Build Coastguard Worker #ifndef LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 10*71db0c75SAndroid Build Coastguard Worker #define LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 11*71db0c75SAndroid Build Coastguard Worker 12*71db0c75SAndroid Build Coastguard Worker #include "hdr/math_macros.h" 13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/BasicOperations.h" 14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h" 15*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FEnvSafeTest.h" 16*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FPMatcher.h" 17*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h" 18*71db0c75SAndroid Build Coastguard Worker #include "utils/MPFRWrapper/MPFRUtils.h" 19*71db0c75SAndroid Build Coastguard Worker 20*71db0c75SAndroid Build Coastguard Worker namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 21*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::Sign; 22*71db0c75SAndroid Build Coastguard Worker 23*71db0c75SAndroid Build Coastguard Worker template <typename T> 24*71db0c75SAndroid Build Coastguard Worker class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { 25*71db0c75SAndroid Build Coastguard Worker using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; 26*71db0c75SAndroid Build Coastguard Worker using StorageType = typename FPBits::StorageType; 27*71db0c75SAndroid Build Coastguard Worker 28*71db0c75SAndroid Build Coastguard Worker const T inf = FPBits::inf(Sign::POS).get_val(); 29*71db0c75SAndroid Build Coastguard Worker const T neg_inf = FPBits::inf(Sign::NEG).get_val(); 30*71db0c75SAndroid Build Coastguard Worker const T zero = FPBits::zero(Sign::POS).get_val(); 31*71db0c75SAndroid Build Coastguard Worker const T neg_zero = FPBits::zero(Sign::NEG).get_val(); 32*71db0c75SAndroid Build Coastguard Worker const T nan = FPBits::quiet_nan().get_val(); 33*71db0c75SAndroid Build Coastguard Worker 34*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MIN_SUBNORMAL = 35*71db0c75SAndroid Build Coastguard Worker FPBits::min_subnormal().uintval(); 36*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MAX_SUBNORMAL = 37*71db0c75SAndroid Build Coastguard Worker FPBits::max_subnormal().uintval(); 38*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); 39*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); 40*71db0c75SAndroid Build Coastguard Worker 41*71db0c75SAndroid Build Coastguard Worker public: 42*71db0c75SAndroid Build Coastguard Worker typedef T (*RemQuoFunc)(T, T, int *); 43*71db0c75SAndroid Build Coastguard Worker testSpecialNumbers(RemQuoFunc func)44*71db0c75SAndroid Build Coastguard Worker void testSpecialNumbers(RemQuoFunc func) { 45*71db0c75SAndroid Build Coastguard Worker int quotient; 46*71db0c75SAndroid Build Coastguard Worker T x, y; 47*71db0c75SAndroid Build Coastguard Worker 48*71db0c75SAndroid Build Coastguard Worker y = T(1.0); 49*71db0c75SAndroid Build Coastguard Worker x = inf; 50*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 51*71db0c75SAndroid Build Coastguard Worker x = neg_inf; 52*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 53*71db0c75SAndroid Build Coastguard Worker 54*71db0c75SAndroid Build Coastguard Worker x = T(1.0); 55*71db0c75SAndroid Build Coastguard Worker y = zero; 56*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 57*71db0c75SAndroid Build Coastguard Worker y = neg_zero; 58*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 59*71db0c75SAndroid Build Coastguard Worker 60*71db0c75SAndroid Build Coastguard Worker y = nan; 61*71db0c75SAndroid Build Coastguard Worker x = T(1.0); 62*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 63*71db0c75SAndroid Build Coastguard Worker 64*71db0c75SAndroid Build Coastguard Worker y = T(1.0); 65*71db0c75SAndroid Build Coastguard Worker x = nan; 66*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 67*71db0c75SAndroid Build Coastguard Worker 68*71db0c75SAndroid Build Coastguard Worker x = nan; 69*71db0c75SAndroid Build Coastguard Worker y = nan; 70*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(nan, func(x, y, "ient)); 71*71db0c75SAndroid Build Coastguard Worker 72*71db0c75SAndroid Build Coastguard Worker x = zero; 73*71db0c75SAndroid Build Coastguard Worker y = T(1.0); 74*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(x, y, "ient), zero); 75*71db0c75SAndroid Build Coastguard Worker 76*71db0c75SAndroid Build Coastguard Worker x = neg_zero; 77*71db0c75SAndroid Build Coastguard Worker y = T(1.0); 78*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(x, y, "ient), neg_zero); 79*71db0c75SAndroid Build Coastguard Worker 80*71db0c75SAndroid Build Coastguard Worker x = T(1.125); 81*71db0c75SAndroid Build Coastguard Worker y = inf; 82*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(x, y, "ient), x); 83*71db0c75SAndroid Build Coastguard Worker EXPECT_EQ(quotient, 0); 84*71db0c75SAndroid Build Coastguard Worker } 85*71db0c75SAndroid Build Coastguard Worker testEqualNumeratorAndDenominator(RemQuoFunc func)86*71db0c75SAndroid Build Coastguard Worker void testEqualNumeratorAndDenominator(RemQuoFunc func) { 87*71db0c75SAndroid Build Coastguard Worker T x = T(1.125), y = T(1.125); 88*71db0c75SAndroid Build Coastguard Worker int q; 89*71db0c75SAndroid Build Coastguard Worker 90*71db0c75SAndroid Build Coastguard Worker // When the remainder is zero, the standard requires it to 91*71db0c75SAndroid Build Coastguard Worker // have the same sign as x. 92*71db0c75SAndroid Build Coastguard Worker 93*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(x, y, &q), zero); 94*71db0c75SAndroid Build Coastguard Worker EXPECT_EQ(q, 1); 95*71db0c75SAndroid Build Coastguard Worker 96*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(x, -y, &q), zero); 97*71db0c75SAndroid Build Coastguard Worker EXPECT_EQ(q, -1); 98*71db0c75SAndroid Build Coastguard Worker 99*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(-x, y, &q), neg_zero); 100*71db0c75SAndroid Build Coastguard Worker EXPECT_EQ(q, -1); 101*71db0c75SAndroid Build Coastguard Worker 102*71db0c75SAndroid Build Coastguard Worker EXPECT_FP_EQ(func(-x, -y, &q), neg_zero); 103*71db0c75SAndroid Build Coastguard Worker EXPECT_EQ(q, 1); 104*71db0c75SAndroid Build Coastguard Worker } 105*71db0c75SAndroid Build Coastguard Worker testSubnormalRange(RemQuoFunc func)106*71db0c75SAndroid Build Coastguard Worker void testSubnormalRange(RemQuoFunc func) { 107*71db0c75SAndroid Build Coastguard Worker constexpr StorageType COUNT = 100'001; 108*71db0c75SAndroid Build Coastguard Worker constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; 109*71db0c75SAndroid Build Coastguard Worker for (StorageType v = MIN_SUBNORMAL, w = MAX_SUBNORMAL; 110*71db0c75SAndroid Build Coastguard Worker v <= MAX_SUBNORMAL && w >= MIN_SUBNORMAL; v += STEP, w -= STEP) { 111*71db0c75SAndroid Build Coastguard Worker T x = FPBits(v).get_val(), y = FPBits(w).get_val(); 112*71db0c75SAndroid Build Coastguard Worker mpfr::BinaryOutput<T> result; 113*71db0c75SAndroid Build Coastguard Worker mpfr::BinaryInput<T> input{x, y}; 114*71db0c75SAndroid Build Coastguard Worker result.f = func(x, y, &result.i); 115*71db0c75SAndroid Build Coastguard Worker ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); 116*71db0c75SAndroid Build Coastguard Worker } 117*71db0c75SAndroid Build Coastguard Worker } 118*71db0c75SAndroid Build Coastguard Worker 119*71db0c75SAndroid Build Coastguard Worker void testNormalRange(RemQuoFunc func) { 120*71db0c75SAndroid Build Coastguard Worker constexpr StorageType COUNT = 1'001; 121*71db0c75SAndroid Build Coastguard Worker constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; 122*71db0c75SAndroid Build Coastguard Worker for (StorageType v = MIN_NORMAL, w = MAX_NORMAL; 123*71db0c75SAndroid Build Coastguard Worker v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) { 124*71db0c75SAndroid Build Coastguard Worker T x = FPBits(v).get_val(), y = FPBits(w).get_val(); 125*71db0c75SAndroid Build Coastguard Worker mpfr::BinaryOutput<T> result; 126*71db0c75SAndroid Build Coastguard Worker mpfr::BinaryInput<T> input{x, y}; 127*71db0c75SAndroid Build Coastguard Worker result.f = func(x, y, &result.i); 128*71db0c75SAndroid Build Coastguard Worker 129*71db0c75SAndroid Build Coastguard Worker // In normal range on x86 platforms, the long double implicit 1 bit can be 130*71db0c75SAndroid Build Coastguard Worker // zero making the numbers NaN. Hence we test for them separately. 131*71db0c75SAndroid Build Coastguard Worker if (FPBits(v).is_nan() || FPBits(w).is_nan()) { 132*71db0c75SAndroid Build Coastguard Worker ASSERT_FP_EQ(result.f, nan); 133*71db0c75SAndroid Build Coastguard Worker continue; 134*71db0c75SAndroid Build Coastguard Worker } 135*71db0c75SAndroid Build Coastguard Worker 136*71db0c75SAndroid Build Coastguard Worker ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); 137*71db0c75SAndroid Build Coastguard Worker } 138*71db0c75SAndroid Build Coastguard Worker } 139*71db0c75SAndroid Build Coastguard Worker }; 140*71db0c75SAndroid Build Coastguard Worker 141*71db0c75SAndroid Build Coastguard Worker #define LIST_REMQUO_TESTS(T, func) \ 142*71db0c75SAndroid Build Coastguard Worker using LlvmLibcRemQuoTest = RemQuoTestTemplate<T>; \ 143*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRemQuoTest, SpecialNumbers) { testSpecialNumbers(&func); } \ 144*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRemQuoTest, EqualNumeratorAndDenominator) { \ 145*71db0c75SAndroid Build Coastguard Worker testEqualNumeratorAndDenominator(&func); \ 146*71db0c75SAndroid Build Coastguard Worker } \ 147*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRemQuoTest, SubnormalRange) { testSubnormalRange(&func); } \ 148*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRemQuoTest, NormalRange) { testNormalRange(&func); } 149*71db0c75SAndroid Build Coastguard Worker 150*71db0c75SAndroid Build Coastguard Worker #endif // LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 151