1 //===-- Utility class to test different flavors of remquo -------*- 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 9 #ifndef LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 10 #define LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 11 12 #include "utils/FPUtil/BasicOperations.h" 13 #include "utils/FPUtil/FPBits.h" 14 #include "utils/FPUtil/TestHelpers.h" 15 #include "utils/MPFRWrapper/MPFRUtils.h" 16 #include "utils/UnitTest/Test.h" 17 #include <math.h> 18 19 namespace mpfr = __llvm_libc::testing::mpfr; 20 21 template <typename T> 22 class RemQuoTestTemplate : public __llvm_libc::testing::Test { 23 using FPBits = __llvm_libc::fputil::FPBits<T>; 24 using UIntType = typename FPBits::UIntType; 25 26 const T zero = __llvm_libc::fputil::FPBits<T>::zero(); 27 const T negZero = __llvm_libc::fputil::FPBits<T>::negZero(); 28 const T inf = __llvm_libc::fputil::FPBits<T>::inf(); 29 const T negInf = __llvm_libc::fputil::FPBits<T>::negInf(); 30 const T nan = __llvm_libc::fputil::FPBits<T>::buildNaN(1); 31 32 public: 33 typedef T (*RemQuoFunc)(T, T, int *); 34 testSpecialNumbers(RemQuoFunc func)35 void testSpecialNumbers(RemQuoFunc func) { 36 int quotient; 37 T x, y; 38 39 y = T(1.0); 40 x = inf; 41 EXPECT_NE(isnan(func(x, y, "ient)), 0); 42 x = negInf; 43 EXPECT_NE(isnan(func(x, y, "ient)), 0); 44 45 x = T(1.0); 46 y = zero; 47 EXPECT_NE(isnan(func(x, y, "ient)), 0); 48 y = negZero; 49 EXPECT_NE(isnan(func(x, y, "ient)), 0); 50 51 y = nan; 52 x = T(1.0); 53 EXPECT_NE(isnan(func(x, y, "ient)), 0); 54 55 y = T(1.0); 56 x = nan; 57 EXPECT_NE(isnan(func(x, y, "ient)), 0); 58 59 x = nan; 60 y = nan; 61 EXPECT_NE(isnan(func(x, y, "ient)), 0); 62 63 x = zero; 64 y = T(1.0); 65 EXPECT_FP_EQ(func(x, y, "ient), zero); 66 67 x = negZero; 68 y = T(1.0); 69 EXPECT_FP_EQ(func(x, y, "ient), negZero); 70 71 x = T(1.125); 72 y = inf; 73 EXPECT_FP_EQ(func(x, y, "ient), x); 74 EXPECT_EQ(quotient, 0); 75 } 76 testEqualNumeratorAndDenominator(RemQuoFunc func)77 void testEqualNumeratorAndDenominator(RemQuoFunc func) { 78 T x = T(1.125), y = T(1.125); 79 int q; 80 81 // When the remainder is zero, the standard requires it to 82 // have the same sign as x. 83 84 EXPECT_FP_EQ(func(x, y, &q), zero); 85 EXPECT_EQ(q, 1); 86 87 EXPECT_FP_EQ(func(x, -y, &q), zero); 88 EXPECT_EQ(q, -1); 89 90 EXPECT_FP_EQ(func(-x, y, &q), negZero); 91 EXPECT_EQ(q, -1); 92 93 EXPECT_FP_EQ(func(-x, -y, &q), negZero); 94 EXPECT_EQ(q, 1); 95 } 96 testSubnormalRange(RemQuoFunc func)97 void testSubnormalRange(RemQuoFunc func) { 98 constexpr UIntType count = 1000001; 99 constexpr UIntType step = 100 (FPBits::maxSubnormal - FPBits::minSubnormal) / count; 101 for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal; 102 v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal; 103 v += step, w -= step) { 104 T x = FPBits(v), y = FPBits(w); 105 mpfr::BinaryOutput<T> result; 106 mpfr::BinaryInput<T> input{x, y}; 107 result.f = func(x, y, &result.i); 108 ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); 109 } 110 } 111 testNormalRange(RemQuoFunc func)112 void testNormalRange(RemQuoFunc func) { 113 constexpr UIntType count = 1000001; 114 constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count; 115 for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; 116 v <= FPBits::maxNormal && w >= FPBits::minNormal; 117 v += step, w -= step) { 118 T x = FPBits(v), y = FPBits(w); 119 mpfr::BinaryOutput<T> result; 120 mpfr::BinaryInput<T> input{x, y}; 121 result.f = func(x, y, &result.i); 122 123 // In normal range on x86 platforms, the long double implicit 1 bit can be 124 // zero making the numbers NaN. Hence we test for them separately. 125 if (isnan(x) || isnan(y)) { 126 ASSERT_NE(isnan(result.f), 0); 127 continue; 128 } 129 130 ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); 131 } 132 } 133 }; 134 135 #define LIST_REMQUO_TESTS(T, func) \ 136 using RemQuoTest = RemQuoTestTemplate<T>; \ 137 TEST_F(RemQuoTest, SpecialNumbers) { testSpecialNumbers(&func); } \ 138 TEST_F(RemQuoTest, EqualNumeratorAndDenominator) { \ 139 testEqualNumeratorAndDenominator(&func); \ 140 } \ 141 TEST_F(RemQuoTest, SubnormalRange) { testSubnormalRange(&func); } \ 142 TEST_F(RemQuoTest, NormalRange) { testNormalRange(&func); } 143 144 #endif // LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 145