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") testConstantMaxPowerOfSqrt2Unsigned()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 testMaxLog10ForLeadingZeros()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") testConstantsPowersOf10()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") testConstantsHalfPowersOf10()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") testConstantsSqrtMaxLong()88 public void testConstantsSqrtMaxLong() { 89 assertEquals(LongMath.sqrt(Long.MAX_VALUE, FLOOR), LongMath.FLOOR_SQRT_MAX_LONG); 90 } 91 92 @GwtIncompatible("TODO") testConstantsFactorials()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") testConstantsBiggestBinomials()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") testConstantsBiggestSimpleBinomials()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 testLessThanBranchFree()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") simpleBinomial(int n, int k)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") testIsPowerOfTwo()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 testLog2ZeroAlwaysThrows()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 testLog2NegativeAlwaysThrows()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. */ testLog2MatchesBigInteger()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). */ testLog2Exact()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") testLog10ZeroAlwaysThrows()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") testLog10NegativeAlwaysThrows()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") testLog10MatchesBigInteger()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") testLog10Exact()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") testLog10TrivialOnPowerOf10()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") testSqrtNegativeAlwaysThrows()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") testSqrtMatchesBigInteger()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") testSqrtExactMatchesFloorOrThrows()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") testPow()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") testDivNonZero()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") testDivNonZeroExact()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") testZeroDivIsAlwaysZero()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") testDivByZeroAlwaysFails()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") testIntMod()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") testIntModNegativeModulusFails()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") testIntModZeroModulusFails()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") testMod()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") testModNegativeModulusFails()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 testGCDExhaustive()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") testGCDZero()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") testGCDNegativePositiveThrows()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") testGCDNegativeZeroThrows()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") testCheckedAdd()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") testCheckedSubtract()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") testCheckedMultiply()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") testCheckedPow()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") testFactorial()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") testFactorialNegative()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. testBinomial()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") testBinomial_exhaustiveNotOverflowing()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 testBinomialOutside()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 testBinomialNegative()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") testSqrtOfPerfectSquareAsDoubleIsPerfect()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 testSqrtOfLongIsAtMostFloorSqrtMaxLong()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") testMean()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 */ assertMean(long expectedMean, long x, long y)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 */ assertMean(long x, long y)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 */ computeMeanSafely(long x, long y)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 fitsInLong(BigInteger big)685 private static boolean fitsInLong(BigInteger big) { 686 return big.bitLength() <= 63; 687 } 688 689 @GwtIncompatible("NullPointerTester") testNullPointers()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