1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.math;
18
19 import static com.google.common.math.MathTesting.ALL_DOUBLE_CANDIDATES;
20 import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
21 import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
22 import static com.google.common.math.MathTesting.DOUBLE_CANDIDATES_EXCEPT_NAN;
23 import static com.google.common.math.MathTesting.FINITE_DOUBLE_CANDIDATES;
24 import static com.google.common.math.MathTesting.FRACTIONAL_DOUBLE_CANDIDATES;
25 import static com.google.common.math.MathTesting.INFINITIES;
26 import static com.google.common.math.MathTesting.INTEGRAL_DOUBLE_CANDIDATES;
27 import static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES;
28 import static com.google.common.math.MathTesting.POSITIVE_FINITE_DOUBLE_CANDIDATES;
29 import static java.math.RoundingMode.CEILING;
30 import static java.math.RoundingMode.DOWN;
31 import static java.math.RoundingMode.FLOOR;
32 import static java.math.RoundingMode.HALF_DOWN;
33 import static java.math.RoundingMode.HALF_EVEN;
34 import static java.math.RoundingMode.HALF_UP;
35 import static java.math.RoundingMode.UNNECESSARY;
36 import static java.math.RoundingMode.UP;
37 import static java.util.Arrays.asList;
38
39 import com.google.common.annotations.GwtCompatible;
40 import com.google.common.annotations.GwtIncompatible;
41 import com.google.common.collect.ImmutableList;
42 import com.google.common.collect.Iterables;
43 import com.google.common.primitives.Doubles;
44 import com.google.common.testing.NullPointerTester;
45
46 import junit.framework.TestCase;
47
48 import java.math.BigDecimal;
49 import java.math.BigInteger;
50 import java.math.RoundingMode;
51 import java.util.Arrays;
52 import java.util.List;
53
54
55
56
57
58
59 @GwtCompatible(emulated = true)
60 public class DoubleMathTest extends TestCase {
61
62 private static final BigDecimal MAX_INT_AS_BIG_DECIMAL = BigDecimal.valueOf(Integer.MAX_VALUE);
63 private static final BigDecimal MIN_INT_AS_BIG_DECIMAL = BigDecimal.valueOf(Integer.MIN_VALUE);
64
65 private static final BigDecimal MAX_LONG_AS_BIG_DECIMAL = BigDecimal.valueOf(Long.MAX_VALUE);
66 private static final BigDecimal MIN_LONG_AS_BIG_DECIMAL = BigDecimal.valueOf(Long.MIN_VALUE);
67
68 public void testConstantsMaxFactorial() {
69 BigInteger maxDoubleValue = BigDecimal.valueOf(Double.MAX_VALUE).toBigInteger();
70 assertTrue(BigIntegerMath.factorial(DoubleMath.MAX_FACTORIAL).compareTo(maxDoubleValue) <= 0);
71 assertTrue(
72 BigIntegerMath.factorial(DoubleMath.MAX_FACTORIAL + 1).compareTo(maxDoubleValue) > 0);
73 }
74
75 public void testConstantsEverySixteenthFactorial() {
76 for (int i = 0, n = 0; n <= DoubleMath.MAX_FACTORIAL; i++, n += 16) {
77 assertEquals(
78 BigIntegerMath.factorial(n).doubleValue(), DoubleMath.everySixteenthFactorial[i]);
79 }
80 }
81
82 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)")
83 public void testRoundIntegralDoubleToInt() {
84 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
85 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
86 BigDecimal expected = new BigDecimal(d).setScale(0, mode);
87 boolean isInBounds = expected.compareTo(MAX_INT_AS_BIG_DECIMAL) <= 0
88 & expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0;
89
90 try {
91 assertEquals(expected.intValue(), DoubleMath.roundToInt(d, mode));
92 assertTrue(isInBounds);
93 } catch (ArithmeticException e) {
94 assertFalse(isInBounds);
95 }
96 }
97 }
98 }
99
100 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)")
101 public void testRoundFractionalDoubleToInt() {
102 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
103 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
104 BigDecimal expected = new BigDecimal(d).setScale(0, mode);
105 boolean isInBounds = expected.compareTo(MAX_INT_AS_BIG_DECIMAL) <= 0
106 & expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0;
107
108 try {
109 assertEquals(expected.intValue(), DoubleMath.roundToInt(d, mode));
110 assertTrue(isInBounds);
111 } catch (ArithmeticException e) {
112 assertFalse(isInBounds);
113 }
114 }
115 }
116 }
117
118 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)")
119 public void testRoundExactIntegralDoubleToInt() {
120 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
121 BigDecimal expected = new BigDecimal(d).setScale(0, UNNECESSARY);
122 boolean isInBounds = expected.compareTo(MAX_INT_AS_BIG_DECIMAL) <= 0
123 & expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0;
124
125 try {
126 assertEquals(expected.intValue(), DoubleMath.roundToInt(d, UNNECESSARY));
127 assertTrue(isInBounds);
128 } catch (ArithmeticException e) {
129 assertFalse(isInBounds);
130 }
131 }
132 }
133
134 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)")
135 public void testRoundExactFractionalDoubleToIntFails() {
136 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
137 try {
138 DoubleMath.roundToInt(d, UNNECESSARY);
139 fail("Expected ArithmeticException");
140 } catch (ArithmeticException expected) {}
141 }
142 }
143
144 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)")
145 public void testRoundNaNToIntAlwaysFails() {
146 for (RoundingMode mode : ALL_ROUNDING_MODES) {
147 try {
148 DoubleMath.roundToInt(Double.NaN, mode);
149 fail("Expected ArithmeticException");
150 } catch (ArithmeticException expected) {}
151 }
152 }
153
154 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)")
155 public void testRoundInfiniteToIntAlwaysFails() {
156 for (RoundingMode mode : ALL_ROUNDING_MODES) {
157 try {
158 DoubleMath.roundToInt(Double.POSITIVE_INFINITY, mode);
159 fail("Expected ArithmeticException");
160 } catch (ArithmeticException expected) {}
161 try {
162 DoubleMath.roundToInt(Double.NEGATIVE_INFINITY, mode);
163 fail("Expected ArithmeticException");
164 } catch (ArithmeticException expected) {}
165 }
166 }
167
168 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)")
169 public void testRoundIntegralDoubleToLong() {
170 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
171 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
172 BigDecimal expected = new BigDecimal(d).setScale(0, mode);
173 boolean isInBounds = expected.compareTo(MAX_LONG_AS_BIG_DECIMAL) <= 0
174 & expected.compareTo(MIN_LONG_AS_BIG_DECIMAL) >= 0;
175
176 try {
177 assertEquals(expected.longValue(), DoubleMath.roundToLong(d, mode));
178 assertTrue(isInBounds);
179 } catch (ArithmeticException e) {
180 assertFalse(isInBounds);
181 }
182 }
183 }
184 }
185
186 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)")
187 public void testRoundFractionalDoubleToLong() {
188 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
189 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
190 BigDecimal expected = new BigDecimal(d).setScale(0, mode);
191 boolean isInBounds = expected.compareTo(MAX_LONG_AS_BIG_DECIMAL) <= 0
192 & expected.compareTo(MIN_LONG_AS_BIG_DECIMAL) >= 0;
193
194 try {
195 assertEquals(expected.longValue(), DoubleMath.roundToLong(d, mode));
196 assertTrue(isInBounds);
197 } catch (ArithmeticException e) {
198 assertFalse(isInBounds);
199 }
200 }
201 }
202 }
203
204 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)")
205 public void testRoundExactIntegralDoubleToLong() {
206 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
207
208 BigDecimal expected = new BigDecimal(d).setScale(0, UNNECESSARY);
209 boolean isInBounds = expected.compareTo(MAX_LONG_AS_BIG_DECIMAL) <= 0
210 & expected.compareTo(MIN_LONG_AS_BIG_DECIMAL) >= 0;
211
212 try {
213 assertEquals(expected.longValue(), DoubleMath.roundToLong(d, UNNECESSARY));
214 assertTrue(isInBounds);
215 } catch (ArithmeticException e) {
216 assertFalse(isInBounds);
217 }
218 }
219 }
220
221 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)")
222 public void testRoundExactFractionalDoubleToLongFails() {
223 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
224 try {
225 DoubleMath.roundToLong(d, UNNECESSARY);
226 fail("Expected ArithmeticException");
227 } catch (ArithmeticException expected) {}
228 }
229 }
230
231 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)")
232 public void testRoundNaNToLongAlwaysFails() {
233 for (RoundingMode mode : ALL_ROUNDING_MODES) {
234 try {
235 DoubleMath.roundToLong(Double.NaN, mode);
236 fail("Expected ArithmeticException");
237 } catch (ArithmeticException expected) {}
238 }
239 }
240
241 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)")
242 public void testRoundInfiniteToLongAlwaysFails() {
243 for (RoundingMode mode : ALL_ROUNDING_MODES) {
244 try {
245 DoubleMath.roundToLong(Double.POSITIVE_INFINITY, mode);
246 fail("Expected ArithmeticException");
247 } catch (ArithmeticException expected) {}
248 try {
249 DoubleMath.roundToLong(Double.NEGATIVE_INFINITY, mode);
250 fail("Expected ArithmeticException");
251 } catch (ArithmeticException expected) {}
252 }
253 }
254
255 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
256 public void testRoundIntegralDoubleToBigInteger() {
257 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
258 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
259 BigDecimal expected = new BigDecimal(d).setScale(0, mode);
260 assertEquals(expected.toBigInteger(), DoubleMath.roundToBigInteger(d, mode));
261 }
262 }
263 }
264
265 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
266 public void testRoundFractionalDoubleToBigInteger() {
267 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
268 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
269 BigDecimal expected = new BigDecimal(d).setScale(0, mode);
270 assertEquals(expected.toBigInteger(), DoubleMath.roundToBigInteger(d, mode));
271 }
272 }
273 }
274
275 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
276 public void testRoundExactIntegralDoubleToBigInteger() {
277 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
278 BigDecimal expected = new BigDecimal(d).setScale(0, UNNECESSARY);
279 assertEquals(expected.toBigInteger(), DoubleMath.roundToBigInteger(d, UNNECESSARY));
280 }
281 }
282
283 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
284 public void testRoundExactFractionalDoubleToBigIntegerFails() {
285 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
286 try {
287 DoubleMath.roundToBigInteger(d, UNNECESSARY);
288 fail("Expected ArithmeticException");
289 } catch (ArithmeticException expected) {}
290 }
291 }
292
293 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
294 public void testRoundNaNToBigIntegerAlwaysFails() {
295 for (RoundingMode mode : ALL_ROUNDING_MODES) {
296 try {
297 DoubleMath.roundToBigInteger(Double.NaN, mode);
298 fail("Expected ArithmeticException");
299 } catch (ArithmeticException expected) {}
300 }
301 }
302
303 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
304 public void testRoundInfiniteToBigIntegerAlwaysFails() {
305 for (RoundingMode mode : ALL_ROUNDING_MODES) {
306 try {
307 DoubleMath.roundToBigInteger(Double.POSITIVE_INFINITY, mode);
308 fail("Expected ArithmeticException");
309 } catch (ArithmeticException expected) {}
310 try {
311 DoubleMath.roundToBigInteger(Double.NEGATIVE_INFINITY, mode);
312 fail("Expected ArithmeticException");
313 } catch (ArithmeticException expected) {}
314 }
315 }
316
317 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)")
318 public void testRoundLog2Floor() {
319 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
320 int log2 = DoubleMath.log2(d, FLOOR);
321 assertTrue(StrictMath.pow(2.0, log2) <= d);
322 assertTrue(StrictMath.pow(2.0, log2 + 1) > d);
323 }
324 }
325
326 @GwtIncompatible("DoubleMath.log2(double, RoundingMode), StrictMath")
327 public void testRoundLog2Ceiling() {
328 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
329 int log2 = DoubleMath.log2(d, CEILING);
330 assertTrue(StrictMath.pow(2.0, log2) >= d);
331 double z = StrictMath.pow(2.0, log2 - 1);
332 assertTrue(z < d);
333 }
334 }
335
336 @GwtIncompatible("DoubleMath.log2(double, RoundingMode), StrictMath")
337 public void testRoundLog2Down() {
338 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
339 int log2 = DoubleMath.log2(d, DOWN);
340 if (d >= 1.0) {
341 assertTrue(log2 >= 0);
342 assertTrue(StrictMath.pow(2.0, log2) <= d);
343 assertTrue(StrictMath.pow(2.0, log2 + 1) > d);
344 } else {
345 assertTrue(log2 <= 0);
346 assertTrue(StrictMath.pow(2.0, log2) >= d);
347 assertTrue(StrictMath.pow(2.0, log2 - 1) < d);
348 }
349 }
350 }
351
352 @GwtIncompatible("DoubleMath.log2(double, RoundingMode), StrictMath")
353 public void testRoundLog2Up() {
354 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
355 int log2 = DoubleMath.log2(d, UP);
356 if (d >= 1.0) {
357 assertTrue(log2 >= 0);
358 assertTrue(StrictMath.pow(2.0, log2) >= d);
359 assertTrue(StrictMath.pow(2.0, log2 - 1) < d);
360 } else {
361 assertTrue(log2 <= 0);
362 assertTrue(StrictMath.pow(2.0, log2) <= d);
363 assertTrue(StrictMath.pow(2.0, log2 + 1) > d);
364 }
365 }
366 }
367
368 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)")
369 public void testRoundLog2Half() {
370
371 for (int exp : asList(-1022, -50, -1, 0, 1, 2, 3, 4, 100, 1022, 1023)) {
372 for (RoundingMode mode : asList(HALF_EVEN, HALF_UP, HALF_DOWN)) {
373 double x = Math.scalb(Math.sqrt(2) + 0.001, exp);
374 double y = Math.scalb(Math.sqrt(2) - 0.001, exp);
375 if (exp < 0) {
376 assertEquals(exp + 1, DoubleMath.log2(x, mode));
377 assertEquals(exp, DoubleMath.log2(y, mode));
378 } else {
379 assertEquals(exp + 1, DoubleMath.log2(x, mode));
380 assertEquals(exp, DoubleMath.log2(y, mode));
381 }
382 }
383 }
384 }
385
386 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)")
387 public void testRoundLog2Exact() {
388 for (double x : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
389 boolean isPowerOfTwo = StrictMath.pow(2.0, DoubleMath.log2(x, FLOOR)) == x;
390 try {
391 int log2 = DoubleMath.log2(x, UNNECESSARY);
392 assertEquals(x, Math.scalb(1.0, log2));
393 assertTrue(isPowerOfTwo);
394 } catch (ArithmeticException e) {
395 assertFalse(isPowerOfTwo);
396 }
397 }
398 }
399
400 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)")
401 public void testRoundLog2ThrowsOnZerosInfinitiesAndNaN() {
402 for (RoundingMode mode : ALL_ROUNDING_MODES) {
403 for (double d :
404 asList(0.0, -0.0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) {
405 try {
406 DoubleMath.log2(d, mode);
407 fail("Expected IllegalArgumentException");
408 } catch (IllegalArgumentException expected) {}
409 }
410 }
411 }
412
413 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)")
414 public void testRoundLog2ThrowsOnNegative() {
415 for (RoundingMode mode : ALL_ROUNDING_MODES) {
416 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
417 try {
418 DoubleMath.log2(-d, mode);
419 fail("Expected IllegalArgumentException");
420 } catch (IllegalArgumentException expected) {}
421 }
422 }
423 }
424
425 @GwtIncompatible("DoubleMath.isPowerOfTwo, DoubleMath.log2(double, RoundingMode), StrictMath")
426 public void testIsPowerOfTwoYes() {
427 for (int i = -1074; i <= 1023; i++) {
428 assertTrue(DoubleMath.isPowerOfTwo(StrictMath.pow(2.0, i)));
429 }
430 }
431
432 @GwtIncompatible("DoubleMath.isPowerOfTwo, DoubleMath.log2(double, RoundingMode), StrictMath")
433 public void testIsPowerOfTwo() {
434 for (double x : ALL_DOUBLE_CANDIDATES) {
435 boolean expected = x > 0 && !Double.isInfinite(x) && !Double.isNaN(x)
436 && StrictMath.pow(2.0, DoubleMath.log2(x, FLOOR)) == x;
437 assertEquals(expected, DoubleMath.isPowerOfTwo(x));
438 }
439 }
440
441 @GwtIncompatible("#trueLog2, Math.ulp")
442 public void testLog2Accuracy() {
443 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
444 double dmLog2 = DoubleMath.log2(d);
445 double trueLog2 = trueLog2(d);
446 assertTrue(Math.abs(dmLog2 - trueLog2) <= Math.ulp(trueLog2));
447 }
448 }
449
450 public void testLog2SemiMonotonic() {
451 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
452 assertTrue(DoubleMath.log2(d + 0.01) >= DoubleMath.log2(d));
453 }
454 }
455
456 public void testLog2Negative() {
457 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) {
458 assertTrue(Double.isNaN(DoubleMath.log2(-d)));
459 }
460 }
461
462 public void testLog2Zero() {
463 assertEquals(Double.NEGATIVE_INFINITY, DoubleMath.log2(0.0));
464 assertEquals(Double.NEGATIVE_INFINITY, DoubleMath.log2(-0.0));
465 }
466
467 public void testLog2NaNInfinity() {
468 assertEquals(Double.POSITIVE_INFINITY, DoubleMath.log2(Double.POSITIVE_INFINITY));
469 assertTrue(Double.isNaN(DoubleMath.log2(Double.NEGATIVE_INFINITY)));
470 assertTrue(Double.isNaN(DoubleMath.log2(Double.NaN)));
471 }
472
473 @GwtIncompatible("StrictMath")
474 private strictfp double trueLog2(double d) {
475 double trueLog2 = StrictMath.log(d) / StrictMath.log(2);
476
477 while (StrictMath.pow(2.0, trueLog2) < d) {
478 trueLog2 = StrictMath.nextUp(trueLog2);
479 }
480
481 while (StrictMath.pow(2.0, trueLog2) > d) {
482 trueLog2 = StrictMath.nextAfter(trueLog2, Double.NEGATIVE_INFINITY);
483 }
484 if (StrictMath.abs(StrictMath.pow(2.0, trueLog2) - d)
485 > StrictMath.abs(StrictMath.pow(2.0, StrictMath.nextUp(trueLog2)) - d)) {
486 trueLog2 = StrictMath.nextUp(trueLog2);
487 }
488 return trueLog2;
489 }
490
491 @GwtIncompatible("DoubleMath.isMathematicalInteger")
492 public void testIsMathematicalIntegerIntegral() {
493 for (double d : INTEGRAL_DOUBLE_CANDIDATES) {
494 assertTrue(DoubleMath.isMathematicalInteger(d));
495 }
496 }
497
498 @GwtIncompatible("DoubleMath.isMathematicalInteger")
499 public void testIsMathematicalIntegerFractional() {
500 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) {
501 assertFalse(DoubleMath.isMathematicalInteger(d));
502 }
503 }
504
505 @GwtIncompatible("DoubleMath.isMathematicalInteger")
506 public void testIsMathematicalIntegerNotFinite() {
507 for (double d :
508 Arrays.asList(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) {
509 assertFalse(DoubleMath.isMathematicalInteger(d));
510 }
511 }
512
513 @GwtIncompatible("Math.ulp")
514 public void testFactorial() {
515 for (int i = 0; i <= DoubleMath.MAX_FACTORIAL; i++) {
516 double actual = BigIntegerMath.factorial(i).doubleValue();
517 double result = DoubleMath.factorial(i);
518 assertEquals(actual, result, Math.ulp(actual));
519 }
520 }
521
522 public void testFactorialTooHigh() {
523 assertEquals(Double.POSITIVE_INFINITY, DoubleMath.factorial(DoubleMath.MAX_FACTORIAL + 1));
524 assertEquals(Double.POSITIVE_INFINITY, DoubleMath.factorial(DoubleMath.MAX_FACTORIAL + 20));
525 }
526
527 public void testFactorialNegative() {
528 for (int n : NEGATIVE_INTEGER_CANDIDATES) {
529 try {
530 DoubleMath.factorial(n);
531 fail("Expected IllegalArgumentException");
532 } catch (IllegalArgumentException expected) {}
533 }
534 }
535
536 private static final ImmutableList<Double> FINITE_TOLERANCE_CANDIDATES =
537 ImmutableList.of(-0.0, 0.0, 1.0, 100.0, 10000.0, Double.MAX_VALUE);
538
539 private static final Iterable<Double> TOLERANCE_CANDIDATES =
540 Iterables.concat(FINITE_TOLERANCE_CANDIDATES, ImmutableList.of(Double.POSITIVE_INFINITY));
541
542 private static final List<Double> BAD_TOLERANCE_CANDIDATES =
543 Doubles.asList(-Double.MIN_VALUE, -Double.MIN_NORMAL, -1, -20, Double.NaN,
544 Double.NEGATIVE_INFINITY, -0.001);
545
546 public void testFuzzyEqualsFinite() {
547 for (double a : FINITE_DOUBLE_CANDIDATES) {
548 for (double b : FINITE_DOUBLE_CANDIDATES) {
549 for (double tolerance : FINITE_TOLERANCE_CANDIDATES) {
550 assertEquals(
551 Math.abs(a - b) <= tolerance,
552 DoubleMath.fuzzyEquals(a, b, tolerance));
553 }
554 }
555 }
556 }
557
558 public void testFuzzyInfiniteVersusFiniteWithFiniteTolerance() {
559 for (double inf : INFINITIES) {
560 for (double a : FINITE_DOUBLE_CANDIDATES) {
561 for (double tolerance : FINITE_TOLERANCE_CANDIDATES) {
562 assertFalse(DoubleMath.fuzzyEquals(a, inf, tolerance));
563 assertFalse(DoubleMath.fuzzyEquals(inf, a, tolerance));
564 }
565 }
566 }
567 }
568
569 public void testFuzzyInfiniteVersusInfiniteWithFiniteTolerance() {
570 for (double inf : INFINITIES) {
571 for (double tolerance : FINITE_TOLERANCE_CANDIDATES) {
572 assertTrue(DoubleMath.fuzzyEquals(inf, inf, tolerance));
573 assertFalse(DoubleMath.fuzzyEquals(inf, -inf, tolerance));
574 }
575 }
576 }
577
578 public void testFuzzyEqualsInfiniteTolerance() {
579 for (double a : DOUBLE_CANDIDATES_EXCEPT_NAN) {
580 for (double b : DOUBLE_CANDIDATES_EXCEPT_NAN) {
581 assertTrue(DoubleMath.fuzzyEquals(a, b, Double.POSITIVE_INFINITY));
582 }
583 }
584 }
585
586 public void testFuzzyEqualsOneNaN() {
587 for (double a : DOUBLE_CANDIDATES_EXCEPT_NAN) {
588 for (double tolerance : TOLERANCE_CANDIDATES) {
589 assertFalse(DoubleMath.fuzzyEquals(a, Double.NaN, tolerance));
590 assertFalse(DoubleMath.fuzzyEquals(Double.NaN, a, tolerance));
591 }
592 }
593 }
594
595 public void testFuzzyEqualsTwoNaNs() {
596 for (double tolerance : TOLERANCE_CANDIDATES) {
597 assertTrue(DoubleMath.fuzzyEquals(Double.NaN, Double.NaN, tolerance));
598 }
599 }
600
601 public void testFuzzyEqualsZeroTolerance() {
602
603 for (double zero : Doubles.asList(0.0, -0.0)) {
604 for (double a : ALL_DOUBLE_CANDIDATES) {
605 for (double b : ALL_DOUBLE_CANDIDATES) {
606 assertEquals(a == b || (Double.isNaN(a) && Double.isNaN(b)),
607 DoubleMath.fuzzyEquals(a, b, zero));
608 }
609 }
610 }
611 }
612
613 public void testFuzzyEqualsBadTolerance() {
614 for (double tolerance : BAD_TOLERANCE_CANDIDATES) {
615 try {
616 DoubleMath.fuzzyEquals(1, 2, tolerance);
617 fail("Expected IllegalArgumentException");
618 } catch (IllegalArgumentException expected) {
619
620 }
621 }
622 }
623
624 public void testFuzzyCompare() {
625 for (double a : ALL_DOUBLE_CANDIDATES) {
626 for (double b : ALL_DOUBLE_CANDIDATES) {
627 for (double tolerance : TOLERANCE_CANDIDATES) {
628 int expected = DoubleMath.fuzzyEquals(a, b, tolerance) ? 0 : Double.compare(a, b);
629 int actual = DoubleMath.fuzzyCompare(a, b, tolerance);
630 assertEquals(Integer.signum(expected), Integer.signum(actual));
631 }
632 }
633 }
634 }
635
636 public void testFuzzyCompareBadTolerance() {
637 for (double tolerance : BAD_TOLERANCE_CANDIDATES) {
638 try {
639 DoubleMath.fuzzyCompare(1, 2, tolerance);
640 fail("Expected IllegalArgumentException");
641 } catch (IllegalArgumentException expected) {
642
643 }
644 }
645 }
646
647 @GwtIncompatible("DoubleMath.mean")
648 public void testMean_doubleVarargs() {
649 assertEquals(-1.375, DoubleMath.mean(1.1, -2.2, 4.4, -8.8), 1.0e-10);
650 assertEquals(1.1, DoubleMath.mean(1.1), 1.0e-10);
651 try {
652 DoubleMath.mean(Double.NaN);
653 fail("Expected IllegalArgumentException");
654 } catch (IllegalArgumentException expected) {
655 }
656 try {
657 DoubleMath.mean(Double.POSITIVE_INFINITY);
658 fail("Expected IllegalArgumentException");
659 } catch (IllegalArgumentException expected) {
660 }
661 }
662
663 @GwtIncompatible("DoubleMath.mean")
664 public void testMean_intVarargs() {
665 assertEquals(-13.75, DoubleMath.mean(11, -22, 44, -88), 1.0e-10);
666 assertEquals(11.0, DoubleMath.mean(11), 1.0e-10);
667 }
668
669 @GwtIncompatible("DoubleMath.mean")
670 public void testMean_longVarargs() {
671 assertEquals(-13.75, DoubleMath.mean(11L, -22L, 44L, -88L), 1.0e-10);
672 assertEquals(11.0, DoubleMath.mean(11L), 1.0e-10);
673 }
674
675 @GwtIncompatible("DoubleMath.mean")
676 public void testMean_emptyVarargs() {
677 try {
678 DoubleMath.mean();
679 fail("Expected IllegalArgumentException");
680 } catch (IllegalArgumentException expected) {
681 }
682 }
683
684 @GwtIncompatible("DoubleMath.mean")
685 public void testMean_doubleIterable() {
686 assertEquals(-1.375, DoubleMath.mean(ImmutableList.of(1.1, -2.2, 4.4, -8.8)), 1.0e-10);
687 assertEquals(1.1, DoubleMath.mean(ImmutableList.of(1.1)), 1.0e-10);
688 try {
689 DoubleMath.mean(ImmutableList.<Double>of());
690 fail("Expected IllegalArgumentException");
691 } catch (IllegalArgumentException expected) {
692 }
693 try {
694 DoubleMath.mean(ImmutableList.of(Double.NaN));
695 fail("Expected IllegalArgumentException");
696 } catch (IllegalArgumentException expected) {
697 }
698 try {
699 DoubleMath.mean(ImmutableList.of(Double.POSITIVE_INFINITY));
700 fail("Expected IllegalArgumentException");
701 } catch (IllegalArgumentException expected) {
702 }
703 }
704
705 @GwtIncompatible("DoubleMath.mean")
706 public void testMean_intIterable() {
707 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11, -22, 44, -88)), 1.0e-10);
708 assertEquals(11, DoubleMath.mean(ImmutableList.of(11)), 1.0e-10);
709 try {
710 DoubleMath.mean(ImmutableList.<Integer>of());
711 fail("Expected IllegalArgumentException");
712 } catch (IllegalArgumentException expected) {
713 }
714 }
715
716 @GwtIncompatible("DoubleMath.mean")
717 public void testMean_longIterable() {
718 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11L, -22L, 44L, -88L)), 1.0e-10);
719 assertEquals(11, DoubleMath.mean(ImmutableList.of(11L)), 1.0e-10);
720 try {
721 DoubleMath.mean(ImmutableList.<Long>of());
722 fail("Expected IllegalArgumentException");
723 } catch (IllegalArgumentException expected) {
724 }
725 }
726
727 @GwtIncompatible("DoubleMath.mean")
728 public void testMean_intIterator() {
729 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11, -22, 44, -88).iterator()), 1.0e-10);
730 assertEquals(11, DoubleMath.mean(ImmutableList.of(11).iterator()), 1.0e-10);
731 try {
732 DoubleMath.mean(ImmutableList.<Integer>of().iterator());
733 fail("Expected IllegalArgumentException");
734 } catch (IllegalArgumentException expected) {
735 }
736 }
737
738 @GwtIncompatible("DoubleMath.mean")
739 public void testMean_longIterator() {
740 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11L, -22L, 44L, -88L).iterator()),
741 1.0e-10);
742 assertEquals(11, DoubleMath.mean(ImmutableList.of(11L).iterator()), 1.0e-10);
743 try {
744 DoubleMath.mean(ImmutableList.<Long>of().iterator());
745 fail("Expected IllegalArgumentException");
746 } catch (IllegalArgumentException expected) {
747 }
748 }
749
750 @GwtIncompatible("NullPointerTester")
751 public void testNullPointers() {
752 NullPointerTester tester = new NullPointerTester();
753 tester.setDefault(double.class, 3.0);
754 tester.testAllPublicStaticMethods(DoubleMath.class);
755 }
756 }