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