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 }