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 "src/__support/FPUtil/BasicOperations.h" 13 #include "src/__support/FPUtil/FPBits.h" 14 #include "utils/MPFRWrapper/MPFRUtils.h" 15 #include "utils/UnitTest/FPMatcher.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 = T(__llvm_libc::fputil::FPBits<T>::zero()); 27 const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero()); 28 const T inf = T(__llvm_libc::fputil::FPBits<T>::inf()); 29 const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf()); 30 const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(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_FP_EQ(nan, func(x, y, "ient)); 42 x = neg_inf; 43 EXPECT_FP_EQ(nan, func(x, y, "ient)); 44 45 x = T(1.0); 46 y = zero; 47 EXPECT_FP_EQ(nan, func(x, y, "ient)); 48 y = neg_zero; 49 EXPECT_FP_EQ(nan, func(x, y, "ient)); 50 51 y = nan; 52 x = T(1.0); 53 EXPECT_FP_EQ(nan, func(x, y, "ient)); 54 55 y = T(1.0); 56 x = nan; 57 EXPECT_FP_EQ(nan, func(x, y, "ient)); 58 59 x = nan; 60 y = nan; 61 EXPECT_FP_EQ(nan, func(x, y, "ient)); 62 63 x = zero; 64 y = T(1.0); 65 EXPECT_FP_EQ(func(x, y, "ient), zero); 66 67 x = neg_zero; 68 y = T(1.0); 69 EXPECT_FP_EQ(func(x, y, "ient), neg_zero); 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), neg_zero); 91 EXPECT_EQ(q, -1); 92 93 EXPECT_FP_EQ(func(-x, -y, &q), neg_zero); 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::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; 101 for (UIntType v = FPBits::MIN_SUBNORMAL, w = FPBits::MAX_SUBNORMAL; 102 v <= FPBits::MAX_SUBNORMAL && w >= FPBits::MIN_SUBNORMAL; 103 v += STEP, w -= STEP) { 104 T x = T(FPBits(v)), y = T(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::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; 115 for (UIntType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL; 116 v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL; 117 v += STEP, w -= STEP) { 118 T x = T(FPBits(v)), y = T(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_FP_EQ(result.f, nan); 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 LlvmLibcRemQuoTest = RemQuoTestTemplate<T>; \ 137 TEST_F(LlvmLibcRemQuoTest, SpecialNumbers) { testSpecialNumbers(&func); } \ 138 TEST_F(LlvmLibcRemQuoTest, EqualNumeratorAndDenominator) { \ 139 testEqualNumeratorAndDenominator(&func); \ 140 } \ 141 TEST_F(LlvmLibcRemQuoTest, SubnormalRange) { testSubnormalRange(&func); } \ 142 TEST_F(LlvmLibcRemQuoTest, NormalRange) { testNormalRange(&func); } 143 144 #endif // LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H 145