xref: /aosp_15_r20/external/llvm-libc/test/src/math/smoke/NextTowardTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker //===-- Utility class to test different flavors of nexttoward ---*- 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_NEXTTOWARDTEST_H
10*71db0c75SAndroid Build Coastguard Worker #define LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H
11*71db0c75SAndroid Build Coastguard Worker 
12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/bit.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 "test/UnitTest/FEnvSafeTest.h"
16*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FPMatcher.h"
17*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h"
18*71db0c75SAndroid Build Coastguard Worker 
19*71db0c75SAndroid Build Coastguard Worker #include "hdr/fenv_macros.h"
20*71db0c75SAndroid Build Coastguard Worker 
21*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::Sign;
22*71db0c75SAndroid Build Coastguard Worker 
23*71db0c75SAndroid Build Coastguard Worker // TODO: Strengthen errno,exception checks and remove these assert macros
24*71db0c75SAndroid Build Coastguard Worker // after new matchers/test fixtures are added
25*71db0c75SAndroid Build Coastguard Worker #define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception)      \
26*71db0c75SAndroid Build Coastguard Worker   ASSERT_FP_EQ(result, expected);                                              \
27*71db0c75SAndroid Build Coastguard Worker   ASSERT_FP_EXCEPTION(expected_exception);                                     \
28*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT)
29*71db0c75SAndroid Build Coastguard Worker 
30*71db0c75SAndroid Build Coastguard Worker #define ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected)                          \
31*71db0c75SAndroid Build Coastguard Worker   ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, FE_INEXACT | FE_UNDERFLOW)
32*71db0c75SAndroid Build Coastguard Worker 
33*71db0c75SAndroid Build Coastguard Worker #define ASSERT_FP_EQ_WITH_OVERFLOW(result, expected)                           \
34*71db0c75SAndroid Build Coastguard Worker   ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, FE_INEXACT | FE_OVERFLOW)
35*71db0c75SAndroid Build Coastguard Worker 
36*71db0c75SAndroid Build Coastguard Worker template <typename T>
37*71db0c75SAndroid Build Coastguard Worker class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
38*71db0c75SAndroid Build Coastguard Worker   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
39*71db0c75SAndroid Build Coastguard Worker   using ToFPBits = LIBC_NAMESPACE::fputil::FPBits<long double>;
40*71db0c75SAndroid Build Coastguard Worker   using StorageType = typename FPBits::StorageType;
41*71db0c75SAndroid Build Coastguard Worker 
42*71db0c75SAndroid Build Coastguard Worker   const T inf = FPBits::inf(Sign::POS).get_val();
43*71db0c75SAndroid Build Coastguard Worker   const T neg_inf = FPBits::inf(Sign::NEG).get_val();
44*71db0c75SAndroid Build Coastguard Worker   const T zero = FPBits::zero(Sign::POS).get_val();
45*71db0c75SAndroid Build Coastguard Worker   const T neg_zero = FPBits::zero(Sign::NEG).get_val();
46*71db0c75SAndroid Build Coastguard Worker   const T nan = FPBits::quiet_nan().get_val();
47*71db0c75SAndroid Build Coastguard Worker 
48*71db0c75SAndroid Build Coastguard Worker   const long double to_inf = ToFPBits::inf(Sign::POS).get_val();
49*71db0c75SAndroid Build Coastguard Worker   const long double to_neg_inf = ToFPBits::inf(Sign::NEG).get_val();
50*71db0c75SAndroid Build Coastguard Worker   const long double to_zero = ToFPBits::zero().get_val();
51*71db0c75SAndroid Build Coastguard Worker   const long double to_neg_zero = ToFPBits::zero(Sign::NEG).get_val();
52*71db0c75SAndroid Build Coastguard Worker   const long double to_nan = ToFPBits::quiet_nan().get_val();
53*71db0c75SAndroid Build Coastguard Worker 
54*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType min_subnormal =
55*71db0c75SAndroid Build Coastguard Worker       FPBits::min_subnormal().uintval();
56*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType max_subnormal =
57*71db0c75SAndroid Build Coastguard Worker       FPBits::max_subnormal().uintval();
58*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType min_normal = FPBits::min_normal().uintval();
59*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType max_normal = FPBits::max_normal().uintval();
60*71db0c75SAndroid Build Coastguard Worker 
61*71db0c75SAndroid Build Coastguard Worker public:
62*71db0c75SAndroid Build Coastguard Worker   typedef T (*NextTowardFunc)(T, long double);
63*71db0c75SAndroid Build Coastguard Worker 
testNaN(NextTowardFunc func)64*71db0c75SAndroid Build Coastguard Worker   void testNaN(NextTowardFunc func) {
65*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(func(nan, 0), nan);
66*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(func(0, to_nan), nan);
67*71db0c75SAndroid Build Coastguard Worker   }
68*71db0c75SAndroid Build Coastguard Worker 
testBoundaries(NextTowardFunc func)69*71db0c75SAndroid Build Coastguard Worker   void testBoundaries(NextTowardFunc func) {
70*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(func(zero, to_neg_zero), neg_zero);
71*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(func(neg_zero, to_zero), zero);
72*71db0c75SAndroid Build Coastguard Worker 
73*71db0c75SAndroid Build Coastguard Worker     // 'from' is zero|neg_zero.
74*71db0c75SAndroid Build Coastguard Worker     T x = zero;
75*71db0c75SAndroid Build Coastguard Worker     T result = func(x, 1);
76*71db0c75SAndroid Build Coastguard Worker     StorageType expected_bits = 1;
77*71db0c75SAndroid Build Coastguard Worker     T expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
78*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
79*71db0c75SAndroid Build Coastguard Worker 
80*71db0c75SAndroid Build Coastguard Worker     result = func(x, -1);
81*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + 1;
82*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
83*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
84*71db0c75SAndroid Build Coastguard Worker 
85*71db0c75SAndroid Build Coastguard Worker     x = neg_zero;
86*71db0c75SAndroid Build Coastguard Worker     result = func(x, 1);
87*71db0c75SAndroid Build Coastguard Worker     expected_bits = 1;
88*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
89*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
90*71db0c75SAndroid Build Coastguard Worker 
91*71db0c75SAndroid Build Coastguard Worker     result = func(x, -1);
92*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + 1;
93*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
94*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
95*71db0c75SAndroid Build Coastguard Worker 
96*71db0c75SAndroid Build Coastguard Worker     // 'from' is max subnormal value.
97*71db0c75SAndroid Build Coastguard Worker     x = LIBC_NAMESPACE::cpp::bit_cast<T>(max_subnormal);
98*71db0c75SAndroid Build Coastguard Worker     result = func(x, 1);
99*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(min_normal);
100*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
101*71db0c75SAndroid Build Coastguard Worker 
102*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
103*71db0c75SAndroid Build Coastguard Worker     expected_bits = max_subnormal - 1;
104*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
105*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
106*71db0c75SAndroid Build Coastguard Worker 
107*71db0c75SAndroid Build Coastguard Worker     x = -x;
108*71db0c75SAndroid Build Coastguard Worker 
109*71db0c75SAndroid Build Coastguard Worker     result = func(x, -1);
110*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + min_normal;
111*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
112*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
113*71db0c75SAndroid Build Coastguard Worker 
114*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
115*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + max_subnormal - 1;
116*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
117*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
118*71db0c75SAndroid Build Coastguard Worker 
119*71db0c75SAndroid Build Coastguard Worker     // 'from' is min subnormal value.
120*71db0c75SAndroid Build Coastguard Worker     x = LIBC_NAMESPACE::cpp::bit_cast<T>(min_subnormal);
121*71db0c75SAndroid Build Coastguard Worker     result = func(x, 1);
122*71db0c75SAndroid Build Coastguard Worker     expected_bits = min_subnormal + 1;
123*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
124*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
125*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(func(x, 0), 0);
126*71db0c75SAndroid Build Coastguard Worker 
127*71db0c75SAndroid Build Coastguard Worker     x = -x;
128*71db0c75SAndroid Build Coastguard Worker     result = func(x, -1);
129*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + min_subnormal + 1;
130*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
131*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
132*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(func(x, 0), T(-0.0));
133*71db0c75SAndroid Build Coastguard Worker 
134*71db0c75SAndroid Build Coastguard Worker     // 'from' is min normal.
135*71db0c75SAndroid Build Coastguard Worker     x = LIBC_NAMESPACE::cpp::bit_cast<T>(min_normal);
136*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
137*71db0c75SAndroid Build Coastguard Worker     expected_bits = max_subnormal;
138*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
139*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
140*71db0c75SAndroid Build Coastguard Worker 
141*71db0c75SAndroid Build Coastguard Worker     result = func(x, to_inf);
142*71db0c75SAndroid Build Coastguard Worker     expected_bits = min_normal + 1;
143*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
144*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
145*71db0c75SAndroid Build Coastguard Worker 
146*71db0c75SAndroid Build Coastguard Worker     x = -x;
147*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
148*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + max_subnormal;
149*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
150*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
151*71db0c75SAndroid Build Coastguard Worker 
152*71db0c75SAndroid Build Coastguard Worker     result = func(x, to_neg_inf);
153*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + min_normal + 1;
154*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
155*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
156*71db0c75SAndroid Build Coastguard Worker 
157*71db0c75SAndroid Build Coastguard Worker     // 'from' is max normal
158*71db0c75SAndroid Build Coastguard Worker     x = LIBC_NAMESPACE::cpp::bit_cast<T>(max_normal);
159*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
160*71db0c75SAndroid Build Coastguard Worker     expected_bits = max_normal - 1;
161*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
162*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
163*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_OVERFLOW(func(x, to_inf), inf);
164*71db0c75SAndroid Build Coastguard Worker 
165*71db0c75SAndroid Build Coastguard Worker     x = -x;
166*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
167*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + max_normal - 1;
168*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
169*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
170*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ_WITH_OVERFLOW(func(x, to_neg_inf), neg_inf);
171*71db0c75SAndroid Build Coastguard Worker 
172*71db0c75SAndroid Build Coastguard Worker     // 'from' is infinity.
173*71db0c75SAndroid Build Coastguard Worker     x = inf;
174*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
175*71db0c75SAndroid Build Coastguard Worker     expected_bits = max_normal;
176*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
177*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
178*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(func(x, to_inf), inf);
179*71db0c75SAndroid Build Coastguard Worker 
180*71db0c75SAndroid Build Coastguard Worker     x = neg_inf;
181*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
182*71db0c75SAndroid Build Coastguard Worker     expected_bits = FPBits::SIGN_MASK + max_normal;
183*71db0c75SAndroid Build Coastguard Worker     expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
184*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(result, expected);
185*71db0c75SAndroid Build Coastguard Worker     ASSERT_FP_EQ(func(x, to_neg_inf), neg_inf);
186*71db0c75SAndroid Build Coastguard Worker 
187*71db0c75SAndroid Build Coastguard Worker     // 'from' is a power of 2.
188*71db0c75SAndroid Build Coastguard Worker     x = T(32.0);
189*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
190*71db0c75SAndroid Build Coastguard Worker     FPBits x_bits = FPBits(x);
191*71db0c75SAndroid Build Coastguard Worker     FPBits result_bits = FPBits(result);
192*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_biased_exponent(),
193*71db0c75SAndroid Build Coastguard Worker               uint16_t(x_bits.get_biased_exponent() - 1));
194*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_mantissa(), FPBits::FRACTION_MASK);
195*71db0c75SAndroid Build Coastguard Worker 
196*71db0c75SAndroid Build Coastguard Worker     result = func(x, 33.0);
197*71db0c75SAndroid Build Coastguard Worker     result_bits = FPBits(result);
198*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_biased_exponent(), x_bits.get_biased_exponent());
199*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_mantissa(),
200*71db0c75SAndroid Build Coastguard Worker               static_cast<StorageType>(x_bits.get_mantissa() + StorageType(1)));
201*71db0c75SAndroid Build Coastguard Worker 
202*71db0c75SAndroid Build Coastguard Worker     x = -x;
203*71db0c75SAndroid Build Coastguard Worker 
204*71db0c75SAndroid Build Coastguard Worker     result = func(x, 0);
205*71db0c75SAndroid Build Coastguard Worker     result_bits = FPBits(result);
206*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_biased_exponent(),
207*71db0c75SAndroid Build Coastguard Worker               uint16_t(x_bits.get_biased_exponent() - 1));
208*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_mantissa(), FPBits::FRACTION_MASK);
209*71db0c75SAndroid Build Coastguard Worker 
210*71db0c75SAndroid Build Coastguard Worker     result = func(x, -33.0);
211*71db0c75SAndroid Build Coastguard Worker     result_bits = FPBits(result);
212*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_biased_exponent(), x_bits.get_biased_exponent());
213*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(result_bits.get_mantissa(),
214*71db0c75SAndroid Build Coastguard Worker               static_cast<StorageType>(x_bits.get_mantissa() + StorageType(1)));
215*71db0c75SAndroid Build Coastguard Worker   }
216*71db0c75SAndroid Build Coastguard Worker };
217*71db0c75SAndroid Build Coastguard Worker 
218*71db0c75SAndroid Build Coastguard Worker #define LIST_NEXTTOWARD_TESTS(T, func)                                         \
219*71db0c75SAndroid Build Coastguard Worker   using LlvmLibcNextTowardTest = NextTowardTestTemplate<T>;                    \
220*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibcNextTowardTest, TestNaN) { testNaN(&func); }                  \
221*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibcNextTowardTest, TestBoundaries) { testBoundaries(&func); }
222*71db0c75SAndroid Build Coastguard Worker 
223*71db0c75SAndroid Build Coastguard Worker #endif // LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H
224