BigInteger.java: Updated notice to include years 2002 and 3.
authorRaif S. Naffah <raif@fl.net.au>
Mon, 10 Feb 2003 23:45:31 +0000 (23:45 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Mon, 10 Feb 2003 23:45:31 +0000 (23:45 +0000)
2003-02-10  Raif S. Naffah <raif@fl.net.au>

* java/math/BigInteger.java:
Updated notice to include years 2002 and 3.
Added 2 private (int) arrays with values from the HAC (Handbook of
Applied Cryptography -A. Menezes & al): k[] that contains bit lengths
and t[] that contains nbr. of tests --used in isProbablePrime().

* java/math/BigInteger.java (make(long)): Merged into valueOf(long).

* java/math/BigInteger.java (make(int[],int), add(int,int),
add(BI,BI,int), times(BI,int), divide(long,long,BI,BI,int), gcd(BI),
isProbablePrime(int), shift(BI,int), valueOf(String,int), neg(BI),
bitOp(int,BI,BI), and(BI,int)): Use valueOf(long) instead of
make(long).

* java/math/BigInteger.java (euclidInv): Reduce number of work vars
(euclidInv(int,int,int)): Now returns an array of 2 ints instead of 3.
(euclidInv(BI,BI,BI)): Used to return an array of 2 BIs; now accepts 6
BIs and returns void.
(modInverse(BI)): Use new signatures of euclidInv().

* java/math/BigInteger.java (isProbablePrime(int)): Use divide() with
static small primes instead of remainder().
Use pre-computed max nbr of trials based on bitlength of BI to test.
Use pre-computed small primes for the trial tests instead of random
numbers.

* java/math/BigInteger.java (isOdd, isMinusOne, pow): Removed.
not used.

* java/math/BigInteger.java (format(int,StringBuffer)): Removed
invoacation of MPN.chars_per_word().  not used.

* java/math/BigInteger.java (gcd(int,int)): Declared 'tmp' once as
local var and used where needed.

* java/math/BigInteger.java (modPow(BI,BI)): Fixed spelling.
Combined declaration with initialisation of locals.
Removed unused var.

* java/math/BigInteger.java: Style changes
(pow(int)): Removed 'else' keyword.
(toString(int)): idem.
(doubleValue()): idem.
(bitLength()): idem.
(equals(Object)): Use static methods name in same class w/o prepending
class name.
(doubleValue()): idem.
(setNegative(BI)): idem.
(negate()): idem.
(and(BI,int)): idem.
(and(BI)): idem.
(gcd(BI)): idem.
(byteArrayToIntArray()): Removed casting to (int). this is
std. behaviour.
(canonicalize()): idem.
(alloc(int)): Always instantiate a new BI.

From-SVN: r62656

libjava/ChangeLog
libjava/java/math/BigInteger.java

index 0635ac1663a70af3287b6a9bb095d5ce7747c4b6..0f9454d7781828e5a12b8a105cbe39ef94cdb8a2 100644 (file)
@@ -1,3 +1,62 @@
+2003-02-10  Raif S. Naffah <raif@fl.net.au>
+
+       * java/math/BigInteger.java:
+       Updated notice to include years 2002 and 3.
+       Added 2 private (int) arrays with values from the HAC (Handbook of
+       Applied Cryptography -A. Menezes & al): k[] that contains bit lengths
+       and t[] that contains nbr. of tests --used in isProbablePrime().
+
+       * java/math/BigInteger.java (make(long)): Merged into valueOf(long).
+
+       * java/math/BigInteger.java (make(int[],int), add(int,int),
+       add(BI,BI,int), times(BI,int), divide(long,long,BI,BI,int), gcd(BI),
+       isProbablePrime(int), shift(BI,int), valueOf(String,int), neg(BI),
+       bitOp(int,BI,BI), and(BI,int)): Use valueOf(long) instead of
+       make(long).
+
+       * java/math/BigInteger.java (euclidInv): Reduce number of work vars
+       (euclidInv(int,int,int)): Now returns an array of 2 ints instead of 3.
+       (euclidInv(BI,BI,BI)): Used to return an array of 2 BIs; now accepts 6
+       BIs and returns void.
+       (modInverse(BI)): Use new signatures of euclidInv().
+
+       * java/math/BigInteger.java (isProbablePrime(int)): Use divide() with
+       static small primes instead of remainder().
+       Use pre-computed max nbr of trials based on bitlength of BI to test.
+       Use pre-computed small primes for the trial tests instead of random
+       numbers.
+
+       * java/math/BigInteger.java (isOdd, isMinusOne, pow): Removed.
+       not used.
+
+       * java/math/BigInteger.java (format(int,StringBuffer)): Removed
+       invoacation of MPN.chars_per_word().  not used.
+
+       * java/math/BigInteger.java (gcd(int,int)): Declared 'tmp' once as
+       local var and used where needed.
+
+       * java/math/BigInteger.java (modPow(BI,BI)): Fixed spelling.
+       Combined declaration with initialisation of locals.
+       Removed unused var.
+
+       * java/math/BigInteger.java: Style changes
+       (pow(int)): Removed 'else' keyword.
+       (toString(int)): idem.
+       (doubleValue()): idem.
+       (bitLength()): idem.
+       (equals(Object)): Use static methods name in same class w/o prepending
+       class name.
+       (doubleValue()): idem.
+       (setNegative(BI)): idem.
+       (negate()): idem.
+       (and(BI,int)): idem.
+       (and(BI)): idem.
+       (gcd(BI)): idem.
+       (byteArrayToIntArray()): Removed casting to (int). this is
+       std. behaviour.
+       (canonicalize()): idem.
+       (alloc(int)): Always instantiate a new BI.
+
 2003-02-10  Tom Tromey  <tromey@redhat.com>
 
        * java/sql/Timestamp.java (compareTo(Object)): New method.
index ac21eccc51858a2175081b6bed62b810866f1a63..f72429046711d2d368f16b69c082a50a03b3a7e8 100644 (file)
@@ -1,5 +1,5 @@
 /* java.math.BigInteger -- Arbitary precision integers
-   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -110,6 +110,12 @@ public class BigInteger extends Number implements Comparable
       109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
       191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 };
 
+  /** HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Table 4.4. */
+  private static final int[] k =
+      {100,150,200,250,300,350,400,500,600,800,1250, Integer.MAX_VALUE};
+  private static final int[] t =
+      { 27, 18, 15, 12,  9,  8,  7,  6,  5,  4,   3, 2};
+
   private BigInteger()
   {
   }
@@ -218,38 +224,29 @@ public class BigInteger extends Number implements Comparable
   }
 
   /** Return a (possibly-shared) BigInteger with a given long value. */
-  private static BigInteger make(long value)
+  public static BigInteger valueOf(long val)
   {
-    if (value >= minFixNum && value <= maxFixNum)
-      return smallFixNums[(int)value - minFixNum];
-    int i = (int) value;
-    if ((long)i == value)
+    if (val >= minFixNum && val <= maxFixNum)
+      return smallFixNums[(int) val - minFixNum];
+    int i = (int) val;
+    if ((long) i == val)
       return new BigInteger(i);
     BigInteger result = alloc(2);
     result.ival = 2;
     result.words[0] = i;
-    result.words[1] = (int) (value >> 32);
+    result.words[1] = (int)(val >> 32);
     return result;
   }
 
-  // FIXME: Could simply rename 'make' method above as valueOf while
-  // changing all instances of 'make'.  Don't do this until this class
-  // is done as the Kawa class this is based on has 'make' methods
-  // with other parameters; wait to see if they are used in BigInteger.
-  public static BigInteger valueOf(long val)
-  {
-    return make(val);
-  }
-
   /** Make a canonicalized BigInteger from an array of words.
    * The array may be reused (without copying). */
   private static BigInteger make(int[] words, int len)
   {
     if (words == null)
-      return make(len);
+      return valueOf(len);
     len = BigInteger.wordsNeeded(words, len);
     if (len <= 1)
-      return len == 0 ? ZERO : make(words[0]);
+      return len == 0 ? ZERO : valueOf(words[0]);
     BigInteger num = new BigInteger();
     num.words = words;
     num.ival = len;
@@ -267,15 +264,15 @@ public class BigInteger extends Number implements Comparable
     int bptr = 0;
     int word = sign;
     for (int i = bytes.length % 4; i > 0; --i, bptr++)
-      word = (word << 8) | (((int) bytes[bptr]) & 0xff);
+      word = (word << 8) | (bytes[bptr] & 0xff);
     words[--nwords] = word;
 
     // Elements remaining in byte[] are a multiple of 4.
     while (nwords > 0)
       words[--nwords] = bytes[bptr++] << 24 |
-                       (((int) bytes[bptr++]) & 0xff) << 16 |
-                       (((int) bytes[bptr++]) & 0xff) << 8 |
-                       (((int) bytes[bptr++]) & 0xff);
+                       (bytes[bptr++] & 0xff) << 16 |
+                       (bytes[bptr++] & 0xff) << 8 |
+                       (bytes[bptr++] & 0xff);
     return words;
   }
 
@@ -284,9 +281,8 @@ public class BigInteger extends Number implements Comparable
    */
   private static BigInteger alloc(int nwords)
   {
-    if (nwords <= 1)
-      return new BigInteger();
     BigInteger result = new BigInteger();
+    if (nwords > 1)
     result.words = new int[nwords];
     return result;
   }
@@ -376,12 +372,6 @@ public class BigInteger extends Number implements Comparable
     return compareTo(this, val) > 0 ? this : val;
   }
 
-  private final boolean isOdd()
-  {
-    int low = words == null ? ival : words[0];
-    return (low & 1) != 0;
-  }
-
   private final boolean isZero()
   {
     return words == null && ival == 0;
@@ -392,11 +382,6 @@ public class BigInteger extends Number implements Comparable
     return words == null && ival == 1;
   }
 
-  private final boolean isMinusOne()
-  {
-    return words == null && ival == -1;
-  }
-
   /** Calculate how many words are significant in words[0:len-1].
    * Returns the least value x such that x>0 && words[0:x-1]==words[0:len-1],
    * when words is viewed as a 2's complement integer.
@@ -433,14 +418,14 @@ public class BigInteger extends Number implements Comparable
        words = null;
       }
     if (words == null && ival >= minFixNum && ival <= maxFixNum)
-      return smallFixNums[(int) ival - minFixNum];
+      return smallFixNums[ival - minFixNum];
     return this;
   }
 
   /** Add two ints, yielding a BigInteger. */
   private static final BigInteger add(int x, int y)
   {
-    return BigInteger.make((long) x + (long) y);
+    return valueOf((long) x + (long) y);
   }
 
   /** Add a BigInteger and an int, yielding a new BigInteger. */
@@ -526,13 +511,13 @@ public class BigInteger extends Number implements Comparable
   private static BigInteger add(BigInteger x, BigInteger y, int k)
   {
     if (x.words == null && y.words == null)
-      return BigInteger.make((long) k * (long) y.ival + (long) x.ival);
+      return valueOf((long) k * (long) y.ival + (long) x.ival);
     if (k != 1)
       {
        if (k == -1)
          y = BigInteger.neg(y);
        else
-         y = BigInteger.times(y, BigInteger.make(k));
+         y = BigInteger.times(y, valueOf(k));
       }
     if (x.words == null)
       return BigInteger.add(y, x.ival);
@@ -580,7 +565,7 @@ public class BigInteger extends Number implements Comparable
     int[] xwords = x.words;
     int xlen = x.ival;
     if (xwords == null)
-      return BigInteger.make((long) xlen * (long) y);
+      return valueOf((long) xlen * (long) y);
     boolean negative;
     BigInteger result = BigInteger.alloc(xlen + 1);
     if (xwords[xlen - 1] < 0)
@@ -662,7 +647,7 @@ public class BigInteger extends Number implements Comparable
        xNegative = true;
        if (x == Long.MIN_VALUE)
          {
-           divide(BigInteger.make(x), BigInteger.make(y),
+           divide(valueOf(x), valueOf(y),
                   quotient, remainder, rounding_mode);
            return;
          }
@@ -684,7 +669,7 @@ public class BigInteger extends Number implements Comparable
                  remainder.set(x);
              }
            else
-             divide(BigInteger.make(x), BigInteger.make(y),
+             divide(valueOf(x), valueOf(y),
                      quotient, remainder, rounding_mode);
            return;
          }
@@ -966,39 +951,6 @@ public class BigInteger extends Number implements Comparable
     return rem.canonicalize();
   }
 
-  /** Calculate power for BigInteger exponents.
-   * @param y exponent assumed to be non-negative. */
-  private BigInteger pow(BigInteger y)
-  {
-    if (isOne())
-      return this;
-    if (isMinusOne())
-      return y.isOdd () ? this : ONE;
-    if (y.words == null && y.ival >= 0)
-      return pow(y.ival);
-
-    // Assume exponent is non-negative.
-    if (isZero())
-      return this;
-
-    // Implemented by repeated squaring and multiplication.
-    BigInteger pow2 = this;
-    BigInteger r = null;
-    for (;;)  // for (i = 0;  ; i++)
-      {
-        // pow2 == x**(2**i)
-        // prod = x**(sum(j=0..i-1, (y>>j)&1))
-        if (y.isOdd())
-          r = r == null ? pow2 : times(r, pow2);  // r *= pow2
-        y = BigInteger.shift(y, -1);
-        if (y.isZero())
-          break;
-        // pow2 *= pow2;
-        pow2 = times(pow2, pow2);
-      }
-    return r == null ? ONE : r;
-  }
-
   /** Calculate the integral power of a BigInteger.
    * @param exponent the exponent (must be non-negative)
    */
@@ -1008,7 +960,6 @@ public class BigInteger extends Number implements Comparable
       {
        if (exponent == 0)
          return ONE;
-       else
          throw new ArithmeticException("negative exponent");
       }
     if (isZero())
@@ -1051,51 +1002,36 @@ public class BigInteger extends Number implements Comparable
 
   private static final int[] euclidInv(int a, int b, int prevDiv)
   {
-    // Storage for return values, plus one slot for a temp int (see below).
-    int[] xy;
-
     if (b == 0)
       throw new ArithmeticException("not invertible");
-    else if (b == 1)
-      {
+
+    if (b == 1)
        // Success:  values are indeed invertible!
        // Bottom of the recursion reached; start unwinding.
-        xy = new int[3];
-       xy[0] = -prevDiv;
-       xy[1] = 1;
-       return xy;
-      }
-
-    xy = euclidInv(b, a % b, a / b);   // Recursion happens here.
+       return new int[] { -prevDiv, 1 };
 
-    // xy[2] is just temp storage for intermediate results in the following
-    // calculation.  This saves us a bit of space over having an int
-    // allocated at every level of this recursive method.
-    xy[2] = xy[0];
-    xy[0] = xy[2] * -prevDiv + xy[1];
-    xy[1] = xy[2];
+    int[] xy = euclidInv(b, a % b, a / b);     // Recursion happens here.
+    a = xy[0]; // use our local copy of 'a' as a work var
+    xy[0] = a * -prevDiv + xy[1];
+    xy[1] = a;
     return xy;
   }
 
-  private static final BigInteger[]
-    euclidInv(BigInteger a, BigInteger b, BigInteger prevDiv)
+  private static final void euclidInv(BigInteger a, BigInteger b,
+                                      BigInteger prevDiv, BigInteger xy0,
+                                      BigInteger xy1, BigInteger xy2)
   {
-    // FIXME: This method could be more efficient memory-wise and should be
-    // modified as such since it is recursive.
-
-    // Storage for return values, plus one slot for a temp int (see below).
-    BigInteger[] xy;
-
     if (b.isZero())
       throw new ArithmeticException("not invertible");
-    else if (b.isOne())
+
+    if (b.isOne())
       {
        // Success:  values are indeed invertible!
        // Bottom of the recursion reached; start unwinding.
-        xy = new BigInteger[3];
-       xy[0] = neg(prevDiv);
-       xy[1] = ONE;
-       return xy;
+        // WARNING: xy1 is, and xy0 may be, a shared BI!
+       xy0 = neg(prevDiv);
+       xy1 = ONE;
+       return;
       }
 
     // Recursion happens in the following conditional!
@@ -1104,9 +1040,8 @@ public class BigInteger extends Number implements Comparable
     if (a.words == null)
       {
         int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival);
-        xy = new BigInteger[3];
-       xy[0] = new BigInteger(xyInt[0]);
-       xy[1] = new BigInteger(xyInt[1]);
+       xy0 = new BigInteger(xyInt[0]); // non-shared BI
+       xy1 = new BigInteger(xyInt[1]); // non-shared BI
       }
     else
       {
@@ -1116,16 +1051,15 @@ public class BigInteger extends Number implements Comparable
         // quot and rem may not be in canonical form. ensure
         rem.canonicalize();
         quot.canonicalize();
-        xy = euclidInv(b, rem, quot);
+        euclidInv(b, rem, quot, xy0, xy1, xy2);
       }
 
-    // xy[2] is just temp storage for intermediate results in the following
+    // xy2 is just temp storage for intermediate results in the following
     // calculation.  This saves us a bit of space over having a BigInteger
     // allocated at every level of this recursive method.
-    xy[2] = xy[0];
-    xy[0] = add(xy[1], times(xy[2], prevDiv), -1);
-    xy[1] = xy[2];
-    return xy;
+    xy2 = xy0;
+    xy0 = add(xy1, times(xy2, prevDiv), -1);
+    xy1 = xy2;
   }
 
   public BigInteger modInverse(BigInteger y)
@@ -1136,7 +1070,7 @@ public class BigInteger extends Number implements Comparable
     // Degenerate cases.
     if (y.isOne())
       return ZERO;
-    else if (isOne())
+    if (isOne())
       return ONE;
 
     // Use Euclid's algorithm as in gcd() but do this recursively
@@ -1144,8 +1078,6 @@ public class BigInteger extends Number implements Comparable
     // unwind from the recursion.
     // Used http://www.math.nmsu.edu/~crypto/EuclideanAlgo.html as reference.
     BigInteger result = new BigInteger();
-    int xval = ival;
-    int yval = y.ival;
     boolean swapped = false;
 
     if (y.words == null)
@@ -1156,8 +1088,8 @@ public class BigInteger extends Number implements Comparable
        // math.  Note that BigInteger.mod() must be used even if this is
        // already an int as the % operator would provide a negative result if
        // this is negative, BigInteger.mod() never returns negative values.
-       if (words != null || isNegative())
-         xval = mod(y).ival;
+        int xval = (words != null || isNegative()) ? mod(y).ival : ival;
+        int yval = y.ival;
 
        // Swap values so x > y.
        if (yval > xval)
@@ -1178,16 +1110,13 @@ public class BigInteger extends Number implements Comparable
       }
     else
       {
-       BigInteger x = this;
-
        // As above, force this to be a positive value via modulo math.
-       if (isNegative())
-         x = mod(y);
+       BigInteger x = isNegative() ? this.mod(y) : this;
 
        // Swap values so x > y.
        if (x.compareTo(y) < 0)
          {
-           BigInteger tmp = x; x = y; y = tmp;
+           result = x; x = y; y = result; // use 'result' as a work var
            swapped = true;
          }
        // As above (for ints), result will be in the 2nd element unless
@@ -1198,7 +1127,10 @@ public class BigInteger extends Number implements Comparable
         // quot and rem may not be in canonical form. ensure
         rem.canonicalize();
         quot.canonicalize();
-       result = euclidInv(y, rem, quot)[swapped ? 0 : 1];
+        BigInteger xy0 = new BigInteger();
+        BigInteger xy1 = new BigInteger();
+        euclidInv(y, rem, quot, xy0, xy1, result);
+       result = swapped ? xy0 : xy1;
 
        // Result can't be negative, so make it positive by adding the
        // original modulus, y (which is now x if they were swapped).
@@ -1222,16 +1154,13 @@ public class BigInteger extends Number implements Comparable
     // To do this naively by first raising this to the power of exponent
     // and then performing modulo m would be extremely expensive, especially
     // for very large numbers.  The solution is found in Number Theory
-    // where a combination of partial powers and modulos can be done easily.
+    // where a combination of partial powers and moduli can be done easily.
     //
     // We'll use the algorithm for Additive Chaining which can be found on
     // p. 244 of "Applied Cryptography, Second Edition" by Bruce Schneier.
-    BigInteger s, t, u;
-    int i;
-
-    s = ONE;
-    t = this;
-    u = exponent;
+    BigInteger s = ONE;
+    BigInteger t = this;
+    BigInteger u = exponent;
 
     while (!u.isZero())
       {
@@ -1248,24 +1177,22 @@ public class BigInteger extends Number implements Comparable
   private static final int gcd(int a, int b)
   {
     // Euclid's algorithm, copied from libg++.
+    int tmp;
     if (b > a)
       {
-       int tmp = a; a = b; b = tmp;
+       tmp = a; a = b; b = tmp;
       }
     for(;;)
       {
        if (b == 0)
          return a;
-       else if (b == 1)
+        if (b == 1)
          return b;
-       else
-         {
-           int tmp = b;
+        tmp = b;
            b = a % b;
            a = tmp;
          }
       }
-  }
 
   public BigInteger gcd(BigInteger y)
   {
@@ -1274,7 +1201,7 @@ public class BigInteger extends Number implements Comparable
     if (words == null)
       {
        if (xval == 0)
-         return BigInteger.abs(y);
+         return abs(y);
        if (y.words == null
            && xval != Integer.MIN_VALUE && yval != Integer.MIN_VALUE)
          {
@@ -1282,14 +1209,14 @@ public class BigInteger extends Number implements Comparable
              xval = -xval;
            if (yval < 0)
              yval = -yval;
-           return BigInteger.make(BigInteger.gcd(xval, yval));
+           return valueOf(gcd(xval, yval));
          }
        xval = 1;
       }
     if (y.words == null)
       {
        if (yval == 0)
-         return BigInteger.abs(this);
+         return abs(this);
        yval = 1;
       }
     int len = (xval > yval ? xval : yval) + 1;
@@ -1304,8 +1231,24 @@ public class BigInteger extends Number implements Comparable
     return result.canonicalize();
   }
 
+  /**
+   * <p>Returns <code>true</code> if this BigInteger is probably prime,
+   * <code>false</code> if it's definitely composite. If <code>certainty</code>
+   * is <code><= 0</code>, <code>true</code> is returned.</p>
+   *
+   * @param certainty a measure of the uncertainty that the caller is willing
+   * to tolerate: if the call returns <code>true</code> the probability that
+   * this BigInteger is prime exceeds <code>(1 - 1/2<sup>certainty</sup>)</code>.
+   * The execution time of this method is proportional to the value of this
+   * parameter.
+   * @return <code>true</code> if this BigInteger is probably prime,
+   * <code>false</code> if it's definitely composite.
+   */
   public boolean isProbablePrime(int certainty)
   {
+    if (certainty < 1)
+      return true;
+
     /** We'll use the Rabin-Miller algorithm for doing a probabilistic
      * primality test.  It is fast, easy and has faster decreasing odds of a
      * composite passing than with other tests.  This means that this
@@ -1317,19 +1260,20 @@ public class BigInteger extends Number implements Comparable
      * Cryptography, Second Edition" by Bruce Schneier.
      */
 
-    // First rule out small prime factors and assure the number is odd.
-    for (int i = 0; i < primes.length; i++)
+    // First rule out small prime factors
+    BigInteger rem = new BigInteger();
+    int i;
+    for (i = 0; i < primes.length; i++)
       {
        if (words == null && ival == primes[i])
          return true;
-        if (remainder(make(primes[i])).isZero())
+
+        divide(this, smallFixNums[primes[i] - minFixNum], null, rem, TRUNCATE);
+        if (rem.canonicalize().isZero())
          return false;
       }
 
     // Now perform the Rabin-Miller test.
-    // NB: I know that this can be simplified programatically, but
-    // I have tried to keep it as close as possible to the algorithm
-    // as written in the Schneier book for reference purposes.
 
     // Set b to the number of times 2 evenly divides (this - 1).
     // I.e. 2^b is the largest power of 2 that divides (this - 1).
@@ -1337,22 +1281,31 @@ public class BigInteger extends Number implements Comparable
     int b = pMinus1.getLowestSetBit();
 
     // Set m such that this = 1 + 2^b * m.
-    BigInteger m = pMinus1.divide(make(2L << b - 1));
-
-    Random rand = new Random();
-    while (certainty-- > 0)
-      {
-        // Pick a random number greater than 1 and less than this.
-       // The algorithm says to pick a small number to make the calculations
-       // go faster, but it doesn't say how small; we'll use 2 to 1024.
-       int a = rand.nextInt();
-       a = (a < 0 ? -a : a) % 1023 + 2;
-
-       BigInteger z = make(a).modPow(m, this);
+    BigInteger m = pMinus1.divide(valueOf(2L << b - 1));
+
+    // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
+    // 4.49 (controlling the error probability) gives the number of trials
+    // for an error probability of 1/2**80, given the number of bits in the
+    // number to test.  we shall use these numbers as is if/when 'certainty'
+    // is less or equal to 80, and twice as much if it's greater.
+    int bits = this.bitLength();
+    for (i = 0; i < k.length; i++)
+      if (bits <= k[i])
+        break;
+    int trials = t[i];
+    if (certainty > 80)
+      trials *= 2;
+    BigInteger z;
+    for (int t = 0; t < trials; t++)
+      {
+        // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al.
+        // Remark 4.28 states: "...A strategy that is sometimes employed
+        // is to fix the bases a to be the first few primes instead of
+        // choosing them at random.
+       z = smallFixNums[primes[t] - minFixNum].modPow(m, this);
        if (z.isOne() || z.equals(pMinus1))
          continue;                     // Passes the test; may be prime.
 
-       int i;
        for (i = 0; i < b; )
          {
            if (z.isOne())
@@ -1361,7 +1314,7 @@ public class BigInteger extends Number implements Comparable
            if (z.equals(pMinus1))
              break;                    // Passes the test; may be prime.
 
-           z = z.modPow(make(2), this);
+           z = z.modPow(valueOf(2), this);
          }
 
        if (i == b && !z.equals(pMinus1))
@@ -1462,9 +1415,9 @@ public class BigInteger extends Number implements Comparable
     if (x.words == null)
       {
        if (count <= 0)
-         return make(count > -32 ? x.ival >> (-count) : x.ival < 0 ? -1 : 0);
+         return valueOf(count > -32 ? x.ival >> (-count) : x.ival < 0 ? -1 : 0);
        if (count < 32)
-         return make((long) x.ival << count);
+         return valueOf((long) x.ival << count);
       }
     if (count == 0)
       return x;
@@ -1502,7 +1455,6 @@ public class BigInteger extends Number implements Comparable
          work = words;
        int len = ival;
 
-       int buf_size = len * (MPN.chars_per_word(radix) + 1);
        if (radix == 16)
          {
            if (neg)
@@ -1555,7 +1507,7 @@ public class BigInteger extends Number implements Comparable
   {
     if (words == null)
       return Integer.toString(ival, radix);
-    else if (ival <= 2)
+    if (ival <= 2)
       return Long.toString(longValue(), radix);
     int buf_size = ival * (MPN.chars_per_word(radix) + 1);
     StringBuffer buffer = new StringBuffer(buf_size);
@@ -1605,7 +1557,7 @@ public class BigInteger extends Number implements Comparable
   {
     if (obj == null || ! (obj instanceof BigInteger))
       return false;
-    return BigInteger.equals(this, (BigInteger) obj);
+    return equals(this, (BigInteger) obj);
   }
 
   private static BigInteger valueOf(String s, int radix)
@@ -1615,7 +1567,7 @@ public class BigInteger extends Number implements Comparable
     // Testing (len < MPN.chars_per_word(radix)) would be more accurate,
     // but slightly more expensive, for little practical gain.
     if (len <= 15 && radix <= 16)
-      return BigInteger.make(Long.parseLong(s, radix));
+      return valueOf(Long.parseLong(s, radix));
     
     int byte_len = 0;
     byte[] bytes = new byte[len];
@@ -1660,8 +1612,7 @@ public class BigInteger extends Number implements Comparable
     if (ival <= 2)
       return (double) longValue();
     if (isNegative())
-      return BigInteger.neg(this).roundToDouble(0, true, false);
-    else
+      return neg(this).roundToDouble(0, true, false);
       return roundToDouble(0, false, false);
   }
 
@@ -1769,7 +1720,6 @@ public class BigInteger extends Number implements Comparable
    * Assumes words.length >= (this.words == null ? 1 : this.ival).
    * Result is zero-extended, but need not be a valid 2's complement number.
    */
-    
   private void getAbsolute(int[] words)
   {
     int len;
@@ -1820,7 +1770,7 @@ public class BigInteger extends Number implements Comparable
        return;
       }
     realloc(len + 1);
-    if (BigInteger.negate(words, x.words, len))
+    if (negate(words, x.words, len))
       words[len++] = 0;
     ival = len;
   }
@@ -1844,7 +1794,7 @@ public class BigInteger extends Number implements Comparable
   private static BigInteger neg(BigInteger x)
   {
     if (x.words == null && x.ival != Integer.MIN_VALUE)
-      return make(- x.ival);
+      return valueOf(- x.ival);
     BigInteger result = new BigInteger(0);
     result.setNegative(x);
     return result.canonicalize();
@@ -1852,7 +1802,7 @@ public class BigInteger extends Number implements Comparable
 
   public BigInteger negate()
   {
-    return BigInteger.neg(this);
+    return neg(this);
   }
 
   /** Calculates ceiling(log2(this < 0 ? -this : this+1))
@@ -1862,7 +1812,6 @@ public class BigInteger extends Number implements Comparable
   {
     if (words == null)
       return MPN.intLength(ival);
-    else
       return MPN.intLength(words, ival);
   }
 
@@ -1913,7 +1862,7 @@ public class BigInteger extends Number implements Comparable
         case 1:  return x.and(y);
         case 3:  return x;
         case 5:  return y;
-        case 15: return make(-1);
+        case 15: return valueOf(-1);
       }
     BigInteger result = new BigInteger();
     setBitOp(result, op, x, y);
@@ -2111,15 +2060,15 @@ public class BigInteger extends Number implements Comparable
   private static BigInteger and(BigInteger x, int y)
   {
     if (x.words == null)
-      return BigInteger.make(x.ival & y);
+      return valueOf(x.ival & y);
     if (y >= 0)
-      return BigInteger.make(x.words[0] & y);
+      return valueOf(x.words[0] & y);
     int len = x.ival;
     int[] words = new int[len];
     words[0] = x.words[0] & y;
     while (--len > 0)
       words[len] = x.words[len];
-    return BigInteger.make(words, x.ival);
+    return make(words, x.ival);
   }
 
   /** Return the logical (bit-wise) "and" of two BigIntegers. */
@@ -2142,7 +2091,7 @@ public class BigInteger extends Number implements Comparable
       words[i] = x.words[i] & y.words[i];
     for ( ; i < len;  i++)
       words[i] = x.words[i];
-    return BigInteger.make(words, len);
+    return make(words, len);
   }
 
   /** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */