1 | //===-- flang/unittests/Runtime/Numeric.cpp ---------------------*- 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 | #include "flang/Runtime/numeric.h" |
10 | #include "gtest/gtest.h" |
11 | #include "flang/Common/float128.h" |
12 | #include <cmath> |
13 | #include <limits> |
14 | |
15 | using namespace Fortran::runtime; |
16 | using Fortran::common::TypeCategory; |
17 | template <int KIND> using Int = CppTypeFor<TypeCategory::Integer, KIND>; |
18 | template <int KIND> using Real = CppTypeFor<TypeCategory::Real, KIND>; |
19 | |
20 | // Simple tests of numeric intrinsic functions using examples from Fortran 2018 |
21 | |
22 | TEST(Numeric, Ceiling) { |
23 | EXPECT_EQ(RTNAME(Ceiling4_4)(Real<4>{3.7}), 4); |
24 | EXPECT_EQ(RTNAME(Ceiling8_8)(Real<8>{-3.7}), -3); |
25 | EXPECT_EQ(RTNAME(Ceiling4_1)(Real<4>{0}), 0); |
26 | } |
27 | |
28 | TEST(Numeric, Floor) { |
29 | EXPECT_EQ(RTNAME(Floor4_4)(Real<4>{3.7}), 3); |
30 | EXPECT_EQ(RTNAME(Floor8_8)(Real<8>{-3.7}), -4); |
31 | EXPECT_EQ(RTNAME(Floor4_1)(Real<4>{0}), 0); |
32 | } |
33 | |
34 | TEST(Numeric, Exponent) { |
35 | EXPECT_EQ(RTNAME(Exponent4_4)(Real<4>{0}), 0); |
36 | EXPECT_EQ(RTNAME(Exponent4_8)(Real<4>{1.0}), 1); |
37 | EXPECT_EQ(RTNAME(Exponent8_4)(Real<8>{4.1}), 3); |
38 | EXPECT_EQ(RTNAME(Exponent8_8)(std::numeric_limits<Real<8>>::infinity()), |
39 | std::numeric_limits<Int<8>>::max()); |
40 | EXPECT_EQ(RTNAME(Exponent8_8)(std::numeric_limits<Real<8>>::quiet_NaN()), |
41 | std::numeric_limits<Int<8>>::max()); |
42 | } |
43 | |
44 | TEST(Numeric, Fraction) { |
45 | EXPECT_EQ(RTNAME(Fraction4)(Real<4>{0}), 0); |
46 | EXPECT_EQ(RTNAME(Fraction8)(Real<8>{3.0}), 0.75); |
47 | EXPECT_TRUE( |
48 | std::isnan(RTNAME(Fraction4)(std::numeric_limits<Real<4>>::infinity()))); |
49 | EXPECT_TRUE( |
50 | std::isnan(RTNAME(Fraction8)(std::numeric_limits<Real<8>>::quiet_NaN()))); |
51 | } |
52 | |
53 | TEST(Numeric, IsNaN) { |
54 | EXPECT_FALSE(RTNAME(IsNaN4)(Real<4>{0})); |
55 | EXPECT_FALSE(RTNAME(IsNaN8)(std::numeric_limits<Real<8>>::infinity())); |
56 | EXPECT_TRUE(RTNAME(IsNaN8)(std::numeric_limits<Real<8>>::quiet_NaN())); |
57 | } |
58 | |
59 | TEST(Numeric, Mod) { |
60 | EXPECT_EQ(RTNAME(ModInteger1)(Int<1>{8}, Int<1>(5)), 3); |
61 | EXPECT_EQ(RTNAME(ModInteger4)(Int<4>{-8}, Int<4>(5)), -3); |
62 | EXPECT_EQ(RTNAME(ModInteger2)(Int<2>{8}, Int<2>(-5)), 3); |
63 | EXPECT_EQ(RTNAME(ModInteger8)(Int<8>{-8}, Int<8>(-5)), -3); |
64 | EXPECT_EQ(RTNAME(ModReal4)(Real<4>{8.0}, Real<4>(5.0)), 3.0); |
65 | EXPECT_EQ(RTNAME(ModReal4)(Real<4>{-8.0}, Real<4>(5.0)), -3.0); |
66 | EXPECT_EQ(RTNAME(ModReal8)(Real<8>{8.0}, Real<8>(-5.0)), 3.0); |
67 | EXPECT_EQ(RTNAME(ModReal8)(Real<8>{-8.0}, Real<8>(-5.0)), -3.0); |
68 | EXPECT_EQ( |
69 | RTNAME(ModReal4)(Real<4>{0.5}, std::numeric_limits<Real<4>>::infinity()), |
70 | 0.5); |
71 | EXPECT_EQ( |
72 | RTNAME(ModReal4)(Real<4>{-0.5}, std::numeric_limits<Real<4>>::infinity()), |
73 | -0.5); |
74 | EXPECT_EQ( |
75 | RTNAME(ModReal4)(Real<4>{0.5}, -std::numeric_limits<Real<4>>::infinity()), |
76 | 0.5); |
77 | EXPECT_EQ(RTNAME(ModReal4)( |
78 | Real<4>{-0.5}, -std::numeric_limits<Real<4>>::infinity()), |
79 | -0.5); |
80 | EXPECT_EQ( |
81 | RTNAME(ModReal8)(Real<8>{0.5}, std::numeric_limits<Real<8>>::infinity()), |
82 | 0.5); |
83 | EXPECT_EQ( |
84 | RTNAME(ModReal8)(Real<8>{-0.5}, std::numeric_limits<Real<8>>::infinity()), |
85 | -0.5); |
86 | EXPECT_EQ( |
87 | RTNAME(ModReal8)(Real<8>{0.5}, -std::numeric_limits<Real<8>>::infinity()), |
88 | 0.5); |
89 | EXPECT_EQ(RTNAME(ModReal8)( |
90 | Real<8>{-0.5}, -std::numeric_limits<Real<8>>::infinity()), |
91 | -0.5); |
92 | } |
93 | |
94 | TEST(Numeric, Modulo) { |
95 | EXPECT_EQ(RTNAME(ModuloInteger1)(Int<1>{8}, Int<1>(5)), 3); |
96 | EXPECT_EQ(RTNAME(ModuloInteger4)(Int<4>{-8}, Int<4>(5)), 2); |
97 | EXPECT_EQ(RTNAME(ModuloInteger2)(Int<2>{8}, Int<2>(-5)), -2); |
98 | EXPECT_EQ(RTNAME(ModuloInteger8)(Int<8>{-8}, Int<8>(-5)), -3); |
99 | EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{8.0}, Real<4>(5.0)), 3.0); |
100 | EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{-8.0}, Real<4>(5.0)), 2.0); |
101 | EXPECT_EQ(RTNAME(ModuloReal8)(Real<8>{8.0}, Real<8>(-5.0)), -2.0); |
102 | EXPECT_EQ(RTNAME(ModuloReal8)(Real<8>{-8.0}, Real<8>(-5.0)), -3.0); |
103 | // MODULO(x, INF) == NaN |
104 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal4)( |
105 | Real<4>{0.5}, std::numeric_limits<Real<4>>::infinity()))); |
106 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal4)( |
107 | Real<4>{-0.5}, std::numeric_limits<Real<4>>::infinity()))); |
108 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal4)( |
109 | Real<4>{0.5}, -std::numeric_limits<Real<4>>::infinity()))); |
110 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal4)( |
111 | Real<4>{-0.5}, -std::numeric_limits<Real<4>>::infinity()))); |
112 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal8)( |
113 | Real<8>{-0.5}, std::numeric_limits<Real<8>>::infinity()))); |
114 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal8)( |
115 | Real<8>{0.5}, std::numeric_limits<Real<8>>::infinity()))); |
116 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal8)( |
117 | Real<8>{-0.5}, -std::numeric_limits<Real<8>>::infinity()))); |
118 | EXPECT_TRUE(std::isnan(RTNAME(ModuloReal8)( |
119 | Real<8>{0.5}, -std::numeric_limits<Real<8>>::infinity()))); |
120 | // MODULO(x, y) for integer values of x and y with 0 remainder. |
121 | EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{5.0}, Real<4>(1.0)), 0.0); |
122 | EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{5.0}, Real<4>(-1.0)), -0.0); |
123 | EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{-5.0}, Real<4>(1.0)), 0.0); |
124 | EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{-5.0}, Real<4>(-1.0)), -0.0); |
125 | } |
126 | |
127 | TEST(Numeric, Nearest) { |
128 | EXPECT_EQ(RTNAME(Nearest4)(Real<4>{0}, true), |
129 | std::numeric_limits<Real<4>>::denorm_min()); |
130 | EXPECT_EQ(RTNAME(Nearest4)(Real<4>{3.0}, true), |
131 | Real<4>{3.0} + std::ldexp(Real<4>{1.0}, -22)); |
132 | EXPECT_EQ(RTNAME(Nearest8)(Real<8>{1.0}, true), |
133 | Real<8>{1.0} + std::ldexp(Real<8>{1.0}, -52)); |
134 | EXPECT_EQ(RTNAME(Nearest8)(Real<8>{1.0}, false), |
135 | Real<8>{1.0} - 0.5 * std::ldexp(Real<8>{1.0}, -52)); |
136 | } |
137 | |
138 | TEST(Numeric, Nint) { |
139 | EXPECT_EQ(RTNAME(Nint4_4)(Real<4>{2.783}), 3); |
140 | EXPECT_EQ(RTNAME(Nint8_4)(Real<8>{-2.783}), -3); |
141 | EXPECT_EQ(RTNAME(Nint4_4)(Real<4>{2.5}), 3); |
142 | EXPECT_EQ(RTNAME(Nint8_4)(Real<8>{-2.5}), -3); |
143 | EXPECT_EQ(RTNAME(Nint8_8)(Real<8>{0}), 0); |
144 | } |
145 | |
146 | TEST(Numeric, RRSpacing) { |
147 | EXPECT_EQ(RTNAME(RRSpacing8)(Real<8>{0}), 0); |
148 | EXPECT_EQ(RTNAME(RRSpacing4)(Real<4>{-3.0}), 0.75 * (1 << 24)); |
149 | EXPECT_EQ(RTNAME(RRSpacing8)(Real<8>{-3.0}), 0.75 * (std::int64_t{1} << 53)); |
150 | EXPECT_TRUE( |
151 | std::isnan(RTNAME(RRSpacing4)(std::numeric_limits<Real<4>>::infinity()))); |
152 | EXPECT_TRUE(std::isnan( |
153 | RTNAME(RRSpacing8)(std::numeric_limits<Real<8>>::quiet_NaN()))); |
154 | } |
155 | |
156 | TEST(Numeric, Scale) { |
157 | EXPECT_EQ(RTNAME(Scale4)(Real<4>{0}, 0), 0); |
158 | EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, 0), 1.0); |
159 | EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, 1), 2.0); |
160 | EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, -1), 0.5); |
161 | EXPECT_TRUE( |
162 | std::isinf(RTNAME(Scale4)(std::numeric_limits<Real<4>>::infinity(), 1))); |
163 | EXPECT_TRUE( |
164 | std::isnan(RTNAME(Scale8)(std::numeric_limits<Real<8>>::quiet_NaN(), 1))); |
165 | } |
166 | |
167 | TEST(Numeric, SetExponent) { |
168 | EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{0}, 0), 0); |
169 | EXPECT_EQ(RTNAME(SetExponent8)(Real<8>{0}, 666), 0); |
170 | EXPECT_EQ(RTNAME(SetExponent8)(Real<8>{3.0}, 0), 0.75); |
171 | EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, 0), 0.5); |
172 | EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, 1), 1.0); |
173 | EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, -1), 0.25); |
174 | EXPECT_TRUE(std::isnan( |
175 | RTNAME(SetExponent4)(std::numeric_limits<Real<4>>::infinity(), 1))); |
176 | EXPECT_TRUE(std::isnan( |
177 | RTNAME(SetExponent8)(std::numeric_limits<Real<8>>::quiet_NaN(), 1))); |
178 | } |
179 | |
180 | TEST(Numeric, SelectedIntKind) { |
181 | std::int8_t r0 = 1; |
182 | std::int16_t r1 = 3; |
183 | std::int32_t r2 = 8; |
184 | std::int64_t r3 = 10; |
185 | std::int32_t r4 = -10; |
186 | std::int32_t r5 = 100; |
187 | EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r0, 1), 1); |
188 | EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r1, 2), 2); |
189 | EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r2, 4), 4); |
190 | EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r3, 8), 8); |
191 | EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r4, 4), 1); |
192 | EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r5, 4), -1); |
193 | } |
194 | |
195 | TEST(Numeric, SelectedRealKind) { |
196 | std::int8_t p_s = 1; |
197 | std::int16_t p[11] = {-10, 1, 1, 4, 50, 1, 1, 4, 1, 1, 50}; |
198 | std::int32_t r[11] = {-1, 1, 1, 1, 2, 1, 20, 20, 100, 5000, 5000}; |
199 | std::int64_t d[11] = {2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2}; |
200 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
201 | __FILE__, __LINE__, &p[0], 2, &r[0], 4, &d[0], 8), |
202 | 2); |
203 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
204 | __FILE__, __LINE__, &p[1], 2, &r[1], 4, &d[1], 8), |
205 | -5); |
206 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
207 | __FILE__, __LINE__, &p[2], 2, &r[2], 4, &d[2], 8), |
208 | 2); |
209 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
210 | __FILE__, __LINE__, &p[3], 2, &r[3], 4, &d[3], 8), |
211 | 4); |
212 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
213 | __FILE__, __LINE__, &p[4], 2, &r[4], 4, &d[4], 8), |
214 | -1); |
215 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
216 | __FILE__, __LINE__, &p[5], 2, &r[5], 4, &d[5], 8), |
217 | 2); |
218 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
219 | __FILE__, __LINE__, &p[6], 2, &r[6], 4, &d[6], 8), |
220 | 3); |
221 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
222 | __FILE__, __LINE__, &p[7], 2, &r[7], 4, &d[7], 8), |
223 | 4); |
224 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
225 | __FILE__, __LINE__, &p[8], 2, &r[8], 4, &d[8], 8), |
226 | 8); |
227 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
228 | __FILE__, __LINE__, &p[9], 2, &r[9], 4, &d[9], 8), |
229 | -2); |
230 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
231 | __FILE__, __LINE__, &p[10], 2, &r[10], 4, &d[10], 8), |
232 | -3); |
233 | EXPECT_EQ( |
234 | RTNAME(SelectedRealKind)(__FILE__, __LINE__, &p_s, 1, &r[0], 4, &d[0], 8), |
235 | 2); |
236 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
237 | __FILE__, __LINE__, nullptr, 0, &r[0], 4, &d[0], 8), |
238 | 2); |
239 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
240 | __FILE__, __LINE__, &p[0], 2, nullptr, 0, &d[0], 8), |
241 | 2); |
242 | EXPECT_EQ(RTNAME(SelectedRealKind)( |
243 | __FILE__, __LINE__, &p[0], 2, &r[0], 4, nullptr, 0), |
244 | 2); |
245 | } |
246 | |
247 | TEST(Numeric, Spacing) { |
248 | EXPECT_EQ(RTNAME(Spacing8)(Real<8>{0}), std::numeric_limits<Real<8>>::min()); |
249 | EXPECT_EQ(RTNAME(Spacing4)(Real<4>{3.0}), std::ldexp(Real<4>{1.0}, -22)); |
250 | EXPECT_TRUE( |
251 | std::isnan(RTNAME(Spacing4)(std::numeric_limits<Real<4>>::infinity()))); |
252 | EXPECT_TRUE( |
253 | std::isnan(RTNAME(Spacing8)(std::numeric_limits<Real<8>>::quiet_NaN()))); |
254 | } |
255 | |
256 | TEST(Numeric, FPowI) { |
257 | EXPECT_EQ(RTNAME(FPow4i)(Real<4>{0}, Int<4>{0}), Real<4>{1}); |
258 | EXPECT_EQ(RTNAME(FPow4i)(Real<4>{0.3}, Int<4>{0}), Real<4>{1}); |
259 | EXPECT_EQ(RTNAME(FPow4i)(Real<4>{2}, Int<4>{-1}), Real<4>{0.5}); |
260 | EXPECT_EQ(RTNAME(FPow4i)(Real<4>{0.5}, Int<4>{-1}), Real<4>{2}); |
261 | EXPECT_EQ(RTNAME(FPow4i)(Real<4>{-3}, Int<4>{3}), Real<4>{-27}); |
262 | EXPECT_EQ(RTNAME(FPow4i)(Real<4>{-2}, Int<4>{-3}), Real<4>{-0.125}); |
263 | |
264 | EXPECT_EQ(RTNAME(FPow4k)(Real<4>{0}, Int<8>{0}), Real<4>{1}); |
265 | EXPECT_EQ(RTNAME(FPow4k)(Real<4>{0.3}, Int<8>{0}), Real<4>{1}); |
266 | EXPECT_EQ(RTNAME(FPow4k)(Real<4>{2}, Int<8>{-1}), Real<4>{0.5}); |
267 | EXPECT_EQ(RTNAME(FPow4k)(Real<4>{0.5}, Int<8>{-1}), Real<4>{2}); |
268 | EXPECT_EQ(RTNAME(FPow4k)(Real<4>{-3}, Int<8>{3}), Real<4>{-27}); |
269 | EXPECT_EQ(RTNAME(FPow4k)(Real<4>{-2}, Int<8>{-3}), Real<4>{-0.125}); |
270 | |
271 | EXPECT_EQ(RTNAME(FPow8i)(Real<8>{0}, Int<4>{0}), Real<8>{1}); |
272 | EXPECT_EQ(RTNAME(FPow8i)(Real<8>{0.3}, Int<4>{0}), Real<8>{1}); |
273 | EXPECT_EQ(RTNAME(FPow8i)(Real<8>{2}, Int<4>{-1}), Real<8>{0.5}); |
274 | EXPECT_EQ(RTNAME(FPow8i)(Real<8>{0.5}, Int<4>{-1}), Real<8>{2}); |
275 | EXPECT_EQ(RTNAME(FPow8i)(Real<8>{-3}, Int<4>{3}), Real<8>{-27}); |
276 | EXPECT_EQ(RTNAME(FPow8i)(Real<8>{-2}, Int<4>{-3}), Real<8>{-0.125}); |
277 | |
278 | EXPECT_EQ(RTNAME(FPow8k)(Real<8>{0}, Int<8>{0}), Real<8>{1}); |
279 | EXPECT_EQ(RTNAME(FPow8k)(Real<8>{0.3}, Int<8>{0}), Real<8>{1}); |
280 | EXPECT_EQ(RTNAME(FPow8k)(Real<8>{2}, Int<8>{-1}), Real<8>{0.5}); |
281 | EXPECT_EQ(RTNAME(FPow8k)(Real<8>{0.5}, Int<8>{-1}), Real<8>{2}); |
282 | EXPECT_EQ(RTNAME(FPow8k)(Real<8>{-3}, Int<8>{3}), Real<8>{-27}); |
283 | EXPECT_EQ(RTNAME(FPow8k)(Real<8>{-2}, Int<8>{-3}), Real<8>{-0.125}); |
284 | |
285 | #if LDBL_MANT_DIG == 64 |
286 | EXPECT_EQ(RTNAME(FPow10i)(Real<10>{0}, Int<4>{0}), Real<10>{1}); |
287 | EXPECT_EQ(RTNAME(FPow10i)(Real<10>{0.3}, Int<4>{0}), Real<10>{1}); |
288 | EXPECT_EQ(RTNAME(FPow10i)(Real<10>{2}, Int<4>{-1}), Real<10>{0.5}); |
289 | EXPECT_EQ(RTNAME(FPow10i)(Real<10>{0.5}, Int<4>{-1}), Real<10>{2}); |
290 | EXPECT_EQ(RTNAME(FPow10i)(Real<10>{-3}, Int<4>{3}), Real<10>{-27}); |
291 | EXPECT_EQ(RTNAME(FPow10i)(Real<10>{-2}, Int<4>{-3}), Real<10>{-0.125}); |
292 | |
293 | EXPECT_EQ(RTNAME(FPow10k)(Real<10>{0}, Int<8>{0}), Real<10>{1}); |
294 | EXPECT_EQ(RTNAME(FPow10k)(Real<10>{0.3}, Int<8>{0}), Real<10>{1}); |
295 | EXPECT_EQ(RTNAME(FPow10k)(Real<10>{2}, Int<8>{-1}), Real<10>{0.5}); |
296 | EXPECT_EQ(RTNAME(FPow10k)(Real<10>{0.5}, Int<8>{-1}), Real<10>{2}); |
297 | EXPECT_EQ(RTNAME(FPow10k)(Real<10>{-3}, Int<8>{3}), Real<10>{-27}); |
298 | EXPECT_EQ(RTNAME(FPow10k)(Real<10>{-2}, Int<8>{-3}), Real<10>{-0.125}); |
299 | #endif |
300 | #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 |
301 | EXPECT_EQ(RTNAME(FPow16i)(Real<16>{0}, Int<4>{0}), Real<16>{1}); |
302 | EXPECT_EQ(RTNAME(FPow16i)(Real<16>{0.3}, Int<4>{0}), Real<16>{1}); |
303 | EXPECT_EQ(RTNAME(FPow16i)(Real<16>{2}, Int<4>{-1}), Real<16>{0.5}); |
304 | EXPECT_EQ(RTNAME(FPow16i)(Real<16>{0.5}, Int<4>{-1}), Real<16>{2}); |
305 | EXPECT_EQ(RTNAME(FPow16i)(Real<16>{-3}, Int<4>{3}), Real<16>{-27}); |
306 | EXPECT_EQ(RTNAME(FPow16i)(Real<16>{-2}, Int<4>{-3}), Real<16>{-0.125}); |
307 | |
308 | EXPECT_EQ(RTNAME(FPow16k)(Real<16>{0}, Int<8>{0}), Real<16>{1}); |
309 | EXPECT_EQ(RTNAME(FPow16k)(Real<16>{0.3}, Int<8>{0}), Real<16>{1}); |
310 | EXPECT_EQ(RTNAME(FPow16k)(Real<16>{2}, Int<8>{-1}), Real<16>{0.5}); |
311 | EXPECT_EQ(RTNAME(FPow16k)(Real<16>{0.5}, Int<8>{-1}), Real<16>{2}); |
312 | EXPECT_EQ(RTNAME(FPow16k)(Real<16>{-3}, Int<8>{3}), Real<16>{-27}); |
313 | EXPECT_EQ(RTNAME(FPow16k)(Real<16>{-2}, Int<8>{-3}), Real<16>{-0.125}); |
314 | #endif |
315 | |
316 | // Test some extreme values. |
317 | if (sizeof(double) == sizeof(std::uint64_t)) { |
318 | // (0x3FF0000000000001 ** -2147483648) ~ 0x3FEFFFFF00000401 |
319 | double base; |
320 | *reinterpret_cast<std::uint64_t *>(&base) = 4607182418800017409ULL; |
321 | double result; |
322 | *reinterpret_cast<std::uint64_t *>(&result) = 4607182414505051137ULL; |
323 | EXPECT_TRUE(std::abs(RTNAME(FPow8i)(Real<8>{base}, |
324 | Int<4>{std::numeric_limits<Int<4>>::min()}) - |
325 | Real<8>{result}) < 0.00000000001); |
326 | |
327 | // (0x3FF0000000000001 ** 4294967296ULL) ~ 0x3FF00001000007FF |
328 | *reinterpret_cast<std::uint64_t *>(&base) = 4607182418800017409ULL; |
329 | *reinterpret_cast<std::uint64_t *>(&result) = 4607182423094986751ULL; |
330 | EXPECT_TRUE(std::abs(RTNAME(FPow8k)(Real<8>{base}, Int<8>{4294967296ULL}) - |
331 | Real<8>{result}) < 0.00000000001); |
332 | } |
333 | } |
334 | |