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