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