mfbt/tests/TestFloatingPoint.cpp

changeset 2
7e26c7da4463
equal deleted inserted replaced
-1:000000000000 0:a6076e2fb9f4
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "mozilla/FloatingPoint.h"
7
8 #include <math.h>
9
10 using mozilla::ExponentComponent;
11 using mozilla::FloatingPoint;
12 using mozilla::FuzzyEqualsAdditive;
13 using mozilla::FuzzyEqualsMultiplicative;
14 using mozilla::IsFinite;
15 using mozilla::IsInfinite;
16 using mozilla::IsNaN;
17 using mozilla::IsNegative;
18 using mozilla::IsNegativeZero;
19 using mozilla::NegativeInfinity;
20 using mozilla::NumberEqualsInt32;
21 using mozilla::NumberIsInt32;
22 using mozilla::NumbersAreIdentical;
23 using mozilla::PositiveInfinity;
24 using mozilla::SpecificNaN;
25 using mozilla::UnspecifiedNaN;
26
27 template<typename T>
28 static void
29 ShouldBeIdentical(T d1, T d2)
30 {
31 MOZ_RELEASE_ASSERT(NumbersAreIdentical(d1, d2));
32 MOZ_RELEASE_ASSERT(NumbersAreIdentical(d2, d1));
33 }
34
35 template<typename T>
36 static void
37 ShouldNotBeIdentical(T d1, T d2)
38 {
39 MOZ_RELEASE_ASSERT(!NumbersAreIdentical(d1, d2));
40 MOZ_RELEASE_ASSERT(!NumbersAreIdentical(d2, d1));
41 }
42
43 static void
44 TestDoublesAreIdentical()
45 {
46 ShouldBeIdentical(+0.0, +0.0);
47 ShouldBeIdentical(-0.0, -0.0);
48 ShouldNotBeIdentical(+0.0, -0.0);
49
50 ShouldBeIdentical(1.0, 1.0);
51 ShouldNotBeIdentical(-1.0, 1.0);
52 ShouldBeIdentical(4294967295.0, 4294967295.0);
53 ShouldNotBeIdentical(-4294967295.0, 4294967295.0);
54 ShouldBeIdentical(4294967296.0, 4294967296.0);
55 ShouldBeIdentical(4294967297.0, 4294967297.0);
56 ShouldBeIdentical(1e300, 1e300);
57
58 ShouldBeIdentical(PositiveInfinity<double>(), PositiveInfinity<double>());
59 ShouldBeIdentical(NegativeInfinity<double>(), NegativeInfinity<double>());
60 ShouldNotBeIdentical(PositiveInfinity<double>(), NegativeInfinity<double>());
61
62 ShouldNotBeIdentical(-0.0, NegativeInfinity<double>());
63 ShouldNotBeIdentical(+0.0, NegativeInfinity<double>());
64 ShouldNotBeIdentical(1e300, NegativeInfinity<double>());
65 ShouldNotBeIdentical(3.141592654, NegativeInfinity<double>());
66
67 ShouldBeIdentical(UnspecifiedNaN<double>(), UnspecifiedNaN<double>());
68 ShouldBeIdentical(-UnspecifiedNaN<double>(), UnspecifiedNaN<double>());
69 ShouldBeIdentical(UnspecifiedNaN<double>(), -UnspecifiedNaN<double>());
70
71 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 42));
72 ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(1, 42));
73 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(1, 42));
74 ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 42));
75
76 const uint64_t Mask = 0xfffffffffffffULL;
77 for (unsigned i = 0; i < 52; i++) {
78 for (unsigned j = 0; j < 52; j++) {
79 for (unsigned sign = 0; i < 2; i++) {
80 ShouldBeIdentical(SpecificNaN<double>(0, 1ULL << i), SpecificNaN<double>(sign, 1ULL << j));
81 ShouldBeIdentical(SpecificNaN<double>(1, 1ULL << i), SpecificNaN<double>(sign, 1ULL << j));
82
83 ShouldBeIdentical(SpecificNaN<double>(0, Mask & ~(1ULL << i)),
84 SpecificNaN<double>(sign, Mask & ~(1ULL << j)));
85 ShouldBeIdentical(SpecificNaN<double>(1, Mask & ~(1ULL << i)),
86 SpecificNaN<double>(sign, Mask & ~(1ULL << j)));
87 }
88 }
89 }
90 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x8000000000000ULL));
91 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x4000000000000ULL));
92 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x2000000000000ULL));
93 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x1000000000000ULL));
94 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0800000000000ULL));
95 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0400000000000ULL));
96 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0200000000000ULL));
97 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0100000000000ULL));
98 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0080000000000ULL));
99 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0040000000000ULL));
100 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0020000000000ULL));
101 ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0010000000000ULL));
102 ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 0xff0ffffffffffULL));
103 ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 0xfffffffffff0fULL));
104
105 ShouldNotBeIdentical(UnspecifiedNaN<double>(), +0.0);
106 ShouldNotBeIdentical(UnspecifiedNaN<double>(), -0.0);
107 ShouldNotBeIdentical(UnspecifiedNaN<double>(), 1.0);
108 ShouldNotBeIdentical(UnspecifiedNaN<double>(), -1.0);
109 ShouldNotBeIdentical(UnspecifiedNaN<double>(), PositiveInfinity<double>());
110 ShouldNotBeIdentical(UnspecifiedNaN<double>(), NegativeInfinity<double>());
111 }
112
113 static void
114 TestFloatsAreIdentical()
115 {
116 ShouldBeIdentical(+0.0f, +0.0f);
117 ShouldBeIdentical(-0.0f, -0.0f);
118 ShouldNotBeIdentical(+0.0f, -0.0f);
119
120 ShouldBeIdentical(1.0f, 1.0f);
121 ShouldNotBeIdentical(-1.0f, 1.0f);
122 ShouldBeIdentical(8388607.0f, 8388607.0f);
123 ShouldNotBeIdentical(-8388607.0f, 8388607.0f);
124 ShouldBeIdentical(8388608.0f, 8388608.0f);
125 ShouldBeIdentical(8388609.0f, 8388609.0f);
126 ShouldBeIdentical(1e36f, 1e36f);
127
128 ShouldBeIdentical(PositiveInfinity<float>(), PositiveInfinity<float>());
129 ShouldBeIdentical(NegativeInfinity<float>(), NegativeInfinity<float>());
130 ShouldNotBeIdentical(PositiveInfinity<float>(), NegativeInfinity<float>());
131
132 ShouldNotBeIdentical(-0.0f, NegativeInfinity<float>());
133 ShouldNotBeIdentical(+0.0f, NegativeInfinity<float>());
134 ShouldNotBeIdentical(1e36f, NegativeInfinity<float>());
135 ShouldNotBeIdentical(3.141592654f, NegativeInfinity<float>());
136
137 ShouldBeIdentical(UnspecifiedNaN<float>(), UnspecifiedNaN<float>());
138 ShouldBeIdentical(-UnspecifiedNaN<float>(), UnspecifiedNaN<float>());
139 ShouldBeIdentical(UnspecifiedNaN<float>(), -UnspecifiedNaN<float>());
140
141 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 42));
142 ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(1, 42));
143 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(1, 42));
144 ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 42));
145
146 const uint32_t Mask = 0x7fffffUL;
147 for (unsigned i = 0; i < 23; i++) {
148 for (unsigned j = 0; j < 23; j++) {
149 for (unsigned sign = 0; i < 2; i++) {
150 ShouldBeIdentical(SpecificNaN<float>(0, 1UL << i), SpecificNaN<float>(sign, 1UL << j));
151 ShouldBeIdentical(SpecificNaN<float>(1, 1UL << i), SpecificNaN<float>(sign, 1UL << j));
152
153 ShouldBeIdentical(SpecificNaN<float>(0, Mask & ~(1UL << i)),
154 SpecificNaN<float>(sign, Mask & ~(1UL << j)));
155 ShouldBeIdentical(SpecificNaN<float>(1, Mask & ~(1UL << i)),
156 SpecificNaN<float>(sign, Mask & ~(1UL << j)));
157 }
158 }
159 }
160 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x700000));
161 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x400000));
162 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x200000));
163 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x100000));
164 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x080000));
165 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x040000));
166 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x020000));
167 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x010000));
168 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x008000));
169 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x004000));
170 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x002000));
171 ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x001000));
172 ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 0x7f0fff));
173 ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 0x7fff0f));
174
175 ShouldNotBeIdentical(UnspecifiedNaN<float>(), +0.0f);
176 ShouldNotBeIdentical(UnspecifiedNaN<float>(), -0.0f);
177 ShouldNotBeIdentical(UnspecifiedNaN<float>(), 1.0f);
178 ShouldNotBeIdentical(UnspecifiedNaN<float>(), -1.0f);
179 ShouldNotBeIdentical(UnspecifiedNaN<float>(), PositiveInfinity<float>());
180 ShouldNotBeIdentical(UnspecifiedNaN<float>(), NegativeInfinity<float>());
181 }
182
183 static void
184 TestAreIdentical()
185 {
186 TestDoublesAreIdentical();
187 TestFloatsAreIdentical();
188 }
189
190 static void
191 TestDoubleExponentComponent()
192 {
193 MOZ_RELEASE_ASSERT(ExponentComponent(0.0) == -int_fast16_t(FloatingPoint<double>::ExponentBias));
194 MOZ_RELEASE_ASSERT(ExponentComponent(-0.0) == -int_fast16_t(FloatingPoint<double>::ExponentBias));
195 MOZ_RELEASE_ASSERT(ExponentComponent(0.125) == -3);
196 MOZ_RELEASE_ASSERT(ExponentComponent(0.5) == -1);
197 MOZ_RELEASE_ASSERT(ExponentComponent(1.0) == 0);
198 MOZ_RELEASE_ASSERT(ExponentComponent(1.5) == 0);
199 MOZ_RELEASE_ASSERT(ExponentComponent(2.0) == 1);
200 MOZ_RELEASE_ASSERT(ExponentComponent(7.0) == 2);
201 MOZ_RELEASE_ASSERT(ExponentComponent(PositiveInfinity<double>()) == FloatingPoint<double>::ExponentBias + 1);
202 MOZ_RELEASE_ASSERT(ExponentComponent(NegativeInfinity<double>()) == FloatingPoint<double>::ExponentBias + 1);
203 MOZ_RELEASE_ASSERT(ExponentComponent(UnspecifiedNaN<double>()) == FloatingPoint<double>::ExponentBias + 1);
204 }
205
206 static void
207 TestFloatExponentComponent()
208 {
209 MOZ_RELEASE_ASSERT(ExponentComponent(0.0f) == -int_fast16_t(FloatingPoint<float>::ExponentBias));
210 MOZ_RELEASE_ASSERT(ExponentComponent(-0.0f) == -int_fast16_t(FloatingPoint<float>::ExponentBias));
211 MOZ_RELEASE_ASSERT(ExponentComponent(0.125f) == -3);
212 MOZ_RELEASE_ASSERT(ExponentComponent(0.5f) == -1);
213 MOZ_RELEASE_ASSERT(ExponentComponent(1.0f) == 0);
214 MOZ_RELEASE_ASSERT(ExponentComponent(1.5f) == 0);
215 MOZ_RELEASE_ASSERT(ExponentComponent(2.0f) == 1);
216 MOZ_RELEASE_ASSERT(ExponentComponent(7.0f) == 2);
217 MOZ_RELEASE_ASSERT(ExponentComponent(PositiveInfinity<float>()) == FloatingPoint<float>::ExponentBias + 1);
218 MOZ_RELEASE_ASSERT(ExponentComponent(NegativeInfinity<float>()) == FloatingPoint<float>::ExponentBias + 1);
219 MOZ_RELEASE_ASSERT(ExponentComponent(UnspecifiedNaN<float>()) == FloatingPoint<float>::ExponentBias + 1);
220 }
221
222 static void
223 TestExponentComponent()
224 {
225 TestDoubleExponentComponent();
226 TestFloatExponentComponent();
227 }
228
229 static void
230 TestDoublesPredicates()
231 {
232 MOZ_RELEASE_ASSERT(IsNaN(UnspecifiedNaN<double>()));
233 MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<double>(1, 17)));;
234 MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<double>(0, 0xfffffffffff0fULL)));
235 MOZ_RELEASE_ASSERT(!IsNaN(0.0));
236 MOZ_RELEASE_ASSERT(!IsNaN(-0.0));
237 MOZ_RELEASE_ASSERT(!IsNaN(1.0));
238 MOZ_RELEASE_ASSERT(!IsNaN(PositiveInfinity<double>()));
239 MOZ_RELEASE_ASSERT(!IsNaN(NegativeInfinity<double>()));
240
241 MOZ_RELEASE_ASSERT(IsInfinite(PositiveInfinity<double>()));
242 MOZ_RELEASE_ASSERT(IsInfinite(NegativeInfinity<double>()));
243 MOZ_RELEASE_ASSERT(!IsInfinite(UnspecifiedNaN<double>()));
244 MOZ_RELEASE_ASSERT(!IsInfinite(0.0));
245 MOZ_RELEASE_ASSERT(!IsInfinite(-0.0));
246 MOZ_RELEASE_ASSERT(!IsInfinite(1.0));
247
248 MOZ_RELEASE_ASSERT(!IsFinite(PositiveInfinity<double>()));
249 MOZ_RELEASE_ASSERT(!IsFinite(NegativeInfinity<double>()));
250 MOZ_RELEASE_ASSERT(!IsFinite(UnspecifiedNaN<double>()));
251 MOZ_RELEASE_ASSERT(IsFinite(0.0));
252 MOZ_RELEASE_ASSERT(IsFinite(-0.0));
253 MOZ_RELEASE_ASSERT(IsFinite(1.0));
254
255 MOZ_RELEASE_ASSERT(!IsNegative(PositiveInfinity<double>()));
256 MOZ_RELEASE_ASSERT(IsNegative(NegativeInfinity<double>()));
257 MOZ_RELEASE_ASSERT(IsNegative(-0.0));
258 MOZ_RELEASE_ASSERT(!IsNegative(0.0));
259 MOZ_RELEASE_ASSERT(IsNegative(-1.0));
260 MOZ_RELEASE_ASSERT(!IsNegative(1.0));
261
262 MOZ_RELEASE_ASSERT(!IsNegativeZero(PositiveInfinity<double>()));
263 MOZ_RELEASE_ASSERT(!IsNegativeZero(NegativeInfinity<double>()));
264 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(1, 17)));;
265 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(1, 0xfffffffffff0fULL)));
266 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(0, 17)));;
267 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(0, 0xfffffffffff0fULL)));
268 MOZ_RELEASE_ASSERT(!IsNegativeZero(UnspecifiedNaN<double>()));
269 MOZ_RELEASE_ASSERT(IsNegativeZero(-0.0));
270 MOZ_RELEASE_ASSERT(!IsNegativeZero(0.0));
271 MOZ_RELEASE_ASSERT(!IsNegativeZero(-1.0));
272 MOZ_RELEASE_ASSERT(!IsNegativeZero(1.0));
273
274 int32_t i;
275 MOZ_RELEASE_ASSERT(NumberIsInt32(0.0, &i)); MOZ_RELEASE_ASSERT(i == 0);
276 MOZ_RELEASE_ASSERT(!NumberIsInt32(-0.0, &i));
277 MOZ_RELEASE_ASSERT(NumberEqualsInt32(0.0, &i)); MOZ_RELEASE_ASSERT(i == 0);
278 MOZ_RELEASE_ASSERT(NumberEqualsInt32(-0.0, &i)); MOZ_RELEASE_ASSERT(i == 0);
279 MOZ_RELEASE_ASSERT(NumberIsInt32(double(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
280 MOZ_RELEASE_ASSERT(NumberIsInt32(double(INT32_MAX), &i)); MOZ_RELEASE_ASSERT(i == INT32_MAX);
281 MOZ_RELEASE_ASSERT(NumberEqualsInt32(double(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
282 MOZ_RELEASE_ASSERT(NumberEqualsInt32(double(INT32_MAX), &i)); MOZ_RELEASE_ASSERT(i == INT32_MAX);
283 MOZ_RELEASE_ASSERT(!NumberIsInt32(0.5, &i));
284 MOZ_RELEASE_ASSERT(!NumberIsInt32(double(INT32_MAX) + 0.1, &i));
285 MOZ_RELEASE_ASSERT(!NumberIsInt32(double(INT32_MIN) - 0.1, &i));
286 MOZ_RELEASE_ASSERT(!NumberIsInt32(NegativeInfinity<double>(), &i));
287 MOZ_RELEASE_ASSERT(!NumberIsInt32(PositiveInfinity<double>(), &i));
288 MOZ_RELEASE_ASSERT(!NumberIsInt32(UnspecifiedNaN<double>(), &i));
289 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(0.5, &i));
290 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(double(INT32_MAX) + 0.1, &i));
291 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(double(INT32_MIN) - 0.1, &i));
292 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(NegativeInfinity<double>(), &i));
293 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(PositiveInfinity<double>(), &i));
294 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(UnspecifiedNaN<double>(), &i));
295 }
296
297 static void
298 TestFloatsPredicates()
299 {
300 MOZ_RELEASE_ASSERT(IsNaN(UnspecifiedNaN<float>()));
301 MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<float>(1, 17)));;
302 MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<float>(0, 0x7fff0fUL)));
303 MOZ_RELEASE_ASSERT(!IsNaN(0.0f));
304 MOZ_RELEASE_ASSERT(!IsNaN(-0.0f));
305 MOZ_RELEASE_ASSERT(!IsNaN(1.0f));
306 MOZ_RELEASE_ASSERT(!IsNaN(PositiveInfinity<float>()));
307 MOZ_RELEASE_ASSERT(!IsNaN(NegativeInfinity<float>()));
308
309 MOZ_RELEASE_ASSERT(IsInfinite(PositiveInfinity<float>()));
310 MOZ_RELEASE_ASSERT(IsInfinite(NegativeInfinity<float>()));
311 MOZ_RELEASE_ASSERT(!IsInfinite(UnspecifiedNaN<float>()));
312 MOZ_RELEASE_ASSERT(!IsInfinite(0.0f));
313 MOZ_RELEASE_ASSERT(!IsInfinite(-0.0f));
314 MOZ_RELEASE_ASSERT(!IsInfinite(1.0f));
315
316 MOZ_RELEASE_ASSERT(!IsFinite(PositiveInfinity<float>()));
317 MOZ_RELEASE_ASSERT(!IsFinite(NegativeInfinity<float>()));
318 MOZ_RELEASE_ASSERT(!IsFinite(UnspecifiedNaN<float>()));
319 MOZ_RELEASE_ASSERT(IsFinite(0.0f));
320 MOZ_RELEASE_ASSERT(IsFinite(-0.0f));
321 MOZ_RELEASE_ASSERT(IsFinite(1.0f));
322
323 MOZ_RELEASE_ASSERT(!IsNegative(PositiveInfinity<float>()));
324 MOZ_RELEASE_ASSERT(IsNegative(NegativeInfinity<float>()));
325 MOZ_RELEASE_ASSERT(IsNegative(-0.0f));
326 MOZ_RELEASE_ASSERT(!IsNegative(0.0f));
327 MOZ_RELEASE_ASSERT(IsNegative(-1.0f));
328 MOZ_RELEASE_ASSERT(!IsNegative(1.0f));
329
330 MOZ_RELEASE_ASSERT(!IsNegativeZero(PositiveInfinity<float>()));
331 MOZ_RELEASE_ASSERT(!IsNegativeZero(NegativeInfinity<float>()));
332 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(1, 17)));;
333 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(1, 0x7fff0fUL)));
334 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(0, 17)));;
335 MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(0, 0x7fff0fUL)));
336 MOZ_RELEASE_ASSERT(!IsNegativeZero(UnspecifiedNaN<float>()));
337 MOZ_RELEASE_ASSERT(IsNegativeZero(-0.0f));
338 MOZ_RELEASE_ASSERT(!IsNegativeZero(0.0f));
339 MOZ_RELEASE_ASSERT(!IsNegativeZero(-1.0f));
340 MOZ_RELEASE_ASSERT(!IsNegativeZero(1.0f));
341
342 int32_t i;
343 const int32_t BIG = 2097151;
344 MOZ_RELEASE_ASSERT(NumberIsInt32(0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0);
345 MOZ_RELEASE_ASSERT(!NumberIsInt32(-0.0f, &i));
346 MOZ_RELEASE_ASSERT(NumberEqualsInt32(0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0);
347 MOZ_RELEASE_ASSERT(NumberEqualsInt32(-0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0);
348 MOZ_RELEASE_ASSERT(NumberIsInt32(float(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
349 MOZ_RELEASE_ASSERT(NumberIsInt32(float(BIG), &i)); MOZ_RELEASE_ASSERT(i == BIG);
350 MOZ_RELEASE_ASSERT(NumberEqualsInt32(float(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
351 MOZ_RELEASE_ASSERT(NumberEqualsInt32(float(BIG), &i)); MOZ_RELEASE_ASSERT(i == BIG);
352 MOZ_RELEASE_ASSERT(!NumberIsInt32(0.5f, &i));
353 MOZ_RELEASE_ASSERT(!NumberIsInt32(float(BIG) + 0.1f, &i));
354 MOZ_RELEASE_ASSERT(!NumberIsInt32(NegativeInfinity<float>(), &i));
355 MOZ_RELEASE_ASSERT(!NumberIsInt32(PositiveInfinity<float>(), &i));
356 MOZ_RELEASE_ASSERT(!NumberIsInt32(UnspecifiedNaN<float>(), &i));
357 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(0.5f, &i));
358 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(float(BIG) + 0.1f, &i));
359 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(NegativeInfinity<float>(), &i));
360 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(PositiveInfinity<float>(), &i));
361 MOZ_RELEASE_ASSERT(!NumberEqualsInt32(UnspecifiedNaN<float>(), &i));
362 }
363
364 static void
365 TestPredicates()
366 {
367 TestFloatsPredicates();
368 TestDoublesPredicates();
369 }
370
371 static void
372 TestFloatsAreApproximatelyEqual()
373 {
374 float epsilon = mozilla::detail::FuzzyEqualsEpsilon<float>::value();
375 float lessThanEpsilon = epsilon / 2.0f;
376 float moreThanEpsilon = epsilon * 2.0f;
377
378 // Additive tests using the default epsilon
379 // ... around 1.0
380 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f + lessThanEpsilon));
381 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f - lessThanEpsilon));
382 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f + epsilon));
383 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f - epsilon));
384 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0f, 1.0f + moreThanEpsilon));
385 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0f, 1.0f - moreThanEpsilon));
386 // ... around 1.0e2 (this is near the upper bound of the range where
387 // adding moreThanEpsilon will still be representable and return false)
388 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + lessThanEpsilon));
389 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + epsilon));
390 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e2f, 1.0e2f + moreThanEpsilon));
391 // ... around 1.0e-10
392 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + lessThanEpsilon));
393 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + epsilon));
394 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + moreThanEpsilon));
395 // ... straddling 0
396 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-6f, -1.0e-6f));
397 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-5f, -1.0e-5f));
398 // Using a small epsilon
399 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-9f));
400 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-11f));
401 // Using a big epsilon
402 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e16f));
403 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e14f));
404
405 // Multiplicative tests using the default epsilon
406 // ... around 1.0
407 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f + lessThanEpsilon));
408 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f - lessThanEpsilon));
409 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f + epsilon));
410 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f - epsilon));
411 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f + moreThanEpsilon));
412 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f - moreThanEpsilon));
413 // ... around 1.0e10
414 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (lessThanEpsilon * 1.0e10f)));
415 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (moreThanEpsilon * 1.0e10f)));
416 // ... around 1.0e-10
417 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-10f, 1.0e-10f + (lessThanEpsilon * 1.0e-10f)));
418 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-10f, 1.0e-10f + (moreThanEpsilon * 1.0e-10f)));
419 // ... straddling 0
420 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f));
421 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f, 1.0e2f));
422 // Using a small epsilon
423 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-4f));
424 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-5f));
425 // Using a big epsilon
426 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 2.0f, 1.0f));
427 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 2.0f, 0.1f));
428
429 // "real world case"
430 float oneThird = 10.0f / 3.0f;
431 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(10.0f, 3.0f * oneThird));
432 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(10.0f, 3.0f * oneThird));
433 // NaN check
434 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<float>(1, 1), SpecificNaN<float>(1, 1)));
435 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<float>(1, 2), SpecificNaN<float>(0, 8)));
436 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<float>(1, 1), SpecificNaN<float>(1, 1)));
437 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<float>(1, 2), SpecificNaN<float>(0, 200)));
438 }
439
440 static void
441 TestDoublesAreApproximatelyEqual()
442 {
443 double epsilon = mozilla::detail::FuzzyEqualsEpsilon<double>::value();
444 double lessThanEpsilon = epsilon / 2.0;
445 double moreThanEpsilon = epsilon * 2.0;
446
447 // Additive tests using the default epsilon
448 // ... around 1.0
449 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 + lessThanEpsilon));
450 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 - lessThanEpsilon));
451 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 + epsilon));
452 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 - epsilon));
453 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0, 1.0 + moreThanEpsilon));
454 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0, 1.0 - moreThanEpsilon));
455 // ... around 1.0e4 (this is near the upper bound of the range where
456 // adding moreThanEpsilon will still be representable and return false)
457 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e4, 1.0e4 + lessThanEpsilon));
458 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e4, 1.0e4 + epsilon));
459 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e4, 1.0e4 + moreThanEpsilon));
460 // ... around 1.0e-25
461 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + lessThanEpsilon));
462 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + epsilon));
463 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + moreThanEpsilon));
464 // ... straddling 0
465 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-13, -1.0e-13));
466 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-12, -1.0e-12));
467 // Using a small epsilon
468 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-29));
469 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-31));
470 // Using a big epsilon
471 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e26));
472 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e24));
473
474 // Multiplicative tests using the default epsilon
475 // ... around 1.0
476 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 + lessThanEpsilon));
477 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 - lessThanEpsilon));
478 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 + epsilon));
479 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 - epsilon));
480 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 + moreThanEpsilon));
481 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 - moreThanEpsilon));
482 // ... around 1.0e30
483 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (lessThanEpsilon * 1.0e30)));
484 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (moreThanEpsilon * 1.0e30)));
485 // ... around 1.0e-30
486 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (lessThanEpsilon * 1.0e-30)));
487 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (moreThanEpsilon * 1.0e-30)));
488 // ... straddling 0
489 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6));
490 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6, 1.0e2));
491 // Using a small epsilon
492 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-15));
493 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-16));
494 // Using a big epsilon
495 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 1.0));
496 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 0.1));
497
498 // "real world case"
499 double oneThird = 10.0 / 3.0;
500 MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(10.0, 3.0 * oneThird));
501 MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(10.0, 3.0 * oneThird));
502 // NaN check
503 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<double>(1, 1), SpecificNaN<double>(1, 1)));
504 MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<double>(1, 2), SpecificNaN<double>(0, 8)));
505 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<double>(1, 1), SpecificNaN<double>(1, 1)));
506 MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<double>(1, 2), SpecificNaN<double>(0, 200)));
507 }
508
509 static void
510 TestAreApproximatelyEqual()
511 {
512 TestFloatsAreApproximatelyEqual();
513 TestDoublesAreApproximatelyEqual();
514 }
515
516 int
517 main()
518 {
519 TestAreIdentical();
520 TestExponentComponent();
521 TestPredicates();
522 TestAreApproximatelyEqual();
523 }

mercurial