1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gtest/gtest.h"
18
19 #include <cmath>
20 #include <utility> // std::forward
21
22 #include "berberis/base/bit_util.h"
23 #include "berberis/intrinsics/intrinsics_float.h"
24
25 namespace berberis {
26
27 namespace intrinsics {
28
29 // On i386 we have problems with returning NaN floats and doubles from function.
30 // This is ABI issue (passing certain values through 8087 stack corrupts them) and couldn't be
31 // fixed - but could be hidden by optimized build
32 //
33 // This wrapper makes sure function in question is actually called using 8087 stack on IA32 and
34 // using proper calling conventions on other platforms.
35 //
36 // Note: if function is made static or put in the anonymous namespace then clang may change the
37 // calling convention! Keep it exportable to prevent that.
38 template <typename FuncType>
39 class NonInlineWrapper;
40
41 template <typename ResultType, typename... ArgsTypes>
42 class NonInlineWrapper<ResultType(ArgsTypes...)> {
43 public:
44 template <ResultType (*function)(ArgsTypes...)>
Call(ArgsTypes &&...args)45 static ResultType __attribute__((noinline)) Call(ArgsTypes&&... args) {
46 return function(std::forward<ArgsTypes>(args)...);
47 }
48 };
49
50 namespace {
51
52 // We couldn't use float consts here because of bit_cast.
53 constexpr uint32_t kBadNegativeNan32 = 0xff811dea;
54 constexpr uint32_t kBadPositiveNan32 = 0x7f811dea;
55 constexpr uint64_t kBadNegativeNan64 = 0xfff0deadbeaf0000;
56 constexpr uint64_t kBadPositiveNan64 = 0x7ff0deadbeaf0000;
57 // We don't use std::limits because we want to be sure definitions match ARM.
58 constexpr uint32_t kPlusZero32 = 0x00000000;
59 constexpr uint32_t kPlusOne32 = 0x3f800000;
60 constexpr uint32_t kMinusZero32 = 0x80000000;
61 constexpr uint32_t kMinusOne32 = 0xbf800000;
62 constexpr uint32_t kPlusInfinity32 = 0x7f800000;
63 constexpr uint32_t kMinusInfinity32 = 0xff800000;
64 // Default NaN created as result of math operations (when NaN wasn't an input).
65 #if defined(__i386__) || defined(__x86_64__)
66 constexpr uint32_t kDefaultNan32 = 0xffc00000;
67 #else
68 constexpr uint32_t kDefaultNan32 = 0x7fc00000;
69 #endif
70 constexpr uint64_t kPlusZero64 = 0x0000000000000000;
71 // constexpr uint64_t kPlusOne64 = 0x3ff0000000000000;
72 constexpr uint64_t kMinusZero64 = 0x8000000000000000;
73 // constexpr uint64_t kMinusOne64 = 0xbff0000000000000;
74 constexpr uint64_t kPlusInfinity64 = 0x7ff0000000000000;
75 constexpr uint64_t kMinusInfinity64 = 0xfff0000000000000;
76 #if defined(__i386__) || defined(__x86_64__)
77 constexpr uint64_t kDefaultNan64 = 0xfff8000000000000;
78 #else
79 constexpr uint64_t kDefaultNan64 = 0x7ff8000000000000;
80 #endif
81
82 #ifdef __i386__
83
84 // Please note: tests below are NOT GUARANTEED to succeed on ALL IA32 platforms.
85 //
86 // They are only relevant for platforms where 8087 stack is used to pass float/double results.
87 //
88 // If they fail in your platforms then you don't need complex dance in intrinsics_float_x86.h
89
TEST(FPU,float_std_fabs)90 TEST(FPU, float_std_fabs) {
91 uint32_t fabs_result = bit_cast<uint32_t, float>(NonInlineWrapper<float(float)>::Call<std::fabs>(
92 bit_cast<float, uint32_t>(kBadNegativeNan32)));
93 EXPECT_NE(fabs_result, kBadPositiveNan32);
94 }
95
TEST(FPU,float_fabsf)96 TEST(FPU, float_fabsf) {
97 uint32_t fabsf_result = bit_cast<uint32_t, float>(
98 NonInlineWrapper<float(float)>::Call<::fabsf>(bit_cast<float, uint32_t>(kBadNegativeNan32)));
99 EXPECT_NE(fabsf_result, kBadPositiveNan32);
100 }
101
TEST(FPU,double_std_fabs)102 TEST(FPU, double_std_fabs) {
103 uint64_t fabs_result =
104 bit_cast<uint64_t, double>(NonInlineWrapper<double(double)>::Call<std::fabs>(
105 bit_cast<double, uint64_t>(kBadNegativeNan64)));
106 EXPECT_NE(fabs_result, kBadPositiveNan64);
107 }
108
TEST(FPU,double_fabs)109 TEST(FPU, double_fabs) {
110 uint64_t fabs_result = bit_cast<uint64_t, double>(NonInlineWrapper<double(double)>::Call<::fabs>(
111 bit_cast<double, uint64_t>(kBadNegativeNan64)));
112 EXPECT_NE(fabs_result, kBadPositiveNan64);
113 }
114
115 #endif
116
TEST(FPU,Float32_fabs)117 TEST(FPU, Float32_fabs) {
118 uint32_t fabs_result =
119 bit_cast<uint32_t, Float32>(NonInlineWrapper<Float32(const Float32&)>::Call<Absolute>(
120 bit_cast<Float32, uint32_t>(kBadNegativeNan32)));
121 EXPECT_EQ(fabs_result, kBadPositiveNan32);
122 }
123
TEST(FPU,Float64_fabs)124 TEST(FPU, Float64_fabs) {
125 uint64_t fabs_result =
126 bit_cast<uint64_t, Float64>(NonInlineWrapper<Float64(const Float64&)>::Call<Absolute>(
127 bit_cast<Float64, uint64_t>(kBadNegativeNan64)));
128 EXPECT_EQ(fabs_result, kBadPositiveNan64);
129 }
130
TEST(FPU,Float32_fneg)131 TEST(FPU, Float32_fneg) {
132 uint32_t fabs_result =
133 bit_cast<uint32_t, Float32>(NonInlineWrapper<Float32(const Float32&)>::Call<Negative>(
134 bit_cast<Float32, uint32_t>(kBadNegativeNan32)));
135 EXPECT_EQ(fabs_result, kBadPositiveNan32);
136 }
137
TEST(FPU,Float64_fneg)138 TEST(FPU, Float64_fneg) {
139 uint64_t fabs_result =
140 bit_cast<uint64_t, Float64>(NonInlineWrapper<Float64(const Float64&)>::Call<Negative>(
141 bit_cast<Float64, uint64_t>(kBadNegativeNan64)));
142 EXPECT_EQ(fabs_result, kBadPositiveNan64);
143 }
144
TEST(FPU,Float32_InfPlusMinusInf)145 TEST(FPU, Float32_InfPlusMinusInf) {
146 // +inf + +inf => +inf
147 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) +
148 bit_cast<Float32, uint32_t>(kPlusInfinity32));
149 EXPECT_EQ(result, kPlusInfinity32);
150 // -inf + -inf => -inf
151 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) +
152 bit_cast<Float32, uint32_t>(kMinusInfinity32));
153 EXPECT_EQ(result, kMinusInfinity32);
154 // +inf + -inf => dNaN
155 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) +
156 bit_cast<Float32, uint32_t>(kMinusInfinity32));
157 EXPECT_EQ(result, kDefaultNan32);
158 // -inf + +inf => dNaN
159 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) +
160 bit_cast<Float32, uint32_t>(kPlusInfinity32));
161 EXPECT_EQ(result, kDefaultNan32);
162 }
163
TEST(FPU,Float64_InfPlusMinusInf)164 TEST(FPU, Float64_InfPlusMinusInf) {
165 // +inf + +inf => +inf
166 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) +
167 bit_cast<Float64, uint64_t>(kPlusInfinity64));
168 EXPECT_EQ(result, kPlusInfinity64);
169 // -inf + -inf => -inf
170 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) +
171 bit_cast<Float64, uint64_t>(kMinusInfinity64));
172 EXPECT_EQ(result, kMinusInfinity64);
173 // +inf + -inf => dNaN
174 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) +
175 bit_cast<Float64, uint64_t>(kMinusInfinity64));
176 EXPECT_EQ(result, kDefaultNan64);
177 // -inf + +inf => dNaN
178 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) +
179 bit_cast<Float64, uint64_t>(kPlusInfinity64));
180 EXPECT_EQ(result, kDefaultNan64);
181 }
182
TEST(FPU,Float32_ZeroPlusMinusZero)183 TEST(FPU, Float32_ZeroPlusMinusZero) {
184 // +0.f + +0.f => +0.f
185 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) +
186 bit_cast<Float32, uint32_t>(kPlusZero32));
187 EXPECT_EQ(result, kPlusZero32);
188 // +0.f + -0.f => +0.f
189 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) +
190 bit_cast<Float32, uint32_t>(kMinusZero32));
191 EXPECT_EQ(result, kPlusZero32);
192 // -0.f + +0.f => +0.f
193 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) +
194 bit_cast<Float32, uint32_t>(kPlusZero32));
195 EXPECT_EQ(result, kPlusZero32);
196 // -0.f + -0.f => -0.f
197 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) +
198 bit_cast<Float32, uint32_t>(kMinusZero32));
199 EXPECT_EQ(result, kMinusZero32);
200 }
201
TEST(FPU,Float64_ZeroPlusMinusZero)202 TEST(FPU, Float64_ZeroPlusMinusZero) {
203 // +0.f + +0.f => +0.f
204 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) +
205 bit_cast<Float64, uint64_t>(kPlusZero64));
206 EXPECT_EQ(result, kPlusZero64);
207 // +0.f + -0.f => +0.f
208 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) +
209 bit_cast<Float64, uint64_t>(kMinusZero64));
210 EXPECT_EQ(result, kPlusZero64);
211 // -0.f + +0.f => +0.f
212 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) +
213 bit_cast<Float64, uint64_t>(kPlusZero64));
214 EXPECT_EQ(result, kPlusZero64);
215 // -0.f + -0.f => -0.f
216 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) +
217 bit_cast<Float64, uint64_t>(kMinusZero64));
218 EXPECT_EQ(result, kMinusZero64);
219 }
220
TEST(FPU,Float32_InfMinusInf)221 TEST(FPU, Float32_InfMinusInf) {
222 // +inf - -inf => +inf
223 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) -
224 bit_cast<Float32, uint32_t>(kMinusInfinity32));
225 EXPECT_EQ(result, kPlusInfinity32);
226 // -inf - +inf => -inf
227 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) -
228 bit_cast<Float32, uint32_t>(kPlusInfinity32));
229 EXPECT_EQ(result, kMinusInfinity32);
230 // +inf - +inf => dNaN
231 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) -
232 bit_cast<Float32, uint32_t>(kPlusInfinity32));
233 EXPECT_EQ(result, kDefaultNan32);
234 // -inf - -inf => dNaN
235 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) -
236 bit_cast<Float32, uint32_t>(kMinusInfinity32));
237 EXPECT_EQ(result, kDefaultNan32);
238 }
239
TEST(FPU,Float64_InfMinusInf)240 TEST(FPU, Float64_InfMinusInf) {
241 // +inf - -inf => +inf
242 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) -
243 bit_cast<Float64, uint64_t>(kMinusInfinity64));
244 EXPECT_EQ(result, kPlusInfinity64);
245 // -inf - +inf => -inf
246 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) -
247 bit_cast<Float64, uint64_t>(kPlusInfinity64));
248 EXPECT_EQ(result, kMinusInfinity64);
249 // +inf - +inf => dNaN
250 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) -
251 bit_cast<Float64, uint64_t>(kPlusInfinity64));
252 EXPECT_EQ(result, kDefaultNan64);
253 // -inf - -inf => dNaN
254 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) -
255 bit_cast<Float64, uint64_t>(kMinusInfinity64));
256 EXPECT_EQ(result, kDefaultNan64);
257 }
258
TEST(FPU,Float32_ZeroMinusZero)259 TEST(FPU, Float32_ZeroMinusZero) {
260 // +0.f - +0.f => +0.f
261 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) -
262 bit_cast<Float32, uint32_t>(kPlusZero32));
263 EXPECT_EQ(result, kPlusZero32);
264 // +0.f - -0.f => +0.f
265 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) -
266 bit_cast<Float32, uint32_t>(kMinusZero32));
267 EXPECT_EQ(result, kPlusZero32);
268 // -0.f - +0.f => -0.f
269 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) -
270 bit_cast<Float32, uint32_t>(kPlusZero32));
271 EXPECT_EQ(result, kMinusZero32);
272 // -0.f - +0.f => +0.f
273 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) -
274 bit_cast<Float32, uint32_t>(kMinusZero32));
275 EXPECT_EQ(result, kPlusZero32);
276 }
277
TEST(FPU,Float64_ZeroMinusZero)278 TEST(FPU, Float64_ZeroMinusZero) {
279 // +0.0 - +0.0 => +0.0
280 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) -
281 bit_cast<Float64, uint64_t>(kPlusZero64));
282 EXPECT_EQ(result, kPlusZero64);
283 // +0.0 - -0.0 => +0.0
284 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) -
285 bit_cast<Float64, uint64_t>(kMinusZero64));
286 EXPECT_EQ(result, kPlusZero64);
287 // -0.0 - +0.0 => -0.0
288 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) -
289 bit_cast<Float64, uint64_t>(kPlusZero64));
290 EXPECT_EQ(result, kMinusZero64);
291 // -0.0 - +0.0 => +0.0
292 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) -
293 bit_cast<Float64, uint64_t>(kMinusZero64));
294 EXPECT_EQ(result, kPlusZero64);
295 }
296
TEST(FPU,Float32_InfMultiplyByZero)297 TEST(FPU, Float32_InfMultiplyByZero) {
298 // +inf * +0.f => dNaN
299 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) *
300 bit_cast<Float32, uint32_t>(kPlusZero32));
301 EXPECT_EQ(result, kDefaultNan32);
302 // +0.f * +inf => dNaN
303 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) *
304 bit_cast<Float32, uint32_t>(kPlusInfinity32));
305 EXPECT_EQ(result, kDefaultNan32);
306 // +inf * -0.f => dNaN
307 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) *
308 bit_cast<Float32, uint32_t>(kMinusZero32));
309 EXPECT_EQ(result, kDefaultNan32);
310 // -0.f * +inf => dNaN
311 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) *
312 bit_cast<Float32, uint32_t>(kPlusInfinity32));
313 EXPECT_EQ(result, kDefaultNan32);
314 // -inf * +0.f => dNaN
315 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) *
316 bit_cast<Float32, uint32_t>(kPlusZero32));
317 EXPECT_EQ(result, kDefaultNan32);
318 // +0.f * -inf => dNaN
319 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) *
320 bit_cast<Float32, uint32_t>(kMinusInfinity32));
321 EXPECT_EQ(result, kDefaultNan32);
322 // -inf * -0.f => dNaN
323 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) *
324 bit_cast<Float32, uint32_t>(kMinusZero32));
325 EXPECT_EQ(result, kDefaultNan32);
326 // -0.f * -inf => dNaN
327 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) *
328 bit_cast<Float32, uint32_t>(kMinusInfinity32));
329 EXPECT_EQ(result, kDefaultNan32);
330 }
331
TEST(FPU,Float64_InfMultiplyByZero)332 TEST(FPU, Float64_InfMultiplyByZero) {
333 // +inf * +0.0 => dNaN
334 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) *
335 bit_cast<Float64, uint64_t>(kPlusZero64));
336 EXPECT_EQ(result, kDefaultNan64);
337 // +0.0 * +inf => dNaN
338 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) *
339 bit_cast<Float64, uint64_t>(kPlusInfinity64));
340 EXPECT_EQ(result, kDefaultNan64);
341 // +inf * -0.0 => dNaN
342 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) *
343 bit_cast<Float64, uint64_t>(kMinusZero64));
344 EXPECT_EQ(result, kDefaultNan64);
345 // -0.0 * +inf => dNaN
346 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) *
347 bit_cast<Float64, uint64_t>(kPlusInfinity64));
348 EXPECT_EQ(result, kDefaultNan64);
349 // -inf * +0.0 => dNaN
350 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) *
351 bit_cast<Float64, uint64_t>(kPlusZero64));
352 EXPECT_EQ(result, kDefaultNan64);
353 // +0.0 * -inf => dNaN
354 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) *
355 bit_cast<Float64, uint64_t>(kMinusInfinity64));
356 EXPECT_EQ(result, kDefaultNan64);
357 // -inf * -0.0 => dNaN
358 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) *
359 bit_cast<Float64, uint64_t>(kMinusZero64));
360 EXPECT_EQ(result, kDefaultNan64);
361 // -0.0 * -inf => dNaN
362 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) *
363 bit_cast<Float64, uint64_t>(kMinusInfinity64));
364 EXPECT_EQ(result, kDefaultNan64);
365 }
366
TEST(FPU,Float32_ZeroMultiplyByZero)367 TEST(FPU, Float32_ZeroMultiplyByZero) {
368 // +0.f * +0.f => +0.f
369 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) *
370 bit_cast<Float32, uint32_t>(kPlusZero32));
371 EXPECT_EQ(result, kPlusZero32);
372 // +0.f * -0.f => -0.f
373 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) *
374 bit_cast<Float32, uint32_t>(kMinusZero32));
375 EXPECT_EQ(result, kMinusZero32);
376 // -0.f * +0.f => -0.f
377 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) *
378 bit_cast<Float32, uint32_t>(kPlusZero32));
379 EXPECT_EQ(result, kMinusZero32);
380 // -0.f * -0.f => +0.f
381 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) *
382 bit_cast<Float32, uint32_t>(kMinusZero32));
383 EXPECT_EQ(result, kPlusZero32);
384 }
385
TEST(FPU,Float64_ZeroMultiplyByZero)386 TEST(FPU, Float64_ZeroMultiplyByZero) {
387 // +0.0 * +0.0 => +0.0
388 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) *
389 bit_cast<Float64, uint64_t>(kPlusZero64));
390 EXPECT_EQ(result, kPlusZero64);
391 // +0.0 * -0.0 => -0.0
392 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) *
393 bit_cast<Float64, uint64_t>(kMinusZero64));
394 EXPECT_EQ(result, kMinusZero64);
395 // -0.0 * +0.0 => -0.0
396 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) *
397 bit_cast<Float64, uint64_t>(kPlusZero64));
398 EXPECT_EQ(result, kMinusZero64);
399 // -0.0 * -0.0 => +0.0
400 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) *
401 bit_cast<Float64, uint64_t>(kMinusZero64));
402 EXPECT_EQ(result, kPlusZero64);
403 }
404
TEST(FPU,Float32_InfDivideByInf)405 TEST(FPU, Float32_InfDivideByInf) {
406 // +inf / +inf => dNaN
407 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) /
408 bit_cast<Float32, uint32_t>(kPlusInfinity32));
409 EXPECT_EQ(result, kDefaultNan32);
410 // +inf / -inf => dNaN
411 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusInfinity32) /
412 bit_cast<Float32, uint32_t>(kMinusInfinity32));
413 EXPECT_EQ(result, kDefaultNan32);
414 // -inf / +inf => dNaN
415 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) /
416 bit_cast<Float32, uint32_t>(kPlusInfinity32));
417 EXPECT_EQ(result, kDefaultNan32);
418 // -inf / -inf => dNaN
419 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusInfinity32) /
420 bit_cast<Float32, uint32_t>(kMinusInfinity32));
421 EXPECT_EQ(result, kDefaultNan32);
422 }
423
TEST(FPU,Float64_InfDivideByInf)424 TEST(FPU, Float64_InfDivideByInf) {
425 // +inf / +inf => dNaN
426 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) /
427 bit_cast<Float64, uint64_t>(kPlusInfinity64));
428 EXPECT_EQ(result, kDefaultNan64);
429 // +inf / -inf => dNaN
430 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusInfinity64) /
431 bit_cast<Float64, uint64_t>(kMinusInfinity64));
432 EXPECT_EQ(result, kDefaultNan64);
433 // -inf / +inf => dNaN
434 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) /
435 bit_cast<Float64, uint64_t>(kPlusInfinity64));
436 EXPECT_EQ(result, kDefaultNan64);
437 // -inf / -inf => dNaN
438 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusInfinity64) /
439 bit_cast<Float64, uint64_t>(kMinusInfinity64));
440 EXPECT_EQ(result, kDefaultNan64);
441 }
442
TEST(FPU,Float32_ZeroDivideByZero)443 TEST(FPU, Float32_ZeroDivideByZero) {
444 // +0.f - +0.f => dNaN
445 uint32_t result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) /
446 bit_cast<Float32, uint32_t>(kPlusZero32));
447 EXPECT_EQ(result, kDefaultNan32);
448 // +0.f - -0.f => dNaN
449 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kPlusZero32) /
450 bit_cast<Float32, uint32_t>(kMinusZero32));
451 EXPECT_EQ(result, kDefaultNan32);
452 // -0.f - +0.f => dNaN
453 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) /
454 bit_cast<Float32, uint32_t>(kPlusZero32));
455 EXPECT_EQ(result, kDefaultNan32);
456 // -0.f - +0.f => dNaN
457 result = bit_cast<uint32_t, Float32>(bit_cast<Float32, uint32_t>(kMinusZero32) /
458 bit_cast<Float32, uint32_t>(kMinusZero32));
459 EXPECT_EQ(result, kDefaultNan32);
460 }
461
TEST(FPU,Float64_ZeroDivideByZero)462 TEST(FPU, Float64_ZeroDivideByZero) {
463 // +0.0 - +0.0 => dNaN
464 uint64_t result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) /
465 bit_cast<Float64, uint64_t>(kPlusZero64));
466 EXPECT_EQ(result, kDefaultNan64);
467 // +0.0 - -0.0 => dNaN
468 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kPlusZero64) /
469 bit_cast<Float64, uint64_t>(kMinusZero64));
470 EXPECT_EQ(result, kDefaultNan64);
471 // -0.0 - +0.0 => dNaN
472 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) /
473 bit_cast<Float64, uint64_t>(kPlusZero64));
474 EXPECT_EQ(result, kDefaultNan64);
475 // -0.0 - +0.0 => dNaN
476 result = bit_cast<uint64_t, Float64>(bit_cast<Float64, uint64_t>(kMinusZero64) /
477 bit_cast<Float64, uint64_t>(kMinusZero64));
478 EXPECT_EQ(result, kDefaultNan64);
479 }
480
TEST(FPU,Float32_Sqrt)481 TEST(FPU, Float32_Sqrt) {
482 // +0.0 => +0.0
483 uint32_t result = bit_cast<uint32_t, Float32>(Sqrt(bit_cast<Float32, uint32_t>(kPlusZero32)));
484 EXPECT_EQ(result, kPlusZero32);
485 // -0.0 => -0.0
486 result = bit_cast<uint32_t, Float32>(Sqrt(bit_cast<Float32, uint32_t>(kMinusZero32)));
487 EXPECT_EQ(result, kMinusZero32);
488 // +1.0 => +1.0
489 result = bit_cast<uint32_t, Float32>(Sqrt(bit_cast<Float32, uint32_t>(kPlusOne32)));
490 EXPECT_EQ(result, kPlusOne32);
491 // -1.0 => dNaN
492 result = bit_cast<uint32_t, Float32>(Sqrt(bit_cast<Float32, uint32_t>(kMinusOne32)));
493 EXPECT_EQ(result, kDefaultNan32);
494 }
495
496 } // namespace
497
498 } // namespace intrinsics
499
500 } // namespace berberis
501