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