1*71db0c75SAndroid Build Coastguard Worker //===-- Utility class to test different flavors of [l|ll]round --*- 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_ROUNDTOINTEGERTEST_H 10*71db0c75SAndroid Build Coastguard Worker #define LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H 11*71db0c75SAndroid Build Coastguard Worker 12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/algorithm.h" 13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FEnvImpl.h" 14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h" 15*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/properties/architectures.h" 16*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FEnvSafeTest.h" 17*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FPMatcher.h" 18*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h" 19*71db0c75SAndroid Build Coastguard Worker #include "utils/MPFRWrapper/MPFRUtils.h" 20*71db0c75SAndroid Build Coastguard Worker 21*71db0c75SAndroid Build Coastguard Worker #include "hdr/math_macros.h" 22*71db0c75SAndroid Build Coastguard Worker 23*71db0c75SAndroid Build Coastguard Worker namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 24*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::Sign; 25*71db0c75SAndroid Build Coastguard Worker 26*71db0c75SAndroid Build Coastguard Worker static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, 27*71db0c75SAndroid Build Coastguard Worker FE_TONEAREST}; 28*71db0c75SAndroid Build Coastguard Worker 29*71db0c75SAndroid Build Coastguard Worker template <typename FloatType, typename IntType, bool TestModes = false> 30*71db0c75SAndroid Build Coastguard Worker class RoundToIntegerTestTemplate 31*71db0c75SAndroid Build Coastguard Worker : public LIBC_NAMESPACE::testing::FEnvSafeTest { 32*71db0c75SAndroid Build Coastguard Worker public: 33*71db0c75SAndroid Build Coastguard Worker typedef IntType (*RoundToIntegerFunc)(FloatType); 34*71db0c75SAndroid Build Coastguard Worker 35*71db0c75SAndroid Build Coastguard Worker private: 36*71db0c75SAndroid Build Coastguard Worker using FPBits = LIBC_NAMESPACE::fputil::FPBits<FloatType>; 37*71db0c75SAndroid Build Coastguard Worker using StorageType = typename FPBits::StorageType; 38*71db0c75SAndroid Build Coastguard Worker 39*71db0c75SAndroid Build Coastguard Worker const FloatType zero = FPBits::zero().get_val(); 40*71db0c75SAndroid Build Coastguard Worker const FloatType neg_zero = FPBits::zero(Sign::NEG).get_val(); 41*71db0c75SAndroid Build Coastguard Worker const FloatType inf = FPBits::inf().get_val(); 42*71db0c75SAndroid Build Coastguard Worker const FloatType neg_inf = FPBits::inf(Sign::NEG).get_val(); 43*71db0c75SAndroid Build Coastguard Worker const FloatType nan = FPBits::quiet_nan().get_val(); 44*71db0c75SAndroid Build Coastguard Worker 45*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); 46*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); 47*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MAX_SUBNORMAL = 48*71db0c75SAndroid Build Coastguard Worker FPBits::max_subnormal().uintval(); 49*71db0c75SAndroid Build Coastguard Worker static constexpr StorageType MIN_SUBNORMAL = 50*71db0c75SAndroid Build Coastguard Worker FPBits::min_subnormal().uintval(); 51*71db0c75SAndroid Build Coastguard Worker 52*71db0c75SAndroid Build Coastguard Worker static constexpr IntType INTEGER_MIN = IntType(1) 53*71db0c75SAndroid Build Coastguard Worker << (sizeof(IntType) * 8 - 1); 54*71db0c75SAndroid Build Coastguard Worker static constexpr IntType INTEGER_MAX = -(INTEGER_MIN + 1); 55*71db0c75SAndroid Build Coastguard Worker test_one_input(RoundToIntegerFunc func,FloatType input,IntType expected,bool expectError)56*71db0c75SAndroid Build Coastguard Worker void test_one_input(RoundToIntegerFunc func, FloatType input, 57*71db0c75SAndroid Build Coastguard Worker IntType expected, bool expectError) { 58*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::libc_errno = 0; 59*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); 60*71db0c75SAndroid Build Coastguard Worker 61*71db0c75SAndroid Build Coastguard Worker ASSERT_EQ(func(input), expected); 62*71db0c75SAndroid Build Coastguard Worker 63*71db0c75SAndroid Build Coastguard Worker // TODO: Handle the !expectError case. It used to expect 64*71db0c75SAndroid Build Coastguard Worker // 0 for errno and exceptions, but this doesn't hold for 65*71db0c75SAndroid Build Coastguard Worker // all math functions using RoundToInteger test: 66*71db0c75SAndroid Build Coastguard Worker // https://github.com/llvm/llvm-project/pull/88816 67*71db0c75SAndroid Build Coastguard Worker if (expectError) { 68*71db0c75SAndroid Build Coastguard Worker ASSERT_FP_EXCEPTION(FE_INVALID); 69*71db0c75SAndroid Build Coastguard Worker ASSERT_MATH_ERRNO(EDOM); 70*71db0c75SAndroid Build Coastguard Worker } 71*71db0c75SAndroid Build Coastguard Worker } 72*71db0c75SAndroid Build Coastguard Worker to_mpfr_rounding_mode(int mode)73*71db0c75SAndroid Build Coastguard Worker static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) { 74*71db0c75SAndroid Build Coastguard Worker switch (mode) { 75*71db0c75SAndroid Build Coastguard Worker case FE_UPWARD: 76*71db0c75SAndroid Build Coastguard Worker return mpfr::RoundingMode::Upward; 77*71db0c75SAndroid Build Coastguard Worker case FE_DOWNWARD: 78*71db0c75SAndroid Build Coastguard Worker return mpfr::RoundingMode::Downward; 79*71db0c75SAndroid Build Coastguard Worker case FE_TOWARDZERO: 80*71db0c75SAndroid Build Coastguard Worker return mpfr::RoundingMode::TowardZero; 81*71db0c75SAndroid Build Coastguard Worker case FE_TONEAREST: 82*71db0c75SAndroid Build Coastguard Worker return mpfr::RoundingMode::Nearest; 83*71db0c75SAndroid Build Coastguard Worker default: 84*71db0c75SAndroid Build Coastguard Worker __builtin_unreachable(); 85*71db0c75SAndroid Build Coastguard Worker } 86*71db0c75SAndroid Build Coastguard Worker } 87*71db0c75SAndroid Build Coastguard Worker 88*71db0c75SAndroid Build Coastguard Worker public: SetUp()89*71db0c75SAndroid Build Coastguard Worker void SetUp() override { 90*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::testing::FEnvSafeTest::SetUp(); 91*71db0c75SAndroid Build Coastguard Worker 92*71db0c75SAndroid Build Coastguard Worker if (math_errhandling & MATH_ERREXCEPT) { 93*71db0c75SAndroid Build Coastguard Worker // We will disable all exceptions so that the test will not 94*71db0c75SAndroid Build Coastguard Worker // crash with SIGFPE. We can still use fetestexcept to check 95*71db0c75SAndroid Build Coastguard Worker // if the appropriate flag was raised. 96*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT); 97*71db0c75SAndroid Build Coastguard Worker } 98*71db0c75SAndroid Build Coastguard Worker } 99*71db0c75SAndroid Build Coastguard Worker do_infinity_and_na_n_test(RoundToIntegerFunc func)100*71db0c75SAndroid Build Coastguard Worker void do_infinity_and_na_n_test(RoundToIntegerFunc func) { 101*71db0c75SAndroid Build Coastguard Worker test_one_input(func, inf, INTEGER_MAX, true); 102*71db0c75SAndroid Build Coastguard Worker test_one_input(func, neg_inf, INTEGER_MIN, true); 103*71db0c75SAndroid Build Coastguard Worker // This is currently never enabled, the 104*71db0c75SAndroid Build Coastguard Worker // LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR CMake option in 105*71db0c75SAndroid Build Coastguard Worker // libc/CMakeLists.txt is not forwarded to C++. 106*71db0c75SAndroid Build Coastguard Worker #if LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR 107*71db0c75SAndroid Build Coastguard Worker // Result is not well-defined, we always returns INTEGER_MAX 108*71db0c75SAndroid Build Coastguard Worker test_one_input(func, nan, INTEGER_MAX, true); 109*71db0c75SAndroid Build Coastguard Worker #endif // LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR 110*71db0c75SAndroid Build Coastguard Worker } 111*71db0c75SAndroid Build Coastguard Worker testInfinityAndNaN(RoundToIntegerFunc func)112*71db0c75SAndroid Build Coastguard Worker void testInfinityAndNaN(RoundToIntegerFunc func) { 113*71db0c75SAndroid Build Coastguard Worker if (TestModes) { 114*71db0c75SAndroid Build Coastguard Worker for (int mode : ROUNDING_MODES) { 115*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(mode); 116*71db0c75SAndroid Build Coastguard Worker do_infinity_and_na_n_test(func); 117*71db0c75SAndroid Build Coastguard Worker } 118*71db0c75SAndroid Build Coastguard Worker } else { 119*71db0c75SAndroid Build Coastguard Worker do_infinity_and_na_n_test(func); 120*71db0c75SAndroid Build Coastguard Worker } 121*71db0c75SAndroid Build Coastguard Worker } 122*71db0c75SAndroid Build Coastguard Worker do_round_numbers_test(RoundToIntegerFunc func)123*71db0c75SAndroid Build Coastguard Worker void do_round_numbers_test(RoundToIntegerFunc func) { 124*71db0c75SAndroid Build Coastguard Worker test_one_input(func, zero, IntType(0), false); 125*71db0c75SAndroid Build Coastguard Worker test_one_input(func, neg_zero, IntType(0), false); 126*71db0c75SAndroid Build Coastguard Worker test_one_input(func, FloatType(1.0), IntType(1), false); 127*71db0c75SAndroid Build Coastguard Worker test_one_input(func, FloatType(-1.0), IntType(-1), false); 128*71db0c75SAndroid Build Coastguard Worker test_one_input(func, FloatType(10.0), IntType(10), false); 129*71db0c75SAndroid Build Coastguard Worker test_one_input(func, FloatType(-10.0), IntType(-10), false); 130*71db0c75SAndroid Build Coastguard Worker test_one_input(func, FloatType(1234.0), IntType(1234), false); 131*71db0c75SAndroid Build Coastguard Worker test_one_input(func, FloatType(-1234.0), IntType(-1234), false); 132*71db0c75SAndroid Build Coastguard Worker 133*71db0c75SAndroid Build Coastguard Worker // The rest of this function compares with an equivalent MPFR function 134*71db0c75SAndroid Build Coastguard Worker // which rounds floating point numbers to long values. There is no MPFR 135*71db0c75SAndroid Build Coastguard Worker // function to round to long long or wider integer values. So, we will 136*71db0c75SAndroid Build Coastguard Worker // the remaining tests only if the width of IntType less than equal to that 137*71db0c75SAndroid Build Coastguard Worker // of long. 138*71db0c75SAndroid Build Coastguard Worker if (sizeof(IntType) > sizeof(long)) 139*71db0c75SAndroid Build Coastguard Worker return; 140*71db0c75SAndroid Build Coastguard Worker 141*71db0c75SAndroid Build Coastguard Worker constexpr int EXPONENT_LIMIT = sizeof(IntType) * 8 - 1; 142*71db0c75SAndroid Build Coastguard Worker constexpr int BIASED_EXPONENT_LIMIT = EXPONENT_LIMIT + FPBits::EXP_BIAS; 143*71db0c75SAndroid Build Coastguard Worker if (BIASED_EXPONENT_LIMIT > FPBits::MAX_BIASED_EXPONENT) 144*71db0c75SAndroid Build Coastguard Worker return; 145*71db0c75SAndroid Build Coastguard Worker // We start with 1.0 so that the implicit bit for x86 long doubles 146*71db0c75SAndroid Build Coastguard Worker // is set. 147*71db0c75SAndroid Build Coastguard Worker FPBits bits(FloatType(1.0)); 148*71db0c75SAndroid Build Coastguard Worker bits.set_biased_exponent(BIASED_EXPONENT_LIMIT); 149*71db0c75SAndroid Build Coastguard Worker bits.set_sign(Sign::NEG); 150*71db0c75SAndroid Build Coastguard Worker bits.set_mantissa(0); 151*71db0c75SAndroid Build Coastguard Worker 152*71db0c75SAndroid Build Coastguard Worker FloatType x = bits.get_val(); 153*71db0c75SAndroid Build Coastguard Worker long mpfr_result; 154*71db0c75SAndroid Build Coastguard Worker bool erangeflag = mpfr::round_to_long(x, mpfr_result); 155*71db0c75SAndroid Build Coastguard Worker ASSERT_FALSE(erangeflag); 156*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, mpfr_result, false); 157*71db0c75SAndroid Build Coastguard Worker } 158*71db0c75SAndroid Build Coastguard Worker testRoundNumbers(RoundToIntegerFunc func)159*71db0c75SAndroid Build Coastguard Worker void testRoundNumbers(RoundToIntegerFunc func) { 160*71db0c75SAndroid Build Coastguard Worker if (TestModes) { 161*71db0c75SAndroid Build Coastguard Worker for (int mode : ROUNDING_MODES) { 162*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(mode); 163*71db0c75SAndroid Build Coastguard Worker do_round_numbers_test(func); 164*71db0c75SAndroid Build Coastguard Worker } 165*71db0c75SAndroid Build Coastguard Worker } else { 166*71db0c75SAndroid Build Coastguard Worker do_round_numbers_test(func); 167*71db0c75SAndroid Build Coastguard Worker } 168*71db0c75SAndroid Build Coastguard Worker } 169*71db0c75SAndroid Build Coastguard Worker do_fractions_test(RoundToIntegerFunc func,int mode)170*71db0c75SAndroid Build Coastguard Worker void do_fractions_test(RoundToIntegerFunc func, int mode) { 171*71db0c75SAndroid Build Coastguard Worker constexpr FloatType FRACTIONS[] = { 172*71db0c75SAndroid Build Coastguard Worker FloatType(0.5), FloatType(-0.5), FloatType(0.115), 173*71db0c75SAndroid Build Coastguard Worker FloatType(-0.115), FloatType(0.715), FloatType(-0.715), 174*71db0c75SAndroid Build Coastguard Worker }; 175*71db0c75SAndroid Build Coastguard Worker for (FloatType x : FRACTIONS) { 176*71db0c75SAndroid Build Coastguard Worker long mpfr_long_result; 177*71db0c75SAndroid Build Coastguard Worker bool erangeflag; 178*71db0c75SAndroid Build Coastguard Worker if (TestModes) 179*71db0c75SAndroid Build Coastguard Worker erangeflag = mpfr::round_to_long(x, to_mpfr_rounding_mode(mode), 180*71db0c75SAndroid Build Coastguard Worker mpfr_long_result); 181*71db0c75SAndroid Build Coastguard Worker else 182*71db0c75SAndroid Build Coastguard Worker erangeflag = mpfr::round_to_long(x, mpfr_long_result); 183*71db0c75SAndroid Build Coastguard Worker ASSERT_FALSE(erangeflag); 184*71db0c75SAndroid Build Coastguard Worker IntType mpfr_result = mpfr_long_result; 185*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, mpfr_result, false); 186*71db0c75SAndroid Build Coastguard Worker } 187*71db0c75SAndroid Build Coastguard Worker } 188*71db0c75SAndroid Build Coastguard Worker testFractions(RoundToIntegerFunc func)189*71db0c75SAndroid Build Coastguard Worker void testFractions(RoundToIntegerFunc func) { 190*71db0c75SAndroid Build Coastguard Worker if (TestModes) { 191*71db0c75SAndroid Build Coastguard Worker for (int mode : ROUNDING_MODES) { 192*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(mode); 193*71db0c75SAndroid Build Coastguard Worker do_fractions_test(func, mode); 194*71db0c75SAndroid Build Coastguard Worker } 195*71db0c75SAndroid Build Coastguard Worker } else { 196*71db0c75SAndroid Build Coastguard Worker // Passing 0 for mode has no effect as it is not used in doFractionsTest 197*71db0c75SAndroid Build Coastguard Worker // when `TestModes` is false; 198*71db0c75SAndroid Build Coastguard Worker do_fractions_test(func, 0); 199*71db0c75SAndroid Build Coastguard Worker } 200*71db0c75SAndroid Build Coastguard Worker } 201*71db0c75SAndroid Build Coastguard Worker testIntegerOverflow(RoundToIntegerFunc func)202*71db0c75SAndroid Build Coastguard Worker void testIntegerOverflow(RoundToIntegerFunc func) { 203*71db0c75SAndroid Build Coastguard Worker // This function compares with an equivalent MPFR function which rounds 204*71db0c75SAndroid Build Coastguard Worker // floating point numbers to long values. There is no MPFR function to 205*71db0c75SAndroid Build Coastguard Worker // round to long long or wider integer values. So, we will peform the 206*71db0c75SAndroid Build Coastguard Worker // comparisons in this function only if the width of IntType less than equal 207*71db0c75SAndroid Build Coastguard Worker // to that of long. 208*71db0c75SAndroid Build Coastguard Worker if (sizeof(IntType) > sizeof(long)) 209*71db0c75SAndroid Build Coastguard Worker return; 210*71db0c75SAndroid Build Coastguard Worker 211*71db0c75SAndroid Build Coastguard Worker constexpr int EXPONENT_LIMIT = sizeof(IntType) * 8 - 1; 212*71db0c75SAndroid Build Coastguard Worker constexpr int BIASED_EXPONENT_LIMIT = EXPONENT_LIMIT + FPBits::EXP_BIAS; 213*71db0c75SAndroid Build Coastguard Worker if (BIASED_EXPONENT_LIMIT > FPBits::MAX_BIASED_EXPONENT) 214*71db0c75SAndroid Build Coastguard Worker return; 215*71db0c75SAndroid Build Coastguard Worker // We start with 1.0 so that the implicit bit for x86 long doubles 216*71db0c75SAndroid Build Coastguard Worker // is set. 217*71db0c75SAndroid Build Coastguard Worker FPBits bits(FloatType(1.0)); 218*71db0c75SAndroid Build Coastguard Worker bits.set_biased_exponent(BIASED_EXPONENT_LIMIT); 219*71db0c75SAndroid Build Coastguard Worker bits.set_sign(Sign::NEG); 220*71db0c75SAndroid Build Coastguard Worker bits.set_mantissa(FPBits::FRACTION_MASK); 221*71db0c75SAndroid Build Coastguard Worker 222*71db0c75SAndroid Build Coastguard Worker FloatType x = bits.get_val(); 223*71db0c75SAndroid Build Coastguard Worker if (TestModes) { 224*71db0c75SAndroid Build Coastguard Worker for (int m : ROUNDING_MODES) { 225*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(m); 226*71db0c75SAndroid Build Coastguard Worker long mpfr_long_result; 227*71db0c75SAndroid Build Coastguard Worker bool erangeflag = 228*71db0c75SAndroid Build Coastguard Worker mpfr::round_to_long(x, to_mpfr_rounding_mode(m), mpfr_long_result); 229*71db0c75SAndroid Build Coastguard Worker ASSERT_TRUE(erangeflag); 230*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, INTEGER_MIN, true); 231*71db0c75SAndroid Build Coastguard Worker } 232*71db0c75SAndroid Build Coastguard Worker } else { 233*71db0c75SAndroid Build Coastguard Worker long mpfr_long_result; 234*71db0c75SAndroid Build Coastguard Worker bool erangeflag = mpfr::round_to_long(x, mpfr_long_result); 235*71db0c75SAndroid Build Coastguard Worker ASSERT_TRUE(erangeflag); 236*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, INTEGER_MIN, true); 237*71db0c75SAndroid Build Coastguard Worker } 238*71db0c75SAndroid Build Coastguard Worker } 239*71db0c75SAndroid Build Coastguard Worker testSubnormalRange(RoundToIntegerFunc func)240*71db0c75SAndroid Build Coastguard Worker void testSubnormalRange(RoundToIntegerFunc func) { 241*71db0c75SAndroid Build Coastguard Worker constexpr int COUNT = 1'000'001; 242*71db0c75SAndroid Build Coastguard Worker constexpr StorageType STEP = LIBC_NAMESPACE::cpp::max( 243*71db0c75SAndroid Build Coastguard Worker static_cast<StorageType>((MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT), 244*71db0c75SAndroid Build Coastguard Worker StorageType(1)); 245*71db0c75SAndroid Build Coastguard Worker for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) { 246*71db0c75SAndroid Build Coastguard Worker FloatType x = FPBits(i).get_val(); 247*71db0c75SAndroid Build Coastguard Worker if (x == FloatType(0.0)) 248*71db0c75SAndroid Build Coastguard Worker continue; 249*71db0c75SAndroid Build Coastguard Worker // All subnormal numbers should round to zero. 250*71db0c75SAndroid Build Coastguard Worker if (TestModes) { 251*71db0c75SAndroid Build Coastguard Worker if (x > 0) { 252*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_UPWARD); 253*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(1), false); 254*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD); 255*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(0), false); 256*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO); 257*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(0), false); 258*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST); 259*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(0), false); 260*71db0c75SAndroid Build Coastguard Worker } else { 261*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_UPWARD); 262*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(0), false); 263*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_DOWNWARD); 264*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(-1), false); 265*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_TOWARDZERO); 266*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(0), false); 267*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(FE_TONEAREST); 268*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, IntType(0), false); 269*71db0c75SAndroid Build Coastguard Worker } 270*71db0c75SAndroid Build Coastguard Worker } else { 271*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, 0L, false); 272*71db0c75SAndroid Build Coastguard Worker } 273*71db0c75SAndroid Build Coastguard Worker } 274*71db0c75SAndroid Build Coastguard Worker } 275*71db0c75SAndroid Build Coastguard Worker testNormalRange(RoundToIntegerFunc func)276*71db0c75SAndroid Build Coastguard Worker void testNormalRange(RoundToIntegerFunc func) { 277*71db0c75SAndroid Build Coastguard Worker // This function compares with an equivalent MPFR function which rounds 278*71db0c75SAndroid Build Coastguard Worker // floating point numbers to long values. There is no MPFR function to 279*71db0c75SAndroid Build Coastguard Worker // round to long long or wider integer values. So, we will peform the 280*71db0c75SAndroid Build Coastguard Worker // comparisons in this function only if the width of IntType less than equal 281*71db0c75SAndroid Build Coastguard Worker // to that of long. 282*71db0c75SAndroid Build Coastguard Worker if (sizeof(IntType) > sizeof(long)) 283*71db0c75SAndroid Build Coastguard Worker return; 284*71db0c75SAndroid Build Coastguard Worker 285*71db0c75SAndroid Build Coastguard Worker constexpr int COUNT = 1'000'001; 286*71db0c75SAndroid Build Coastguard Worker constexpr StorageType STEP = LIBC_NAMESPACE::cpp::max( 287*71db0c75SAndroid Build Coastguard Worker static_cast<StorageType>((MAX_NORMAL - MIN_NORMAL) / COUNT), 288*71db0c75SAndroid Build Coastguard Worker StorageType(1)); 289*71db0c75SAndroid Build Coastguard Worker for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) { 290*71db0c75SAndroid Build Coastguard Worker FPBits xbits(i); 291*71db0c75SAndroid Build Coastguard Worker FloatType x = xbits.get_val(); 292*71db0c75SAndroid Build Coastguard Worker // In normal range on x86 platforms, the long double implicit 1 bit can be 293*71db0c75SAndroid Build Coastguard Worker // zero making the numbers NaN. We will skip them. 294*71db0c75SAndroid Build Coastguard Worker if (xbits.is_nan()) 295*71db0c75SAndroid Build Coastguard Worker continue; 296*71db0c75SAndroid Build Coastguard Worker 297*71db0c75SAndroid Build Coastguard Worker if (TestModes) { 298*71db0c75SAndroid Build Coastguard Worker for (int m : ROUNDING_MODES) { 299*71db0c75SAndroid Build Coastguard Worker long mpfr_long_result; 300*71db0c75SAndroid Build Coastguard Worker bool erangeflag = mpfr::round_to_long(x, to_mpfr_rounding_mode(m), 301*71db0c75SAndroid Build Coastguard Worker mpfr_long_result); 302*71db0c75SAndroid Build Coastguard Worker IntType mpfr_result = mpfr_long_result; 303*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::fputil::set_round(m); 304*71db0c75SAndroid Build Coastguard Worker if (erangeflag) 305*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true); 306*71db0c75SAndroid Build Coastguard Worker else 307*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, mpfr_result, false); 308*71db0c75SAndroid Build Coastguard Worker } 309*71db0c75SAndroid Build Coastguard Worker } else { 310*71db0c75SAndroid Build Coastguard Worker long mpfr_long_result; 311*71db0c75SAndroid Build Coastguard Worker bool erangeflag = mpfr::round_to_long(x, mpfr_long_result); 312*71db0c75SAndroid Build Coastguard Worker IntType mpfr_result = mpfr_long_result; 313*71db0c75SAndroid Build Coastguard Worker if (erangeflag) 314*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, x > 0 ? INTEGER_MAX : INTEGER_MIN, true); 315*71db0c75SAndroid Build Coastguard Worker else 316*71db0c75SAndroid Build Coastguard Worker test_one_input(func, x, mpfr_result, false); 317*71db0c75SAndroid Build Coastguard Worker } 318*71db0c75SAndroid Build Coastguard Worker } 319*71db0c75SAndroid Build Coastguard Worker } 320*71db0c75SAndroid Build Coastguard Worker }; 321*71db0c75SAndroid Build Coastguard Worker 322*71db0c75SAndroid Build Coastguard Worker #define LIST_ROUND_TO_INTEGER_TESTS_HELPER(FloatType, IntType, func, \ 323*71db0c75SAndroid Build Coastguard Worker TestModes) \ 324*71db0c75SAndroid Build Coastguard Worker using LlvmLibcRoundToIntegerTest = \ 325*71db0c75SAndroid Build Coastguard Worker RoundToIntegerTestTemplate<FloatType, IntType, TestModes>; \ 326*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRoundToIntegerTest, InfinityAndNaN) { \ 327*71db0c75SAndroid Build Coastguard Worker testInfinityAndNaN(&func); \ 328*71db0c75SAndroid Build Coastguard Worker } \ 329*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRoundToIntegerTest, RoundNumbers) { \ 330*71db0c75SAndroid Build Coastguard Worker testRoundNumbers(&func); \ 331*71db0c75SAndroid Build Coastguard Worker } \ 332*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRoundToIntegerTest, Fractions) { testFractions(&func); } \ 333*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRoundToIntegerTest, IntegerOverflow) { \ 334*71db0c75SAndroid Build Coastguard Worker testIntegerOverflow(&func); \ 335*71db0c75SAndroid Build Coastguard Worker } \ 336*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRoundToIntegerTest, SubnormalRange) { \ 337*71db0c75SAndroid Build Coastguard Worker testSubnormalRange(&func); \ 338*71db0c75SAndroid Build Coastguard Worker } \ 339*71db0c75SAndroid Build Coastguard Worker TEST_F(LlvmLibcRoundToIntegerTest, NormalRange) { testNormalRange(&func); } 340*71db0c75SAndroid Build Coastguard Worker 341*71db0c75SAndroid Build Coastguard Worker #define LIST_ROUND_TO_INTEGER_TESTS(FloatType, IntType, func) \ 342*71db0c75SAndroid Build Coastguard Worker LIST_ROUND_TO_INTEGER_TESTS_HELPER(FloatType, IntType, func, false) 343*71db0c75SAndroid Build Coastguard Worker 344*71db0c75SAndroid Build Coastguard Worker #define LIST_ROUND_TO_INTEGER_TESTS_WITH_MODES(FloatType, IntType, func) \ 345*71db0c75SAndroid Build Coastguard Worker LIST_ROUND_TO_INTEGER_TESTS_HELPER(FloatType, IntType, func, true) 346*71db0c75SAndroid Build Coastguard Worker 347*71db0c75SAndroid Build Coastguard Worker #endif // LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H 348