1 /* 2 * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @library /test/lib 27 * @run main BigIntegerTest 28 * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 29 * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) 30 * @run main/timeout=400 BigIntegerTest 31 * @author madbot 32 * @key randomness 33 */ 34 35 import java.io.File; 36 import java.io.FileInputStream; 37 import java.io.FileOutputStream; 38 import java.io.ObjectInputStream; 39 import java.io.ObjectOutputStream; 40 import java.math.BigDecimal; 41 import java.math.BigInteger; 42 import java.util.Random; 43 import java.util.function.ToIntFunction; 44 import java.util.stream.Collectors; 45 import java.util.stream.DoubleStream; 46 import java.util.stream.IntStream; 47 import java.util.stream.LongStream; 48 import java.util.stream.Stream; 49 import jdk.test.lib.RandomFactory; 50 51 /** 52 * This is a simple test class created to ensure that the results 53 * generated by BigInteger adhere to certain identities. Passing 54 * this test is a strong assurance that the BigInteger operations 55 * are working correctly. 56 * 57 * Four arguments may be specified which give the number of 58 * decimal digits you desire in the four batches of test numbers. 59 * 60 * The tests are performed on arrays of random numbers which are 61 * generated by a Random class as well as special cases which 62 * throw in boundary numbers such as 0, 1, maximum sized, etc. 63 * 64 */ 65 public class BigIntegerTest { 66 // 67 // Bit large number thresholds based on the int thresholds 68 // defined in BigInteger itself: 69 // 70 // KARATSUBA_THRESHOLD = 80 ints = 2560 bits 71 // TOOM_COOK_THRESHOLD = 240 ints = 7680 bits 72 // KARATSUBA_SQUARE_THRESHOLD = 128 ints = 4096 bits 73 // TOOM_COOK_SQUARE_THRESHOLD = 216 ints = 6912 bits 74 // 75 // SCHOENHAGE_BASE_CONVERSION_THRESHOLD = 20 ints = 640 bits 76 // 77 // BURNIKEL_ZIEGLER_THRESHOLD = 80 ints = 2560 bits 78 // 79 static final int BITS_KARATSUBA = 2560; 80 static final int BITS_TOOM_COOK = 7680; 81 static final int BITS_KARATSUBA_SQUARE = 4096; 82 static final int BITS_TOOM_COOK_SQUARE = 6912; 83 static final int BITS_SCHOENHAGE_BASE = 640; 84 static final int BITS_BURNIKEL_ZIEGLER = 2560; 85 static final int BITS_BURNIKEL_ZIEGLER_OFFSET = 1280; 86 87 static final int ORDER_SMALL = 60; 88 static final int ORDER_MEDIUM = 100; 89 // #bits for testing Karatsuba 90 static final int ORDER_KARATSUBA = 2760; 91 // #bits for testing Toom-Cook and Burnikel-Ziegler 92 static final int ORDER_TOOM_COOK = 8000; 93 // #bits for testing Karatsuba squaring 94 static final int ORDER_KARATSUBA_SQUARE = 4200; 95 // #bits for testing Toom-Cook squaring 96 static final int ORDER_TOOM_COOK_SQUARE = 7000; 97 98 static final int SIZE = 1000; // numbers per batch 99 100 private static Random random = RandomFactory.getRandom(); 101 102 static boolean failure = false; 103 104 public static void constructor() { 105 int failCount = 0; 106 107 // --- guard condition tests for array indexing --- 108 109 int arrayLength = 23; 110 int halfLength = arrayLength/2; 111 byte[] array = new byte[arrayLength]; 112 random.nextBytes(array); 113 114 int[][] offLen = new int[][] { // offset, length, num exceptions 115 {-1, arrayLength, 1}, // negative offset 116 {0, arrayLength, 0}, // OK 117 {1, arrayLength, 1}, // length overflow 118 {arrayLength - 1, 1, 0}, // OK 119 {arrayLength, 1, 1}, // offset overflow 120 {0, -1, 1}, // negative length 121 {halfLength, arrayLength - halfLength + 1, 1} // length overflow 122 }; 123 124 // two's complement 125 for (int[] ol : offLen) { 126 int numExceptions = 0; 127 try { 128 BigInteger bi = new BigInteger(array, ol[0], ol[1]); 129 } catch (IndexOutOfBoundsException e) { 130 numExceptions++; 131 } 132 if (numExceptions != ol[2]) { 133 System.err.println("IndexOutOfBoundsException did not occur for " 134 + " two's complement constructor with parameters offset " 135 + ol[0] + " and length " + ol[1]); 136 failCount++; 137 } 138 } 139 140 // sign-magnitude 141 for (int[] ol : offLen) { 142 int numExceptions = 0; 143 try { 144 BigInteger bi = new BigInteger(1, array, ol[0], ol[1]); 145 } catch (IndexOutOfBoundsException e) { 146 numExceptions++; 147 } 148 if (numExceptions != ol[2]) { 149 System.err.println("IndexOutOfBoundsException did not occur for " 150 + " sign-magnitude constructor with parameters offset " 151 + ol[0] + " and length " + ol[1]); 152 failCount++; 153 } 154 } 155 156 // --- tests for creation of zero-valued BigIntegers --- 157 158 byte[] magZeroLength = new byte[0]; 159 for (int signum = -1; signum <= 1; signum++) { 160 BigInteger bi = new BigInteger(signum, magZeroLength); 161 if (bi.compareTo(BigInteger.ZERO) != 0) { 162 System.err.println("A: Zero length BigInteger != 0 for signum " + signum); 163 failCount++; 164 } 165 } 166 167 for (int signum = -1; signum <= 1; signum++) { 168 BigInteger bi = new BigInteger(signum, magZeroLength, 0, 0); 169 if (bi.compareTo(BigInteger.ZERO) != 0) { 170 System.err.println("B: Zero length BigInteger != 0 for signum " + signum); 171 failCount++; 172 } 173 } 174 175 byte[] magNonZeroLength = new byte[42]; 176 random.nextBytes(magNonZeroLength); 177 for (int signum = -1; signum <= 1; signum++) { 178 BigInteger bi = new BigInteger(signum, magNonZeroLength, 0, 0); 179 if (bi.compareTo(BigInteger.ZERO) != 0) { 180 System.err.println("C: Zero length BigInteger != 0 for signum " + signum); 181 failCount++; 182 } 183 } 184 185 // --- tests for accurate creation of non-zero BigIntegers --- 186 187 for (int i = 0; i < SIZE; i++) { 188 // create reference value via a different code path from those tested 189 BigInteger reference = new BigInteger(2 + random.nextInt(336), 4, random); 190 191 byte[] refArray = reference.toByteArray(); 192 int refLen = refArray.length; 193 int factor = random.nextInt(5); 194 int objLen = refArray.length + factor*random.nextInt(refArray.length) + 1; 195 int offset = random.nextInt(objLen - refLen); 196 byte[] objArray = new byte[objLen]; 197 System.arraycopy(refArray, 0, objArray, offset, refLen); 198 199 BigInteger twosComp = new BigInteger(objArray, offset, refLen); 200 if (twosComp.compareTo(reference) != 0) { 201 System.err.println("Two's-complement BigInteger not equal for offset " + 202 offset + " and length " + refLen); 203 failCount++; 204 } 205 206 boolean isNegative = random.nextBoolean(); 207 BigInteger signMag = new BigInteger(isNegative ? -1 : 1, objArray, offset, refLen); 208 if (signMag.compareTo(isNegative ? reference.negate() : reference) != 0) { 209 System.err.println("Sign-magnitude BigInteger not equal for offset " + 210 offset + " and length " + refLen); 211 failCount++; 212 } 213 } 214 215 report("Constructor", failCount); 216 } 217 218 public static void pow(int order) { 219 int failCount1 = 0; 220 221 for (int i=0; i<SIZE; i++) { 222 // Test identity x^power == x*x*x ... *x 223 int power = random.nextInt(6) + 2; 224 BigInteger x = fetchNumber(order); 225 BigInteger y = x.pow(power); 226 BigInteger z = x; 227 228 for (int j=1; j<power; j++) 229 z = z.multiply(x); 230 231 if (!y.equals(z)) 232 failCount1++; 233 } 234 report("pow for " + order + " bits", failCount1); 235 } 236 237 public static void square(int order) { 238 int failCount1 = 0; 239 240 for (int i=0; i<SIZE; i++) { 241 // Test identity x^2 == x*x 242 BigInteger x = fetchNumber(order); 243 BigInteger xx = x.multiply(x); 244 BigInteger x2 = x.pow(2); 245 246 if (!x2.equals(xx)) 247 failCount1++; 248 } 249 report("square for " + order + " bits", failCount1); 250 } 251 252 private static void printErr(String msg) { 253 System.err.println(msg); 254 } 255 256 private static int checkResult(BigInteger expected, BigInteger actual, 257 String failureMessage) { 258 if (expected.compareTo(actual) != 0) { 259 printErr(failureMessage + " - expected: " + expected 260 + ", actual: " + actual); 261 return 1; 262 } 263 return 0; 264 } 265 266 private static void squareRootSmall() { 267 int failCount = 0; 268 269 // A negative value should cause an exception. 270 BigInteger n = BigInteger.ONE.negate(); 271 BigInteger s; 272 try { 273 s = n.sqrt(); 274 // If sqrt() does not throw an exception that is a failure. 275 failCount++; 276 printErr("sqrt() of negative number did not throw an exception"); 277 } catch (ArithmeticException expected) { 278 // A negative value should cause an exception and is not a failure. 279 } 280 281 // A zero value should return BigInteger.ZERO. 282 failCount += checkResult(BigInteger.ZERO, BigInteger.ZERO.sqrt(), 283 "sqrt(0) != BigInteger.ZERO"); 284 285 // 1 <= value < 4 should return BigInteger.ONE. 286 long[] smalls = new long[] {1, 2, 3}; 287 for (long small : smalls) { 288 failCount += checkResult(BigInteger.ONE, 289 BigInteger.valueOf(small).sqrt(), "sqrt("+small+") != 1"); 290 } 291 292 report("squareRootSmall", failCount); 293 } 294 295 public static void squareRoot() { 296 squareRootSmall(); 297 298 ToIntFunction<BigInteger> f = (n) -> { 299 int failCount = 0; 300 301 // square root of n^2 -> n 302 BigInteger n2 = n.pow(2); 303 failCount += checkResult(n, n2.sqrt(), "sqrt() n^2 -> n"); 304 305 // square root of n^2 + 1 -> n 306 BigInteger n2up = n2.add(BigInteger.ONE); 307 failCount += checkResult(n, n2up.sqrt(), "sqrt() n^2 + 1 -> n"); 308 309 // square root of (n + 1)^2 - 1 -> n 310 BigInteger up = 311 n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); 312 failCount += checkResult(n, up.sqrt(), "sqrt() (n + 1)^2 - 1 -> n"); 313 314 // sqrt(n)^2 <= n 315 BigInteger s = n.sqrt(); 316 if (s.multiply(s).compareTo(n) > 0) { 317 failCount++; 318 printErr("sqrt(n)^2 > n for n = " + n); 319 } 320 321 // (sqrt(n) + 1)^2 > n 322 if (s.add(BigInteger.ONE).pow(2).compareTo(n) <= 0) { 323 failCount++; 324 printErr("(sqrt(n) + 1)^2 <= n for n = " + n); 325 } 326 327 return failCount; 328 }; 329 330 Stream.Builder<BigInteger> sb = Stream.builder(); 331 int maxExponent = Double.MAX_EXPONENT + 1; 332 for (int i = 1; i <= maxExponent; i++) { 333 BigInteger p2 = BigInteger.ONE.shiftLeft(i); 334 sb.add(p2.subtract(BigInteger.ONE)); 335 sb.add(p2); 336 sb.add(p2.add(BigInteger.ONE)); 337 } 338 sb.add((new BigDecimal(Double.MAX_VALUE)).toBigInteger()); 339 sb.add((new BigDecimal(Double.MAX_VALUE)).toBigInteger().add(BigInteger.ONE)); 340 report("squareRoot for 2^N and 2^N - 1, 1 <= N <= Double.MAX_EXPONENT", 341 sb.build().collect(Collectors.summingInt(f))); 342 343 IntStream ints = random.ints(SIZE, 4, Integer.MAX_VALUE); 344 report("squareRoot for int", ints.mapToObj(x -> 345 BigInteger.valueOf(x)).collect(Collectors.summingInt(f))); 346 347 LongStream longs = random.longs(SIZE, (long)Integer.MAX_VALUE + 1L, 348 Long.MAX_VALUE); 349 report("squareRoot for long", longs.mapToObj(x -> 350 BigInteger.valueOf(x)).collect(Collectors.summingInt(f))); 351 352 DoubleStream doubles = random.doubles(SIZE, 353 (double) Long.MAX_VALUE + 1.0, Math.sqrt(Double.MAX_VALUE)); 354 report("squareRoot for double", doubles.mapToObj(x -> 355 BigDecimal.valueOf(x).toBigInteger()).collect(Collectors.summingInt(f))); 356 } 357 358 public static void squareRootAndRemainder() { 359 ToIntFunction<BigInteger> g = (n) -> { 360 int failCount = 0; 361 BigInteger n2 = n.pow(2); 362 363 // square root of n^2 -> n 364 BigInteger[] actual = n2.sqrtAndRemainder(); 365 failCount += checkResult(n, actual[0], "sqrtAndRemainder()[0]"); 366 failCount += checkResult(BigInteger.ZERO, actual[1], 367 "sqrtAndRemainder()[1]"); 368 369 // square root of n^2 + 1 -> n 370 BigInteger n2up = n2.add(BigInteger.ONE); 371 actual = n2up.sqrtAndRemainder(); 372 failCount += checkResult(n, actual[0], "sqrtAndRemainder()[0]"); 373 failCount += checkResult(BigInteger.ONE, actual[1], 374 "sqrtAndRemainder()[1]"); 375 376 // square root of (n + 1)^2 - 1 -> n 377 BigInteger up = 378 n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); 379 actual = up.sqrtAndRemainder(); 380 failCount += checkResult(n, actual[0], "sqrtAndRemainder()[0]"); 381 BigInteger r = up.subtract(n2); 382 failCount += checkResult(r, actual[1], "sqrtAndRemainder()[1]"); 383 384 return failCount; 385 }; 386 387 IntStream bits = random.ints(SIZE, 3, Short.MAX_VALUE); 388 report("sqrtAndRemainder", bits.mapToObj(x -> 389 BigInteger.valueOf(x)).collect(Collectors.summingInt(g))); 390 } 391 392 public static void arithmetic(int order) { 393 int failCount = 0; 394 395 for (int i=0; i<SIZE; i++) { 396 BigInteger x = fetchNumber(order); 397 while(x.compareTo(BigInteger.ZERO) != 1) 398 x = fetchNumber(order); 399 BigInteger y = fetchNumber(order/2); 400 while(x.compareTo(y) == -1) 401 y = fetchNumber(order/2); 402 if (y.equals(BigInteger.ZERO)) 403 y = y.add(BigInteger.ONE); 404 405 // Test identity ((x/y))*y + x%y - x == 0 406 // using separate divide() and remainder() 407 BigInteger baz = x.divide(y); 408 baz = baz.multiply(y); 409 baz = baz.add(x.remainder(y)); 410 baz = baz.subtract(x); 411 if (!baz.equals(BigInteger.ZERO)) 412 failCount++; 413 } 414 report("Arithmetic I for " + order + " bits", failCount); 415 416 failCount = 0; 417 for (int i=0; i<100; i++) { 418 BigInteger x = fetchNumber(order); 419 while(x.compareTo(BigInteger.ZERO) != 1) 420 x = fetchNumber(order); 421 BigInteger y = fetchNumber(order/2); 422 while(x.compareTo(y) == -1) 423 y = fetchNumber(order/2); 424 if (y.equals(BigInteger.ZERO)) 425 y = y.add(BigInteger.ONE); 426 427 // Test identity ((x/y))*y + x%y - x == 0 428 // using divideAndRemainder() 429 BigInteger baz[] = x.divideAndRemainder(y); 430 baz[0] = baz[0].multiply(y); 431 baz[0] = baz[0].add(baz[1]); 432 baz[0] = baz[0].subtract(x); 433 if (!baz[0].equals(BigInteger.ZERO)) 434 failCount++; 435 } 436 report("Arithmetic II for " + order + " bits", failCount); 437 } 438 439 /** 440 * Sanity test for Karatsuba and 3-way Toom-Cook multiplication. 441 * For each of the Karatsuba and 3-way Toom-Cook multiplication thresholds, 442 * construct two factors each with a mag array one element shorter than the 443 * threshold, and with the most significant bit set and the rest of the bits 444 * random. Each of these numbers will therefore be below the threshold but 445 * if shifted left be above the threshold. Call the numbers 'u' and 'v' and 446 * define random shifts 'a' and 'b' in the range [1,32]. Then we have the 447 * identity 448 * <pre> 449 * (u << a)*(v << b) = (u*v) << (a + b) 450 * </pre> 451 * For Karatsuba multiplication, the right hand expression will be evaluated 452 * using the standard naive algorithm, and the left hand expression using 453 * the Karatsuba algorithm. For 3-way Toom-Cook multiplication, the right 454 * hand expression will be evaluated using Karatsuba multiplication, and the 455 * left hand expression using 3-way Toom-Cook multiplication. 456 */ 457 public static void multiplyLarge() { 458 int failCount = 0; 459 460 BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA - 32 - 1); 461 for (int i=0; i<SIZE; i++) { 462 BigInteger x = fetchNumber(BITS_KARATSUBA - 32 - 1); 463 BigInteger u = base.add(x); 464 int a = 1 + random.nextInt(31); 465 BigInteger w = u.shiftLeft(a); 466 467 BigInteger y = fetchNumber(BITS_KARATSUBA - 32 - 1); 468 BigInteger v = base.add(y); 469 int b = 1 + random.nextInt(32); 470 BigInteger z = v.shiftLeft(b); 471 472 BigInteger multiplyResult = u.multiply(v).shiftLeft(a + b); 473 BigInteger karatsubaMultiplyResult = w.multiply(z); 474 475 if (!multiplyResult.equals(karatsubaMultiplyResult)) { 476 failCount++; 477 } 478 } 479 480 report("multiplyLarge Karatsuba", failCount); 481 482 failCount = 0; 483 base = base.shiftLeft(BITS_TOOM_COOK - BITS_KARATSUBA); 484 for (int i=0; i<SIZE; i++) { 485 BigInteger x = fetchNumber(BITS_TOOM_COOK - 32 - 1); 486 BigInteger u = base.add(x); 487 BigInteger u2 = u.shiftLeft(1); 488 BigInteger y = fetchNumber(BITS_TOOM_COOK - 32 - 1); 489 BigInteger v = base.add(y); 490 BigInteger v2 = v.shiftLeft(1); 491 492 BigInteger multiplyResult = u.multiply(v).shiftLeft(2); 493 BigInteger toomCookMultiplyResult = u2.multiply(v2); 494 495 if (!multiplyResult.equals(toomCookMultiplyResult)) { 496 failCount++; 497 } 498 } 499 500 report("multiplyLarge Toom-Cook", failCount); 501 } 502 503 /** 504 * Sanity test for Karatsuba and 3-way Toom-Cook squaring. 505 * This test is analogous to {@link AbstractMethodError#multiplyLarge} 506 * with both factors being equal. The squaring methods will not be tested 507 * unless the <code>bigInteger.multiply(bigInteger)</code> tests whether 508 * the parameter is the same instance on which the method is being invoked 509 * and calls <code>square()</code> accordingly. 510 */ 511 public static void squareLarge() { 512 int failCount = 0; 513 514 BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA_SQUARE - 32 - 1); 515 for (int i=0; i<SIZE; i++) { 516 BigInteger x = fetchNumber(BITS_KARATSUBA_SQUARE - 32 - 1); 517 BigInteger u = base.add(x); 518 int a = 1 + random.nextInt(31); 519 BigInteger w = u.shiftLeft(a); 520 521 BigInteger squareResult = u.multiply(u).shiftLeft(2*a); 522 BigInteger karatsubaSquareResult = w.multiply(w); 523 524 if (!squareResult.equals(karatsubaSquareResult)) { 525 failCount++; 526 } 527 } 528 529 report("squareLarge Karatsuba", failCount); 530 531 failCount = 0; 532 base = base.shiftLeft(BITS_TOOM_COOK_SQUARE - BITS_KARATSUBA_SQUARE); 533 for (int i=0; i<SIZE; i++) { 534 BigInteger x = fetchNumber(BITS_TOOM_COOK_SQUARE - 32 - 1); 535 BigInteger u = base.add(x); 536 int a = 1 + random.nextInt(31); 537 BigInteger w = u.shiftLeft(a); 538 539 BigInteger squareResult = u.multiply(u).shiftLeft(2*a); 540 BigInteger toomCookSquareResult = w.multiply(w); 541 542 if (!squareResult.equals(toomCookSquareResult)) { 543 failCount++; 544 } 545 } 546 547 report("squareLarge Toom-Cook", failCount); 548 } 549 550 /** 551 * Sanity test for Burnikel-Ziegler division. The Burnikel-Ziegler division 552 * algorithm is used when each of the dividend and the divisor has at least 553 * a specified number of ints in its representation. This test is based on 554 * the observation that if {@code w = u*pow(2,a)} and {@code z = v*pow(2,b)} 555 * where {@code abs(u) > abs(v)} and {@code a > b && b > 0}, then if 556 * {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then 557 * {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}. The test 558 * ensures that {@code v} is just under the B-Z threshold, that {@code z} is 559 * over the threshold and {@code w} is much larger than {@code z}. This 560 * implies that {@code u/v} uses the standard division algorithm and 561 * {@code w/z} uses the B-Z algorithm. The results of the two algorithms 562 * are then compared using the observation described in the foregoing and 563 * if they are not equal a failure is logged. 564 */ 565 public static void divideLarge() { 566 int failCount = 0; 567 568 BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 33); 569 for (int i=0; i<SIZE; i++) { 570 BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 34, random); 571 BigInteger v = base.add(addend); 572 573 BigInteger u = v.multiply(BigInteger.valueOf(2 + random.nextInt(Short.MAX_VALUE - 1))); 574 575 if(random.nextBoolean()) { 576 u = u.negate(); 577 } 578 if(random.nextBoolean()) { 579 v = v.negate(); 580 } 581 582 int a = BITS_BURNIKEL_ZIEGLER_OFFSET + random.nextInt(16); 583 int b = 1 + random.nextInt(16); 584 BigInteger w = u.multiply(BigInteger.ONE.shiftLeft(a)); 585 BigInteger z = v.multiply(BigInteger.ONE.shiftLeft(b)); 586 587 BigInteger[] divideResult = u.divideAndRemainder(v); 588 divideResult[0] = divideResult[0].multiply(BigInteger.ONE.shiftLeft(a - b)); 589 divideResult[1] = divideResult[1].multiply(BigInteger.ONE.shiftLeft(b)); 590 BigInteger[] bzResult = w.divideAndRemainder(z); 591 592 if (divideResult[0].compareTo(bzResult[0]) != 0 || 593 divideResult[1].compareTo(bzResult[1]) != 0) { 594 failCount++; 595 } 596 } 597 598 report("divideLarge", failCount); 599 } 600 601 public static void bitCount() { 602 int failCount = 0; 603 604 for (int i=0; i<SIZE*10; i++) { 605 int x = random.nextInt(); 606 BigInteger bigX = BigInteger.valueOf((long)x); 607 int bit = (x < 0 ? 0 : 1); 608 int tmp = x, bitCount = 0; 609 for (int j=0; j<32; j++) { 610 bitCount += ((tmp & 1) == bit ? 1 : 0); 611 tmp >>= 1; 612 } 613 614 if (bigX.bitCount() != bitCount) { 615 //System.err.println(x+": "+bitCount+", "+bigX.bitCount()); 616 failCount++; 617 } 618 } 619 report("Bit Count", failCount); 620 } 621 622 public static void bitLength() { 623 int failCount = 0; 624 625 for (int i=0; i<SIZE*10; i++) { 626 int x = random.nextInt(); 627 BigInteger bigX = BigInteger.valueOf((long)x); 628 int signBit = (x < 0 ? 0x80000000 : 0); 629 int tmp = x, bitLength, j; 630 for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++) 631 tmp <<= 1; 632 bitLength = 32 - j; 633 634 if (bigX.bitLength() != bitLength) { 635 //System.err.println(x+": "+bitLength+", "+bigX.bitLength()); 636 failCount++; 637 } 638 } 639 640 report("BitLength", failCount); 641 } 642 643 public static void bitOps(int order) { 644 int failCount1 = 0, failCount2 = 0, failCount3 = 0; 645 646 for (int i=0; i<SIZE*5; i++) { 647 BigInteger x = fetchNumber(order); 648 BigInteger y; 649 650 // Test setBit and clearBit (and testBit) 651 if (x.signum() < 0) { 652 y = BigInteger.valueOf(-1); 653 for (int j=0; j<x.bitLength(); j++) 654 if (!x.testBit(j)) 655 y = y.clearBit(j); 656 } else { 657 y = BigInteger.ZERO; 658 for (int j=0; j<x.bitLength(); j++) 659 if (x.testBit(j)) 660 y = y.setBit(j); 661 } 662 if (!x.equals(y)) 663 failCount1++; 664 665 // Test flipBit (and testBit) 666 y = BigInteger.valueOf(x.signum()<0 ? -1 : 0); 667 for (int j=0; j<x.bitLength(); j++) 668 if (x.signum()<0 ^ x.testBit(j)) 669 y = y.flipBit(j); 670 if (!x.equals(y)) 671 failCount2++; 672 } 673 report("clearBit/testBit for " + order + " bits", failCount1); 674 report("flipBit/testBit for " + order + " bits", failCount2); 675 676 for (int i=0; i<SIZE*5; i++) { 677 BigInteger x = fetchNumber(order); 678 679 // Test getLowestSetBit() 680 int k = x.getLowestSetBit(); 681 if (x.signum() == 0) { 682 if (k != -1) 683 failCount3++; 684 } else { 685 BigInteger z = x.and(x.negate()); 686 int j; 687 for (j=0; j<z.bitLength() && !z.testBit(j); j++) 688 ; 689 if (k != j) 690 failCount3++; 691 } 692 } 693 report("getLowestSetBit for " + order + " bits", failCount3); 694 } 695 696 public static void bitwise(int order) { 697 698 // Test identity x^y == x|y &~ x&y 699 int failCount = 0; 700 for (int i=0; i<SIZE; i++) { 701 BigInteger x = fetchNumber(order); 702 BigInteger y = fetchNumber(order); 703 BigInteger z = x.xor(y); 704 BigInteger w = x.or(y).andNot(x.and(y)); 705 if (!z.equals(w)) 706 failCount++; 707 } 708 report("Logic (^ | & ~) for " + order + " bits", failCount); 709 710 // Test identity x &~ y == ~(~x | y) 711 failCount = 0; 712 for (int i=0; i<SIZE; i++) { 713 BigInteger x = fetchNumber(order); 714 BigInteger y = fetchNumber(order); 715 BigInteger z = x.andNot(y); 716 BigInteger w = x.not().or(y).not(); 717 if (!z.equals(w)) 718 failCount++; 719 } 720 report("Logic (&~ | ~) for " + order + " bits", failCount); 721 } 722 723 public static void shift(int order) { 724 int failCount1 = 0; 725 int failCount2 = 0; 726 int failCount3 = 0; 727 728 for (int i=0; i<100; i++) { 729 BigInteger x = fetchNumber(order); 730 int n = Math.abs(random.nextInt()%200); 731 732 if (!x.shiftLeft(n).equals 733 (x.multiply(BigInteger.valueOf(2L).pow(n)))) 734 failCount1++; 735 736 BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n)); 737 BigInteger z = (x.signum()<0 && y[1].signum()!=0 738 ? y[0].subtract(BigInteger.ONE) 739 : y[0]); 740 741 BigInteger b = x.shiftRight(n); 742 743 if (!b.equals(z)) { 744 System.err.println("Input is "+x.toString(2)); 745 System.err.println("shift is "+n); 746 747 System.err.println("Divided "+z.toString(2)); 748 System.err.println("Shifted is "+b.toString(2)); 749 if (b.toString().equals(z.toString())) 750 System.err.println("Houston, we have a problem."); 751 failCount2++; 752 } 753 754 if (!x.shiftLeft(n).shiftRight(n).equals(x)) 755 failCount3++; 756 } 757 report("baz shiftLeft for " + order + " bits", failCount1); 758 report("baz shiftRight for " + order + " bits", failCount2); 759 report("baz shiftLeft/Right for " + order + " bits", failCount3); 760 } 761 762 public static void divideAndRemainder(int order) { 763 int failCount1 = 0; 764 765 for (int i=0; i<SIZE; i++) { 766 BigInteger x = fetchNumber(order).abs(); 767 while(x.compareTo(BigInteger.valueOf(3L)) != 1) 768 x = fetchNumber(order).abs(); 769 BigInteger z = x.divide(BigInteger.valueOf(2L)); 770 BigInteger y[] = x.divideAndRemainder(x); 771 if (!y[0].equals(BigInteger.ONE)) { 772 failCount1++; 773 System.err.println("fail1 x :"+x); 774 System.err.println(" y :"+y); 775 } 776 else if (!y[1].equals(BigInteger.ZERO)) { 777 failCount1++; 778 System.err.println("fail2 x :"+x); 779 System.err.println(" y :"+y); 780 } 781 782 y = x.divideAndRemainder(z); 783 if (!y[0].equals(BigInteger.valueOf(2))) { 784 failCount1++; 785 System.err.println("fail3 x :"+x); 786 System.err.println(" y :"+y); 787 } 788 } 789 report("divideAndRemainder for " + order + " bits", failCount1); 790 } 791 792 public static void stringConv() { 793 int failCount = 0; 794 795 // Generic string conversion. 796 for (int i=0; i<100; i++) { 797 byte xBytes[] = new byte[Math.abs(random.nextInt())%100+1]; 798 random.nextBytes(xBytes); 799 BigInteger x = new BigInteger(xBytes); 800 801 for (int radix=Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) { 802 String result = x.toString(radix); 803 BigInteger test = new BigInteger(result, radix); 804 if (!test.equals(x)) { 805 failCount++; 806 System.err.println("BigInteger toString: "+x); 807 System.err.println("Test: "+test); 808 System.err.println(radix); 809 } 810 } 811 } 812 813 // String conversion straddling the Schoenhage algorithm crossover 814 // threshold, and at twice and four times the threshold. 815 for (int k = 0; k <= 2; k++) { 816 int factor = 1 << k; 817 int upper = factor * BITS_SCHOENHAGE_BASE + 33; 818 int lower = upper - 35; 819 820 for (int bits = upper; bits >= lower; bits--) { 821 for (int i = 0; i < 50; i++) { 822 BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, random)); 823 824 for (int radix = Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) { 825 String result = x.toString(radix); 826 BigInteger test = new BigInteger(result, radix); 827 if (!test.equals(x)) { 828 failCount++; 829 System.err.println("BigInteger toString: " + x); 830 System.err.println("Test: " + test); 831 System.err.println(radix); 832 } 833 } 834 } 835 } 836 } 837 838 report("String Conversion", failCount); 839 } 840 841 public static void byteArrayConv(int order) { 842 int failCount = 0; 843 844 for (int i=0; i<SIZE; i++) { 845 BigInteger x = fetchNumber(order); 846 while (x.equals(BigInteger.ZERO)) 847 x = fetchNumber(order); 848 BigInteger y = new BigInteger(x.toByteArray()); 849 if (!x.equals(y)) { 850 failCount++; 851 System.err.println("orig is "+x); 852 System.err.println("new is "+y); 853 } 854 } 855 report("Array Conversion for " + order + " bits", failCount); 856 } 857 858 public static void modInv(int order) { 859 int failCount = 0, successCount = 0, nonInvCount = 0; 860 861 for (int i=0; i<SIZE; i++) { 862 BigInteger x = fetchNumber(order); 863 while(x.equals(BigInteger.ZERO)) 864 x = fetchNumber(order); 865 BigInteger m = fetchNumber(order).abs(); 866 while(m.compareTo(BigInteger.ONE) != 1) 867 m = fetchNumber(order).abs(); 868 869 try { 870 BigInteger inv = x.modInverse(m); 871 BigInteger prod = inv.multiply(x).remainder(m); 872 873 if (prod.signum() == -1) 874 prod = prod.add(m); 875 876 if (prod.equals(BigInteger.ONE)) 877 successCount++; 878 else 879 failCount++; 880 } catch(ArithmeticException e) { 881 nonInvCount++; 882 } 883 } 884 report("Modular Inverse for " + order + " bits", failCount); 885 } 886 887 public static void modExp(int order1, int order2) { 888 int failCount = 0; 889 890 for (int i=0; i<SIZE/10; i++) { 891 BigInteger m = fetchNumber(order1).abs(); 892 while(m.compareTo(BigInteger.ONE) != 1) 893 m = fetchNumber(order1).abs(); 894 BigInteger base = fetchNumber(order2); 895 BigInteger exp = fetchNumber(8).abs(); 896 897 BigInteger z = base.modPow(exp, m); 898 BigInteger w = base.pow(exp.intValue()).mod(m); 899 if (!z.equals(w)) { 900 System.err.println("z is "+z); 901 System.err.println("w is "+w); 902 System.err.println("mod is "+m); 903 System.err.println("base is "+base); 904 System.err.println("exp is "+exp); 905 failCount++; 906 } 907 } 908 report("Exponentiation I for " + order1 + " and " + 909 order2 + " bits", failCount); 910 } 911 912 // This test is based on Fermat's theorem 913 // which is not ideal because base must not be multiple of modulus 914 // and modulus must be a prime or pseudoprime (Carmichael number) 915 public static void modExp2(int order) { 916 int failCount = 0; 917 918 for (int i=0; i<10; i++) { 919 BigInteger m = new BigInteger(100, 5, random); 920 while(m.compareTo(BigInteger.ONE) != 1) 921 m = new BigInteger(100, 5, random); 922 BigInteger exp = m.subtract(BigInteger.ONE); 923 BigInteger base = fetchNumber(order).abs(); 924 while(base.compareTo(m) != -1) 925 base = fetchNumber(order).abs(); 926 while(base.equals(BigInteger.ZERO)) 927 base = fetchNumber(order).abs(); 928 929 BigInteger one = base.modPow(exp, m); 930 if (!one.equals(BigInteger.ONE)) { 931 System.err.println("m is "+m); 932 System.err.println("base is "+base); 933 System.err.println("exp is "+exp); 934 failCount++; 935 } 936 } 937 report("Exponentiation II for " + order + " bits", failCount); 938 } 939 940 private static final int[] mersenne_powers = { 941 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 942 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 943 1257787, 1398269, 2976221, 3021377, 6972593, 13466917 }; 944 945 private static final long[] carmichaels = { 946 561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633, 947 62745,63973,75361,101101,115921,126217,162401,172081,188461,252601, 948 278545,294409,314821,334153,340561,399001,410041,449065,488881,512461, 949 225593397919L }; 950 951 // Note: testing the larger ones takes too long. 952 private static final int NUM_MERSENNES_TO_TEST = 7; 953 // Note: this constant used for computed Carmichaels, not the array above 954 private static final int NUM_CARMICHAELS_TO_TEST = 5; 955 956 private static final String[] customer_primes = { 957 "120000000000000000000000000000000019", 958 "633825300114114700748351603131", 959 "1461501637330902918203684832716283019651637554291", 960 "779626057591079617852292862756047675913380626199", 961 "857591696176672809403750477631580323575362410491", 962 "910409242326391377348778281801166102059139832131", 963 "929857869954035706722619989283358182285540127919", 964 "961301750640481375785983980066592002055764391999", 965 "1267617700951005189537696547196156120148404630231", 966 "1326015641149969955786344600146607663033642528339" }; 967 968 private static final BigInteger ZERO = BigInteger.ZERO; 969 private static final BigInteger ONE = BigInteger.ONE; 970 private static final BigInteger TWO = new BigInteger("2"); 971 private static final BigInteger SIX = new BigInteger("6"); 972 private static final BigInteger TWELVE = new BigInteger("12"); 973 private static final BigInteger EIGHTEEN = new BigInteger("18"); 974 975 public static void prime() { 976 BigInteger p1, p2, c1; 977 int failCount = 0; 978 979 // Test consistency 980 for(int i=0; i<10; i++) { 981 p1 = BigInteger.probablePrime(100, random); 982 if (!p1.isProbablePrime(100)) { 983 System.err.println("Consistency "+p1.toString(16)); 984 failCount++; 985 } 986 } 987 988 // Test some known Mersenne primes (2^n)-1 989 // The array holds the exponents, not the numbers being tested 990 for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) { 991 p1 = new BigInteger("2"); 992 p1 = p1.pow(mersenne_powers[i]); 993 p1 = p1.subtract(BigInteger.ONE); 994 if (!p1.isProbablePrime(100)) { 995 System.err.println("Mersenne prime "+i+ " failed."); 996 failCount++; 997 } 998 } 999 1000 // Test some primes reported by customers as failing in the past 1001 for (int i=0; i<customer_primes.length; i++) { 1002 p1 = new BigInteger(customer_primes[i]); 1003 if (!p1.isProbablePrime(100)) { 1004 System.err.println("Customer prime "+i+ " failed."); 1005 failCount++; 1006 } 1007 } 1008 1009 // Test some known Carmichael numbers. 1010 for (int i=0; i<carmichaels.length; i++) { 1011 c1 = BigInteger.valueOf(carmichaels[i]); 1012 if(c1.isProbablePrime(100)) { 1013 System.err.println("Carmichael "+i+ " reported as prime."); 1014 failCount++; 1015 } 1016 } 1017 1018 // Test some computed Carmichael numbers. 1019 // Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if 1020 // each of the factors is prime 1021 int found = 0; 1022 BigInteger f1 = new BigInteger(40, 100, random); 1023 while (found < NUM_CARMICHAELS_TO_TEST) { 1024 BigInteger k = null; 1025 BigInteger f2, f3; 1026 f1 = f1.nextProbablePrime(); 1027 BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX); 1028 if (result[1].equals(ZERO)) { 1029 k = result[0]; 1030 f2 = k.multiply(TWELVE).add(ONE); 1031 if (f2.isProbablePrime(100)) { 1032 f3 = k.multiply(EIGHTEEN).add(ONE); 1033 if (f3.isProbablePrime(100)) { 1034 c1 = f1.multiply(f2).multiply(f3); 1035 if (c1.isProbablePrime(100)) { 1036 System.err.println("Computed Carmichael " 1037 +c1.toString(16)); 1038 failCount++; 1039 } 1040 found++; 1041 } 1042 } 1043 } 1044 f1 = f1.add(TWO); 1045 } 1046 1047 // Test some composites that are products of 2 primes 1048 for (int i=0; i<50; i++) { 1049 p1 = BigInteger.probablePrime(100, random); 1050 p2 = BigInteger.probablePrime(100, random); 1051 c1 = p1.multiply(p2); 1052 if (c1.isProbablePrime(100)) { 1053 System.err.println("Composite failed "+c1.toString(16)); 1054 failCount++; 1055 } 1056 } 1057 1058 for (int i=0; i<4; i++) { 1059 p1 = BigInteger.probablePrime(600, random); 1060 p2 = BigInteger.probablePrime(600, random); 1061 c1 = p1.multiply(p2); 1062 if (c1.isProbablePrime(100)) { 1063 System.err.println("Composite failed "+c1.toString(16)); 1064 failCount++; 1065 } 1066 } 1067 1068 report("Prime", failCount); 1069 } 1070 1071 private static final long[] primesTo100 = { 1072 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97 1073 }; 1074 1075 private static final long[] aPrimeSequence = { 1076 1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L, 1077 1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L, 1078 1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L, 1079 1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L, 1080 1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L, 1081 1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L, 1082 1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L, 1083 1999999853L, 1999999861L, 1999999871L, 1999999873 1084 }; 1085 1086 public static void nextProbablePrime() throws Exception { 1087 int failCount = 0; 1088 BigInteger p1, p2, p3; 1089 p1 = p2 = p3 = ZERO; 1090 1091 // First test nextProbablePrime on the low range starting at zero 1092 for (int i=0; i<primesTo100.length; i++) { 1093 p1 = p1.nextProbablePrime(); 1094 if (p1.longValue() != primesTo100[i]) { 1095 System.err.println("low range primes failed"); 1096 System.err.println("p1 is "+p1); 1097 System.err.println("expected "+primesTo100[i]); 1098 failCount++; 1099 } 1100 } 1101 1102 // Test nextProbablePrime on a relatively small, known prime sequence 1103 p1 = BigInteger.valueOf(aPrimeSequence[0]); 1104 for (int i=1; i<aPrimeSequence.length; i++) { 1105 p1 = p1.nextProbablePrime(); 1106 if (p1.longValue() != aPrimeSequence[i]) { 1107 System.err.println("prime sequence failed"); 1108 failCount++; 1109 } 1110 } 1111 1112 // Next, pick some large primes, use nextProbablePrime to find the 1113 // next one, and make sure there are no primes in between 1114 for (int i=0; i<100; i+=10) { 1115 p1 = BigInteger.probablePrime(50 + i, random); 1116 p2 = p1.add(ONE); 1117 p3 = p1.nextProbablePrime(); 1118 while(p2.compareTo(p3) < 0) { 1119 if (p2.isProbablePrime(100)){ 1120 System.err.println("nextProbablePrime failed"); 1121 System.err.println("along range "+p1.toString(16)); 1122 System.err.println("to "+p3.toString(16)); 1123 failCount++; 1124 break; 1125 } 1126 p2 = p2.add(ONE); 1127 } 1128 } 1129 1130 report("nextProbablePrime", failCount); 1131 } 1132 1133 public static void serialize() throws Exception { 1134 int failCount = 0; 1135 1136 String bitPatterns[] = { 1137 "ffffffff00000000ffffffff00000000ffffffff00000000", 1138 "ffffffffffffffffffffffff000000000000000000000000", 1139 "ffffffff0000000000000000000000000000000000000000", 1140 "10000000ffffffffffffffffffffffffffffffffffffffff", 1141 "100000000000000000000000000000000000000000000000", 1142 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 1143 "-ffffffff00000000ffffffff00000000ffffffff00000000", 1144 "-ffffffffffffffffffffffff000000000000000000000000", 1145 "-ffffffff0000000000000000000000000000000000000000", 1146 "-10000000ffffffffffffffffffffffffffffffffffffffff", 1147 "-100000000000000000000000000000000000000000000000", 1148 "-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 1149 }; 1150 1151 for(int i = 0; i < bitPatterns.length; i++) { 1152 BigInteger b1 = new BigInteger(bitPatterns[i], 16); 1153 BigInteger b2 = null; 1154 1155 File f = new File("serialtest"); 1156 1157 try (FileOutputStream fos = new FileOutputStream(f)) { 1158 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) { 1159 oos.writeObject(b1); 1160 oos.flush(); 1161 } 1162 1163 try (FileInputStream fis = new FileInputStream(f); 1164 ObjectInputStream ois = new ObjectInputStream(fis)) 1165 { 1166 b2 = (BigInteger)ois.readObject(); 1167 } 1168 1169 if (!b1.equals(b2) || 1170 !b1.equals(b1.or(b2))) { 1171 failCount++; 1172 System.err.println("Serialized failed for hex " + 1173 b1.toString(16)); 1174 } 1175 } 1176 f.delete(); 1177 } 1178 1179 for(int i=0; i<10; i++) { 1180 BigInteger b1 = fetchNumber(random.nextInt(100)); 1181 BigInteger b2 = null; 1182 File f = new File("serialtest"); 1183 try (FileOutputStream fos = new FileOutputStream(f)) { 1184 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) { 1185 oos.writeObject(b1); 1186 oos.flush(); 1187 } 1188 1189 try (FileInputStream fis = new FileInputStream(f); 1190 ObjectInputStream ois = new ObjectInputStream(fis)) 1191 { 1192 b2 = (BigInteger)ois.readObject(); 1193 } 1194 } 1195 1196 if (!b1.equals(b2) || 1197 !b1.equals(b1.or(b2))) 1198 failCount++; 1199 f.delete(); 1200 } 1201 1202 report("Serialize", failCount); 1203 } 1204 1205 /** 1206 * Main to interpret arguments and run several tests. 1207 * 1208 * Up to three arguments may be given to specify the SIZE of BigIntegers 1209 * used for call parameters 1, 2, and 3. The SIZE is interpreted as 1210 * the maximum number of decimal digits that the parameters will have. 1211 * 1212 */ 1213 public static void main(String[] args) throws Exception { 1214 // Some variables for sizing test numbers in bits 1215 int order1 = ORDER_MEDIUM; 1216 int order2 = ORDER_SMALL; 1217 int order3 = ORDER_KARATSUBA; 1218 int order4 = ORDER_TOOM_COOK; 1219 1220 if (args.length >0) 1221 order1 = (int)((Integer.parseInt(args[0]))* 3.333); 1222 if (args.length >1) 1223 order2 = (int)((Integer.parseInt(args[1]))* 3.333); 1224 if (args.length >2) 1225 order3 = (int)((Integer.parseInt(args[2]))* 3.333); 1226 if (args.length >3) 1227 order4 = (int)((Integer.parseInt(args[3]))* 3.333); 1228 1229 constructor(); 1230 1231 prime(); 1232 nextProbablePrime(); 1233 1234 arithmetic(order1); // small numbers 1235 arithmetic(order3); // Karatsuba range 1236 arithmetic(order4); // Toom-Cook / Burnikel-Ziegler range 1237 1238 divideAndRemainder(order1); // small numbers 1239 divideAndRemainder(order3); // Karatsuba range 1240 divideAndRemainder(order4); // Toom-Cook / Burnikel-Ziegler range 1241 1242 pow(order1); 1243 pow(order3); 1244 pow(order4); 1245 1246 square(ORDER_MEDIUM); 1247 square(ORDER_KARATSUBA_SQUARE); 1248 square(ORDER_TOOM_COOK_SQUARE); 1249 1250 squareRoot(); 1251 squareRootAndRemainder(); 1252 1253 bitCount(); 1254 bitLength(); 1255 bitOps(order1); 1256 bitwise(order1); 1257 1258 shift(order1); 1259 1260 byteArrayConv(order1); 1261 1262 modInv(order1); // small numbers 1263 modInv(order3); // Karatsuba range 1264 modInv(order4); // Toom-Cook / Burnikel-Ziegler range 1265 1266 modExp(order1, order2); 1267 modExp2(order1); 1268 1269 stringConv(); 1270 serialize(); 1271 1272 multiplyLarge(); 1273 squareLarge(); 1274 divideLarge(); 1275 1276 if (failure) 1277 throw new RuntimeException("Failure in BigIntegerTest."); 1278 } 1279 1280 /* 1281 * Get a random or boundary-case number. This is designed to provide 1282 * a lot of numbers that will find failure points, such as max sized 1283 * numbers, empty BigIntegers, etc. 1284 * 1285 * If order is less than 2, order is changed to 2. 1286 */ 1287 private static BigInteger fetchNumber(int order) { 1288 boolean negative = random.nextBoolean(); 1289 int numType = random.nextInt(7); 1290 BigInteger result = null; 1291 if (order < 2) order = 2; 1292 1293 switch (numType) { 1294 case 0: // Empty 1295 result = BigInteger.ZERO; 1296 break; 1297 1298 case 1: // One 1299 result = BigInteger.ONE; 1300 break; 1301 1302 case 2: // All bits set in number 1303 int numBytes = (order+7)/8; 1304 byte[] fullBits = new byte[numBytes]; 1305 for(int i=0; i<numBytes; i++) 1306 fullBits[i] = (byte)0xff; 1307 int excessBits = 8*numBytes - order; 1308 fullBits[0] &= (1 << (8-excessBits)) - 1; 1309 result = new BigInteger(1, fullBits); 1310 break; 1311 1312 case 3: // One bit in number 1313 result = BigInteger.ONE.shiftLeft(random.nextInt(order)); 1314 break; 1315 1316 case 4: // Random bit density 1317 byte[] val = new byte[(order+7)/8]; 1318 int iterations = random.nextInt(order); 1319 for (int i=0; i<iterations; i++) { 1320 int bitIdx = random.nextInt(order); 1321 val[bitIdx/8] |= 1 << (bitIdx%8); 1322 } 1323 result = new BigInteger(1, val); 1324 break; 1325 case 5: // Runs of consecutive ones and zeros 1326 result = ZERO; 1327 int remaining = order; 1328 int bit = random.nextInt(2); 1329 while (remaining > 0) { 1330 int runLength = Math.min(remaining, random.nextInt(order)); 1331 result = result.shiftLeft(runLength); 1332 if (bit > 0) 1333 result = result.add(ONE.shiftLeft(runLength).subtract(ONE)); 1334 remaining -= runLength; 1335 bit = 1 - bit; 1336 } 1337 break; 1338 1339 default: // random bits 1340 result = new BigInteger(order, random); 1341 } 1342 1343 if (negative) 1344 result = result.negate(); 1345 1346 return result; 1347 } 1348 1349 static void report(String testName, int failCount) { 1350 System.err.println(testName+": " + 1351 (failCount==0 ? "Passed":"Failed("+failCount+")")); 1352 if (failCount > 0) 1353 failure = true; 1354 } 1355 }