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