10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/*
20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2011 The Guava Authors
30888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * you may not use this file except in compliance with the License.
60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * You may obtain a copy of the License at
70888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software
110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130888a09821a98ac0680fad765217302858e70fa4Paul Duffin * See the License for the specific language governing permissions and
140888a09821a98ac0680fad765217302858e70fa4Paul Duffin * limitations under the License.
150888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
160888a09821a98ac0680fad765217302858e70fa4Paul Duffin
170888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.math;
180888a09821a98ac0680fad765217302858e70fa4Paul Duffin
190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.ALL_INTEGER_CANDIDATES;
200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
210888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.EXPONENTS;
230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES;
240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.NONZERO_INTEGER_CANDIDATES;
250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.MathTesting.POSITIVE_INTEGER_CANDIDATES;
260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.math.TestPlatform.intsCanGoOutOfRange;
270888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.math.BigInteger.valueOf;
280888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.math.RoundingMode.UNNECESSARY;
290888a09821a98ac0680fad765217302858e70fa4Paul Duffin
300888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.GwtCompatible;
310888a09821a98ac0680fad765217302858e70fa4Paul Duffin
320888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase;
330888a09821a98ac0680fad765217302858e70fa4Paul Duffin
340888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.math.BigDecimal;
350888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.math.BigInteger;
360888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.math.RoundingMode;
370888a09821a98ac0680fad765217302858e70fa4Paul Duffin
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin/**
390888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Tests for {@link IntMath}.
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
410888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Louis Wasserman
420888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
430888a09821a98ac0680fad765217302858e70fa4Paul Duffin@GwtCompatible(emulated = true)
440888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic class IntMathTest extends TestCase {
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testLessThanBranchFree() {
470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : ALL_INTEGER_CANDIDATES) {
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int y : ALL_INTEGER_CANDIDATES) {
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (LongMath.fitsInInt((long) x - y)) {
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin          int expected = (x < y) ? 1 : 0;
510888a09821a98ac0680fad765217302858e70fa4Paul Duffin          int actual = IntMath.lessThanBranchFree(x, y);
520888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(expected, actual);
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testLog2ZeroAlwaysThrows() {
590888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (RoundingMode mode : ALL_ROUNDING_MODES) {
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.log2(0, mode);
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected IllegalArgumentException");
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (IllegalArgumentException expected) {}
640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
660888a09821a98ac0680fad765217302858e70fa4Paul Duffin
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testLog2NegativeAlwaysThrows() {
680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : NEGATIVE_INTEGER_CANDIDATES) {
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (RoundingMode mode : ALL_ROUNDING_MODES) {
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
710888a09821a98ac0680fad765217302858e70fa4Paul Duffin          IntMath.log2(x, mode);
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin          fail("Expected IllegalArgumentException");
730888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (IllegalArgumentException expected) {}
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin
780888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Relies on the correctness of BigIntegrerMath.log2 for all modes except UNNECESSARY.
790888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testLog2MatchesBigInteger() {
800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : POSITIVE_INTEGER_CANDIDATES) {
810888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertEquals(BigIntegerMath.log2(valueOf(x), mode), IntMath.log2(x, mode));
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
850888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin
870888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Relies on the correctness of isPowerOfTwo(int).
880888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testLog2Exact() {
890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : POSITIVE_INTEGER_CANDIDATES) {
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // We only expect an exception if x was not a power of 2.
910888a09821a98ac0680fad765217302858e70fa4Paul Duffin      boolean isPowerOf2 = IntMath.isPowerOfTwo(x);
920888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
930888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertEquals(x, 1 << IntMath.log2(x, UNNECESSARY));
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertTrue(isPowerOf2);
950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (ArithmeticException e) {
960888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertFalse(isPowerOf2);
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Relies on the correctness of BigIntegerMath.log10 for all modes except UNNECESSARY.
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Relies on the correctness of log10(int, FLOOR) and of pow(int, int).
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Simple test to cover sqrt(0) for all types and all modes.
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /* Relies on the correctness of BigIntegerMath.sqrt for all modes except UNNECESSARY. */
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /* Relies on the correctness of sqrt(int, FLOOR). */
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testDivNonZero() {
1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int p : NONZERO_INTEGER_CANDIDATES) {
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int q : NONZERO_INTEGER_CANDIDATES) {
1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin        for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin          // Skip some tests that fail due to GWT's non-compliant int implementation.
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin          // TODO(cpovirk): does this test fail for only some rounding modes or for all?
1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin          if (p == -2147483648 && q == -1 && intsCanGoOutOfRange()) {
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin            continue;
1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin          }
1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin          int expected =
1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin              new BigDecimal(valueOf(p)).divide(new BigDecimal(valueOf(q)), 0, mode).intValue();
1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(p + "/" + q, force32(expected), IntMath.divide(p, q, mode));
1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testDivNonZeroExact() {
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int p : NONZERO_INTEGER_CANDIDATES) {
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int q : NONZERO_INTEGER_CANDIDATES) {
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin        // Skip some tests that fail due to GWT's non-compliant int implementation.
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (p == -2147483648 && q == -1 && intsCanGoOutOfRange()) {
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin          continue;
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean dividesEvenly = (p % q) == 0;
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(p + "/" + q, p, IntMath.divide(p, q, UNNECESSARY) * q);
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertTrue(p + "/" + q + " not expected to divide evenly", dividesEvenly);
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException e) {
1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertFalse(p + "/" + q + " expected to divide evenly", dividesEvenly);
1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testZeroDivIsAlwaysZero() {
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int q : NONZERO_INTEGER_CANDIDATES) {
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (RoundingMode mode : ALL_ROUNDING_MODES) {
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertEquals(0, IntMath.divide(0, q, mode));
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testDivByZeroAlwaysFails() {
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int p : ALL_INTEGER_CANDIDATES) {
1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (RoundingMode mode : ALL_ROUNDING_MODES) {
1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin          IntMath.divide(p, 0, mode);
1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin          fail("Expected ArithmeticException");
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException expected) {}
1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testMod() {
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : ALL_INTEGER_CANDIDATES) {
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int m : POSITIVE_INTEGER_CANDIDATES) {
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertEquals(valueOf(x).mod(valueOf(m)).intValue(), IntMath.mod(x, m));
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testModNegativeModulusFails() {
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : POSITIVE_INTEGER_CANDIDATES) {
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int m : NEGATIVE_INTEGER_CANDIDATES) {
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin          IntMath.mod(x, m);
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin          fail("Expected ArithmeticException");
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException expected) {}
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testModZeroModulusFails() {
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int x : ALL_INTEGER_CANDIDATES) {
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.mod(x, 0);
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected ArithmeticException");
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (ArithmeticException expected) {}
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testGCD() {
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : POSITIVE_INTEGER_CANDIDATES) {
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int b : POSITIVE_INTEGER_CANDIDATES) {
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin        assertEquals(valueOf(a).gcd(valueOf(b)), valueOf(IntMath.gcd(a, b)));
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testGCDZero() {
2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : POSITIVE_INTEGER_CANDIDATES) {
2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertEquals(a, IntMath.gcd(a, 0));
2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertEquals(a, IntMath.gcd(0, a));
2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, IntMath.gcd(0, 0));
2070888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testGCDNegativePositiveThrows() {
2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : NEGATIVE_INTEGER_CANDIDATES) {
2110888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.gcd(a, 3);
2130888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected IllegalArgumentException");
2140888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (IllegalArgumentException expected) {}
2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.gcd(3, a);
2170888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected IllegalArgumentException");
2180888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (IllegalArgumentException expected) {}
2190888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2200888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2210888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2220888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testGCDNegativeZeroThrows() {
2230888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : NEGATIVE_INTEGER_CANDIDATES) {
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.gcd(a, 0);
2260888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected IllegalArgumentException");
2270888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (IllegalArgumentException expected) {}
2280888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.gcd(0, a);
2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected IllegalArgumentException");
2310888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (IllegalArgumentException expected) {}
2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2340888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2350888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testCheckedAdd() {
2360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : ALL_INTEGER_CANDIDATES) {
2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int b : ALL_INTEGER_CANDIDATES) {
2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BigInteger expectedResult = valueOf(a).add(valueOf(b));
2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean expectedSuccess = fitsInInt(expectedResult);
2400888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(a + b, IntMath.checkedAdd(a, b));
2420888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertTrue(expectedSuccess);
2430888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException e) {
2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertFalse(expectedSuccess);
2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
2460888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testCheckedSubtract() {
2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : ALL_INTEGER_CANDIDATES) {
2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int b : ALL_INTEGER_CANDIDATES) {
2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BigInteger expectedResult = valueOf(a).subtract(valueOf(b));
2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean expectedSuccess = fitsInInt(expectedResult);
2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(a - b, IntMath.checkedSubtract(a, b));
2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertTrue(expectedSuccess);
2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException e) {
2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertFalse(expectedSuccess);
2600888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testCheckedMultiply() {
2660888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int a : ALL_INTEGER_CANDIDATES) {
2670888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int b : ALL_INTEGER_CANDIDATES) {
2680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BigInteger expectedResult = valueOf(a).multiply(valueOf(b));
2690888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean expectedSuccess = fitsInInt(expectedResult);
2700888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(a * b, IntMath.checkedMultiply(a, b));
2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertTrue(expectedSuccess);
2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException e) {
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertFalse(expectedSuccess);
2750888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
2760888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2800888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testCheckedPow() {
2810888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int b : ALL_INTEGER_CANDIDATES) {
2820888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (int k : EXPONENTS) {
2830888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BigInteger expectedResult = valueOf(b).pow(k);
2840888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean expectedSuccess = fitsInInt(expectedResult);
2850888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
2860888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertEquals(b + "^" + k, force32(expectedResult.intValue()), IntMath.checkedPow(b, k));
2870888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertTrue(b + "^" + k + " should have succeeded", expectedSuccess);
2880888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (ArithmeticException e) {
2890888a09821a98ac0680fad765217302858e70fa4Paul Duffin          assertFalse(b + "^" + k + " should have failed", expectedSuccess);
2900888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2920888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2930888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2940888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2950888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Depends on the correctness of BigIntegerMath.factorial.
2960888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testFactorial() {
2970888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int n = 0; n <= 50; n++) {
2980888a09821a98ac0680fad765217302858e70fa4Paul Duffin      BigInteger expectedBig = BigIntegerMath.factorial(n);
2990888a09821a98ac0680fad765217302858e70fa4Paul Duffin      int expectedInt = fitsInInt(expectedBig) ? expectedBig.intValue() : Integer.MAX_VALUE;
3000888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertEquals(expectedInt, IntMath.factorial(n));
3010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3020888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3030888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3040888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testFactorialNegative() {
3050888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int n : NEGATIVE_INTEGER_CANDIDATES) {
3060888a09821a98ac0680fad765217302858e70fa4Paul Duffin      try {
3070888a09821a98ac0680fad765217302858e70fa4Paul Duffin        IntMath.factorial(n);
3080888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fail("Expected IllegalArgumentException");
3090888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } catch (IllegalArgumentException expected) {}
3100888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3110888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3120888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3130888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Depends on the correctness of BigIntegerMath.binomial.
3140888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3150888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
3160888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Helper method that asserts the arithmetic mean of x and y is equal
3170888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * to the expectedMean.
3180888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
3190888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertMean(int expectedMean, int x, int y) {
3200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals("The expectedMean should be the same as computeMeanSafely",
3210888a09821a98ac0680fad765217302858e70fa4Paul Duffin        expectedMean, computeMeanSafely(x, y));
3220888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertMean(x, y);
3230888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3240888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3250888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
3260888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Helper method that asserts the arithmetic mean of x and y is equal
3270888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * to the result of computeMeanSafely.
3280888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
3290888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertMean(int x, int y) {
3300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    int expectedMean = computeMeanSafely(x, y);
3310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(expectedMean, IntMath.mean(x, y));
3320888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals("The mean of x and y should equal the mean of y and x",
3330888a09821a98ac0680fad765217302858e70fa4Paul Duffin        expectedMean, IntMath.mean(y, x));
3340888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3350888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3360888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
3370888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Computes the mean in a way that is obvious and resilient to
3380888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * overflow by using BigInteger arithmetic.
3390888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
3400888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static int computeMeanSafely(int x, int y) {
3410888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BigInteger bigX = BigInteger.valueOf(x);
3420888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BigInteger bigY = BigInteger.valueOf(y);
3430888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BigDecimal bigMean = new BigDecimal(bigX.add(bigY))
3440888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .divide(BigDecimal.valueOf(2), BigDecimal.ROUND_FLOOR);
3450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // parseInt blows up on overflow as opposed to intValue() which does not.
3460888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Integer.parseInt(bigMean.toString());
3470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3480888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3490888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static boolean fitsInInt(BigInteger big) {
3500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return big.bitLength() <= 31;
3510888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3520888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static int force32(int value) {
3540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // GWT doesn't consistently overflow values to make them 32-bit, so we need to force it.
3550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return value & 0xffffffff;
3560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3570888a09821a98ac0680fad765217302858e70fa4Paul Duffin}
3580888a09821a98ac0680fad765217302858e70fa4Paul Duffin
359