• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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