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