Home | History | Annotate | Download | only in math
      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 
     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  * Tests for {@code DoubleMath}.
     56  *
     57  * @author Louis Wasserman
     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       // every mode except UNNECESSARY
    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     // We don't expect perfect rounding accuracy.
    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     // increment until it's >= the true value
    477     while (StrictMath.pow(2.0, trueLog2) < d) {
    478       trueLog2 = StrictMath.nextUp(trueLog2);
    479     }
    480     // decrement until it's <= the true value
    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     // make sure we test -0 tolerance
    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         // success
    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         // success
    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 }
    757