1 /*
   2  * Copyright 1998-2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any 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             FileOutputStream fos = new FileOutputStream(f);
 649             try {
 650                 ObjectOutputStream oos = new ObjectOutputStream(fos);
 651                 try {
 652                     oos.writeObject(b1);
 653                     oos.flush();
 654                 } finally {
 655                     oos.close();
 656                 }
 657 
 658                 FileInputStream fis = new FileInputStream(f);
 659                 try {
 660                     ObjectInputStream ois = new ObjectInputStream(fis);
 661                     try {
 662                         b2 = (BigInteger)ois.readObject();
 663                     } finally {
 664                         ois.close();
 665                     }
 666                 } finally {
 667                     fis.close();
 668                 }
 669 
 670                 if (!b1.equals(b2) ||
 671                     !b1.equals(b1.or(b2))) {
 672                     failCount++;
 673                     System.err.println("Serialized failed for hex " +
 674                                        b1.toString(16));
 675                 }
 676             } finally {
 677                 fos.close();
 678             }
 679             f.delete();
 680         }
 681 
 682         for(int i=0; i<10; i++) {
 683             BigInteger b1 = fetchNumber(rnd.nextInt(100));
 684             BigInteger b2 = null;
 685             File f = new File("serialtest");
 686             FileOutputStream fos = new FileOutputStream(f);
 687             try {
 688                 ObjectOutputStream oos = new ObjectOutputStream(fos);
 689                 try {
 690                     oos.writeObject(b1);
 691                     oos.flush();
 692                 } finally {
 693                     oos.close();
 694                 }
 695 
 696                 FileInputStream fis = new FileInputStream(f);
 697                 try {
 698                     ObjectInputStream ois = new ObjectInputStream(fis);
 699                     try {
 700                         b2 = (BigInteger)ois.readObject();
 701                     } finally {
 702                         ois.close();
 703                     }
 704                 } finally {
 705                     fis.close();
 706                 }
 707             } finally {
 708                 fos.close();
 709             }
 710 
 711             if (!b1.equals(b2) ||
 712                 !b1.equals(b1.or(b2)))
 713                 failCount++;
 714             f.delete();
 715         }
 716 
 717         report("Serialize", failCount);
 718     }
 719 
 720     /**
 721      * Main to interpret arguments and run several tests.
 722      *
 723      * Up to three arguments may be given to specify the size of BigIntegers
 724      * used for call parameters 1, 2, and 3. The size is interpreted as
 725      * the maximum number of decimal digits that the parameters will have.
 726      *
 727      */
 728     public static void main(String[] args) throws Exception {
 729 
 730         if (args.length >0)
 731             order1 = (int)((Integer.parseInt(args[0]))* 3.333);
 732         if (args.length >1)
 733             order2 = (int)((Integer.parseInt(args[1]))* 3.333);
 734         if (args.length >2)
 735             order3 = (int)((Integer.parseInt(args[2]))* 3.333);
 736 
 737         prime();
 738         nextProbablePrime();
 739 
 740         arithmetic();
 741         divideAndRemainder();
 742         pow();
 743 
 744         bitCount();
 745         bitLength();
 746         bitOps();
 747         bitwise();
 748 
 749         shift();
 750 
 751         byteArrayConv();
 752 
 753         modInv();
 754         modExp();
 755         modExp2();
 756 
 757         stringConv();
 758         serialize();
 759 
 760         if (failure)
 761             throw new RuntimeException("Failure in BigIntegerTest.");
 762     }
 763 
 764     /*
 765      * Get a random or boundary-case number. This is designed to provide
 766      * a lot of numbers that will find failure points, such as max sized
 767      * numbers, empty BigIntegers, etc.
 768      *
 769      * If order is less than 2, order is changed to 2.
 770      */
 771     private static BigInteger fetchNumber(int order) {
 772         boolean negative = rnd.nextBoolean();
 773         int numType = rnd.nextInt(6);
 774         BigInteger result = null;
 775         if (order < 2) order = 2;
 776 
 777         switch (numType) {
 778             case 0: // Empty
 779                 result = BigInteger.ZERO;
 780                 break;
 781 
 782             case 1: // One
 783                 result = BigInteger.ONE;
 784                 break;
 785 
 786             case 2: // All bits set in number
 787                 int numBytes = (order+7)/8;
 788                 byte[] fullBits = new byte[numBytes];
 789                 for(int i=0; i<numBytes; i++)
 790                     fullBits[i] = (byte)0xff;
 791                 int excessBits = 8*numBytes - order;
 792                 fullBits[0] &= (1 << (8-excessBits)) - 1;
 793                 result = new BigInteger(1, fullBits);
 794                 break;
 795 
 796             case 3: // One bit in number
 797                 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
 798                 break;
 799 
 800             case 4: // Random bit density
 801                 int iterations = rnd.nextInt(order-1);
 802                 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
 803                 for(int i=0; i<iterations; i++) {
 804                     BigInteger temp = BigInteger.ONE.shiftLeft(
 805                                                 rnd.nextInt(order));
 806                     result = result.or(temp);
 807                 }
 808                 break;
 809 
 810             default: // random bits
 811                 result = new BigInteger(order, rnd);
 812         }
 813 
 814         if (negative)
 815             result = result.negate();
 816 
 817         return result;
 818     }
 819 
 820     static void report(String testName, int failCount) {
 821         System.err.println(testName+": " +
 822                            (failCount==0 ? "Passed":"Failed("+failCount+")"));
 823         if (failCount > 0)
 824             failure = true;
 825     }
 826 }