1/*
2 * Copyright (C) 2011 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.math;
18
19import static com.google.common.math.MathTesting.ALL_INTEGER_CANDIDATES;
20import static com.google.common.math.MathTesting.ALL_LONG_CANDIDATES;
21import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
22import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
23import static com.google.common.math.MathTesting.EXPONENTS;
24import static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES;
25import static com.google.common.math.MathTesting.NEGATIVE_LONG_CANDIDATES;
26import static com.google.common.math.MathTesting.NONZERO_LONG_CANDIDATES;
27import static com.google.common.math.MathTesting.POSITIVE_INTEGER_CANDIDATES;
28import static com.google.common.math.MathTesting.POSITIVE_LONG_CANDIDATES;
29import static java.math.BigInteger.valueOf;
30import static java.math.RoundingMode.FLOOR;
31import static java.math.RoundingMode.UNNECESSARY;
32
33import com.google.common.annotations.GwtCompatible;
34import com.google.common.annotations.GwtIncompatible;
35import com.google.common.testing.NullPointerTester;
36
37import junit.framework.TestCase;
38
39import java.math.BigDecimal;
40import java.math.BigInteger;
41import java.math.RoundingMode;
42
43/**
44 * Tests for LongMath.
45 *
46 * @author Louis Wasserman
47 */
48@GwtCompatible(emulated = true)
49public 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