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 "utils/CPP/TypeTraits.h"
13 #include "utils/FPUtil/BasicOperations.h"
14 #include "utils/FPUtil/FPBits.h"
15 #include "utils/FPUtil/TestHelpers.h"
16 #include "utils/UnitTest/Test.h"
17 #include <math.h>
18 
19 template <typename T>
20 class NextAfterTestTemplate : public __llvm_libc::testing::Test {
21   using FPBits = __llvm_libc::fputil::FPBits<T>;
22   using MantissaWidth = __llvm_libc::fputil::MantissaWidth<T>;
23   using UIntType = typename FPBits::UIntType;
24 
25 #if (defined(__x86_64__) || defined(__i386__))
26   static constexpr int bitWidthOfType =
27       __llvm_libc::cpp::IsSame<T, long double>::Value ? 80 : (sizeof(T) * 8);
28 #else
29   static constexpr int bitWidthOfType = sizeof(T) * 8;
30 #endif
31 
32   const T zero = FPBits::zero();
33   const T negZero = FPBits::negZero();
34   const T inf = FPBits::inf();
35   const T negInf = FPBits::negInf();
36   const T nan = FPBits::buildNaN(1);
37   const UIntType minSubnormal = FPBits::minSubnormal;
38   const UIntType maxSubnormal = FPBits::maxSubnormal;
39   const UIntType minNormal = FPBits::minNormal;
40   const UIntType maxNormal = FPBits::maxNormal;
41 
42 public:
43   typedef T (*NextAfterFunc)(T, T);
44 
45   void testNaN(NextAfterFunc func) {
46     ASSERT_FP_EQ(func(nan, 0), nan);
47     ASSERT_FP_EQ(func(0, nan), nan);
48   }
49 
50   void testBoundaries(NextAfterFunc func) {
51     ASSERT_FP_EQ(func(zero, negZero), negZero);
52     ASSERT_FP_EQ(func(negZero, zero), zero);
53 
54     // 'from' is zero|negZero.
55     T x = zero;
56     T result = func(x, T(1));
57     UIntType expectedBits = 1;
58     T expected = *reinterpret_cast<T *>(&expectedBits);
59     ASSERT_FP_EQ(result, expected);
60 
61     result = func(x, T(-1));
62     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + 1;
63     expected = *reinterpret_cast<T *>(&expectedBits);
64     ASSERT_FP_EQ(result, expected);
65 
66     x = negZero;
67     result = func(x, 1);
68     expectedBits = 1;
69     expected = *reinterpret_cast<T *>(&expectedBits);
70     ASSERT_FP_EQ(result, expected);
71 
72     result = func(x, -1);
73     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + 1;
74     expected = *reinterpret_cast<T *>(&expectedBits);
75     ASSERT_FP_EQ(result, expected);
76 
77     // 'from' is max subnormal value.
78     x = *reinterpret_cast<const T *>(&maxSubnormal);
79     result = func(x, 1);
80     expected = *reinterpret_cast<const T *>(&minNormal);
81     ASSERT_FP_EQ(result, expected);
82 
83     result = func(x, 0);
84     expectedBits = maxSubnormal - 1;
85     expected = *reinterpret_cast<T *>(&expectedBits);
86     ASSERT_FP_EQ(result, expected);
87 
88     x = -x;
89 
90     result = func(x, -1);
91     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + minNormal;
92     expected = *reinterpret_cast<T *>(&expectedBits);
93     ASSERT_FP_EQ(result, expected);
94 
95     result = func(x, 0);
96     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + maxSubnormal - 1;
97     expected = *reinterpret_cast<T *>(&expectedBits);
98     ASSERT_FP_EQ(result, expected);
99 
100     // 'from' is min subnormal value.
101     x = *reinterpret_cast<const T *>(&minSubnormal);
102     result = func(x, 1);
103     expectedBits = minSubnormal + 1;
104     expected = *reinterpret_cast<T *>(&expectedBits);
105     ASSERT_FP_EQ(result, expected);
106     ASSERT_FP_EQ(func(x, 0), 0);
107 
108     x = -x;
109     result = func(x, -1);
110     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + minSubnormal + 1;
111     expected = *reinterpret_cast<T *>(&expectedBits);
112     ASSERT_FP_EQ(result, expected);
113     ASSERT_FP_EQ(func(x, 0), T(-0.0));
114 
115     // 'from' is min normal.
116     x = *reinterpret_cast<const T *>(&minNormal);
117     result = func(x, 0);
118     expectedBits = maxSubnormal;
119     expected = *reinterpret_cast<T *>(&expectedBits);
120     ASSERT_FP_EQ(result, expected);
121 
122     result = func(x, inf);
123     expectedBits = minNormal + 1;
124     expected = *reinterpret_cast<T *>(&expectedBits);
125     ASSERT_FP_EQ(result, expected);
126 
127     x = -x;
128     result = func(x, 0);
129     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + maxSubnormal;
130     expected = *reinterpret_cast<T *>(&expectedBits);
131     ASSERT_FP_EQ(result, expected);
132 
133     result = func(x, -inf);
134     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + minNormal + 1;
135     expected = *reinterpret_cast<T *>(&expectedBits);
136     ASSERT_FP_EQ(result, expected);
137 
138     // 'from' is max normal and 'to' is infinity.
139     x = *reinterpret_cast<const T *>(&maxNormal);
140     result = func(x, inf);
141     ASSERT_FP_EQ(result, inf);
142 
143     result = func(-x, -inf);
144     ASSERT_FP_EQ(result, -inf);
145 
146     // 'from' is infinity.
147     x = inf;
148     result = func(x, 0);
149     expectedBits = maxNormal;
150     expected = *reinterpret_cast<T *>(&expectedBits);
151     ASSERT_FP_EQ(result, expected);
152     ASSERT_FP_EQ(func(x, inf), inf);
153 
154     x = negInf;
155     result = func(x, 0);
156     expectedBits = (UIntType(1) << (bitWidthOfType - 1)) + maxNormal;
157     expected = *reinterpret_cast<T *>(&expectedBits);
158     ASSERT_FP_EQ(result, expected);
159     ASSERT_FP_EQ(func(x, negInf), negInf);
160 
161     // 'from' is a power of 2.
162     x = T(32.0);
163     result = func(x, 0);
164     FPBits xBits = FPBits(x);
165     FPBits resultBits = FPBits(result);
166     ASSERT_EQ(resultBits.exponent, uint16_t(xBits.exponent - 1));
167     ASSERT_EQ(resultBits.mantissa, (UIntType(1) << MantissaWidth::value) - 1);
168 
169     result = func(x, T(33.0));
170     resultBits = FPBits(result);
171     ASSERT_EQ(resultBits.exponent, xBits.exponent);
172     ASSERT_EQ(resultBits.mantissa, xBits.mantissa + UIntType(1));
173 
174     x = -x;
175 
176     result = func(x, 0);
177     resultBits = FPBits(result);
178     ASSERT_EQ(resultBits.exponent, uint16_t(xBits.exponent - 1));
179     ASSERT_EQ(resultBits.mantissa, (UIntType(1) << MantissaWidth::value) - 1);
180 
181     result = func(x, T(-33.0));
182     resultBits = FPBits(result);
183     ASSERT_EQ(resultBits.exponent, xBits.exponent);
184     ASSERT_EQ(resultBits.mantissa, xBits.mantissa + UIntType(1));
185   }
186 };
187 
188 #define LIST_NEXTAFTER_TESTS(T, func)                                          \
189   using LlvmLibcNextAfterTest = NextAfterTestTemplate<T>;                      \
190   TEST_F(LlvmLibcNextAfterTest, TestNaN) { testNaN(&func); }                   \
191   TEST_F(LlvmLibcNextAfterTest, TestBoundaries) { testBoundaries(&func); }
192 
193 #endif // LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H
194