1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/Assertions.h"
8 #include "mozilla/FloatingPoint.h"
12 using mozilla::ExponentComponent
;
13 using mozilla::FloatingPoint
;
14 using mozilla::FuzzyEqualsAdditive
;
15 using mozilla::FuzzyEqualsMultiplicative
;
16 using mozilla::IsFloat32Representable
;
17 using mozilla::IsNegative
;
18 using mozilla::IsNegativeZero
;
19 using mozilla::IsPositiveZero
;
20 using mozilla::NegativeInfinity
;
21 using mozilla::NumberEqualsInt32
;
22 using mozilla::NumberEqualsInt64
;
23 using mozilla::NumberIsInt32
;
24 using mozilla::NumberIsInt64
;
25 using mozilla::NumbersAreIdentical
;
26 using mozilla::PositiveInfinity
;
27 using mozilla::SpecificNaN
;
28 using mozilla::UnspecifiedNaN
;
32 #define A(a) MOZ_RELEASE_ASSERT(a)
35 static void ShouldBeIdentical(T aD1
, T aD2
) {
36 A(NumbersAreIdentical(aD1
, aD2
));
37 A(NumbersAreIdentical(aD2
, aD1
));
41 static void ShouldNotBeIdentical(T aD1
, T aD2
) {
42 A(!NumbersAreIdentical(aD1
, aD2
));
43 A(!NumbersAreIdentical(aD2
, aD1
));
46 static void TestDoublesAreIdentical() {
47 ShouldBeIdentical(+0.0, +0.0);
48 ShouldBeIdentical(-0.0, -0.0);
49 ShouldNotBeIdentical(+0.0, -0.0);
51 ShouldBeIdentical(1.0, 1.0);
52 ShouldNotBeIdentical(-1.0, 1.0);
53 ShouldBeIdentical(4294967295.0, 4294967295.0);
54 ShouldNotBeIdentical(-4294967295.0, 4294967295.0);
55 ShouldBeIdentical(4294967296.0, 4294967296.0);
56 ShouldBeIdentical(4294967297.0, 4294967297.0);
57 ShouldBeIdentical(1e300
, 1e300
);
59 ShouldBeIdentical(PositiveInfinity
<double>(), PositiveInfinity
<double>());
60 ShouldBeIdentical(NegativeInfinity
<double>(), NegativeInfinity
<double>());
61 ShouldNotBeIdentical(PositiveInfinity
<double>(), NegativeInfinity
<double>());
63 ShouldNotBeIdentical(-0.0, NegativeInfinity
<double>());
64 ShouldNotBeIdentical(+0.0, NegativeInfinity
<double>());
65 ShouldNotBeIdentical(1e300
, NegativeInfinity
<double>());
66 ShouldNotBeIdentical(3.141592654, NegativeInfinity
<double>());
68 ShouldBeIdentical(UnspecifiedNaN
<double>(), UnspecifiedNaN
<double>());
69 ShouldBeIdentical(-UnspecifiedNaN
<double>(), UnspecifiedNaN
<double>());
70 ShouldBeIdentical(UnspecifiedNaN
<double>(), -UnspecifiedNaN
<double>());
72 ShouldBeIdentical(SpecificNaN
<double>(0, 17), SpecificNaN
<double>(0, 42));
73 ShouldBeIdentical(SpecificNaN
<double>(1, 17), SpecificNaN
<double>(1, 42));
74 ShouldBeIdentical(SpecificNaN
<double>(0, 17), SpecificNaN
<double>(1, 42));
75 ShouldBeIdentical(SpecificNaN
<double>(1, 17), SpecificNaN
<double>(0, 42));
77 const uint64_t Mask
= 0xfffffffffffffULL
;
78 for (unsigned i
= 0; i
< 52; i
++) {
79 for (unsigned j
= 0; j
< 52; j
++) {
80 for (unsigned sign
= 0; i
< 2; i
++) {
81 ShouldBeIdentical(SpecificNaN
<double>(0, 1ULL << i
),
82 SpecificNaN
<double>(sign
, 1ULL << j
));
83 ShouldBeIdentical(SpecificNaN
<double>(1, 1ULL << i
),
84 SpecificNaN
<double>(sign
, 1ULL << j
));
86 ShouldBeIdentical(SpecificNaN
<double>(0, Mask
& ~(1ULL << i
)),
87 SpecificNaN
<double>(sign
, Mask
& ~(1ULL << j
)));
88 ShouldBeIdentical(SpecificNaN
<double>(1, Mask
& ~(1ULL << i
)),
89 SpecificNaN
<double>(sign
, Mask
& ~(1ULL << j
)));
93 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
94 SpecificNaN
<double>(0, 0x8000000000000ULL
));
95 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
96 SpecificNaN
<double>(0, 0x4000000000000ULL
));
97 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
98 SpecificNaN
<double>(0, 0x2000000000000ULL
));
99 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
100 SpecificNaN
<double>(0, 0x1000000000000ULL
));
101 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
102 SpecificNaN
<double>(0, 0x0800000000000ULL
));
103 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
104 SpecificNaN
<double>(0, 0x0400000000000ULL
));
105 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
106 SpecificNaN
<double>(0, 0x0200000000000ULL
));
107 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
108 SpecificNaN
<double>(0, 0x0100000000000ULL
));
109 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
110 SpecificNaN
<double>(0, 0x0080000000000ULL
));
111 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
112 SpecificNaN
<double>(0, 0x0040000000000ULL
));
113 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
114 SpecificNaN
<double>(0, 0x0020000000000ULL
));
115 ShouldBeIdentical(SpecificNaN
<double>(0, 17),
116 SpecificNaN
<double>(0, 0x0010000000000ULL
));
117 ShouldBeIdentical(SpecificNaN
<double>(1, 17),
118 SpecificNaN
<double>(0, 0xff0ffffffffffULL
));
119 ShouldBeIdentical(SpecificNaN
<double>(1, 17),
120 SpecificNaN
<double>(0, 0xfffffffffff0fULL
));
122 ShouldNotBeIdentical(UnspecifiedNaN
<double>(), +0.0);
123 ShouldNotBeIdentical(UnspecifiedNaN
<double>(), -0.0);
124 ShouldNotBeIdentical(UnspecifiedNaN
<double>(), 1.0);
125 ShouldNotBeIdentical(UnspecifiedNaN
<double>(), -1.0);
126 ShouldNotBeIdentical(UnspecifiedNaN
<double>(), PositiveInfinity
<double>());
127 ShouldNotBeIdentical(UnspecifiedNaN
<double>(), NegativeInfinity
<double>());
130 static void TestFloatsAreIdentical() {
131 ShouldBeIdentical(+0.0f
, +0.0f
);
132 ShouldBeIdentical(-0.0f
, -0.0f
);
133 ShouldNotBeIdentical(+0.0f
, -0.0f
);
135 ShouldBeIdentical(1.0f
, 1.0f
);
136 ShouldNotBeIdentical(-1.0f
, 1.0f
);
137 ShouldBeIdentical(8388607.0f
, 8388607.0f
);
138 ShouldNotBeIdentical(-8388607.0f
, 8388607.0f
);
139 ShouldBeIdentical(8388608.0f
, 8388608.0f
);
140 ShouldBeIdentical(8388609.0f
, 8388609.0f
);
141 ShouldBeIdentical(1e36f
, 1e36f
);
143 ShouldBeIdentical(PositiveInfinity
<float>(), PositiveInfinity
<float>());
144 ShouldBeIdentical(NegativeInfinity
<float>(), NegativeInfinity
<float>());
145 ShouldNotBeIdentical(PositiveInfinity
<float>(), NegativeInfinity
<float>());
147 ShouldNotBeIdentical(-0.0f
, NegativeInfinity
<float>());
148 ShouldNotBeIdentical(+0.0f
, NegativeInfinity
<float>());
149 ShouldNotBeIdentical(1e36f
, NegativeInfinity
<float>());
150 ShouldNotBeIdentical(3.141592654f
, NegativeInfinity
<float>());
152 ShouldBeIdentical(UnspecifiedNaN
<float>(), UnspecifiedNaN
<float>());
153 ShouldBeIdentical(-UnspecifiedNaN
<float>(), UnspecifiedNaN
<float>());
154 ShouldBeIdentical(UnspecifiedNaN
<float>(), -UnspecifiedNaN
<float>());
156 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 42));
157 ShouldBeIdentical(SpecificNaN
<float>(1, 17), SpecificNaN
<float>(1, 42));
158 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(1, 42));
159 ShouldBeIdentical(SpecificNaN
<float>(1, 17), SpecificNaN
<float>(0, 42));
161 const uint32_t Mask
= 0x7fffffUL
;
162 for (unsigned i
= 0; i
< 23; i
++) {
163 for (unsigned j
= 0; j
< 23; j
++) {
164 for (unsigned sign
= 0; i
< 2; i
++) {
165 ShouldBeIdentical(SpecificNaN
<float>(0, 1UL << i
),
166 SpecificNaN
<float>(sign
, 1UL << j
));
167 ShouldBeIdentical(SpecificNaN
<float>(1, 1UL << i
),
168 SpecificNaN
<float>(sign
, 1UL << j
));
170 ShouldBeIdentical(SpecificNaN
<float>(0, Mask
& ~(1UL << i
)),
171 SpecificNaN
<float>(sign
, Mask
& ~(1UL << j
)));
172 ShouldBeIdentical(SpecificNaN
<float>(1, Mask
& ~(1UL << i
)),
173 SpecificNaN
<float>(sign
, Mask
& ~(1UL << j
)));
177 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x700000));
178 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x400000));
179 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x200000));
180 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x100000));
181 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x080000));
182 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x040000));
183 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x020000));
184 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x010000));
185 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x008000));
186 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x004000));
187 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x002000));
188 ShouldBeIdentical(SpecificNaN
<float>(0, 17), SpecificNaN
<float>(0, 0x001000));
189 ShouldBeIdentical(SpecificNaN
<float>(1, 17), SpecificNaN
<float>(0, 0x7f0fff));
190 ShouldBeIdentical(SpecificNaN
<float>(1, 17), SpecificNaN
<float>(0, 0x7fff0f));
192 ShouldNotBeIdentical(UnspecifiedNaN
<float>(), +0.0f
);
193 ShouldNotBeIdentical(UnspecifiedNaN
<float>(), -0.0f
);
194 ShouldNotBeIdentical(UnspecifiedNaN
<float>(), 1.0f
);
195 ShouldNotBeIdentical(UnspecifiedNaN
<float>(), -1.0f
);
196 ShouldNotBeIdentical(UnspecifiedNaN
<float>(), PositiveInfinity
<float>());
197 ShouldNotBeIdentical(UnspecifiedNaN
<float>(), NegativeInfinity
<float>());
200 static void TestAreIdentical() {
201 TestDoublesAreIdentical();
202 TestFloatsAreIdentical();
205 static void TestDoubleExponentComponent() {
206 A(ExponentComponent(0.0) ==
207 -int_fast16_t(FloatingPoint
<double>::kExponentBias
));
208 A(ExponentComponent(-0.0) ==
209 -int_fast16_t(FloatingPoint
<double>::kExponentBias
));
210 A(ExponentComponent(0.125) == -3);
211 A(ExponentComponent(0.5) == -1);
212 A(ExponentComponent(1.0) == 0);
213 A(ExponentComponent(1.5) == 0);
214 A(ExponentComponent(2.0) == 1);
215 A(ExponentComponent(7.0) == 2);
216 A(ExponentComponent(PositiveInfinity
<double>()) ==
217 FloatingPoint
<double>::kExponentBias
+ 1);
218 A(ExponentComponent(NegativeInfinity
<double>()) ==
219 FloatingPoint
<double>::kExponentBias
+ 1);
220 A(ExponentComponent(UnspecifiedNaN
<double>()) ==
221 FloatingPoint
<double>::kExponentBias
+ 1);
224 static void TestFloatExponentComponent() {
225 A(ExponentComponent(0.0f
) ==
226 -int_fast16_t(FloatingPoint
<float>::kExponentBias
));
227 A(ExponentComponent(-0.0f
) ==
228 -int_fast16_t(FloatingPoint
<float>::kExponentBias
));
229 A(ExponentComponent(0.125f
) == -3);
230 A(ExponentComponent(0.5f
) == -1);
231 A(ExponentComponent(1.0f
) == 0);
232 A(ExponentComponent(1.5f
) == 0);
233 A(ExponentComponent(2.0f
) == 1);
234 A(ExponentComponent(7.0f
) == 2);
235 A(ExponentComponent(PositiveInfinity
<float>()) ==
236 FloatingPoint
<float>::kExponentBias
+ 1);
237 A(ExponentComponent(NegativeInfinity
<float>()) ==
238 FloatingPoint
<float>::kExponentBias
+ 1);
239 A(ExponentComponent(UnspecifiedNaN
<float>()) ==
240 FloatingPoint
<float>::kExponentBias
+ 1);
243 static void TestExponentComponent() {
244 TestDoubleExponentComponent();
245 TestFloatExponentComponent();
248 // Used to test Number{Is,Equals}{Int32,Int64} for -0.0, the only case where
249 // NumberEquals* and NumberIs* aren't equivalent.
250 template <typename T
>
251 static void TestEqualsIsForNegativeZero() {
255 A(!NumberIsInt32(negZero
, &i32
));
256 A(NumberEqualsInt32(negZero
, &i32
));
260 A(!NumberIsInt64(negZero
, &i64
));
261 A(NumberEqualsInt64(negZero
, &i64
));
265 // Used to test Number{Is,Equals}{Int32,Int64} for int32 values.
266 template <typename T
>
267 static void TestEqualsIsForInt32(T aVal
) {
269 A(NumberIsInt32(aVal
, &i32
));
270 MOZ_ASSERT(i32
== aVal
);
271 A(NumberEqualsInt32(aVal
, &i32
));
272 MOZ_ASSERT(i32
== aVal
);
275 A(NumberIsInt64(aVal
, &i64
));
276 MOZ_ASSERT(i64
== aVal
);
277 A(NumberEqualsInt64(aVal
, &i64
));
278 MOZ_ASSERT(i64
== aVal
);
281 // Used to test Number{Is,Equals}{Int32,Int64} for values that fit in int64 but
283 template <typename T
>
284 static void TestEqualsIsForInt64(T aVal
) {
286 A(!NumberIsInt32(aVal
, &i32
));
287 A(!NumberEqualsInt32(aVal
, &i32
));
290 A(NumberIsInt64(aVal
, &i64
));
291 MOZ_ASSERT(i64
== aVal
);
292 A(NumberEqualsInt64(aVal
, &i64
));
293 MOZ_ASSERT(i64
== aVal
);
296 // Used to test Number{Is,Equals}{Int32,Int64} for values that aren't equal to
297 // any int32 or int64.
298 template <typename T
>
299 static void TestEqualsIsForNonInteger(T aVal
) {
301 A(!NumberIsInt32(aVal
, &i32
));
302 A(!NumberEqualsInt32(aVal
, &i32
));
305 A(!NumberIsInt64(aVal
, &i64
));
306 A(!NumberEqualsInt64(aVal
, &i64
));
309 static void TestDoublesPredicates() {
310 A(std::isnan(UnspecifiedNaN
<double>()));
311 A(std::isnan(SpecificNaN
<double>(1, 17)));
313 A(std::isnan(SpecificNaN
<double>(0, 0xfffffffffff0fULL
)));
314 A(!std::isnan(PositiveInfinity
<double>()));
315 A(!std::isnan(NegativeInfinity
<double>()));
317 A(std::isinf(PositiveInfinity
<double>()));
318 A(std::isinf(NegativeInfinity
<double>()));
319 A(!std::isinf(UnspecifiedNaN
<double>()));
321 A(!std::isfinite(PositiveInfinity
<double>()));
322 A(!std::isfinite(NegativeInfinity
<double>()));
323 A(!std::isfinite(UnspecifiedNaN
<double>()));
325 A(!IsNegative(PositiveInfinity
<double>()));
326 A(IsNegative(NegativeInfinity
<double>()));
332 A(!IsNegativeZero(PositiveInfinity
<double>()));
333 A(!IsNegativeZero(NegativeInfinity
<double>()));
334 A(!IsNegativeZero(SpecificNaN
<double>(1, 17)));
336 A(!IsNegativeZero(SpecificNaN
<double>(1, 0xfffffffffff0fULL
)));
337 A(!IsNegativeZero(SpecificNaN
<double>(0, 17)));
339 A(!IsNegativeZero(SpecificNaN
<double>(0, 0xfffffffffff0fULL
)));
340 A(!IsNegativeZero(UnspecifiedNaN
<double>()));
341 A(IsNegativeZero(-0.0));
342 A(!IsNegativeZero(0.0));
343 A(!IsNegativeZero(-1.0));
344 A(!IsNegativeZero(1.0));
346 // Edge case: negative zero.
347 TestEqualsIsForNegativeZero
<double>();
350 auto testInt32
= TestEqualsIsForInt32
<double>;
353 testInt32(INT32_MIN
);
354 testInt32(INT32_MAX
);
356 // Int64 values that don't fit in int32.
357 auto testInt64
= TestEqualsIsForInt64
<double>;
358 testInt64(2147483648);
359 testInt64(2147483649);
360 testInt64(-2147483649);
361 testInt64(INT64_MIN
);
362 // Note: INT64_MAX can't be represented exactly as double. Use a large double
364 testInt64(9223372036854772000.0);
366 constexpr double MinSafeInteger
= -9007199254740991.0;
367 constexpr double MaxSafeInteger
= 9007199254740991.0;
368 testInt64(MinSafeInteger
);
369 testInt64(MaxSafeInteger
);
371 // Doubles that aren't equal to any int32 or int64.
372 auto testNonInteger
= TestEqualsIsForNonInteger
<double>;
373 testNonInteger(NegativeInfinity
<double>());
374 testNonInteger(PositiveInfinity
<double>());
375 testNonInteger(UnspecifiedNaN
<double>());
376 testNonInteger(-double(1ULL << 52) + 0.5);
377 testNonInteger(double(1ULL << 52) - 0.5);
378 testNonInteger(double(INT32_MAX
) + 0.1);
379 testNonInteger(double(INT32_MIN
) - 0.1);
381 testNonInteger(-0.0001);
382 testNonInteger(-9223372036854778000.0);
383 testNonInteger(9223372036854776000.0);
385 // Sanity-check that the IEEE-754 double-precision-derived literals used in
386 // testing here work as we intend them to.
387 A(exp2(-1075.0) == 0.0);
388 A(exp2(-1074.0) != 0.0);
389 testNonInteger(exp2(-1074.0));
390 testNonInteger(2 * exp2(-1074.0));
392 A(1.0 - exp2(-54.0) == 1.0);
393 A(1.0 - exp2(-53.0) != 1.0);
394 testNonInteger(1.0 - exp2(-53.0));
395 testNonInteger(1.0 - exp2(-52.0));
397 A(1.0 + exp2(-53.0) == 1.0f
);
398 A(1.0 + exp2(-52.0) != 1.0f
);
399 testNonInteger(1.0 + exp2(-52.0));
402 static void TestFloatsPredicates() {
403 A(std::isnan(UnspecifiedNaN
<float>()));
404 A(std::isnan(SpecificNaN
<float>(1, 17)));
406 A(std::isnan(SpecificNaN
<float>(0, 0x7fff0fUL
)));
407 A(!std::isnan(PositiveInfinity
<float>()));
408 A(!std::isnan(NegativeInfinity
<float>()));
410 A(std::isinf(PositiveInfinity
<float>()));
411 A(std::isinf(NegativeInfinity
<float>()));
412 A(!std::isinf(UnspecifiedNaN
<float>()));
414 A(!std::isfinite(PositiveInfinity
<float>()));
415 A(!std::isfinite(NegativeInfinity
<float>()));
416 A(!std::isfinite(UnspecifiedNaN
<float>()));
418 A(!IsNegative(PositiveInfinity
<float>()));
419 A(IsNegative(NegativeInfinity
<float>()));
420 A(IsNegative(-0.0f
));
421 A(!IsNegative(0.0f
));
422 A(IsNegative(-1.0f
));
423 A(!IsNegative(1.0f
));
425 A(!IsNegativeZero(PositiveInfinity
<float>()));
426 A(!IsNegativeZero(NegativeInfinity
<float>()));
427 A(!IsNegativeZero(SpecificNaN
<float>(1, 17)));
429 A(!IsNegativeZero(SpecificNaN
<float>(1, 0x7fff0fUL
)));
430 A(!IsNegativeZero(SpecificNaN
<float>(0, 17)));
432 A(!IsNegativeZero(SpecificNaN
<float>(0, 0x7fff0fUL
)));
433 A(!IsNegativeZero(UnspecifiedNaN
<float>()));
434 A(IsNegativeZero(-0.0f
));
435 A(!IsNegativeZero(0.0f
));
436 A(!IsNegativeZero(-1.0f
));
437 A(!IsNegativeZero(1.0f
));
439 A(!IsPositiveZero(PositiveInfinity
<float>()));
440 A(!IsPositiveZero(NegativeInfinity
<float>()));
441 A(!IsPositiveZero(SpecificNaN
<float>(1, 17)));
443 A(!IsPositiveZero(SpecificNaN
<float>(1, 0x7fff0fUL
)));
444 A(!IsPositiveZero(SpecificNaN
<float>(0, 17)));
446 A(!IsPositiveZero(SpecificNaN
<float>(0, 0x7fff0fUL
)));
447 A(!IsPositiveZero(UnspecifiedNaN
<float>()));
448 A(IsPositiveZero(0.0f
));
449 A(!IsPositiveZero(-0.0f
));
450 A(!IsPositiveZero(-1.0f
));
451 A(!IsPositiveZero(1.0f
));
453 // Edge case: negative zero.
454 TestEqualsIsForNegativeZero
<float>();
457 auto testInt32
= TestEqualsIsForInt32
<float>;
460 testInt32(INT32_MIN
);
461 testInt32(float(2147483648 - 128)); // max int32_t fitting in float
462 const int32_t BIG
= 2097151;
465 // Int64 values that don't fit in int32.
466 auto testInt64
= TestEqualsIsForInt64
<float>;
467 testInt64(INT64_MIN
);
468 testInt64(9007199254740992.0f
);
469 testInt64(-float(2147483648) - 256);
470 testInt64(float(2147483648));
471 testInt64(float(2147483648) + 256);
473 // Floats that aren't equal to any int32 or int64.
474 auto testNonInteger
= TestEqualsIsForNonInteger
<float>;
475 testNonInteger(NegativeInfinity
<float>());
476 testNonInteger(PositiveInfinity
<float>());
477 testNonInteger(UnspecifiedNaN
<float>());
478 testNonInteger(0.5f
);
479 testNonInteger(1.5f
);
480 testNonInteger(-0.0001f
);
481 testNonInteger(-19223373116872850000.0f
);
482 testNonInteger(19223373116872850000.0f
);
483 testNonInteger(float(BIG
) + 0.1f
);
485 A(powf(2.0f
, -150.0f
) == 0.0f
);
486 A(powf(2.0f
, -149.0f
) != 0.0f
);
487 testNonInteger(powf(2.0f
, -149.0f
));
488 testNonInteger(2 * powf(2.0f
, -149.0f
));
490 A(1.0f
- powf(2.0f
, -25.0f
) == 1.0f
);
491 A(1.0f
- powf(2.0f
, -24.0f
) != 1.0f
);
492 testNonInteger(1.0f
- powf(2.0f
, -24.0f
));
493 testNonInteger(1.0f
- powf(2.0f
, -23.0f
));
495 A(1.0f
+ powf(2.0f
, -24.0f
) == 1.0f
);
496 A(1.0f
+ powf(2.0f
, -23.0f
) != 1.0f
);
497 testNonInteger(1.0f
+ powf(2.0f
, -23.0f
));
500 static void TestPredicates() {
501 TestFloatsPredicates();
502 TestDoublesPredicates();
505 static void TestFloatsAreApproximatelyEqual() {
506 float epsilon
= mozilla::detail::FuzzyEqualsEpsilon
<float>::value();
507 float lessThanEpsilon
= epsilon
/ 2.0f
;
508 float moreThanEpsilon
= epsilon
* 2.0f
;
510 // Additive tests using the default epsilon
512 A(FuzzyEqualsAdditive(1.0f
, 1.0f
+ lessThanEpsilon
));
513 A(FuzzyEqualsAdditive(1.0f
, 1.0f
- lessThanEpsilon
));
514 A(FuzzyEqualsAdditive(1.0f
, 1.0f
+ epsilon
));
515 A(FuzzyEqualsAdditive(1.0f
, 1.0f
- epsilon
));
516 A(!FuzzyEqualsAdditive(1.0f
, 1.0f
+ moreThanEpsilon
));
517 A(!FuzzyEqualsAdditive(1.0f
, 1.0f
- moreThanEpsilon
));
518 // ... around 1.0e2 (this is near the upper bound of the range where
519 // adding moreThanEpsilon will still be representable and return false)
520 A(FuzzyEqualsAdditive(1.0e2f
, 1.0e2f
+ lessThanEpsilon
));
521 A(FuzzyEqualsAdditive(1.0e2f
, 1.0e2f
+ epsilon
));
522 A(!FuzzyEqualsAdditive(1.0e2f
, 1.0e2f
+ moreThanEpsilon
));
523 // ... around 1.0e-10
524 A(FuzzyEqualsAdditive(1.0e-10f
, 1.0e-10f
+ lessThanEpsilon
));
525 A(FuzzyEqualsAdditive(1.0e-10f
, 1.0e-10f
+ epsilon
));
526 A(!FuzzyEqualsAdditive(1.0e-10f
, 1.0e-10f
+ moreThanEpsilon
));
528 A(FuzzyEqualsAdditive(1.0e-6f
, -1.0e-6f
));
529 A(!FuzzyEqualsAdditive(1.0e-5f
, -1.0e-5f
));
530 // Using a small epsilon
531 A(FuzzyEqualsAdditive(1.0e-5f
, 1.0e-5f
+ 1.0e-10f
, 1.0e-9f
));
532 A(!FuzzyEqualsAdditive(1.0e-5f
, 1.0e-5f
+ 1.0e-10f
, 1.0e-11f
));
533 // Using a big epsilon
534 A(FuzzyEqualsAdditive(1.0e20f
, 1.0e20f
+ 1.0e15f
, 1.0e16f
));
535 A(!FuzzyEqualsAdditive(1.0e20f
, 1.0e20f
+ 1.0e15f
, 1.0e14f
));
537 // Multiplicative tests using the default epsilon
539 A(FuzzyEqualsMultiplicative(1.0f
, 1.0f
+ lessThanEpsilon
));
540 A(FuzzyEqualsMultiplicative(1.0f
, 1.0f
- lessThanEpsilon
));
541 A(FuzzyEqualsMultiplicative(1.0f
, 1.0f
+ epsilon
));
542 A(!FuzzyEqualsMultiplicative(1.0f
, 1.0f
- epsilon
));
543 A(!FuzzyEqualsMultiplicative(1.0f
, 1.0f
+ moreThanEpsilon
));
544 A(!FuzzyEqualsMultiplicative(1.0f
, 1.0f
- moreThanEpsilon
));
546 A(FuzzyEqualsMultiplicative(1.0e10f
, 1.0e10f
+ (lessThanEpsilon
* 1.0e10f
)));
547 A(!FuzzyEqualsMultiplicative(1.0e10f
, 1.0e10f
+ (moreThanEpsilon
* 1.0e10f
)));
548 // ... around 1.0e-10
549 A(FuzzyEqualsMultiplicative(1.0e-10f
,
550 1.0e-10f
+ (lessThanEpsilon
* 1.0e-10f
)));
551 A(!FuzzyEqualsMultiplicative(1.0e-10f
,
552 1.0e-10f
+ (moreThanEpsilon
* 1.0e-10f
)));
554 A(!FuzzyEqualsMultiplicative(1.0e-6f
, -1.0e-6f
));
555 A(FuzzyEqualsMultiplicative(1.0e-6f
, -1.0e-6f
, 1.0e2f
));
556 // Using a small epsilon
557 A(FuzzyEqualsMultiplicative(1.0e-5f
, 1.0e-5f
+ 1.0e-10f
, 1.0e-4f
));
558 A(!FuzzyEqualsMultiplicative(1.0e-5f
, 1.0e-5f
+ 1.0e-10f
, 1.0e-5f
));
559 // Using a big epsilon
560 A(FuzzyEqualsMultiplicative(1.0f
, 2.0f
, 1.0f
));
561 A(!FuzzyEqualsMultiplicative(1.0f
, 2.0f
, 0.1f
));
564 float oneThird
= 10.0f
/ 3.0f
;
565 A(FuzzyEqualsAdditive(10.0f
, 3.0f
* oneThird
));
566 A(FuzzyEqualsMultiplicative(10.0f
, 3.0f
* oneThird
));
568 A(!FuzzyEqualsAdditive(SpecificNaN
<float>(1, 1), SpecificNaN
<float>(1, 1)));
569 A(!FuzzyEqualsAdditive(SpecificNaN
<float>(1, 2), SpecificNaN
<float>(0, 8)));
570 A(!FuzzyEqualsMultiplicative(SpecificNaN
<float>(1, 1),
571 SpecificNaN
<float>(1, 1)));
572 A(!FuzzyEqualsMultiplicative(SpecificNaN
<float>(1, 2),
573 SpecificNaN
<float>(0, 200)));
576 static void TestDoublesAreApproximatelyEqual() {
577 double epsilon
= mozilla::detail::FuzzyEqualsEpsilon
<double>::value();
578 double lessThanEpsilon
= epsilon
/ 2.0;
579 double moreThanEpsilon
= epsilon
* 2.0;
581 // Additive tests using the default epsilon
583 A(FuzzyEqualsAdditive(1.0, 1.0 + lessThanEpsilon
));
584 A(FuzzyEqualsAdditive(1.0, 1.0 - lessThanEpsilon
));
585 A(FuzzyEqualsAdditive(1.0, 1.0 + epsilon
));
586 A(FuzzyEqualsAdditive(1.0, 1.0 - epsilon
));
587 A(!FuzzyEqualsAdditive(1.0, 1.0 + moreThanEpsilon
));
588 A(!FuzzyEqualsAdditive(1.0, 1.0 - moreThanEpsilon
));
589 // ... around 1.0e4 (this is near the upper bound of the range where
590 // adding moreThanEpsilon will still be representable and return false)
591 A(FuzzyEqualsAdditive(1.0e4
, 1.0e4
+ lessThanEpsilon
));
592 A(FuzzyEqualsAdditive(1.0e4
, 1.0e4
+ epsilon
));
593 A(!FuzzyEqualsAdditive(1.0e4
, 1.0e4
+ moreThanEpsilon
));
594 // ... around 1.0e-25
595 A(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + lessThanEpsilon
));
596 A(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + epsilon
));
597 A(!FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + moreThanEpsilon
));
599 A(FuzzyEqualsAdditive(1.0e-13, -1.0e-13));
600 A(!FuzzyEqualsAdditive(1.0e-12, -1.0e-12));
601 // Using a small epsilon
602 A(FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-29));
603 A(!FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-31));
604 // Using a big epsilon
605 A(FuzzyEqualsAdditive(1.0e40
, 1.0e40
+ 1.0e25
, 1.0e26
));
606 A(!FuzzyEqualsAdditive(1.0e40
, 1.0e40
+ 1.0e25
, 1.0e24
));
608 // Multiplicative tests using the default epsilon
610 A(FuzzyEqualsMultiplicative(1.0, 1.0 + lessThanEpsilon
));
611 A(FuzzyEqualsMultiplicative(1.0, 1.0 - lessThanEpsilon
));
612 A(FuzzyEqualsMultiplicative(1.0, 1.0 + epsilon
));
613 A(!FuzzyEqualsMultiplicative(1.0, 1.0 - epsilon
));
614 A(!FuzzyEqualsMultiplicative(1.0, 1.0 + moreThanEpsilon
));
615 A(!FuzzyEqualsMultiplicative(1.0, 1.0 - moreThanEpsilon
));
617 A(FuzzyEqualsMultiplicative(1.0e30
, 1.0e30
+ (lessThanEpsilon
* 1.0e30
)));
618 A(!FuzzyEqualsMultiplicative(1.0e30
, 1.0e30
+ (moreThanEpsilon
* 1.0e30
)));
619 // ... around 1.0e-30
620 A(FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (lessThanEpsilon
* 1.0e-30)));
621 A(!FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (moreThanEpsilon
* 1.0e-30)));
623 A(!FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6));
624 A(FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6, 1.0e2
));
625 // Using a small epsilon
626 A(FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-15));
627 A(!FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-16));
628 // Using a big epsilon
629 A(FuzzyEqualsMultiplicative(1.0e40
, 2.0e40
, 1.0));
630 A(!FuzzyEqualsMultiplicative(1.0e40
, 2.0e40
, 0.1));
633 double oneThird
= 10.0 / 3.0;
634 A(FuzzyEqualsAdditive(10.0, 3.0 * oneThird
));
635 A(FuzzyEqualsMultiplicative(10.0, 3.0 * oneThird
));
637 A(!FuzzyEqualsAdditive(SpecificNaN
<double>(1, 1), SpecificNaN
<double>(1, 1)));
638 A(!FuzzyEqualsAdditive(SpecificNaN
<double>(1, 2), SpecificNaN
<double>(0, 8)));
639 A(!FuzzyEqualsMultiplicative(SpecificNaN
<double>(1, 1),
640 SpecificNaN
<double>(1, 1)));
641 A(!FuzzyEqualsMultiplicative(SpecificNaN
<double>(1, 2),
642 SpecificNaN
<double>(0, 200)));
645 static void TestAreApproximatelyEqual() {
646 TestFloatsAreApproximatelyEqual();
647 TestDoublesAreApproximatelyEqual();
650 static void TestIsFloat32Representable() {
651 // Zeroes are representable.
652 A(IsFloat32Representable(+0.0));
653 A(IsFloat32Representable(-0.0));
655 // NaN and infinities are representable.
656 A(IsFloat32Representable(UnspecifiedNaN
<double>()));
657 A(IsFloat32Representable(SpecificNaN
<double>(0, 1)));
658 A(IsFloat32Representable(SpecificNaN
<double>(0, 71389)));
659 A(IsFloat32Representable(SpecificNaN
<double>(0, (uint64_t(1) << 52) - 2)));
660 A(IsFloat32Representable(SpecificNaN
<double>(1, 1)));
661 A(IsFloat32Representable(SpecificNaN
<double>(1, 71389)));
662 A(IsFloat32Representable(SpecificNaN
<double>(1, (uint64_t(1) << 52) - 2)));
663 A(IsFloat32Representable(PositiveInfinity
<double>()));
664 A(IsFloat32Representable(NegativeInfinity
<double>()));
666 // Sanity-check that the IEEE-754 double-precision-derived literals used in
667 // testing here work as we intend them to.
668 A(exp2(-1075.0) == 0.0);
669 A(exp2(-1074.0) != 0.0);
671 for (double littleExp
= -1074.0; littleExp
< -149.0; littleExp
++) {
672 // Powers of two representable as doubles but not as floats aren't
674 A(!IsFloat32Representable(exp2(littleExp
)));
677 // Sanity-check that the IEEE-754 single-precision-derived literals used in
678 // testing here work as we intend them to.
679 A(exp2f(-150.0f
) == 0.0);
680 A(exp2f(-149.0f
) != 0.0);
682 // Exact powers of two within the available range are representable.
683 for (double exponent
= -149.0; exponent
< 128.0; exponent
++) {
684 A(IsFloat32Representable(exp2(exponent
)));
687 // Powers of two above the available range aren't representable.
688 for (double bigExp
= 128.0; bigExp
< 1024.0; bigExp
++) {
689 A(!IsFloat32Representable(exp2(bigExp
)));
692 // Various denormal (i.e. super-small) doubles with MSB and LSB as far apart
693 // as possible are representable (but taken one bit further apart are not
696 // Note that the final iteration tests non-denormal with exponent field
697 // containing (biased) 1, as |oneTooSmall| and |widestPossible| happen still
698 // to be correct for that exponent due to the extra bit of precision in the
700 double oneTooSmall
= exp2(-150.0);
701 for (double denormExp
= -149.0;
702 denormExp
< 1 - double(FloatingPoint
<double>::kExponentBias
) + 1;
704 double baseDenorm
= exp2(denormExp
);
705 double tooWide
= baseDenorm
+ oneTooSmall
;
706 A(!IsFloat32Representable(tooWide
));
708 double widestPossible
= baseDenorm
;
709 if (oneTooSmall
* 2.0 != baseDenorm
) {
710 widestPossible
+= oneTooSmall
* 2.0;
713 A(IsFloat32Representable(widestPossible
));
716 // Finally, check certain interesting/special values for basic sanity.
717 A(!IsFloat32Representable(2147483647.0));
718 A(!IsFloat32Representable(-2147483647.0));
725 TestExponentComponent();
727 TestAreApproximatelyEqual();
728 TestIsFloat32Representable();