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