1 //===-- Utility class to test different flavors of rint ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H
10 #define LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H
12 #include "src/__support/FPUtil/FEnvImpl.h"
13 #include "src/__support/FPUtil/FPBits.h"
14 #include "test/UnitTest/FPMatcher.h"
15 #include "test/UnitTest/Test.h"
16 #include "utils/MPFRWrapper/MPFRUtils.h"
22 namespace mpfr
= LIBC_NAMESPACE::testing::mpfr
;
24 static constexpr int ROUNDING_MODES
[4] = {FE_UPWARD
, FE_DOWNWARD
, FE_TOWARDZERO
,
28 class RIntTestTemplate
: public LIBC_NAMESPACE::testing::Test
{
30 typedef T (*RIntFunc
)(T
);
33 using FPBits
= LIBC_NAMESPACE::fputil::FPBits
<T
>;
34 using UIntType
= typename
FPBits::UIntType
;
36 const T zero
= T(FPBits::zero());
37 const T neg_zero
= T(FPBits::neg_zero());
38 const T inf
= T(FPBits::inf());
39 const T neg_inf
= T(FPBits::neg_inf());
40 const T nan
= T(FPBits::build_quiet_nan(1));
42 static inline mpfr::RoundingMode
to_mpfr_rounding_mode(int mode
) {
45 return mpfr::RoundingMode::Upward
;
47 return mpfr::RoundingMode::Downward
;
49 return mpfr::RoundingMode::TowardZero
;
51 return mpfr::RoundingMode::Nearest
;
53 __builtin_unreachable();
58 void testSpecialNumbers(RIntFunc func
) {
59 for (int mode
: ROUNDING_MODES
) {
60 LIBC_NAMESPACE::fputil::set_round(mode
);
61 ASSERT_FP_EQ(inf
, func(inf
));
62 ASSERT_FP_EQ(neg_inf
, func(neg_inf
));
63 ASSERT_FP_EQ(nan
, func(nan
));
64 ASSERT_FP_EQ(zero
, func(zero
));
65 ASSERT_FP_EQ(neg_zero
, func(neg_zero
));
69 void testRoundNumbers(RIntFunc func
) {
70 for (int mode
: ROUNDING_MODES
) {
71 LIBC_NAMESPACE::fputil::set_round(mode
);
72 mpfr::RoundingMode mpfr_mode
= to_mpfr_rounding_mode(mode
);
73 ASSERT_FP_EQ(func(T(1.0)), mpfr::round(T(1.0), mpfr_mode
));
74 ASSERT_FP_EQ(func(T(-1.0)), mpfr::round(T(-1.0), mpfr_mode
));
75 ASSERT_FP_EQ(func(T(10.0)), mpfr::round(T(10.0), mpfr_mode
));
76 ASSERT_FP_EQ(func(T(-10.0)), mpfr::round(T(-10.0), mpfr_mode
));
77 ASSERT_FP_EQ(func(T(1234.0)), mpfr::round(T(1234.0), mpfr_mode
));
78 ASSERT_FP_EQ(func(T(-1234.0)), mpfr::round(T(-1234.0), mpfr_mode
));
82 void testFractions(RIntFunc func
) {
83 for (int mode
: ROUNDING_MODES
) {
84 LIBC_NAMESPACE::fputil::set_round(mode
);
85 mpfr::RoundingMode mpfr_mode
= to_mpfr_rounding_mode(mode
);
86 ASSERT_FP_EQ(func(T(0.5)), mpfr::round(T(0.5), mpfr_mode
));
87 ASSERT_FP_EQ(func(T(-0.5)), mpfr::round(T(-0.5), mpfr_mode
));
88 ASSERT_FP_EQ(func(T(0.115)), mpfr::round(T(0.115), mpfr_mode
));
89 ASSERT_FP_EQ(func(T(-0.115)), mpfr::round(T(-0.115), mpfr_mode
));
90 ASSERT_FP_EQ(func(T(0.715)), mpfr::round(T(0.715), mpfr_mode
));
91 ASSERT_FP_EQ(func(T(-0.715)), mpfr::round(T(-0.715), mpfr_mode
));
95 void testSubnormalRange(RIntFunc func
) {
96 constexpr UIntType COUNT
= 100'001;
97 constexpr UIntType STEP
=
98 (UIntType(FPBits::MAX_SUBNORMAL
) - UIntType(FPBits::MIN_SUBNORMAL
)) /
100 for (UIntType i
= FPBits::MIN_SUBNORMAL
; i
<= FPBits::MAX_SUBNORMAL
;
103 for (int mode
: ROUNDING_MODES
) {
104 LIBC_NAMESPACE::fputil::set_round(mode
);
105 mpfr::RoundingMode mpfr_mode
= to_mpfr_rounding_mode(mode
);
106 ASSERT_FP_EQ(func(x
), mpfr::round(x
, mpfr_mode
));
111 void testNormalRange(RIntFunc func
) {
112 constexpr UIntType COUNT
= 100'001;
113 constexpr UIntType STEP
=
114 (UIntType(FPBits::MAX_NORMAL
) - UIntType(FPBits::MIN_NORMAL
)) / COUNT
;
115 for (UIntType i
= FPBits::MIN_NORMAL
; i
<= FPBits::MAX_NORMAL
; i
+= STEP
) {
117 // In normal range on x86 platforms, the long double implicit 1 bit can be
118 // zero making the numbers NaN. We will skip them.
123 for (int mode
: ROUNDING_MODES
) {
124 LIBC_NAMESPACE::fputil::set_round(mode
);
125 mpfr::RoundingMode mpfr_mode
= to_mpfr_rounding_mode(mode
);
126 ASSERT_FP_EQ(func(x
), mpfr::round(x
, mpfr_mode
));
132 #define LIST_RINT_TESTS(F, func) \
133 using LlvmLibcRIntTest = RIntTestTemplate<F>; \
134 TEST_F(LlvmLibcRIntTest, specialNumbers) { testSpecialNumbers(&func); } \
135 TEST_F(LlvmLibcRIntTest, RoundNumbers) { testRoundNumbers(&func); } \
136 TEST_F(LlvmLibcRIntTest, Fractions) { testFractions(&func); } \
137 TEST_F(LlvmLibcRIntTest, SubnormalRange) { testSubnormalRange(&func); } \
138 TEST_F(LlvmLibcRIntTest, NormalRange) { testNormalRange(&func); }
140 #endif // LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H