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/CPP/TypeTraits.h"
14 #include "src/__support/FPUtil/BasicOperations.h"
15 #include "src/__support/FPUtil/FPBits.h"
16 #include "utils/UnitTest/FPMatcher.h"
17 #include "utils/UnitTest/Test.h"
18 #include <math.h>
19 
20 template <typename T>
21 class NextAfterTestTemplate : public __llvm_libc::testing::Test {
22   using FPBits = __llvm_libc::fputil::FPBits<T>;
23   using MantissaWidth = __llvm_libc::fputil::MantissaWidth<T>;
24   using UIntType = typename FPBits::UIntType;
25 
26   static constexpr int BIT_WIDTH_OF_TYPE =
27       __llvm_libc::fputil::FloatProperties<T>::BIT_WIDTH;
28 
29   const T zero = T(FPBits::zero());
30   const T neg_zero = T(FPBits::neg_zero());
31   const T inf = T(FPBits::inf());
32   const T neg_inf = T(FPBits::neg_inf());
33   const T nan = T(FPBits::build_nan(1));
34   const UIntType min_subnormal = FPBits::MIN_SUBNORMAL;
35   const UIntType max_subnormal = FPBits::MAX_SUBNORMAL;
36   const UIntType min_normal = FPBits::MIN_NORMAL;
37   const UIntType max_normal = FPBits::MAX_NORMAL;
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     UIntType expected_bits = 1;
55     T expected = __llvm_libc::bit_cast<T>(expected_bits);
56     ASSERT_FP_EQ(result, expected);
57 
58     result = func(x, T(-1));
59     expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + 1;
60     expected = __llvm_libc::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 = __llvm_libc::bit_cast<T>(expected_bits);
67     ASSERT_FP_EQ(result, expected);
68 
69     result = func(x, -1);
70     expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + 1;
71     expected = __llvm_libc::bit_cast<T>(expected_bits);
72     ASSERT_FP_EQ(result, expected);
73 
74     // 'from' is max subnormal value.
75     x = __llvm_libc::bit_cast<T>(max_subnormal);
76     result = func(x, 1);
77     expected = __llvm_libc::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 = __llvm_libc::bit_cast<T>(expected_bits);
83     ASSERT_FP_EQ(result, expected);
84 
85     x = -x;
86 
87     result = func(x, -1);
88     expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + min_normal;
89     expected = __llvm_libc::bit_cast<T>(expected_bits);
90     ASSERT_FP_EQ(result, expected);
91 
92     result = func(x, 0);
93     expected_bits =
94         (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + max_subnormal - 1;
95     expected = __llvm_libc::bit_cast<T>(expected_bits);
96     ASSERT_FP_EQ(result, expected);
97 
98     // 'from' is min subnormal value.
99     x = __llvm_libc::bit_cast<T>(min_subnormal);
100     result = func(x, 1);
101     expected_bits = min_subnormal + 1;
102     expected = __llvm_libc::bit_cast<T>(expected_bits);
103     ASSERT_FP_EQ(result, expected);
104     ASSERT_FP_EQ(func(x, 0), 0);
105 
106     x = -x;
107     result = func(x, -1);
108     expected_bits =
109         (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + min_subnormal + 1;
110     expected = __llvm_libc::bit_cast<T>(expected_bits);
111     ASSERT_FP_EQ(result, expected);
112     ASSERT_FP_EQ(func(x, 0), T(-0.0));
113 
114     // 'from' is min normal.
115     x = __llvm_libc::bit_cast<T>(min_normal);
116     result = func(x, 0);
117     expected_bits = max_subnormal;
118     expected = __llvm_libc::bit_cast<T>(expected_bits);
119     ASSERT_FP_EQ(result, expected);
120 
121     result = func(x, inf);
122     expected_bits = min_normal + 1;
123     expected = __llvm_libc::bit_cast<T>(expected_bits);
124     ASSERT_FP_EQ(result, expected);
125 
126     x = -x;
127     result = func(x, 0);
128     expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + max_subnormal;
129     expected = __llvm_libc::bit_cast<T>(expected_bits);
130     ASSERT_FP_EQ(result, expected);
131 
132     result = func(x, -inf);
133     expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + min_normal + 1;
134     expected = __llvm_libc::bit_cast<T>(expected_bits);
135     ASSERT_FP_EQ(result, expected);
136 
137     // 'from' is max normal and 'to' is infinity.
138     x = __llvm_libc::bit_cast<T>(max_normal);
139     result = func(x, inf);
140     ASSERT_FP_EQ(result, inf);
141 
142     result = func(-x, -inf);
143     ASSERT_FP_EQ(result, -inf);
144 
145     // 'from' is infinity.
146     x = inf;
147     result = func(x, 0);
148     expected_bits = max_normal;
149     expected = __llvm_libc::bit_cast<T>(expected_bits);
150     ASSERT_FP_EQ(result, expected);
151     ASSERT_FP_EQ(func(x, inf), inf);
152 
153     x = neg_inf;
154     result = func(x, 0);
155     expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + max_normal;
156     expected = __llvm_libc::bit_cast<T>(expected_bits);
157     ASSERT_FP_EQ(result, expected);
158     ASSERT_FP_EQ(func(x, neg_inf), neg_inf);
159 
160     // 'from' is a power of 2.
161     x = T(32.0);
162     result = func(x, 0);
163     FPBits x_bits = FPBits(x);
164     FPBits result_bits = FPBits(result);
165     ASSERT_EQ(result_bits.get_unbiased_exponent(),
166               uint16_t(x_bits.get_unbiased_exponent() - 1));
167     ASSERT_EQ(result_bits.get_mantissa(),
168               (UIntType(1) << MantissaWidth::VALUE) - 1);
169 
170     result = func(x, T(33.0));
171     result_bits = FPBits(result);
172     ASSERT_EQ(result_bits.get_unbiased_exponent(),
173               x_bits.get_unbiased_exponent());
174     ASSERT_EQ(result_bits.get_mantissa(), x_bits.get_mantissa() + UIntType(1));
175 
176     x = -x;
177 
178     result = func(x, 0);
179     result_bits = FPBits(result);
180     ASSERT_EQ(result_bits.get_unbiased_exponent(),
181               uint16_t(x_bits.get_unbiased_exponent() - 1));
182     ASSERT_EQ(result_bits.get_mantissa(),
183               (UIntType(1) << MantissaWidth::VALUE) - 1);
184 
185     result = func(x, T(-33.0));
186     result_bits = FPBits(result);
187     ASSERT_EQ(result_bits.get_unbiased_exponent(),
188               x_bits.get_unbiased_exponent());
189     ASSERT_EQ(result_bits.get_mantissa(), x_bits.get_mantissa() + UIntType(1));
190   }
191 };
192 
193 #define LIST_NEXTAFTER_TESTS(T, func)                                          \
194   using LlvmLibcNextAfterTest = NextAfterTestTemplate<T>;                      \
195   TEST_F(LlvmLibcNextAfterTest, TestNaN) { testNaN(&func); }                   \
196   TEST_F(LlvmLibcNextAfterTest, TestBoundaries) { testBoundaries(&func); }
197 
198 #endif // LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H
199