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_LONG_CANDIDATES; 20 import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES; 21 import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES; 22 import static com.google.common.math.MathTesting.EXPONENTS; 23 import static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES; 24 import static com.google.common.math.MathTesting.NEGATIVE_LONG_CANDIDATES; 25 import static com.google.common.math.MathTesting.NONZERO_LONG_CANDIDATES; 26 import static com.google.common.math.MathTesting.POSITIVE_INTEGER_CANDIDATES; 27 import static com.google.common.math.MathTesting.POSITIVE_LONG_CANDIDATES; 28 import static com.google.common.truth.Truth.assertThat; 29 import static com.google.common.truth.Truth.assertWithMessage; 30 import static java.math.BigInteger.valueOf; 31 import static java.math.RoundingMode.FLOOR; 32 import static java.math.RoundingMode.UNNECESSARY; 33 34 import com.google.common.annotations.GwtCompatible; 35 import com.google.common.annotations.GwtIncompatible; 36 import com.google.common.annotations.J2ktIncompatible; 37 import com.google.common.testing.NullPointerTester; 38 import java.math.BigDecimal; 39 import java.math.BigInteger; 40 import java.math.RoundingMode; 41 import java.util.EnumSet; 42 import java.util.Random; 43 import junit.framework.TestCase; 44 45 /** 46 * Tests for LongMath. 47 * 48 * @author Louis Wasserman 49 */ 50 @GwtCompatible(emulated = true) 51 public class LongMathTest extends TestCase { 52 @SuppressWarnings("ConstantOverflow") testMaxSignedPowerOfTwo()53 public void testMaxSignedPowerOfTwo() { 54 assertTrue(LongMath.isPowerOfTwo(LongMath.MAX_SIGNED_POWER_OF_TWO)); 55 assertFalse(LongMath.isPowerOfTwo(LongMath.MAX_SIGNED_POWER_OF_TWO * 2)); 56 } 57 testCeilingPowerOfTwo()58 public void testCeilingPowerOfTwo() { 59 for (long x : POSITIVE_LONG_CANDIDATES) { 60 BigInteger expectedResult = BigIntegerMath.ceilingPowerOfTwo(BigInteger.valueOf(x)); 61 if (fitsInLong(expectedResult)) { 62 assertEquals(expectedResult.longValue(), LongMath.ceilingPowerOfTwo(x)); 63 } else { 64 try { 65 LongMath.ceilingPowerOfTwo(x); 66 fail("Expected ArithmeticException"); 67 } catch (ArithmeticException expected) { 68 } 69 } 70 } 71 } 72 testFloorPowerOfTwo()73 public void testFloorPowerOfTwo() { 74 for (long x : POSITIVE_LONG_CANDIDATES) { 75 BigInteger expectedResult = BigIntegerMath.floorPowerOfTwo(BigInteger.valueOf(x)); 76 assertEquals(expectedResult.longValue(), LongMath.floorPowerOfTwo(x)); 77 } 78 } 79 testCeilingPowerOfTwoNegative()80 public void testCeilingPowerOfTwoNegative() { 81 for (long x : NEGATIVE_LONG_CANDIDATES) { 82 try { 83 LongMath.ceilingPowerOfTwo(x); 84 fail("Expected IllegalArgumentException"); 85 } catch (IllegalArgumentException expected) { 86 } 87 } 88 } 89 testFloorPowerOfTwoNegative()90 public void testFloorPowerOfTwoNegative() { 91 for (long x : NEGATIVE_LONG_CANDIDATES) { 92 try { 93 LongMath.floorPowerOfTwo(x); 94 fail("Expected IllegalArgumentException"); 95 } catch (IllegalArgumentException expected) { 96 } 97 } 98 } 99 testCeilingPowerOfTwoZero()100 public void testCeilingPowerOfTwoZero() { 101 try { 102 LongMath.ceilingPowerOfTwo(0L); 103 fail("Expected IllegalArgumentException"); 104 } catch (IllegalArgumentException expected) { 105 } 106 } 107 testFloorPowerOfTwoZero()108 public void testFloorPowerOfTwoZero() { 109 try { 110 LongMath.floorPowerOfTwo(0L); 111 fail("Expected IllegalArgumentException"); 112 } catch (IllegalArgumentException expected) { 113 } 114 } 115 116 @GwtIncompatible // TODO testConstantMaxPowerOfSqrt2Unsigned()117 public void testConstantMaxPowerOfSqrt2Unsigned() { 118 assertEquals( 119 /*expected=*/ BigIntegerMath.sqrt(BigInteger.ZERO.setBit(2 * Long.SIZE - 1), FLOOR) 120 .longValue(), 121 /*actual=*/ LongMath.MAX_POWER_OF_SQRT2_UNSIGNED); 122 } 123 124 @GwtIncompatible // BigIntegerMath // TODO(cpovirk): GWT-enable BigIntegerMath testMaxLog10ForLeadingZeros()125 public void testMaxLog10ForLeadingZeros() { 126 for (int i = 0; i < Long.SIZE; i++) { 127 assertEquals( 128 BigIntegerMath.log10(BigInteger.ONE.shiftLeft(Long.SIZE - i), FLOOR), 129 LongMath.maxLog10ForLeadingZeros[i]); 130 } 131 } 132 133 @GwtIncompatible // TODO testConstantsPowersOf10()134 public void testConstantsPowersOf10() { 135 for (int i = 0; i < LongMath.powersOf10.length; i++) { 136 assertEquals(LongMath.checkedPow(10, i), LongMath.powersOf10[i]); 137 } 138 try { 139 LongMath.checkedPow(10, LongMath.powersOf10.length); 140 fail("Expected ArithmeticException"); 141 } catch (ArithmeticException expected) { 142 } 143 } 144 145 @GwtIncompatible // TODO testConstantsHalfPowersOf10()146 public void testConstantsHalfPowersOf10() { 147 for (int i = 0; i < LongMath.halfPowersOf10.length; i++) { 148 assertEquals( 149 BigIntegerMath.sqrt(BigInteger.TEN.pow(2 * i + 1), FLOOR), 150 BigInteger.valueOf(LongMath.halfPowersOf10[i])); 151 } 152 BigInteger nextBigger = 153 BigIntegerMath.sqrt(BigInteger.TEN.pow(2 * LongMath.halfPowersOf10.length + 1), FLOOR); 154 assertTrue(nextBigger.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0); 155 } 156 157 @GwtIncompatible // TODO testConstantsSqrtMaxLong()158 public void testConstantsSqrtMaxLong() { 159 assertEquals( 160 /*expected=*/ LongMath.sqrt(Long.MAX_VALUE, FLOOR), 161 /*actual=*/ LongMath.FLOOR_SQRT_MAX_LONG); 162 } 163 164 @GwtIncompatible // TODO testConstantsFactorials()165 public void testConstantsFactorials() { 166 long expected = 1; 167 for (int i = 0; i < LongMath.factorials.length; i++, expected *= i) { 168 assertEquals(expected, LongMath.factorials[i]); 169 } 170 try { 171 LongMath.checkedMultiply( 172 LongMath.factorials[LongMath.factorials.length - 1], LongMath.factorials.length); 173 fail("Expected ArithmeticException"); 174 } catch (ArithmeticException expect) { 175 } 176 } 177 178 @GwtIncompatible // TODO testConstantsBiggestBinomials()179 public void testConstantsBiggestBinomials() { 180 for (int k = 0; k < LongMath.biggestBinomials.length; k++) { 181 assertTrue(fitsInLong(BigIntegerMath.binomial(LongMath.biggestBinomials[k], k))); 182 assertTrue( 183 LongMath.biggestBinomials[k] == Integer.MAX_VALUE 184 || !fitsInLong(BigIntegerMath.binomial(LongMath.biggestBinomials[k] + 1, k))); 185 // In the first case, any long is valid; in the second, we want to test that the next-bigger 186 // long overflows. 187 } 188 int k = LongMath.biggestBinomials.length; 189 assertFalse(fitsInLong(BigIntegerMath.binomial(2 * k, k))); 190 // 2 * k is the smallest value for which we don't replace k with (n-k). 191 } 192 193 @GwtIncompatible // TODO testConstantsBiggestSimpleBinomials()194 public void testConstantsBiggestSimpleBinomials() { 195 for (int k = 0; k < LongMath.biggestSimpleBinomials.length; k++) { 196 assertTrue(LongMath.biggestSimpleBinomials[k] <= LongMath.biggestBinomials[k]); 197 long unused = simpleBinomial(LongMath.biggestSimpleBinomials[k], k); // mustn't throw 198 if (LongMath.biggestSimpleBinomials[k] < Integer.MAX_VALUE) { 199 // unless all n are fair game with this k 200 try { 201 simpleBinomial(LongMath.biggestSimpleBinomials[k] + 1, k); 202 fail("Expected ArithmeticException"); 203 } catch (ArithmeticException expected) { 204 } 205 } 206 } 207 try { 208 int k = LongMath.biggestSimpleBinomials.length; 209 simpleBinomial(2 * k, k); 210 // 2 * k is the smallest value for which we don't replace k with (n-k). 211 fail("Expected ArithmeticException"); 212 } catch (ArithmeticException expected) { 213 } 214 } 215 216 @AndroidIncompatible // slow testLessThanBranchFree()217 public void testLessThanBranchFree() { 218 for (long x : ALL_LONG_CANDIDATES) { 219 for (long y : ALL_LONG_CANDIDATES) { 220 BigInteger difference = BigInteger.valueOf(x).subtract(BigInteger.valueOf(y)); 221 if (fitsInLong(difference)) { 222 int expected = (x < y) ? 1 : 0; 223 int actual = LongMath.lessThanBranchFree(x, y); 224 assertEquals(expected, actual); 225 } 226 } 227 } 228 } 229 230 // Throws an ArithmeticException if "the simple implementation" of binomial coefficients overflows 231 @GwtIncompatible // TODO simpleBinomial(int n, int k)232 private long simpleBinomial(int n, int k) { 233 long accum = 1; 234 for (int i = 0; i < k; i++) { 235 accum = LongMath.checkedMultiply(accum, n - i); 236 accum /= i + 1; 237 } 238 return accum; 239 } 240 241 @GwtIncompatible // java.math.BigInteger testIsPowerOfTwo()242 public void testIsPowerOfTwo() { 243 for (long x : ALL_LONG_CANDIDATES) { 244 // Checks for a single bit set. 245 BigInteger bigX = BigInteger.valueOf(x); 246 boolean expected = (bigX.signum() > 0) && (bigX.bitCount() == 1); 247 assertEquals(expected, LongMath.isPowerOfTwo(x)); 248 } 249 } 250 testLog2ZeroAlwaysThrows()251 public void testLog2ZeroAlwaysThrows() { 252 for (RoundingMode mode : ALL_ROUNDING_MODES) { 253 try { 254 LongMath.log2(0L, mode); 255 fail("Expected IllegalArgumentException"); 256 } catch (IllegalArgumentException expected) { 257 } 258 } 259 } 260 testLog2NegativeAlwaysThrows()261 public void testLog2NegativeAlwaysThrows() { 262 for (long x : NEGATIVE_LONG_CANDIDATES) { 263 for (RoundingMode mode : ALL_ROUNDING_MODES) { 264 try { 265 LongMath.log2(x, mode); 266 fail("Expected IllegalArgumentException"); 267 } catch (IllegalArgumentException expected) { 268 } 269 } 270 } 271 } 272 273 /* Relies on the correctness of BigIntegerMath.log2 for all modes except UNNECESSARY. */ testLog2MatchesBigInteger()274 public void testLog2MatchesBigInteger() { 275 for (long x : POSITIVE_LONG_CANDIDATES) { 276 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 277 // The BigInteger implementation is tested separately, use it as the reference. 278 assertEquals(BigIntegerMath.log2(valueOf(x), mode), LongMath.log2(x, mode)); 279 } 280 } 281 } 282 283 /* Relies on the correctness of isPowerOfTwo(long). */ testLog2Exact()284 public void testLog2Exact() { 285 for (long x : POSITIVE_LONG_CANDIDATES) { 286 // We only expect an exception if x was not a power of 2. 287 boolean isPowerOf2 = LongMath.isPowerOfTwo(x); 288 try { 289 assertEquals(x, 1L << LongMath.log2(x, UNNECESSARY)); 290 assertTrue(isPowerOf2); 291 } catch (ArithmeticException e) { 292 assertFalse(isPowerOf2); 293 } 294 } 295 } 296 297 @GwtIncompatible // TODO testLog10ZeroAlwaysThrows()298 public void testLog10ZeroAlwaysThrows() { 299 for (RoundingMode mode : ALL_ROUNDING_MODES) { 300 try { 301 LongMath.log10(0L, mode); 302 fail("Expected IllegalArgumentException"); 303 } catch (IllegalArgumentException expected) { 304 } 305 } 306 } 307 308 @GwtIncompatible // TODO testLog10NegativeAlwaysThrows()309 public void testLog10NegativeAlwaysThrows() { 310 for (long x : NEGATIVE_LONG_CANDIDATES) { 311 for (RoundingMode mode : ALL_ROUNDING_MODES) { 312 try { 313 LongMath.log10(x, mode); 314 fail("Expected IllegalArgumentException"); 315 } catch (IllegalArgumentException expected) { 316 } 317 } 318 } 319 } 320 321 // Relies on the correctness of BigIntegerMath.log10 for all modes except UNNECESSARY. 322 @GwtIncompatible // TODO testLog10MatchesBigInteger()323 public void testLog10MatchesBigInteger() { 324 for (long x : POSITIVE_LONG_CANDIDATES) { 325 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 326 assertEquals(BigIntegerMath.log10(valueOf(x), mode), LongMath.log10(x, mode)); 327 } 328 } 329 } 330 331 // Relies on the correctness of log10(long, FLOOR) and of pow(long, int). 332 @GwtIncompatible // TODO testLog10Exact()333 public void testLog10Exact() { 334 for (long x : POSITIVE_LONG_CANDIDATES) { 335 int floor = LongMath.log10(x, FLOOR); 336 boolean expectedSuccess = LongMath.pow(10, floor) == x; 337 try { 338 assertEquals(floor, LongMath.log10(x, UNNECESSARY)); 339 assertTrue(expectedSuccess); 340 } catch (ArithmeticException e) { 341 if (expectedSuccess) { 342 failFormat("expected log10(%s, UNNECESSARY) = %s; got ArithmeticException", x, floor); 343 } 344 } 345 } 346 } 347 348 @GwtIncompatible // TODO testLog10TrivialOnPowerOf10()349 public void testLog10TrivialOnPowerOf10() { 350 long x = 1000000000000L; 351 for (RoundingMode mode : ALL_ROUNDING_MODES) { 352 assertEquals(12, LongMath.log10(x, mode)); 353 } 354 } 355 356 @GwtIncompatible // TODO testSqrtNegativeAlwaysThrows()357 public void testSqrtNegativeAlwaysThrows() { 358 for (long x : NEGATIVE_LONG_CANDIDATES) { 359 for (RoundingMode mode : ALL_ROUNDING_MODES) { 360 try { 361 LongMath.sqrt(x, mode); 362 fail("Expected IllegalArgumentException"); 363 } catch (IllegalArgumentException expected) { 364 } 365 } 366 } 367 } 368 369 // Relies on the correctness of BigIntegerMath.sqrt for all modes except UNNECESSARY. 370 @GwtIncompatible // TODO testSqrtMatchesBigInteger()371 public void testSqrtMatchesBigInteger() { 372 for (long x : POSITIVE_LONG_CANDIDATES) { 373 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 374 // Promote the long value (rather than using longValue() on the expected value) to avoid 375 // any risk of truncation which could lead to a false positive. 376 assertEquals(BigIntegerMath.sqrt(valueOf(x), mode), valueOf(LongMath.sqrt(x, mode))); 377 } 378 } 379 } 380 381 /* Relies on the correctness of sqrt(long, FLOOR). */ 382 @GwtIncompatible // TODO testSqrtExactMatchesFloorOrThrows()383 public void testSqrtExactMatchesFloorOrThrows() { 384 for (long x : POSITIVE_LONG_CANDIDATES) { 385 long sqrtFloor = LongMath.sqrt(x, FLOOR); 386 // We only expect an exception if x was not a perfect square. 387 boolean isPerfectSquare = (sqrtFloor * sqrtFloor == x); 388 try { 389 assertEquals(sqrtFloor, LongMath.sqrt(x, UNNECESSARY)); 390 assertTrue(isPerfectSquare); 391 } catch (ArithmeticException e) { 392 assertFalse(isPerfectSquare); 393 } 394 } 395 } 396 397 @GwtIncompatible // TODO testPow()398 public void testPow() { 399 for (long i : ALL_LONG_CANDIDATES) { 400 for (int exp : EXPONENTS) { 401 assertEquals(LongMath.pow(i, exp), valueOf(i).pow(exp).longValue()); 402 } 403 } 404 } 405 406 @J2ktIncompatible // J2kt BigDecimal.divide also has the rounding bug 407 @GwtIncompatible // TODO 408 @AndroidIncompatible // TODO(cpovirk): File BigDecimal.divide() rounding bug. testDivNonZero()409 public void testDivNonZero() { 410 for (long p : NONZERO_LONG_CANDIDATES) { 411 for (long q : NONZERO_LONG_CANDIDATES) { 412 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 413 long expected = 414 new BigDecimal(valueOf(p)).divide(new BigDecimal(valueOf(q)), 0, mode).longValue(); 415 long actual = LongMath.divide(p, q, mode); 416 if (expected != actual) { 417 failFormat("expected divide(%s, %s, %s) = %s; got %s", p, q, mode, expected, actual); 418 } 419 } 420 } 421 } 422 } 423 424 @GwtIncompatible // TODO 425 @AndroidIncompatible // Bug in older versions of Android we test against, since fixed. testDivNonZeroExact()426 public void testDivNonZeroExact() { 427 for (long p : NONZERO_LONG_CANDIDATES) { 428 for (long q : NONZERO_LONG_CANDIDATES) { 429 boolean expectedSuccess = (p % q) == 0L; 430 431 try { 432 assertEquals(p, LongMath.divide(p, q, UNNECESSARY) * q); 433 assertTrue(expectedSuccess); 434 } catch (ArithmeticException e) { 435 if (expectedSuccess) { 436 failFormat( 437 "expected divide(%s, %s, UNNECESSARY) to succeed; got ArithmeticException", p, q); 438 } 439 } 440 } 441 } 442 } 443 444 @GwtIncompatible // TODO testZeroDivIsAlwaysZero()445 public void testZeroDivIsAlwaysZero() { 446 for (long q : NONZERO_LONG_CANDIDATES) { 447 for (RoundingMode mode : ALL_ROUNDING_MODES) { 448 assertEquals(0L, LongMath.divide(0L, q, mode)); 449 } 450 } 451 } 452 453 @GwtIncompatible // TODO testDivByZeroAlwaysFails()454 public void testDivByZeroAlwaysFails() { 455 for (long p : ALL_LONG_CANDIDATES) { 456 for (RoundingMode mode : ALL_ROUNDING_MODES) { 457 try { 458 LongMath.divide(p, 0L, mode); 459 fail("Expected ArithmeticException"); 460 } catch (ArithmeticException expected) { 461 } 462 } 463 } 464 } 465 466 @GwtIncompatible // TODO testIntMod()467 public void testIntMod() { 468 for (long x : ALL_LONG_CANDIDATES) { 469 for (int m : POSITIVE_INTEGER_CANDIDATES) { 470 assertEquals(valueOf(x).mod(valueOf(m)).intValue(), LongMath.mod(x, m)); 471 } 472 } 473 } 474 475 @GwtIncompatible // TODO testIntModNegativeModulusFails()476 public void testIntModNegativeModulusFails() { 477 for (long x : ALL_LONG_CANDIDATES) { 478 for (int m : NEGATIVE_INTEGER_CANDIDATES) { 479 try { 480 LongMath.mod(x, m); 481 fail("Expected ArithmeticException"); 482 } catch (ArithmeticException expected) { 483 } 484 } 485 } 486 } 487 488 @GwtIncompatible // TODO testIntModZeroModulusFails()489 public void testIntModZeroModulusFails() { 490 for (long x : ALL_LONG_CANDIDATES) { 491 try { 492 LongMath.mod(x, 0); 493 fail("Expected AE"); 494 } catch (ArithmeticException expected) { 495 } 496 } 497 } 498 499 @AndroidIncompatible // slow 500 @GwtIncompatible // TODO testMod()501 public void testMod() { 502 for (long x : ALL_LONG_CANDIDATES) { 503 for (long m : POSITIVE_LONG_CANDIDATES) { 504 assertEquals(valueOf(x).mod(valueOf(m)).longValue(), LongMath.mod(x, m)); 505 } 506 } 507 } 508 509 @GwtIncompatible // TODO testModNegativeModulusFails()510 public void testModNegativeModulusFails() { 511 for (long x : ALL_LONG_CANDIDATES) { 512 for (long m : NEGATIVE_LONG_CANDIDATES) { 513 try { 514 LongMath.mod(x, m); 515 fail("Expected ArithmeticException"); 516 } catch (ArithmeticException expected) { 517 } 518 } 519 } 520 } 521 testGCDExhaustive()522 public void testGCDExhaustive() { 523 for (long a : POSITIVE_LONG_CANDIDATES) { 524 for (long b : POSITIVE_LONG_CANDIDATES) { 525 assertEquals(valueOf(a).gcd(valueOf(b)), valueOf(LongMath.gcd(a, b))); 526 } 527 } 528 } 529 530 @GwtIncompatible // TODO testGCDZero()531 public void testGCDZero() { 532 for (long a : POSITIVE_LONG_CANDIDATES) { 533 assertEquals(a, LongMath.gcd(a, 0)); 534 assertEquals(a, LongMath.gcd(0, a)); 535 } 536 assertEquals(0, LongMath.gcd(0, 0)); 537 } 538 539 @GwtIncompatible // TODO testGCDNegativePositiveThrows()540 public void testGCDNegativePositiveThrows() { 541 for (long a : NEGATIVE_LONG_CANDIDATES) { 542 try { 543 LongMath.gcd(a, 3); 544 fail("Expected IllegalArgumentException"); 545 } catch (IllegalArgumentException expected) { 546 } 547 try { 548 LongMath.gcd(3, a); 549 fail("Expected IllegalArgumentException"); 550 } catch (IllegalArgumentException expected) { 551 } 552 } 553 } 554 555 @GwtIncompatible // TODO testGCDNegativeZeroThrows()556 public void testGCDNegativeZeroThrows() { 557 for (long a : NEGATIVE_LONG_CANDIDATES) { 558 try { 559 LongMath.gcd(a, 0); 560 fail("Expected IllegalArgumentException"); 561 } catch (IllegalArgumentException expected) { 562 } 563 try { 564 LongMath.gcd(0, a); 565 fail("Expected IllegalArgumentException"); 566 } catch (IllegalArgumentException expected) { 567 } 568 } 569 } 570 571 @AndroidIncompatible // slow testCheckedAdd()572 public void testCheckedAdd() { 573 for (long a : ALL_LONG_CANDIDATES) { 574 for (long b : ALL_LONG_CANDIDATES) { 575 BigInteger expectedResult = valueOf(a).add(valueOf(b)); 576 boolean expectedSuccess = fitsInLong(expectedResult); 577 try { 578 assertEquals(a + b, LongMath.checkedAdd(a, b)); 579 assertTrue(expectedSuccess); 580 } catch (ArithmeticException e) { 581 if (expectedSuccess) { 582 failFormat( 583 "expected checkedAdd(%s, %s) = %s; got ArithmeticException", a, b, expectedResult); 584 } 585 } 586 } 587 } 588 } 589 590 @GwtIncompatible // TODO 591 @AndroidIncompatible // slow testCheckedSubtract()592 public void testCheckedSubtract() { 593 for (long a : ALL_LONG_CANDIDATES) { 594 for (long b : ALL_LONG_CANDIDATES) { 595 BigInteger expectedResult = valueOf(a).subtract(valueOf(b)); 596 boolean expectedSuccess = fitsInLong(expectedResult); 597 try { 598 assertEquals(a - b, LongMath.checkedSubtract(a, b)); 599 assertTrue(expectedSuccess); 600 } catch (ArithmeticException e) { 601 if (expectedSuccess) { 602 failFormat( 603 "expected checkedSubtract(%s, %s) = %s; got ArithmeticException", 604 a, b, expectedResult); 605 } 606 } 607 } 608 } 609 } 610 611 @AndroidIncompatible // slow testCheckedMultiply()612 public void testCheckedMultiply() { 613 boolean isAndroid = TestPlatform.isAndroid(); 614 for (long a : ALL_LONG_CANDIDATES) { 615 for (long b : ALL_LONG_CANDIDATES) { 616 if (isAndroid && a == -4294967296L && b == 2147483648L) { 617 /* 618 * Bug in older versions of Android we test against, since fixed: -9223372036854775808L / 619 * -4294967296L = -9223372036854775808L! 620 * 621 * To be clear, this bug affects not the test's computation of the expected result but the 622 * _actual prod code_. But it probably affects only unusual cases. 623 */ 624 continue; 625 } 626 BigInteger expectedResult = valueOf(a).multiply(valueOf(b)); 627 boolean expectedSuccess = fitsInLong(expectedResult); 628 try { 629 assertEquals(a * b, LongMath.checkedMultiply(a, b)); 630 assertTrue(expectedSuccess); 631 } catch (ArithmeticException e) { 632 if (expectedSuccess) { 633 failFormat( 634 "expected checkedMultiply(%s, %s) = %s; got ArithmeticException", 635 a, b, expectedResult); 636 } 637 } 638 } 639 } 640 } 641 642 @GwtIncompatible // TODO testCheckedPow()643 public void testCheckedPow() { 644 for (long b : ALL_LONG_CANDIDATES) { 645 for (int exp : EXPONENTS) { 646 BigInteger expectedResult = valueOf(b).pow(exp); 647 boolean expectedSuccess = fitsInLong(expectedResult); 648 try { 649 assertEquals(expectedResult.longValue(), LongMath.checkedPow(b, exp)); 650 assertTrue(expectedSuccess); 651 } catch (ArithmeticException e) { 652 if (expectedSuccess) { 653 failFormat( 654 "expected checkedPow(%s, %s) = %s; got ArithmeticException", 655 b, exp, expectedResult); 656 } 657 } 658 } 659 } 660 } 661 662 @AndroidIncompatible // slow 663 @GwtIncompatible // TODO testSaturatedAdd()664 public void testSaturatedAdd() { 665 for (long a : ALL_LONG_CANDIDATES) { 666 for (long b : ALL_LONG_CANDIDATES) { 667 assertOperationEquals( 668 a, b, "s+", saturatedCast(valueOf(a).add(valueOf(b))), LongMath.saturatedAdd(a, b)); 669 } 670 } 671 } 672 673 @AndroidIncompatible // slow 674 @GwtIncompatible // TODO testSaturatedSubtract()675 public void testSaturatedSubtract() { 676 for (long a : ALL_LONG_CANDIDATES) { 677 for (long b : ALL_LONG_CANDIDATES) { 678 assertOperationEquals( 679 a, 680 b, 681 "s-", 682 saturatedCast(valueOf(a).subtract(valueOf(b))), 683 LongMath.saturatedSubtract(a, b)); 684 } 685 } 686 } 687 688 @AndroidIncompatible // slow 689 @GwtIncompatible // TODO testSaturatedMultiply()690 public void testSaturatedMultiply() { 691 for (long a : ALL_LONG_CANDIDATES) { 692 for (long b : ALL_LONG_CANDIDATES) { 693 assertOperationEquals( 694 a, 695 b, 696 "s*", 697 saturatedCast(valueOf(a).multiply(valueOf(b))), 698 LongMath.saturatedMultiply(a, b)); 699 } 700 } 701 } 702 703 @GwtIncompatible // TODO testSaturatedPow()704 public void testSaturatedPow() { 705 for (long a : ALL_LONG_CANDIDATES) { 706 for (int b : EXPONENTS) { 707 assertOperationEquals( 708 a, b, "s^", saturatedCast(valueOf(a).pow(b)), LongMath.saturatedPow(a, b)); 709 } 710 } 711 } 712 assertOperationEquals(long a, long b, String op, long expected, long actual)713 private void assertOperationEquals(long a, long b, String op, long expected, long actual) { 714 if (expected != actual) { 715 fail("Expected for " + a + " " + op + " " + b + " = " + expected + ", but got " + actual); 716 } 717 } 718 719 // Depends on the correctness of BigIntegerMath.factorial. 720 @GwtIncompatible // TODO testFactorial()721 public void testFactorial() { 722 for (int n = 0; n <= 50; n++) { 723 BigInteger expectedBig = BigIntegerMath.factorial(n); 724 long expectedLong = fitsInLong(expectedBig) ? expectedBig.longValue() : Long.MAX_VALUE; 725 assertEquals(expectedLong, LongMath.factorial(n)); 726 } 727 } 728 729 @GwtIncompatible // TODO testFactorialNegative()730 public void testFactorialNegative() { 731 for (int n : NEGATIVE_INTEGER_CANDIDATES) { 732 try { 733 LongMath.factorial(n); 734 fail("Expected IllegalArgumentException"); 735 } catch (IllegalArgumentException expected) { 736 } 737 } 738 } 739 740 // Depends on the correctness of BigIntegerMath.binomial. testBinomial()741 public void testBinomial() { 742 for (int n = 0; n <= 70; n++) { 743 for (int k = 0; k <= n; k++) { 744 BigInteger expectedBig = BigIntegerMath.binomial(n, k); 745 long expectedLong = fitsInLong(expectedBig) ? expectedBig.longValue() : Long.MAX_VALUE; 746 assertEquals(expectedLong, LongMath.binomial(n, k)); 747 } 748 } 749 } 750 751 752 @GwtIncompatible // Slow testBinomial_exhaustiveNotOverflowing()753 public void testBinomial_exhaustiveNotOverflowing() { 754 // Tests all of the inputs to LongMath.binomial that won't cause it to overflow, that weren't 755 // tested in the previous method, for k >= 3. 756 for (int k = 3; k < LongMath.biggestBinomials.length; k++) { 757 for (int n = 70; n <= LongMath.biggestBinomials[k]; n++) { 758 assertEquals(BigIntegerMath.binomial(n, k).longValue(), LongMath.binomial(n, k)); 759 } 760 } 761 } 762 testBinomialOutside()763 public void testBinomialOutside() { 764 for (int n = 0; n <= 50; n++) { 765 try { 766 LongMath.binomial(n, -1); 767 fail("Expected IllegalArgumentException"); 768 } catch (IllegalArgumentException expected) { 769 } 770 try { 771 LongMath.binomial(n, n + 1); 772 fail("Expected IllegalArgumentException"); 773 } catch (IllegalArgumentException expected) { 774 } 775 } 776 } 777 testBinomialNegative()778 public void testBinomialNegative() { 779 for (int n : NEGATIVE_INTEGER_CANDIDATES) { 780 try { 781 LongMath.binomial(n, 0); 782 fail("Expected IllegalArgumentException"); 783 } catch (IllegalArgumentException expected) { 784 } 785 } 786 } 787 788 789 @J2ktIncompatible // slow enough to cause flakiness 790 @GwtIncompatible // far too slow testSqrtOfPerfectSquareAsDoubleIsPerfect()791 public void testSqrtOfPerfectSquareAsDoubleIsPerfect() { 792 // This takes just over a minute on my machine. 793 for (long n = 0; n <= LongMath.FLOOR_SQRT_MAX_LONG; n++) { 794 long actual = (long) Math.sqrt(n * n); 795 assertTrue(actual == n); 796 } 797 } 798 testSqrtOfLongIsAtMostFloorSqrtMaxLong()799 public void testSqrtOfLongIsAtMostFloorSqrtMaxLong() { 800 long sqrtMaxLong = (long) Math.sqrt(Long.MAX_VALUE); 801 assertTrue(sqrtMaxLong <= LongMath.FLOOR_SQRT_MAX_LONG); 802 } 803 804 @AndroidIncompatible // slow 805 @GwtIncompatible // java.math.BigInteger testMean()806 public void testMean() { 807 // Odd-sized ranges have an obvious mean 808 assertMean(2, 1, 3); 809 810 assertMean(-2, -3, -1); 811 assertMean(0, -1, 1); 812 assertMean(1, -1, 3); 813 assertMean((1L << 62) - 1, -1, Long.MAX_VALUE); 814 815 // Even-sized ranges should prefer the lower mean 816 assertMean(2, 1, 4); 817 assertMean(-3, -4, -1); 818 assertMean(0, -1, 2); 819 assertMean(0, Long.MIN_VALUE + 2, Long.MAX_VALUE); 820 assertMean(0, 0, 1); 821 assertMean(-1, -1, 0); 822 assertMean(-1, Long.MIN_VALUE, Long.MAX_VALUE); 823 824 // x == y == mean 825 assertMean(1, 1, 1); 826 assertMean(0, 0, 0); 827 assertMean(-1, -1, -1); 828 assertMean(Long.MIN_VALUE, Long.MIN_VALUE, Long.MIN_VALUE); 829 assertMean(Long.MAX_VALUE, Long.MAX_VALUE, Long.MAX_VALUE); 830 831 // Exhaustive checks 832 for (long x : ALL_LONG_CANDIDATES) { 833 for (long y : ALL_LONG_CANDIDATES) { 834 assertMean(x, y); 835 } 836 } 837 } 838 839 /** Helper method that asserts the arithmetic mean of x and y is equal to the expectedMean. */ assertMean(long expectedMean, long x, long y)840 private static void assertMean(long expectedMean, long x, long y) { 841 assertEquals( 842 "The expectedMean should be the same as computeMeanSafely", 843 expectedMean, 844 computeMeanSafely(x, y)); 845 assertMean(x, y); 846 } 847 848 /** 849 * Helper method that asserts the arithmetic mean of x and y is equal to the result of 850 * computeMeanSafely. 851 */ assertMean(long x, long y)852 private static void assertMean(long x, long y) { 853 long expectedMean = computeMeanSafely(x, y); 854 assertEquals(expectedMean, LongMath.mean(x, y)); 855 assertEquals( 856 "The mean of x and y should equal the mean of y and x", expectedMean, LongMath.mean(y, x)); 857 } 858 859 /** 860 * Computes the mean in a way that is obvious and resilient to overflow by using BigInteger 861 * arithmetic. 862 */ computeMeanSafely(long x, long y)863 private static long computeMeanSafely(long x, long y) { 864 BigInteger bigX = BigInteger.valueOf(x); 865 BigInteger bigY = BigInteger.valueOf(y); 866 BigDecimal bigMean = 867 new BigDecimal(bigX.add(bigY)).divide(BigDecimal.valueOf(2), BigDecimal.ROUND_FLOOR); 868 // parseInt blows up on overflow as opposed to intValue() which does not. 869 return Long.parseLong(bigMean.toString()); 870 } 871 fitsInLong(BigInteger big)872 private static boolean fitsInLong(BigInteger big) { 873 return big.bitLength() <= 63; 874 } 875 876 private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); 877 private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); 878 saturatedCast(BigInteger big)879 private static long saturatedCast(BigInteger big) { 880 if (big.compareTo(MAX_LONG) > 0) { 881 return Long.MAX_VALUE; 882 } 883 if (big.compareTo(MIN_LONG) < 0) { 884 return Long.MIN_VALUE; 885 } 886 return big.longValue(); 887 } 888 889 @J2ktIncompatible 890 @GwtIncompatible // NullPointerTester testNullPointers()891 public void testNullPointers() { 892 NullPointerTester tester = new NullPointerTester(); 893 tester.setDefault(int.class, 1); 894 tester.setDefault(long.class, 1L); 895 tester.testAllPublicStaticMethods(LongMath.class); 896 } 897 898 @GwtIncompatible // isPrime is GWT-incompatible testIsPrimeSmall()899 public void testIsPrimeSmall() { 900 // Check the first 1000 integers 901 for (int i = 2; i < 1000; i++) { 902 assertEquals(BigInteger.valueOf(i).isProbablePrime(100), LongMath.isPrime(i)); 903 } 904 } 905 906 @GwtIncompatible // isPrime is GWT-incompatible testIsPrimeManyConstants()907 public void testIsPrimeManyConstants() { 908 // Test the thorough test inputs, which also includes special constants in the Miller-Rabin 909 // tests. 910 for (long l : POSITIVE_LONG_CANDIDATES) { 911 assertEquals(BigInteger.valueOf(l).isProbablePrime(100), LongMath.isPrime(l)); 912 } 913 } 914 915 @GwtIncompatible // isPrime is GWT-incompatible testIsPrimeOnUniformRandom()916 public void testIsPrimeOnUniformRandom() { 917 Random rand = new Random(1); 918 for (int bits = 10; bits < 63; bits++) { 919 for (int i = 0; i < 2000; i++) { 920 // A random long between 0 and Long.MAX_VALUE, inclusive. 921 long l = rand.nextLong() & ((1L << bits) - 1); 922 assertEquals(BigInteger.valueOf(l).isProbablePrime(100), LongMath.isPrime(l)); 923 } 924 } 925 } 926 927 @GwtIncompatible // isPrime is GWT-incompatible testIsPrimeOnRandomPrimes()928 public void testIsPrimeOnRandomPrimes() { 929 Random rand = new Random(1); 930 for (int bits = 10; bits < 63; bits++) { 931 for (int i = 0; i < 100; i++) { 932 long p = BigInteger.probablePrime(bits, rand).longValue(); 933 assertTrue(LongMath.isPrime(p)); 934 } 935 } 936 } 937 938 @GwtIncompatible // isPrime is GWT-incompatible testIsPrimeOnRandomComposites()939 public void testIsPrimeOnRandomComposites() { 940 Random rand = new Random(1); 941 for (int bits = 5; bits < 32; bits++) { 942 for (int i = 0; i < 100; i++) { 943 long p = BigInteger.probablePrime(bits, rand).longValue(); 944 long q = BigInteger.probablePrime(bits, rand).longValue(); 945 assertFalse(LongMath.isPrime(p * q)); 946 } 947 } 948 } 949 950 @GwtIncompatible // isPrime is GWT-incompatible testIsPrimeThrowsOnNegative()951 public void testIsPrimeThrowsOnNegative() { 952 try { 953 LongMath.isPrime(-1); 954 fail("Expected IllegalArgumentException"); 955 } catch (IllegalArgumentException expected) { 956 } 957 } 958 959 private static final long[] roundToDoubleTestCandidates = { 960 0, 961 16, 962 1L << 53, 963 (1L << 53) + 1, 964 (1L << 53) + 2, 965 (1L << 53) + 3, 966 (1L << 53) + 4, 967 1L << 54, 968 (1L << 54) + 1, 969 (1L << 54) + 2, 970 (1L << 54) + 3, 971 (1L << 54) + 4, 972 0x7ffffffffffffe00L, // halfway between 2^63 and next-lower double 973 0x7ffffffffffffe01L, // above + 1 974 0x7ffffffffffffdffL, // above - 1 975 Long.MAX_VALUE - (1L << 11) + 1, 976 Long.MAX_VALUE - 2, 977 Long.MAX_VALUE - 1, 978 Long.MAX_VALUE, 979 -16, 980 -1L << 53, 981 -(1L << 53) - 1, 982 -(1L << 53) - 2, 983 -(1L << 53) - 3, 984 -(1L << 53) - 4, 985 -1L << 54, 986 -(1L << 54) - 1, 987 -(1L << 54) - 2, 988 -(1L << 54) - 3, 989 -(1L << 54) - 4, 990 Long.MIN_VALUE + 2, 991 Long.MIN_VALUE + 1, 992 Long.MIN_VALUE 993 }; 994 995 @J2ktIncompatible // EnumSet.complementOf 996 @GwtIncompatible testRoundToDoubleAgainstBigInteger()997 public void testRoundToDoubleAgainstBigInteger() { 998 for (RoundingMode roundingMode : EnumSet.complementOf(EnumSet.of(UNNECESSARY))) { 999 for (long candidate : roundToDoubleTestCandidates) { 1000 assertThat(LongMath.roundToDouble(candidate, roundingMode)) 1001 .isEqualTo(BigIntegerMath.roundToDouble(BigInteger.valueOf(candidate), roundingMode)); 1002 } 1003 } 1004 } 1005 1006 @GwtIncompatible testRoundToDoubleAgainstBigIntegerUnnecessary()1007 public void testRoundToDoubleAgainstBigIntegerUnnecessary() { 1008 for (long candidate : roundToDoubleTestCandidates) { 1009 Double expectedDouble = null; 1010 try { 1011 expectedDouble = BigIntegerMath.roundToDouble(BigInteger.valueOf(candidate), UNNECESSARY); 1012 } catch (ArithmeticException expected) { 1013 // do nothing 1014 } 1015 1016 if (expectedDouble != null) { 1017 assertThat(LongMath.roundToDouble(candidate, UNNECESSARY)).isEqualTo(expectedDouble); 1018 } else { 1019 try { 1020 LongMath.roundToDouble(candidate, UNNECESSARY); 1021 fail("Expected ArithmeticException on roundToDouble(" + candidate + ", UNNECESSARY)"); 1022 } catch (ArithmeticException expected) { 1023 // success 1024 } 1025 } 1026 } 1027 } 1028 failFormat(String template, Object... args)1029 private static void failFormat(String template, Object... args) { 1030 assertWithMessage(template, args).fail(); 1031 } 1032 } 1033