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_INTEGER_CANDIDATES;
     20 import static com.google.common.math.MathTesting.ALL_LONG_CANDIDATES;
     21 import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
     22 import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
     23 import static com.google.common.math.MathTesting.EXPONENTS;
     24 import static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES;
     25 import static com.google.common.math.MathTesting.NEGATIVE_LONG_CANDIDATES;
     26 import static com.google.common.math.MathTesting.NONZERO_LONG_CANDIDATES;
     27 import static com.google.common.math.MathTesting.POSITIVE_INTEGER_CANDIDATES;
     28 import static com.google.common.math.MathTesting.POSITIVE_LONG_CANDIDATES;
     29 import static java.math.BigInteger.valueOf;
     30 import static java.math.RoundingMode.FLOOR;
     31 import static java.math.RoundingMode.UNNECESSARY;
     32 
     33 import com.google.common.annotations.GwtCompatible;
     34 import com.google.common.annotations.GwtIncompatible;
     35 import com.google.common.testing.NullPointerTester;
     36 
     37 import junit.framework.TestCase;
     38 
     39 import java.math.BigDecimal;
     40 import java.math.BigInteger;
     41 import java.math.RoundingMode;
     42 
     43 /**
     44  * Tests for LongMath.
     45  *
     46  * @author Louis Wasserman
     47  */
     48 @GwtCompatible(emulated = true)
     49 public class LongMathTest extends TestCase {
     50   @GwtIncompatible("TODO")
     51   public void testConstantMaxPowerOfSqrt2Unsigned() {
     52     assertEquals(BigIntegerMath.sqrt(BigInteger.ZERO.setBit(2 * Long.SIZE - 1), FLOOR).longValue(),
     53         LongMath.MAX_POWER_OF_SQRT2_UNSIGNED);
     54   }
     55 
     56   @GwtIncompatible("BigIntegerMath") // TODO(cpovirk): GWT-enable BigIntegerMath
     57   public void testMaxLog10ForLeadingZeros() {
     58     for (int i = 0; i < Long.SIZE; i++) {
     59       assertEquals(
     60           BigIntegerMath.log10(BigInteger.ONE.shiftLeft(Long.SIZE - i), FLOOR),
     61           LongMath.maxLog10ForLeadingZeros[i]);
     62     }
     63   }
     64 
     65   @GwtIncompatible("TODO")
     66   public void testConstantsPowersOf10() {
     67     for (int i = 0; i < LongMath.powersOf10.length; i++) {
     68       assertEquals(LongMath.checkedPow(10, i), LongMath.powersOf10[i]);
     69     }
     70     try {
     71       LongMath.checkedPow(10, LongMath.powersOf10.length);
     72       fail("Expected ArithmeticException");
     73     } catch (ArithmeticException expected) {}
     74   }
     75 
     76   @GwtIncompatible("TODO")
     77   public void testConstantsHalfPowersOf10() {
     78     for (int i = 0; i < LongMath.halfPowersOf10.length; i++) {
     79       assertEquals(BigIntegerMath.sqrt(BigInteger.TEN.pow(2 * i + 1), FLOOR),
     80           BigInteger.valueOf(LongMath.halfPowersOf10[i]));
     81     }
     82     BigInteger nextBigger =
     83         BigIntegerMath.sqrt(BigInteger.TEN.pow(2 * LongMath.halfPowersOf10.length + 1), FLOOR);
     84     assertTrue(nextBigger.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0);
     85   }
     86 
     87   @GwtIncompatible("TODO")
     88   public void testConstantsSqrtMaxLong() {
     89     assertEquals(LongMath.sqrt(Long.MAX_VALUE, FLOOR), LongMath.FLOOR_SQRT_MAX_LONG);
     90   }
     91 
     92   @GwtIncompatible("TODO")
     93   public void testConstantsFactorials() {
     94     long expected = 1;
     95     for (int i = 0; i < LongMath.factorials.length; i++, expected *= i) {
     96       assertEquals(expected, LongMath.factorials[i]);
     97     }
     98     try {
     99       LongMath.checkedMultiply(
    100           LongMath.factorials[LongMath.factorials.length - 1], LongMath.factorials.length);
    101       fail("Expected ArithmeticException");
    102     } catch (ArithmeticException expect) {}
    103   }
    104 
    105   @GwtIncompatible("TODO")
    106   public void testConstantsBiggestBinomials() {
    107     for (int k = 0; k < LongMath.biggestBinomials.length; k++) {
    108       assertTrue(fitsInLong(BigIntegerMath.binomial(LongMath.biggestBinomials[k], k)));
    109       assertTrue(LongMath.biggestBinomials[k] == Integer.MAX_VALUE
    110           || !fitsInLong(BigIntegerMath.binomial(LongMath.biggestBinomials[k] + 1, k)));
    111       // In the first case, any long is valid; in the second, we want to test that the next-bigger
    112       // long overflows.
    113     }
    114     int k = LongMath.biggestBinomials.length;
    115     assertFalse(fitsInLong(BigIntegerMath.binomial(2 * k, k)));
    116     // 2 * k is the smallest value for which we don't replace k with (n-k).
    117   }
    118 
    119   @GwtIncompatible("TODO")
    120   public void testConstantsBiggestSimpleBinomials() {
    121     for (int k = 0; k < LongMath.biggestSimpleBinomials.length; k++) {
    122       assertTrue(LongMath.biggestSimpleBinomials[k] <= LongMath.biggestBinomials[k]);
    123       simpleBinomial(LongMath.biggestSimpleBinomials[k], k); // mustn't throw
    124       if (LongMath.biggestSimpleBinomials[k] < Integer.MAX_VALUE) {
    125         // unless all n are fair game with this k
    126         try {
    127           simpleBinomial(LongMath.biggestSimpleBinomials[k] + 1, k);
    128           fail("Expected ArithmeticException");
    129         } catch (ArithmeticException expected) {}
    130       }
    131     }
    132     try {
    133       int k = LongMath.biggestSimpleBinomials.length;
    134       simpleBinomial(2 * k, k);
    135       // 2 * k is the smallest value for which we don't replace k with (n-k).
    136       fail("Expected ArithmeticException");
    137     } catch (ArithmeticException expected) {}
    138   }
    139 
    140   public void testLessThanBranchFree() {
    141     for (long x : ALL_LONG_CANDIDATES) {
    142       for (long y : ALL_LONG_CANDIDATES) {
    143         BigInteger difference = BigInteger.valueOf(x).subtract(BigInteger.valueOf(y));
    144         if (fitsInLong(difference)) {
    145           int expected = (x < y) ? 1 : 0;
    146           int actual = LongMath.lessThanBranchFree(x, y);
    147           assertEquals(expected, actual);
    148         }
    149       }
    150     }
    151   }
    152 
    153   // Throws an ArithmeticException if "the simple implementation" of binomial coefficients overflows
    154   @GwtIncompatible("TODO")
    155   private long simpleBinomial(int n, int k) {
    156     long accum = 1;
    157     for (int i = 0; i < k; i++) {
    158       accum = LongMath.checkedMultiply(accum, n - i);
    159       accum /= i + 1;
    160     }
    161     return accum;
    162   }
    163 
    164   @GwtIncompatible("java.math.BigInteger")
    165   public void testIsPowerOfTwo() {
    166     for (long x : ALL_LONG_CANDIDATES) {
    167       // Checks for a single bit set.
    168       BigInteger bigX = BigInteger.valueOf(x);
    169       boolean expected = (bigX.signum() > 0) && (bigX.bitCount() == 1);
    170       assertEquals(expected, LongMath.isPowerOfTwo(x));
    171     }
    172   }
    173 
    174   public void testLog2ZeroAlwaysThrows() {
    175     for (RoundingMode mode : ALL_ROUNDING_MODES) {
    176       try {
    177         LongMath.log2(0L, mode);
    178         fail("Expected IllegalArgumentException");
    179       } catch (IllegalArgumentException expected) {}
    180     }
    181   }
    182 
    183   public void testLog2NegativeAlwaysThrows() {
    184     for (long x : NEGATIVE_LONG_CANDIDATES) {
    185       for (RoundingMode mode : ALL_ROUNDING_MODES) {
    186         try {
    187           LongMath.log2(x, mode);
    188           fail("Expected IllegalArgumentException");
    189         } catch (IllegalArgumentException expected) {}
    190       }
    191     }
    192   }
    193 
    194   /* Relies on the correctness of BigIntegerMath.log2 for all modes except UNNECESSARY. */
    195   public void testLog2MatchesBigInteger() {
    196     for (long x : POSITIVE_LONG_CANDIDATES) {
    197       for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
    198         // The BigInteger implementation is tested separately, use it as the reference.
    199         assertEquals(BigIntegerMath.log2(valueOf(x), mode), LongMath.log2(x, mode));
    200       }
    201     }
    202   }
    203 
    204   /* Relies on the correctness of isPowerOfTwo(long). */
    205   public void testLog2Exact() {
    206     for (long x : POSITIVE_LONG_CANDIDATES) {
    207       // We only expect an exception if x was not a power of 2.
    208       boolean isPowerOf2 = LongMath.isPowerOfTwo(x);
    209       try {
    210         assertEquals(x, 1L << LongMath.log2(x, UNNECESSARY));
    211         assertTrue(isPowerOf2);
    212       } catch (ArithmeticException e) {
    213         assertFalse(isPowerOf2);
    214       }
    215     }
    216   }
    217 
    218   @GwtIncompatible("TODO")
    219   public void testLog10ZeroAlwaysThrows() {
    220     for (RoundingMode mode : ALL_ROUNDING_MODES) {
    221       try {
    222         LongMath.log10(0L, mode);
    223         fail("Expected IllegalArgumentException");
    224       } catch (IllegalArgumentException expected) {}
    225     }
    226   }
    227 
    228   @GwtIncompatible("TODO")
    229   public void testLog10NegativeAlwaysThrows() {
    230     for (long x : NEGATIVE_LONG_CANDIDATES) {
    231       for (RoundingMode mode : ALL_ROUNDING_MODES) {
    232         try {
    233           LongMath.log10(x, mode);
    234           fail("Expected IllegalArgumentException");
    235         } catch (IllegalArgumentException expected) {}
    236       }
    237     }
    238   }
    239 
    240   // Relies on the correctness of BigIntegerMath.log10 for all modes except UNNECESSARY.
    241   @GwtIncompatible("TODO")
    242   public void testLog10MatchesBigInteger() {
    243     for (long x : POSITIVE_LONG_CANDIDATES) {
    244       for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
    245         assertEquals(BigIntegerMath.log10(valueOf(x), mode), LongMath.log10(x, mode));
    246       }
    247     }
    248   }
    249 
    250   // Relies on the correctness of log10(long, FLOOR) and of pow(long, int).
    251   @GwtIncompatible("TODO")
    252   public void testLog10Exact() {
    253     for (long x : POSITIVE_LONG_CANDIDATES) {
    254       int floor = LongMath.log10(x, FLOOR);
    255       boolean expectSuccess = LongMath.pow(10, floor) == x;
    256       try {
    257         assertEquals(floor, LongMath.log10(x, UNNECESSARY));
    258         assertTrue(expectSuccess);
    259       } catch (ArithmeticException e) {
    260         assertFalse(expectSuccess);
    261       }
    262     }
    263   }
    264 
    265   @GwtIncompatible("TODO")
    266   public void testLog10TrivialOnPowerOf10() {
    267     long x = 1000000000000L;
    268     for (RoundingMode mode : ALL_ROUNDING_MODES) {
    269       assertEquals(12, LongMath.log10(x, mode));
    270     }
    271   }
    272 
    273   @GwtIncompatible("TODO")
    274   public void testSqrtNegativeAlwaysThrows() {
    275     for (long x : NEGATIVE_LONG_CANDIDATES) {
    276       for (RoundingMode mode : ALL_ROUNDING_MODES) {
    277         try {
    278           LongMath.sqrt(x, mode);
    279           fail("Expected IllegalArgumentException");
    280         } catch (IllegalArgumentException expected) {}
    281       }
    282     }
    283   }
    284 
    285   // Relies on the correctness of BigIntegerMath.sqrt for all modes except UNNECESSARY.
    286   @GwtIncompatible("TODO")
    287   public void testSqrtMatchesBigInteger() {
    288     for (long x : POSITIVE_LONG_CANDIDATES) {
    289       for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
    290         // Promote the long value (rather than using longValue() on the expected value) to avoid
    291         // any risk of truncation which could lead to a false positive.
    292         assertEquals(BigIntegerMath.sqrt(valueOf(x), mode), valueOf(LongMath.sqrt(x, mode)));
    293       }
    294     }
    295   }
    296 
    297   /* Relies on the correctness of sqrt(long, FLOOR). */
    298   @GwtIncompatible("TODO")
    299   public void testSqrtExactMatchesFloorOrThrows() {
    300     for (long x : POSITIVE_LONG_CANDIDATES) {
    301       long sqrtFloor = LongMath.sqrt(x, FLOOR);
    302       // We only expect an exception if x was not a perfect square.
    303       boolean isPerfectSquare = (sqrtFloor * sqrtFloor == x);
    304       try {
    305         assertEquals(sqrtFloor, LongMath.sqrt(x, UNNECESSARY));
    306         assertTrue(isPerfectSquare);
    307       } catch (ArithmeticException e) {
    308         assertFalse(isPerfectSquare);
    309       }
    310     }
    311   }
    312 
    313   @GwtIncompatible("TODO")
    314   public void testPow() {
    315     for (long i : ALL_LONG_CANDIDATES) {
    316       for (int exp : EXPONENTS) {
    317         assertEquals(LongMath.pow(i, exp), valueOf(i)
    318             .pow(exp)
    319             .longValue());
    320       }
    321     }
    322   }
    323 
    324   @GwtIncompatible("TODO")
    325   public void testDivNonZero() {
    326     for (long p : NONZERO_LONG_CANDIDATES) {
    327       for (long q : NONZERO_LONG_CANDIDATES) {
    328         for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
    329           long expected =
    330               new BigDecimal(valueOf(p)).divide(new BigDecimal(valueOf(q)), 0, mode).longValue();
    331           assertEquals(expected, LongMath.divide(p, q, mode));
    332         }
    333       }
    334     }
    335   }
    336 
    337   @GwtIncompatible("TODO")
    338   public void testDivNonZeroExact() {
    339     for (long p : NONZERO_LONG_CANDIDATES) {
    340       for (long q : NONZERO_LONG_CANDIDATES) {
    341         boolean dividesEvenly = (p % q) == 0L;
    342 
    343         try {
    344           assertEquals(p, LongMath.divide(p, q, UNNECESSARY) * q);
    345           assertTrue(dividesEvenly);
    346         } catch (ArithmeticException e) {
    347           assertFalse(dividesEvenly);
    348         }
    349       }
    350     }
    351   }
    352 
    353   @GwtIncompatible("TODO")
    354   public void testZeroDivIsAlwaysZero() {
    355     for (long q : NONZERO_LONG_CANDIDATES) {
    356       for (RoundingMode mode : ALL_ROUNDING_MODES) {
    357         assertEquals(0L, LongMath.divide(0L, q, mode));
    358       }
    359     }
    360   }
    361 
    362   @GwtIncompatible("TODO")
    363   public void testDivByZeroAlwaysFails() {
    364     for (long p : ALL_LONG_CANDIDATES) {
    365       for (RoundingMode mode : ALL_ROUNDING_MODES) {
    366         try {
    367           LongMath.divide(p, 0L, mode);
    368           fail("Expected ArithmeticException");
    369         } catch (ArithmeticException expected) {}
    370       }
    371     }
    372   }
    373 
    374   @GwtIncompatible("TODO")
    375   public void testIntMod() {
    376     for (long x : ALL_LONG_CANDIDATES) {
    377       for (int m : POSITIVE_INTEGER_CANDIDATES) {
    378         assertEquals(valueOf(x)
    379             .mod(valueOf(m))
    380             .intValue(), LongMath.mod(x, m));
    381       }
    382     }
    383   }
    384 
    385   @GwtIncompatible("TODO")
    386   public void testIntModNegativeModulusFails() {
    387     for (long x : ALL_LONG_CANDIDATES) {
    388       for (int m : NEGATIVE_INTEGER_CANDIDATES) {
    389         try {
    390           LongMath.mod(x, m);
    391           fail("Expected ArithmeticException");
    392         } catch (ArithmeticException expected) {}
    393       }
    394     }
    395   }
    396 
    397   @GwtIncompatible("TODO")
    398   public void testIntModZeroModulusFails() {
    399     for (long x : ALL_LONG_CANDIDATES) {
    400       try {
    401         LongMath.mod(x, 0);
    402         fail("Expected AE");
    403       } catch (ArithmeticException expected) {}
    404     }
    405   }
    406 
    407   @GwtIncompatible("TODO")
    408   public void testMod() {
    409     for (long x : ALL_LONG_CANDIDATES) {
    410       for (long m : POSITIVE_LONG_CANDIDATES) {
    411         assertEquals(valueOf(x)
    412             .mod(valueOf(m))
    413             .longValue(), LongMath.mod(x, m));
    414       }
    415     }
    416   }
    417 
    418   @GwtIncompatible("TODO")
    419   public void testModNegativeModulusFails() {
    420     for (long x : ALL_LONG_CANDIDATES) {
    421       for (long m : NEGATIVE_LONG_CANDIDATES) {
    422         try {
    423           LongMath.mod(x, m);
    424           fail("Expected ArithmeticException");
    425         } catch (ArithmeticException expected) {}
    426       }
    427     }
    428   }
    429 
    430   public void testGCDExhaustive() {
    431     for (long a : POSITIVE_LONG_CANDIDATES) {
    432       for (long b : POSITIVE_LONG_CANDIDATES) {
    433         assertEquals(valueOf(a).gcd(valueOf(b)), valueOf(LongMath.gcd(a, b)));
    434       }
    435     }
    436   }
    437 
    438   @GwtIncompatible("TODO")
    439   public void testGCDZero() {
    440     for (long a : POSITIVE_LONG_CANDIDATES) {
    441       assertEquals(a, LongMath.gcd(a, 0));
    442       assertEquals(a, LongMath.gcd(0, a));
    443     }
    444     assertEquals(0, LongMath.gcd(0, 0));
    445   }
    446 
    447   @GwtIncompatible("TODO")
    448   public void testGCDNegativePositiveThrows() {
    449     for (long a : NEGATIVE_LONG_CANDIDATES) {
    450       try {
    451         LongMath.gcd(a, 3);
    452         fail("Expected IllegalArgumentException");
    453       } catch (IllegalArgumentException expected) {}
    454       try {
    455         LongMath.gcd(3, a);
    456         fail("Expected IllegalArgumentException");
    457       } catch (IllegalArgumentException expected) {}
    458     }
    459   }
    460 
    461   @GwtIncompatible("TODO")
    462   public void testGCDNegativeZeroThrows() {
    463     for (long a : NEGATIVE_LONG_CANDIDATES) {
    464       try {
    465         LongMath.gcd(a, 0);
    466         fail("Expected IllegalArgumentException");
    467       } catch (IllegalArgumentException expected) {}
    468       try {
    469         LongMath.gcd(0, a);
    470         fail("Expected IllegalArgumentException");
    471       } catch (IllegalArgumentException expected) {}
    472     }
    473   }
    474 
    475   @GwtIncompatible("TODO")
    476   public void testCheckedAdd() {
    477     for (long a : ALL_INTEGER_CANDIDATES) {
    478       for (long b : ALL_INTEGER_CANDIDATES) {
    479         BigInteger expectedResult = valueOf(a).add(valueOf(b));
    480         boolean expectedSuccess = fitsInLong(expectedResult);
    481         try {
    482           assertEquals(a + b, LongMath.checkedAdd(a, b));
    483           assertTrue(expectedSuccess);
    484         } catch (ArithmeticException e) {
    485           assertFalse(expectedSuccess);
    486         }
    487       }
    488     }
    489   }
    490 
    491   @GwtIncompatible("TODO")
    492   public void testCheckedSubtract() {
    493     for (long a : ALL_INTEGER_CANDIDATES) {
    494       for (long b : ALL_INTEGER_CANDIDATES) {
    495         BigInteger expectedResult = valueOf(a).subtract(valueOf(b));
    496         boolean expectedSuccess = fitsInLong(expectedResult);
    497         try {
    498           assertEquals(a - b, LongMath.checkedSubtract(a, b));
    499           assertTrue(expectedSuccess);
    500         } catch (ArithmeticException e) {
    501           assertFalse(expectedSuccess);
    502         }
    503       }
    504     }
    505   }
    506 
    507   @GwtIncompatible("TODO")
    508   public void testCheckedMultiply() {
    509     for (long a : ALL_INTEGER_CANDIDATES) {
    510       for (long b : ALL_INTEGER_CANDIDATES) {
    511         BigInteger expectedResult = valueOf(a).multiply(valueOf(b));
    512         boolean expectedSuccess = fitsInLong(expectedResult);
    513         try {
    514           assertEquals(a * b, LongMath.checkedMultiply(a, b));
    515           assertTrue(expectedSuccess);
    516         } catch (ArithmeticException e) {
    517           assertFalse(expectedSuccess);
    518         }
    519       }
    520     }
    521   }
    522 
    523   @GwtIncompatible("TODO")
    524   public void testCheckedPow() {
    525     for (long b : ALL_INTEGER_CANDIDATES) {
    526       for (int exp : EXPONENTS) {
    527         BigInteger expectedResult = valueOf(b).pow(exp);
    528         boolean expectedSuccess = fitsInLong(expectedResult);
    529         try {
    530           assertEquals(expectedResult.longValue(), LongMath.checkedPow(b, exp));
    531           assertTrue(expectedSuccess);
    532         } catch (ArithmeticException e) {
    533           assertFalse(expectedSuccess);
    534         }
    535       }
    536     }
    537   }
    538 
    539   // Depends on the correctness of BigIntegerMath.factorial.
    540   @GwtIncompatible("TODO")
    541   public void testFactorial() {
    542     for (int n = 0; n <= 50; n++) {
    543       BigInteger expectedBig = BigIntegerMath.factorial(n);
    544       long expectedLong = fitsInLong(expectedBig) ? expectedBig.longValue() : Long.MAX_VALUE;
    545       assertEquals(expectedLong, LongMath.factorial(n));
    546     }
    547   }
    548 
    549   @GwtIncompatible("TODO")
    550   public void testFactorialNegative() {
    551     for (int n : NEGATIVE_INTEGER_CANDIDATES) {
    552       try {
    553         LongMath.factorial(n);
    554         fail("Expected IllegalArgumentException");
    555       } catch (IllegalArgumentException expected) {}
    556     }
    557   }
    558 
    559   // Depends on the correctness of BigIntegerMath.binomial.
    560   public void testBinomial() {
    561     for (int n = 0; n <= 70; n++) {
    562       for (int k = 0; k <= n; k++) {
    563         BigInteger expectedBig = BigIntegerMath.binomial(n, k);
    564         long expectedLong = fitsInLong(expectedBig) ? expectedBig.longValue() : Long.MAX_VALUE;
    565         assertEquals(expectedLong, LongMath.binomial(n, k));
    566       }
    567     }
    568   }
    569 
    570   @GwtIncompatible("Slow")
    571   public void testBinomial_exhaustiveNotOverflowing() {
    572     // Tests all of the inputs to LongMath.binomial that won't cause it to overflow, that weren't
    573     // tested in the previous method, for k >= 3.
    574     for (int k = 3; k < LongMath.biggestBinomials.length; k++) {
    575       for (int n = 70; n <= LongMath.biggestBinomials[k]; n++) {
    576         assertEquals(BigIntegerMath.binomial(n, k).longValue(), LongMath.binomial(n, k));
    577       }
    578     }
    579   }
    580 
    581   public void testBinomialOutside() {
    582     for (int n = 0; n <= 50; n++) {
    583       try {
    584         LongMath.binomial(n, -1);
    585         fail("Expected IllegalArgumentException");
    586       } catch (IllegalArgumentException expected) {}
    587       try {
    588         LongMath.binomial(n, n + 1);
    589         fail("Expected IllegalArgumentException");
    590       } catch (IllegalArgumentException expected) {}
    591     }
    592   }
    593 
    594   public void testBinomialNegative() {
    595     for (int n : NEGATIVE_INTEGER_CANDIDATES) {
    596       try {
    597         LongMath.binomial(n, 0);
    598         fail("Expected IllegalArgumentException");
    599       } catch (IllegalArgumentException expected) {}
    600     }
    601   }
    602 
    603   @GwtIncompatible("far too slow")
    604   public void testSqrtOfPerfectSquareAsDoubleIsPerfect() {
    605     // This takes just over a minute on my machine.
    606     for (long n = 0; n <= LongMath.FLOOR_SQRT_MAX_LONG; n++) {
    607       long actual = (long) Math.sqrt(n * n);
    608       assertTrue(actual == n);
    609     }
    610   }
    611 
    612   public void testSqrtOfLongIsAtMostFloorSqrtMaxLong() {
    613     long sqrtMaxLong = (long) Math.sqrt(Long.MAX_VALUE);
    614     assertTrue(sqrtMaxLong <= LongMath.FLOOR_SQRT_MAX_LONG);
    615   }
    616 
    617   @GwtIncompatible("java.math.BigInteger")
    618   public void testMean() {
    619     // Odd-sized ranges have an obvious mean
    620     assertMean(2, 1, 3);
    621 
    622     assertMean(-2, -3, -1);
    623     assertMean(0, -1, 1);
    624     assertMean(1, -1, 3);
    625     assertMean((1L << 62) - 1, -1, Long.MAX_VALUE);
    626 
    627     // Even-sized ranges should prefer the lower mean
    628     assertMean(2, 1, 4);
    629     assertMean(-3, -4, -1);
    630     assertMean(0, -1, 2);
    631     assertMean(0, Long.MIN_VALUE + 2, Long.MAX_VALUE);
    632     assertMean(0, 0, 1);
    633     assertMean(-1, -1, 0);
    634     assertMean(-1, Long.MIN_VALUE, Long.MAX_VALUE);
    635 
    636     // x == y == mean
    637     assertMean(1, 1, 1);
    638     assertMean(0, 0, 0);
    639     assertMean(-1, -1, -1);
    640     assertMean(Long.MIN_VALUE, Long.MIN_VALUE, Long.MIN_VALUE);
    641     assertMean(Long.MAX_VALUE, Long.MAX_VALUE, Long.MAX_VALUE);
    642 
    643     // Exhaustive checks
    644     for (long x : ALL_LONG_CANDIDATES) {
    645       for (long y : ALL_LONG_CANDIDATES) {
    646         assertMean(x, y);
    647       }
    648     }
    649   }
    650 
    651   /**
    652    * Helper method that asserts the arithmetic mean of x and y is equal
    653    * to the expectedMean.
    654    */
    655   private static void assertMean(long expectedMean, long x, long y) {
    656     assertEquals("The expectedMean should be the same as computeMeanSafely",
    657         expectedMean, computeMeanSafely(x, y));
    658     assertMean(x, y);
    659   }
    660 
    661   /**
    662    * Helper method that asserts the arithmetic mean of x and y is equal
    663    *to the result of computeMeanSafely.
    664    */
    665   private static void assertMean(long x, long y) {
    666     long expectedMean = computeMeanSafely(x, y);
    667     assertEquals(expectedMean, LongMath.mean(x, y));
    668     assertEquals("The mean of x and y should equal the mean of y and x",
    669         expectedMean, LongMath.mean(y, x));
    670   }
    671 
    672   /**
    673    * Computes the mean in a way that is obvious and resilient to
    674    * overflow by using BigInteger arithmetic.
    675    */
    676   private static long computeMeanSafely(long x, long y) {
    677     BigInteger bigX = BigInteger.valueOf(x);
    678     BigInteger bigY = BigInteger.valueOf(y);
    679     BigDecimal bigMean = new BigDecimal(bigX.add(bigY))
    680         .divide(BigDecimal.valueOf(2), BigDecimal.ROUND_FLOOR);
    681     // parseInt blows up on overflow as opposed to intValue() which does not.
    682     return Long.parseLong(bigMean.toString());
    683   }
    684 
    685   private static boolean fitsInLong(BigInteger big) {
    686     return big.bitLength() <= 63;
    687   }
    688 
    689   @GwtIncompatible("NullPointerTester")
    690   public void testNullPointers() {
    691     NullPointerTester tester = new NullPointerTester();
    692     tester.setDefault(int.class, 1);
    693     tester.setDefault(long.class, 1L);
    694     tester.testAllPublicStaticMethods(LongMath.class);
    695   }
    696 }
    697