1 /*
   2  * Copyright (c) 1998, 2003, 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  * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225
  27  * @summary tests methods in BigInteger
  28  * @run main/timeout=400 BigIntegerTest
  29  * @author madbot
  30  */
  31 
  32 import java.util.Random;
  33 import java.math.BigInteger;
  34 import java.io.*;
  35 
  36 /**
  37  * This is a simple test class created to ensure that the results
  38  * generated by BigInteger adhere to certain identities. Passing
  39  * this test is a strong assurance that the BigInteger operations
  40  * are working correctly.
  41  *
  42  * Three arguments may be specified which give the number of
  43  * decimal digits you desire in the three batches of test numbers.
  44  *
  45  * The tests are performed on arrays of random numbers which are
  46  * generated by a Random class as well as special cases which
  47  * throw in boundary numbers such as 0, 1, maximum sized, etc.
  48  *
  49  */
  50 public class BigIntegerTest {
  51     static Random rnd = new Random();
  52     static int size = 1000; // numbers per batch
  53     static boolean failure = false;
  54 
  55     // Some variables for sizing test numbers in bits
  56     private static int order1 = 100;
  57     private static int order2 = 60;
  58     private static int order3 = 30;
  59 
  60     public static void pow() {
  61         int failCount1 = 0;
  62 
  63         for (int i=0; i<size; i++) {
  64             int power = rnd.nextInt(6) +2;
  65             BigInteger x = fetchNumber(order1);
  66             BigInteger y = x.pow(power);
  67             BigInteger z = x;
  68 
  69             for (int j=1; j<power; j++)
  70                 z = z.multiply(x);
  71 
  72             if (!y.equals(z))
  73                 failCount1++;
  74         }
  75         report("pow", failCount1);
  76     }
  77 
  78     public static void arithmetic() {
  79         int failCount = 0;
  80 
  81         for (int i=0; i<size; i++) {
  82             BigInteger x = fetchNumber(order1);
  83             while(x.compareTo(BigInteger.ZERO) != 1)
  84                 x = fetchNumber(order1);
  85             BigInteger y = fetchNumber(order1/2);
  86             while(x.compareTo(y) == -1)
  87                 y = fetchNumber(order1/2);
  88             if (y.equals(BigInteger.ZERO))
  89                 y = y.add(BigInteger.ONE);
  90 
  91             BigInteger baz = x.divide(y);
  92             baz = baz.multiply(y);
  93             baz = baz.add(x.remainder(y));
  94             baz = baz.subtract(x);
  95             if (!baz.equals(BigInteger.ZERO))
  96                 failCount++;
  97         }
  98         report("Arithmetic I", failCount);
  99 
 100         failCount = 0;
 101         for (int i=0; i<100; i++) {
 102             BigInteger x = fetchNumber(order1);
 103             while(x.compareTo(BigInteger.ZERO) != 1)
 104                 x = fetchNumber(order1);
 105             BigInteger y = fetchNumber(order1/2);
 106             while(x.compareTo(y) == -1)
 107                 y = fetchNumber(order1/2);
 108             if (y.equals(BigInteger.ZERO))
 109                 y = y.add(BigInteger.ONE);
 110 
 111             BigInteger baz[] = x.divideAndRemainder(y);
 112             baz[0] = baz[0].multiply(y);
 113             baz[0] = baz[0].add(baz[1]);
 114             baz[0] = baz[0].subtract(x);
 115             if (!baz[0].equals(BigInteger.ZERO))
 116                 failCount++;
 117         }
 118         report("Arithmetic II", failCount);
 119     }
 120 
 121     public static void bitCount() {
 122         int failCount = 0;
 123 
 124         for (int i=0; i<size*10; i++) {
 125             int x = rnd.nextInt();
 126             BigInteger bigX = BigInteger.valueOf((long)x);
 127             int bit = (x < 0 ? 0 : 1);
 128             int tmp = x, bitCount = 0;
 129             for (int j=0; j<32; j++) {
 130                 bitCount += ((tmp & 1) == bit ? 1 : 0);
 131                 tmp >>= 1;
 132             }
 133 
 134             if (bigX.bitCount() != bitCount) {
 135                 //System.err.println(x+": "+bitCount+", "+bigX.bitCount());
 136                 failCount++;
 137             }
 138         }
 139         report("Bit Count", failCount);
 140     }
 141 
 142     public static void bitLength() {
 143         int failCount = 0;
 144 
 145         for (int i=0; i<size*10; i++) {
 146             int x = rnd.nextInt();
 147             BigInteger bigX = BigInteger.valueOf((long)x);
 148             int signBit = (x < 0 ? 0x80000000 : 0);
 149             int tmp = x, bitLength, j;
 150             for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++)
 151                 tmp <<= 1;
 152             bitLength = 32 - j;
 153 
 154             if (bigX.bitLength() != bitLength) {
 155                 //System.err.println(x+": "+bitLength+", "+bigX.bitLength());
 156                 failCount++;
 157             }
 158         }
 159 
 160         report("BitLength", failCount);
 161     }
 162 
 163     public static void bitOps() {
 164         int failCount1 = 0, failCount2 = 0, failCount3 = 0;
 165 
 166         for (int i=0; i<size*5; i++) {
 167             BigInteger x = fetchNumber(order1);
 168             BigInteger y;
 169 
 170             /* Test setBit and clearBit (and testBit) */
 171             if (x.signum() < 0) {
 172                 y = BigInteger.valueOf(-1);
 173                 for (int j=0; j<x.bitLength(); j++)
 174                     if (!x.testBit(j))
 175                         y = y.clearBit(j);
 176             } else {
 177                 y = BigInteger.ZERO;
 178                 for (int j=0; j<x.bitLength(); j++)
 179                     if (x.testBit(j))
 180                         y = y.setBit(j);
 181             }
 182             if (!x.equals(y))
 183                 failCount1++;
 184 
 185             /* Test flipBit (and testBit) */
 186             y = BigInteger.valueOf(x.signum()<0 ? -1 : 0);
 187             for (int j=0; j<x.bitLength(); j++)
 188                 if (x.signum()<0  ^  x.testBit(j))
 189                     y = y.flipBit(j);
 190             if (!x.equals(y))
 191                 failCount2++;
 192         }
 193         report("clearBit/testBit", failCount1);
 194         report("flipBit/testBit", failCount2);
 195 
 196         for (int i=0; i<size*5; i++) {
 197             BigInteger x = fetchNumber(order1);
 198 
 199             /* Test getLowestSetBit() */
 200             int k = x.getLowestSetBit();
 201             if (x.signum() == 0) {
 202                 if (k != -1)
 203                     failCount3++;
 204             } else {
 205                 BigInteger z = x.and(x.negate());
 206                 int j;
 207                 for (j=0; j<z.bitLength() && !z.testBit(j); j++)
 208                     ;
 209                 if (k != j)
 210                     failCount3++;
 211             }
 212         }
 213         report("getLowestSetBit", failCount3);
 214     }
 215 
 216     public static void bitwise() {
 217 
 218         /* Test identity x^y == x|y &~ x&y */
 219         int failCount = 0;
 220         for (int i=0; i<size; i++) {
 221             BigInteger x = fetchNumber(order1);
 222             BigInteger y = fetchNumber(order1);
 223             BigInteger z = x.xor(y);
 224             BigInteger w = x.or(y).andNot(x.and(y));
 225             if (!z.equals(w))
 226                 failCount++;
 227         }
 228         report("Logic (^ | & ~)", failCount);
 229 
 230         /* Test identity x &~ y == ~(~x | y) */
 231         failCount = 0;
 232         for (int i=0; i<size; i++) {
 233             BigInteger x = fetchNumber(order1);
 234             BigInteger y = fetchNumber(order1);
 235             BigInteger z = x.andNot(y);
 236             BigInteger w = x.not().or(y).not();
 237             if (!z.equals(w))
 238                 failCount++;
 239         }
 240         report("Logic (&~ | ~)", failCount);
 241     }
 242 
 243     public static void shift() {
 244         int failCount1 = 0;
 245         int failCount2 = 0;
 246         int failCount3 = 0;
 247 
 248         for (int i=0; i<100; i++) {
 249             BigInteger x = fetchNumber(order1);
 250             int n = Math.abs(rnd.nextInt()%200);
 251 
 252             if (!x.shiftLeft(n).equals
 253                 (x.multiply(BigInteger.valueOf(2L).pow(n))))
 254                 failCount1++;
 255 
 256             BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n));
 257             BigInteger z = (x.signum()<0 && y[1].signum()!=0
 258                             ? y[0].subtract(BigInteger.ONE)
 259                             : y[0]);
 260 
 261             BigInteger b = x.shiftRight(n);
 262 
 263             if (!b.equals(z)) {
 264                 System.err.println("Input is "+x.toString(2));
 265                 System.err.println("shift is "+n);
 266 
 267                 System.err.println("Divided "+z.toString(2));
 268                 System.err.println("Shifted is "+b.toString(2));
 269                 if (b.toString().equals(z.toString()))
 270                     System.err.println("Houston, we have a problem.");
 271                 failCount2++;
 272             }
 273 
 274             if (!x.shiftLeft(n).shiftRight(n).equals(x))
 275                 failCount3++;
 276         }
 277         report("baz shiftLeft", failCount1);
 278         report("baz shiftRight", failCount2);
 279         report("baz shiftLeft/Right", failCount3);
 280     }
 281 
 282     public static void divideAndRemainder() {
 283         int failCount1 = 0;
 284 
 285         for (int i=0; i<size; i++) {
 286             BigInteger x = fetchNumber(order1).abs();
 287             while(x.compareTo(BigInteger.valueOf(3L)) != 1)
 288                 x = fetchNumber(order1).abs();
 289             BigInteger z = x.divide(BigInteger.valueOf(2L));
 290             BigInteger y[] = x.divideAndRemainder(x);
 291             if (!y[0].equals(BigInteger.ONE)) {
 292                 failCount1++;
 293                 System.err.println("fail1 x :"+x);
 294                 System.err.println("      y :"+y);
 295             }
 296             else if (!y[1].equals(BigInteger.ZERO)) {
 297                 failCount1++;
 298                 System.err.println("fail2 x :"+x);
 299                 System.err.println("      y :"+y);
 300             }
 301 
 302             y = x.divideAndRemainder(z);
 303             if (!y[0].equals(BigInteger.valueOf(2))) {
 304                 failCount1++;
 305                 System.err.println("fail3 x :"+x);
 306                 System.err.println("      y :"+y);
 307             }
 308         }
 309         report("divideAndRemainder I", failCount1);
 310     }
 311 
 312     public static void stringConv() {
 313         int failCount = 0;
 314 
 315         for (int i=0; i<100; i++) {
 316             byte xBytes[] = new byte[Math.abs(rnd.nextInt())%100+1];
 317             rnd.nextBytes(xBytes);
 318             BigInteger x = new BigInteger(xBytes);
 319 
 320             for (int radix=2; radix < 37; radix++) {
 321                 String result = x.toString(radix);
 322                 BigInteger test = new BigInteger(result, radix);
 323                 if (!test.equals(x)) {
 324                     failCount++;
 325                     System.err.println("BigInteger toString: "+x);
 326                     System.err.println("Test: "+test);
 327                     System.err.println(radix);
 328                 }
 329             }
 330         }
 331         report("String Conversion", failCount);
 332     }
 333 
 334     public static void byteArrayConv() {
 335         int failCount = 0;
 336 
 337         for (int i=0; i<size; i++) {
 338             BigInteger x = fetchNumber(order1);
 339             while (x.equals(BigInteger.ZERO))
 340                 x = fetchNumber(order1);
 341             BigInteger y = new BigInteger(x.toByteArray());
 342             if (!x.equals(y)) {
 343                 failCount++;
 344                 System.err.println("orig is "+x);
 345                 System.err.println("new is "+y);
 346             }
 347         }
 348         report("Array Conversion", failCount);
 349     }
 350 
 351     public static void modInv() {
 352         int failCount = 0, successCount = 0, nonInvCount = 0;
 353 
 354         for (int i=0; i<size; i++) {
 355             BigInteger x = fetchNumber(order1);
 356             while(x.equals(BigInteger.ZERO))
 357                 x = fetchNumber(order1);
 358             BigInteger m = fetchNumber(order1).abs();
 359             while(m.compareTo(BigInteger.ONE) != 1)
 360                 m = fetchNumber(order1).abs();
 361 
 362             try {
 363                 BigInteger inv = x.modInverse(m);
 364                 BigInteger prod = inv.multiply(x).remainder(m);
 365 
 366                 if (prod.signum() == -1)
 367                     prod = prod.add(m);
 368 
 369                 if (prod.equals(BigInteger.ONE))
 370                     successCount++;
 371                 else
 372                     failCount++;
 373             } catch(ArithmeticException e) {
 374                 nonInvCount++;
 375             }
 376         }
 377         report("Modular Inverse", failCount);
 378     }
 379 
 380     public static void modExp() {
 381         int failCount = 0;
 382 
 383         for (int i=0; i<size/10; i++) {
 384             BigInteger m = fetchNumber(order1).abs();
 385             while(m.compareTo(BigInteger.ONE) != 1)
 386                 m = fetchNumber(order1).abs();
 387             BigInteger base = fetchNumber(order2);
 388             BigInteger exp = fetchNumber(8).abs();
 389 
 390             BigInteger z = base.modPow(exp, m);
 391             BigInteger w = base.pow(exp.intValue()).mod(m);
 392             if (!z.equals(w)) {
 393                 System.err.println("z is "+z);
 394                 System.err.println("w is "+w);
 395                 System.err.println("mod is "+m);
 396                 System.err.println("base is "+base);
 397                 System.err.println("exp is "+exp);
 398                 failCount++;
 399             }
 400         }
 401         report("Exponentiation I", failCount);
 402     }
 403 
 404     // This test is based on Fermat's theorem
 405     // which is not ideal because base must not be multiple of modulus
 406     // and modulus must be a prime or pseudoprime (Carmichael number)
 407     public static void modExp2() {
 408         int failCount = 0;
 409 
 410         for (int i=0; i<10; i++) {
 411             BigInteger m = new BigInteger(100, 5, rnd);
 412             while(m.compareTo(BigInteger.ONE) != 1)
 413                 m = new BigInteger(100, 5, rnd);
 414             BigInteger exp = m.subtract(BigInteger.ONE);
 415             BigInteger base = fetchNumber(order1).abs();
 416             while(base.compareTo(m) != -1)
 417                 base = fetchNumber(order1).abs();
 418             while(base.equals(BigInteger.ZERO))
 419                 base = fetchNumber(order1).abs();
 420 
 421             BigInteger one = base.modPow(exp, m);
 422             if (!one.equals(BigInteger.ONE)) {
 423                 System.err.println("m is "+m);
 424                 System.err.println("base is "+base);
 425                 System.err.println("exp is "+exp);
 426                 failCount++;
 427             }
 428         }
 429         report("Exponentiation II", failCount);
 430     }
 431 
 432     private static final int[] mersenne_powers = {
 433         521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937,
 434         21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433,
 435         1257787, 1398269, 2976221, 3021377, 6972593, 13466917 };
 436 
 437     private static final long[] carmichaels = {
 438       561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,
 439       62745,63973,75361,101101,115921,126217,162401,172081,188461,252601,
 440       278545,294409,314821,334153,340561,399001,410041,449065,488881,512461,
 441       225593397919L };
 442 
 443     // Note: testing the larger ones takes too long.
 444     private static final int NUM_MERSENNES_TO_TEST = 7;
 445     // Note: this constant used for computed Carmichaels, not the array above
 446     private static final int NUM_CARMICHAELS_TO_TEST = 5;
 447 
 448     private static final String[] customer_primes = {
 449         "120000000000000000000000000000000019",
 450         "633825300114114700748351603131",
 451         "1461501637330902918203684832716283019651637554291",
 452         "779626057591079617852292862756047675913380626199",
 453         "857591696176672809403750477631580323575362410491",
 454         "910409242326391377348778281801166102059139832131",
 455         "929857869954035706722619989283358182285540127919",
 456         "961301750640481375785983980066592002055764391999",
 457         "1267617700951005189537696547196156120148404630231",
 458         "1326015641149969955786344600146607663033642528339" };
 459 
 460     private static final BigInteger ZERO = BigInteger.ZERO;
 461     private static final BigInteger ONE = BigInteger.ONE;
 462     private static final BigInteger TWO = new BigInteger("2");
 463     private static final BigInteger SIX = new BigInteger("6");
 464     private static final BigInteger TWELVE = new BigInteger("12");
 465     private static final BigInteger EIGHTEEN = new BigInteger("18");
 466 
 467     public static void prime() {
 468         BigInteger p1, p2, c1;
 469         int failCount = 0;
 470 
 471         // Test consistency
 472         for(int i=0; i<10; i++) {
 473             p1 = BigInteger.probablePrime(100, rnd);
 474             if (!p1.isProbablePrime(100)) {
 475                 System.err.println("Consistency "+p1.toString(16));
 476                 failCount++;
 477             }
 478         }
 479 
 480         // Test some known Mersenne primes (2^n)-1
 481         // The array holds the exponents, not the numbers being tested
 482         for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) {
 483             p1 = new BigInteger("2");
 484             p1 = p1.pow(mersenne_powers[i]);
 485             p1 = p1.subtract(BigInteger.ONE);
 486             if (!p1.isProbablePrime(100)) {
 487                 System.err.println("Mersenne prime "+i+ " failed.");
 488                 failCount++;
 489             }
 490         }
 491 
 492         // Test some primes reported by customers as failing in the past
 493         for (int i=0; i<customer_primes.length; i++) {
 494             p1 = new BigInteger(customer_primes[i]);
 495             if (!p1.isProbablePrime(100)) {
 496                 System.err.println("Customer prime "+i+ " failed.");
 497                 failCount++;
 498             }
 499         }
 500 
 501         // Test some known Carmichael numbers.
 502         for (int i=0; i<carmichaels.length; i++) {
 503             c1 = BigInteger.valueOf(carmichaels[i]);
 504             if(c1.isProbablePrime(100)) {
 505                 System.err.println("Carmichael "+i+ " reported as prime.");
 506                 failCount++;
 507             }
 508         }
 509 
 510         // Test some computed Carmichael numbers.
 511         // Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if
 512         // each of the factors is prime
 513         int found = 0;
 514         BigInteger f1 = new BigInteger(40, 100, rnd);
 515         while (found < NUM_CARMICHAELS_TO_TEST) {
 516             BigInteger k = null;
 517             BigInteger f2, f3;
 518             f1 = f1.nextProbablePrime();
 519             BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX);
 520             if (result[1].equals(ZERO)) {
 521                 k = result[0];
 522                 f2 = k.multiply(TWELVE).add(ONE);
 523                 if (f2.isProbablePrime(100)) {
 524                     f3 = k.multiply(EIGHTEEN).add(ONE);
 525                     if (f3.isProbablePrime(100)) {
 526                         c1 = f1.multiply(f2).multiply(f3);
 527                         if (c1.isProbablePrime(100)) {
 528                             System.err.println("Computed Carmichael "
 529                                                +c1.toString(16));
 530                             failCount++;
 531                         }
 532                         found++;
 533                     }
 534                 }
 535             }
 536             f1 = f1.add(TWO);
 537         }
 538 
 539         // Test some composites that are products of 2 primes
 540         for (int i=0; i<50; i++) {
 541             p1 = BigInteger.probablePrime(100, rnd);
 542             p2 = BigInteger.probablePrime(100, rnd);
 543             c1 = p1.multiply(p2);
 544             if (c1.isProbablePrime(100)) {
 545                 System.err.println("Composite failed "+c1.toString(16));
 546                 failCount++;
 547             }
 548         }
 549 
 550         for (int i=0; i<4; i++) {
 551             p1 = BigInteger.probablePrime(600, rnd);
 552             p2 = BigInteger.probablePrime(600, rnd);
 553             c1 = p1.multiply(p2);
 554             if (c1.isProbablePrime(100)) {
 555                 System.err.println("Composite failed "+c1.toString(16));
 556                 failCount++;
 557             }
 558         }
 559 
 560         report("Prime", failCount);
 561     }
 562 
 563     private static final long[] primesTo100 = {
 564         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
 565     };
 566 
 567     private static final long[] aPrimeSequence = {
 568         1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L,
 569         1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L,
 570         1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L,
 571         1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L,
 572         1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L,
 573         1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L,
 574         1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L,
 575         1999999853L, 1999999861L, 1999999871L, 1999999873
 576     };
 577 
 578     public static void nextProbablePrime() throws Exception {
 579         int failCount = 0;
 580         BigInteger p1, p2, p3;
 581         p1 = p2 = p3 = ZERO;
 582 
 583         // First test nextProbablePrime on the low range starting at zero
 584         for (int i=0; i<primesTo100.length; i++) {
 585             p1 = p1.nextProbablePrime();
 586             if (p1.longValue() != primesTo100[i]) {
 587                 System.err.println("low range primes failed");
 588                 System.err.println("p1 is "+p1);
 589                 System.err.println("expected "+primesTo100[i]);
 590                 failCount++;
 591             }
 592         }
 593 
 594         // Test nextProbablePrime on a relatively small, known prime sequence
 595         p1 = BigInteger.valueOf(aPrimeSequence[0]);
 596         for (int i=1; i<aPrimeSequence.length; i++) {
 597             p1 = p1.nextProbablePrime();
 598             if (p1.longValue() != aPrimeSequence[i]) {
 599                 System.err.println("prime sequence failed");
 600                 failCount++;
 601             }
 602         }
 603 
 604         // Next, pick some large primes, use nextProbablePrime to find the
 605         // next one, and make sure there are no primes in between
 606         for (int i=0; i<100; i+=10) {
 607             p1 = BigInteger.probablePrime(50 + i, rnd);
 608             p2 = p1.add(ONE);
 609             p3 = p1.nextProbablePrime();
 610             while(p2.compareTo(p3) < 0) {
 611                 if (p2.isProbablePrime(100)){
 612                     System.err.println("nextProbablePrime failed");
 613                     System.err.println("along range "+p1.toString(16));
 614                     System.err.println("to "+p3.toString(16));
 615                     failCount++;
 616                     break;
 617                 }
 618                 p2 = p2.add(ONE);
 619             }
 620         }
 621 
 622         report("nextProbablePrime", failCount);
 623     }
 624 
 625     public static void serialize() throws Exception {
 626         int failCount = 0;
 627 
 628         String bitPatterns[] = {
 629              "ffffffff00000000ffffffff00000000ffffffff00000000",
 630              "ffffffffffffffffffffffff000000000000000000000000",
 631              "ffffffff0000000000000000000000000000000000000000",
 632              "10000000ffffffffffffffffffffffffffffffffffffffff",
 633              "100000000000000000000000000000000000000000000000",
 634              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
 635             "-ffffffff00000000ffffffff00000000ffffffff00000000",
 636             "-ffffffffffffffffffffffff000000000000000000000000",
 637             "-ffffffff0000000000000000000000000000000000000000",
 638             "-10000000ffffffffffffffffffffffffffffffffffffffff",
 639             "-100000000000000000000000000000000000000000000000",
 640             "-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 641         };
 642 
 643         for(int i = 0; i < bitPatterns.length; i++) {
 644             BigInteger b1 = new BigInteger(bitPatterns[i], 16);
 645             BigInteger b2 = null;
 646 
 647             File f = new File("serialtest");
 648 
 649             try (FileOutputStream fos = new FileOutputStream(f)) {
 650                 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
 651                     oos.writeObject(b1);
 652                     oos.flush();
 653                 }
 654 
 655                 try (FileInputStream fis = new FileInputStream(f);
 656                      ObjectInputStream ois = new ObjectInputStream(fis))
 657                 {
 658                     b2 = (BigInteger)ois.readObject();
 659                 }
 660 
 661                 if (!b1.equals(b2) ||
 662                     !b1.equals(b1.or(b2))) {
 663                     failCount++;
 664                     System.err.println("Serialized failed for hex " +
 665                                        b1.toString(16));
 666                 }
 667             }
 668             f.delete();
 669         }
 670 
 671         for(int i=0; i<10; i++) {
 672             BigInteger b1 = fetchNumber(rnd.nextInt(100));
 673             BigInteger b2 = null;
 674             File f = new File("serialtest");
 675             try (FileOutputStream fos = new FileOutputStream(f)) {
 676                 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
 677                     oos.writeObject(b1);
 678                     oos.flush();
 679                 }
 680 
 681                 try (FileInputStream fis = new FileInputStream(f);
 682                      ObjectInputStream ois = new ObjectInputStream(fis))
 683                 {
 684                     b2 = (BigInteger)ois.readObject();
 685                 }
 686             }
 687 
 688             if (!b1.equals(b2) ||
 689                 !b1.equals(b1.or(b2)))
 690                 failCount++;
 691             f.delete();
 692         }
 693 
 694         report("Serialize", failCount);
 695     }
 696 
 697     /**
 698      * Main to interpret arguments and run several tests.
 699      *
 700      * Up to three arguments may be given to specify the size of BigIntegers
 701      * used for call parameters 1, 2, and 3. The size is interpreted as
 702      * the maximum number of decimal digits that the parameters will have.
 703      *
 704      */
 705     public static void main(String[] args) throws Exception {
 706 
 707         if (args.length >0)
 708             order1 = (int)((Integer.parseInt(args[0]))* 3.333);
 709         if (args.length >1)
 710             order2 = (int)((Integer.parseInt(args[1]))* 3.333);
 711         if (args.length >2)
 712             order3 = (int)((Integer.parseInt(args[2]))* 3.333);
 713 
 714         prime();
 715         nextProbablePrime();
 716 
 717         arithmetic();
 718         divideAndRemainder();
 719         pow();
 720 
 721         bitCount();
 722         bitLength();
 723         bitOps();
 724         bitwise();
 725 
 726         shift();
 727 
 728         byteArrayConv();
 729 
 730         modInv();
 731         modExp();
 732         modExp2();
 733 
 734         stringConv();
 735         serialize();
 736 
 737         if (failure)
 738             throw new RuntimeException("Failure in BigIntegerTest.");
 739     }
 740 
 741     /*
 742      * Get a random or boundary-case number. This is designed to provide
 743      * a lot of numbers that will find failure points, such as max sized
 744      * numbers, empty BigIntegers, etc.
 745      *
 746      * If order is less than 2, order is changed to 2.
 747      */
 748     private static BigInteger fetchNumber(int order) {
 749         boolean negative = rnd.nextBoolean();
 750         int numType = rnd.nextInt(6);
 751         BigInteger result = null;
 752         if (order < 2) order = 2;
 753 
 754         switch (numType) {
 755             case 0: // Empty
 756                 result = BigInteger.ZERO;
 757                 break;
 758 
 759             case 1: // One
 760                 result = BigInteger.ONE;
 761                 break;
 762 
 763             case 2: // All bits set in number
 764                 int numBytes = (order+7)/8;
 765                 byte[] fullBits = new byte[numBytes];
 766                 for(int i=0; i<numBytes; i++)
 767                     fullBits[i] = (byte)0xff;
 768                 int excessBits = 8*numBytes - order;
 769                 fullBits[0] &= (1 << (8-excessBits)) - 1;
 770                 result = new BigInteger(1, fullBits);
 771                 break;
 772 
 773             case 3: // One bit in number
 774                 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
 775                 break;
 776 
 777             case 4: // Random bit density
 778                 int iterations = rnd.nextInt(order-1);
 779                 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
 780                 for(int i=0; i<iterations; i++) {
 781                     BigInteger temp = BigInteger.ONE.shiftLeft(
 782                                                 rnd.nextInt(order));
 783                     result = result.or(temp);
 784                 }
 785                 break;
 786 
 787             default: // random bits
 788                 result = new BigInteger(order, rnd);
 789         }
 790 
 791         if (negative)
 792             result = result.negate();
 793 
 794         return result;
 795     }
 796 
 797     static void report(String testName, int failCount) {
 798         System.err.println(testName+": " +
 799                            (failCount==0 ? "Passed":"Failed("+failCount+")"));
 800         if (failCount > 0)
 801             failure = true;
 802     }
 803 }