xref: /aosp_15_r20/external/llvm-libc/test/src/math/RoundToIntegerTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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