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 "utils/FPUtil/FEnv.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"
22 namespace mpfr = __llvm_libc::testing::mpfr;
24 static constexpr int roundingModes[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
28 class RIntTestTemplate : public __llvm_libc::testing::Test {
30 typedef T (*RIntFunc)(T);
33 using FPBits = __llvm_libc::fputil::FPBits<T>;
34 using UIntType = typename FPBits::UIntType;
36 const T zero = FPBits::zero();
37 const T negZero = FPBits::negZero();
38 const T inf = FPBits::inf();
39 const T negInf = FPBits::negInf();
40 const T nan = FPBits::buildNaN(1);
42 static inline mpfr::RoundingMode toMPFRRoundingMode(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 : roundingModes) {
60 __llvm_libc::fputil::setRound(mode);
61 ASSERT_FP_EQ(inf, func(inf));
62 ASSERT_FP_EQ(negInf, func(negInf));
63 ASSERT_FP_EQ(nan, func(nan));
64 ASSERT_FP_EQ(zero, func(zero));
65 ASSERT_FP_EQ(negZero, func(negZero));
69 void testRoundNumbers(RIntFunc func) {
70 for (int mode : roundingModes) {
71 __llvm_libc::fputil::setRound(mode);
72 mpfr::RoundingMode mpfrMode = toMPFRRoundingMode(mode);
73 ASSERT_FP_EQ(func(T(1.0)), mpfr::Round(T(1.0), mpfrMode));
74 ASSERT_FP_EQ(func(T(-1.0)), mpfr::Round(T(-1.0), mpfrMode));
75 ASSERT_FP_EQ(func(T(10.0)), mpfr::Round(T(10.0), mpfrMode));
76 ASSERT_FP_EQ(func(T(-10.0)), mpfr::Round(T(-10.0), mpfrMode));
77 ASSERT_FP_EQ(func(T(1234.0)), mpfr::Round(T(1234.0), mpfrMode));
78 ASSERT_FP_EQ(func(T(-1234.0)), mpfr::Round(T(-1234.0), mpfrMode));
82 void testFractions(RIntFunc func) {
83 for (int mode : roundingModes) {
84 __llvm_libc::fputil::setRound(mode);
85 mpfr::RoundingMode mpfrMode = toMPFRRoundingMode(mode);
86 ASSERT_FP_EQ(func(T(0.5)), mpfr::Round(T(0.5), mpfrMode));
87 ASSERT_FP_EQ(func(T(-0.5)), mpfr::Round(T(-0.5), mpfrMode));
88 ASSERT_FP_EQ(func(T(0.115)), mpfr::Round(T(0.115), mpfrMode));
89 ASSERT_FP_EQ(func(T(-0.115)), mpfr::Round(T(-0.115), mpfrMode));
90 ASSERT_FP_EQ(func(T(0.715)), mpfr::Round(T(0.715), mpfrMode));
91 ASSERT_FP_EQ(func(T(-0.715)), mpfr::Round(T(-0.715), mpfrMode));
95 void testSubnormalRange(RIntFunc func) {
96 constexpr UIntType count = 1000001;
97 constexpr UIntType step =
98 (FPBits::maxSubnormal - FPBits::minSubnormal) / count;
99 for (UIntType i = FPBits::minSubnormal; i <= FPBits::maxSubnormal;
102 for (int mode : roundingModes) {
103 __llvm_libc::fputil::setRound(mode);
104 mpfr::RoundingMode mpfrMode = toMPFRRoundingMode(mode);
105 ASSERT_FP_EQ(func(x), mpfr::Round(x, mpfrMode));
110 void testNormalRange(RIntFunc func) {
111 constexpr UIntType count = 1000001;
112 constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count;
113 for (UIntType i = FPBits::minNormal; i <= FPBits::maxNormal; i += step) {
115 // In normal range on x86 platforms, the long double implicit 1 bit can be
116 // zero making the numbers NaN. We will skip them.
121 for (int mode : roundingModes) {
122 __llvm_libc::fputil::setRound(mode);
123 mpfr::RoundingMode mpfrMode = toMPFRRoundingMode(mode);
124 ASSERT_FP_EQ(func(x), mpfr::Round(x, mpfrMode));
130 #define LIST_RINT_TESTS(F, func) \
131 using RIntTest = RIntTestTemplate<F>; \
132 TEST_F(RIntTest, specialNumbers) { testSpecialNumbers(&func); } \
133 TEST_F(RIntTest, RoundNumbers) { testRoundNumbers(&func); } \
134 TEST_F(RIntTest, Fractions) { testFractions(&func); } \
135 TEST_F(RIntTest, SubnormalRange) { testSubnormalRange(&func); } \
136 TEST_F(RIntTest, NormalRange) { testNormalRange(&func); }
138 #endif // LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H