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