aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/core/src/main/j2me/java/math/BigInteger.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/core/src/main/j2me/java/math/BigInteger.java')
-rw-r--r--libraries/spongycastle/core/src/main/j2me/java/math/BigInteger.java3272
1 files changed, 0 insertions, 3272 deletions
diff --git a/libraries/spongycastle/core/src/main/j2me/java/math/BigInteger.java b/libraries/spongycastle/core/src/main/j2me/java/math/BigInteger.java
deleted file mode 100644
index 9017caa01..000000000
--- a/libraries/spongycastle/core/src/main/j2me/java/math/BigInteger.java
+++ /dev/null
@@ -1,3272 +0,0 @@
-package java.math;
-
-import java.util.Random;
-import java.util.Stack;
-
-import org.spongycastle.util.Arrays;
-
-public class BigInteger
-{
- // The first few odd primes
- /*
- 3 5 7 11 13 17 19 23 29
- 31 37 41 43 47 53 59 61 67 71
- 73 79 83 89 97 101 103 107 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 257 263 269 271 277 281
- 283 293 307 311 313 317 331 337 347 349
- 353 359 367 373 379 383 389 397 401 409
- 419 421 431 433 439 443 449 457 461 463
- 467 479 487 491 499 503 509 521 523 541
- 547 557 563 569 571 577 587 593 599 601
- 607 613 617 619 631 641 643 647 653 659
- 661 673 677 683 691 701 709 719 727 733
- 739 743 751 757 761 769 773 787 797 809
- 811 821 823 827 829 839 853 857 859 863
- 877 881 883 887 907 911 919 929 937 941
- 947 953 967 971 977 983 991 997 1009
- 1013 1019 1021 1031 1033 1039 1049 1051
- 1061 1063 1069 1087 1091 1093 1097 1103
- 1109 1117 1123 1129 1151 1153 1163 1171
- 1181 1187 1193 1201 1213 1217 1223 1229
- 1231 1237 1249 1259 1277 1279 1283 1289
- */
-
- // Each list has a product < 2^31
- private static final int[][] primeLists = new int[][]
- {
- new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 },
- new int[]{ 29, 31, 37, 41, 43 },
- new int[]{ 47, 53, 59, 61, 67 },
- new int[]{ 71, 73, 79, 83 },
- new int[]{ 89, 97, 101, 103 },
-
- new int[]{ 107, 109, 113, 127 },
- new int[]{ 131, 137, 139, 149 },
- new int[]{ 151, 157, 163, 167 },
- new int[]{ 173, 179, 181, 191 },
- new int[]{ 193, 197, 199, 211 },
-
- new int[]{ 223, 227, 229 },
- new int[]{ 233, 239, 241 },
- new int[]{ 251, 257, 263 },
- new int[]{ 269, 271, 277 },
- new int[]{ 281, 283, 293 },
-
- new int[]{ 307, 311, 313 },
- new int[]{ 317, 331, 337 },
- new int[]{ 347, 349, 353 },
- new int[]{ 359, 367, 373 },
- new int[]{ 379, 383, 389 },
-
- new int[]{ 397, 401, 409 },
- new int[]{ 419, 421, 431 },
- new int[]{ 433, 439, 443 },
- new int[]{ 449, 457, 461 },
- new int[]{ 463, 467, 479 },
-
- new int[]{ 487, 491, 499 },
- new int[]{ 503, 509, 521 },
- new int[]{ 523, 541, 547 },
- new int[]{ 557, 563, 569 },
- new int[]{ 571, 577, 587 },
-
- new int[]{ 593, 599, 601 },
- new int[]{ 607, 613, 617 },
- new int[]{ 619, 631, 641 },
- new int[]{ 643, 647, 653 },
- new int[]{ 659, 661, 673 },
-
- new int[]{ 677, 683, 691 },
- new int[]{ 701, 709, 719 },
- new int[]{ 727, 733, 739 },
- new int[]{ 743, 751, 757 },
- new int[]{ 761, 769, 773 },
-
- new int[]{ 787, 797, 809 },
- new int[]{ 811, 821, 823 },
- new int[]{ 827, 829, 839 },
- new int[]{ 853, 857, 859 },
- new int[]{ 863, 877, 881 },
-
- new int[]{ 883, 887, 907 },
- new int[]{ 911, 919, 929 },
- new int[]{ 937, 941, 947 },
- new int[]{ 953, 967, 971 },
- new int[]{ 977, 983, 991 },
-
- new int[]{ 997, 1009, 1013 },
- new int[]{ 1019, 1021, 1031 },
- new int[]{ 1033, 1039, 1049 },
- new int[]{ 1051, 1061, 1063 },
- new int[]{ 1069, 1087, 1091 },
-
- new int[]{ 1093, 1097, 1103 },
- new int[]{ 1109, 1117, 1123 },
- new int[]{ 1129, 1151, 1153 },
- new int[]{ 1163, 1171, 1181 },
- new int[]{ 1187, 1193, 1201 },
-
- new int[]{ 1213, 1217, 1223 },
- new int[]{ 1229, 1231, 1237 },
- new int[]{ 1249, 1259, 1277 },
- new int[]{ 1279, 1283, 1289 },
- };
-
- private static int[] primeProducts;
-
- private static final long IMASK = 0xffffffffL;
-
- private static final int[] ZERO_MAGNITUDE = new int[0];
-
- private static final BigInteger[] SMALL_CONSTANTS = new BigInteger[17];
- public static final BigInteger ZERO;
- public static final BigInteger ONE;
- public static final BigInteger TWO;
- public static final BigInteger THREE;
- public static final BigInteger TEN;
-
- private final static byte[] bitCounts =
- {
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
- };
-
- private final static byte[] bitLengths =
- {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
- };
-
- /*
- * These are the threshold bit-lengths (of an exponent) where we increase the window size.
- * These were calculated according to the expected savings in multiplications.
- * Some squares will also be saved on average, but we offset these against the extra storage costs.
- */
- private static final int[] EXP_WINDOW_THRESHOLDS = { 7, 25, 81, 241, 673, 1793, 4609, Integer.MAX_VALUE };
-
- static
- {
- /*
- * Avoid using large windows in VMs with little memory.
- * Window size limited to 2 below 256kB, then increased by one for every doubling,
- * i.e. at 512kB, 1MB, 2MB, etc...
- */
- long totalMemory = Runtime.getRuntime().totalMemory();
- if (totalMemory <= Integer.MAX_VALUE)
- {
- int mem = (int)totalMemory;
- int maxExpThreshold = 1 + bitLen(mem >> 18);
- if (maxExpThreshold < EXP_WINDOW_THRESHOLDS.length)
- {
- EXP_WINDOW_THRESHOLDS[maxExpThreshold] = Integer.MAX_VALUE;
- }
- }
-
- ZERO = new BigInteger(0, ZERO_MAGNITUDE);
- ZERO.nBits = 0; ZERO.nBitLength = 0;
-
- SMALL_CONSTANTS[0] = ZERO;
- int numBits = 0;
- for (int i = 1; i < SMALL_CONSTANTS.length; ++i)
- {
- SMALL_CONSTANTS[i] = createValueOf(i);
-
- // Check for a power of two
- if ((i & -i) == i)
- {
- SMALL_CONSTANTS[i].nBits = 1;
- ++numBits;
- }
-
- SMALL_CONSTANTS[i].nBitLength = numBits;
- }
-
- ONE = SMALL_CONSTANTS[1];
- TWO = SMALL_CONSTANTS[2];
- THREE = SMALL_CONSTANTS[3];
- TEN = SMALL_CONSTANTS[10];
-
- primeProducts = new int[primeLists.length];
-
- for (int i = 0; i < primeLists.length; ++i)
- {
- int[] primeList = primeLists[i];
- int product = 1;
- for (int j = 0; j < primeList.length; ++j)
- {
- product *= primeList[j];
- }
- primeProducts[i] = product;
- }
- }
-
- private int sign; // -1 means -ve; +1 means +ve; 0 means 0;
- private int[] magnitude; // array of ints with [0] being the most significant
- private int nBits = -1; // cache bitCount() value
- private int nBitLength = -1; // cache bitLength() value
- private int mQuote = 0; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.), 0 when uninitialised
-
- private BigInteger()
- {
- }
-
- private BigInteger(int signum, int[] mag)
- {
- if (mag.length > 0)
- {
- sign = signum;
-
- int i = 0;
- while (i < mag.length && mag[i] == 0)
- {
- i++;
- }
- if (i == 0)
- {
- magnitude = mag;
- }
- else
- {
- // strip leading 0 bytes
- int[] newMag = new int[mag.length - i];
- System.arraycopy(mag, i, newMag, 0, newMag.length);
- magnitude = newMag;
- if (newMag.length == 0)
- sign = 0;
- }
- }
- else
- {
- magnitude = mag;
- sign = 0;
- }
- }
-
- public BigInteger(String sval) throws NumberFormatException
- {
- this(sval, 10);
- }
-
- public BigInteger(String sval, int rdx) throws NumberFormatException
- {
- if (sval.length() == 0)
- {
- throw new NumberFormatException("Zero length BigInteger");
- }
-
- if (rdx < Character.MIN_RADIX || rdx > Character.MAX_RADIX)
- {
- throw new NumberFormatException("Radix out of range");
- }
-
- int index = 0;
- sign = 1;
-
- if (sval.charAt(0) == '-')
- {
- if (sval.length() == 1)
- {
- throw new NumberFormatException("Zero length BigInteger");
- }
-
- sign = -1;
- index = 1;
- }
-
- // strip leading zeros from the string value
- while (index < sval.length() && Character.digit(sval.charAt(index), rdx) == 0)
- {
- index++;
- }
-
- if (index >= sval.length())
- {
- // zero value - we're done
- sign = 0;
- magnitude = new int[0];
- return;
- }
-
- //////
- // could we work out the max number of ints required to store
- // sval.length digits in the given base, then allocate that
- // storage in one hit?, then generate the magnitude in one hit too?
- //////
-
- BigInteger b = ZERO;
- BigInteger r = valueOf(rdx);
- while (index < sval.length())
- {
- // (optimise this by taking chunks of digits instead?)
- b = b.multiply(r).add(valueOf(Character.digit(sval.charAt(index), rdx)));
- index++;
- }
-
- magnitude = b.magnitude;
- return;
- }
-
- public BigInteger(byte[] bval) throws NumberFormatException
- {
- if (bval.length == 0)
- {
- throw new NumberFormatException("Zero length BigInteger");
- }
-
- sign = 1;
- if (bval[0] < 0)
- {
- sign = -1;
- }
- magnitude = makeMagnitude(bval, sign);
- if (magnitude.length == 0) {
- sign = 0;
- }
- }
-
- /**
- * If sign >= 0, packs bytes into an array of ints, most significant first
- * If sign < 0, packs 2's complement of bytes into
- * an array of ints, most significant first,
- * adding an extra most significant byte in case bval = {0x80, 0x00, ..., 0x00}
- *
- * @param bval
- * @param sign
- * @return
- */
- private int[] makeMagnitude(byte[] bval, int sign)
- {
- if (sign >= 0) {
- int i;
- int[] mag;
- int firstSignificant;
-
- // strip leading zeros
- for (firstSignificant = 0; firstSignificant < bval.length
- && bval[firstSignificant] == 0; firstSignificant++);
-
- if (firstSignificant >= bval.length)
- {
- return new int[0];
- }
-
- int nInts = (bval.length - firstSignificant + 3) / 4;
- int bCount = (bval.length - firstSignificant) % 4;
- if (bCount == 0)
- bCount = 4;
- // n = k * (n / k) + n % k
- // bval.length - firstSignificant + 3 = 4 * nInts + bCount - 1
- // bval.length - firstSignificant + 4 - bCount = 4 * nInts
-
- mag = new int[nInts];
- int v = 0;
- int magnitudeIndex = 0;
- for (i = firstSignificant; i < bval.length; i++)
- {
- // bval.length + 4 - bCount - i + 4 * magnitudeIndex = 4 * nInts
- // 1 <= bCount <= 4
- v <<= 8;
- v |= bval[i] & 0xff;
- bCount--;
- if (bCount <= 0)
- {
- mag[magnitudeIndex] = v;
- magnitudeIndex++;
- bCount = 4;
- v = 0;
- }
- }
- // 4 - bCount + 4 * magnitudeIndex = 4 * nInts
- // bCount = 4 * (1 + magnitudeIndex - nInts)
- // 1 <= bCount <= 4
- // So bCount = 4 and magnitudeIndex = nInts = mag.length
-
-// if (magnitudeIndex < mag.length)
-// {
-// mag[magnitudeIndex] = v;
-// }
- return mag;
- }
- else {
- int i;
- int[] mag;
- int firstSignificant;
-
-
- // strip leading -1's
- for (firstSignificant = 0; firstSignificant < bval.length - 1
- && bval[firstSignificant] == 0xff; firstSignificant++);
-
- int nBytes = bval.length;
- boolean leadingByte = false;
-
- // check for -2^(n-1)
- if (bval[firstSignificant] == 0x80) {
- for (i = firstSignificant + 1; i < bval.length; i++) {
- if (bval[i] != 0) {
- break;
- }
- }
- if (i == bval.length) {
- nBytes++;
- leadingByte = true;
- }
- }
-
- int nInts = (nBytes - firstSignificant + 3) / 4;
- int bCount = (nBytes - firstSignificant) % 4;
- if (bCount == 0)
- bCount = 4;
-
- // n = k * (n / k) + n % k
- // nBytes - firstSignificant + 3 = 4 * nInts + bCount - 1
- // nBytes - firstSignificant + 4 - bCount = 4 * nInts
- // 1 <= bCount <= 4
-
- mag = new int[nInts];
- int v = 0;
- int magnitudeIndex = 0;
- // nBytes + 4 - bCount - i + 4 * magnitudeIndex = 4 * nInts
- // 1 <= bCount <= 4
- if (leadingByte) {
- // bval.length + 1 + 4 - bCount - i + 4 * magnitudeIndex = 4 * nInts
- bCount--;
- // bval.length + 1 + 4 - (bCount + 1) - i + 4 * magnitudeIndex = 4 * nInts
- // bval.length + 4 - bCount - i + 4 * magnitudeIndex = 4 * nInts
- if (bCount <= 0)
- {
- magnitudeIndex++;
- bCount = 4;
- }
- // bval.length + 4 - bCount - i + 4 * magnitudeIndex = 4 * nInts
- // 1 <= bCount <= 4
- }
- for (i = firstSignificant; i < bval.length; i++)
- {
- // bval.length + 4 - bCount - i + 4 * magnitudeIndex = 4 * nInts
- // 1 <= bCount <= 4
- v <<= 8;
- v |= ~bval[i] & 0xff;
- bCount--;
- if (bCount <= 0)
- {
- mag[magnitudeIndex] = v;
- magnitudeIndex++;
- bCount = 4;
- v = 0;
- }
- }
- // 4 - bCount + 4 * magnitudeIndex = 4 * nInts
- // 1 <= bCount <= 4
- // bCount = 4 * (1 + magnitudeIndex - nInts)
- // 1 <= bCount <= 4
- // So bCount = 4 and magnitudeIndex = nInts = mag.length
-
-// if (magnitudeIndex < mag.length)
-// {
-// mag[magnitudeIndex] = v;
-// }
- mag = inc(mag);
-
- // TODO Fix above so that this is not necessary?
- if (mag[0] == 0)
- {
- int[] tmp = new int[mag.length - 1];
- System.arraycopy(mag, 1, tmp, 0, tmp.length);
- mag = tmp;
- }
-
- return mag;
- }
- }
-
-
-
- public BigInteger(int sign, byte[] mag) throws NumberFormatException
- {
- if (sign < -1 || sign > 1)
- {
- throw new NumberFormatException("Invalid sign value");
- }
-
- if (sign == 0)
- {
- this.sign = 0;
- this.magnitude = new int[0];
- return;
- }
-
- // copy bytes
- this.magnitude = makeMagnitude(mag, 1);
- this.sign = sign;
- }
-
- public BigInteger(int numBits, Random rnd) throws IllegalArgumentException
- {
- if (numBits < 0)
- {
- throw new IllegalArgumentException("numBits must be non-negative");
- }
-
- this.nBits = -1;
- this.nBitLength = -1;
-
- if (numBits == 0)
- {
-// this.sign = 0;
- this.magnitude = ZERO_MAGNITUDE;
- return;
- }
-
- int nBytes = (numBits + 7) / 8;
-
- byte[] b = new byte[nBytes];
- nextRndBytes(rnd, b);
-
- // strip off any excess bits in the MSB
- int xBits = BITS_PER_BYTE * nBytes - numBits;
- b[0] &= (byte)(255 >>> xBits);
-
- this.magnitude = makeMagnitude(b, 1);
- this.sign = this.magnitude.length < 1 ? 0 : 1;
- }
-
- private static final int BITS_PER_BYTE = 8;
- private static final int BYTES_PER_INT = 4;
-
- /**
- * strictly speaking this is a little dodgey from a compliance
- * point of view as it forces people to be using SecureRandom as
- * well, that being said - this implementation is for a crypto
- * library and you do have the source!
- */
- private void nextRndBytes(Random rnd, byte[] bytes)
- {
- int numRequested = bytes.length;
- int numGot = 0,
- r = 0;
-
- if (rnd instanceof java.security.SecureRandom)
- {
- ((java.security.SecureRandom)rnd).nextBytes(bytes);
- }
- else
- {
- for (; ; )
- {
- for (int i = 0; i < BYTES_PER_INT; i++)
- {
- if (numGot == numRequested)
- {
- return;
- }
-
- r = (i == 0 ? rnd.nextInt() : r >> BITS_PER_BYTE);
- bytes[numGot++] = (byte)r;
- }
- }
- }
- }
-
- public BigInteger(int bitLength, int certainty, Random rnd) throws ArithmeticException
- {
- if (bitLength < 2)
- {
- throw new ArithmeticException("bitLength < 2");
- }
-
- this.sign = 1;
- this.nBitLength = bitLength;
-
- if (bitLength == 2)
- {
- this.magnitude = rnd.nextInt() < 0
- ? TWO.magnitude
- : THREE.magnitude;
- return;
- }
-
- int nBytes = (bitLength + 7) / BITS_PER_BYTE;
- int xBits = BITS_PER_BYTE * nBytes - bitLength;
- byte mask = (byte)(255 >>> xBits);
-
- byte[] b = new byte[nBytes];
-
- for (;;)
- {
- nextRndBytes(rnd, b);
-
- // strip off any excess bits in the MSB
- b[0] &= mask;
-
- // ensure the leading bit is 1 (to meet the strength requirement)
- b[0] |= (byte)(1 << (7 - xBits));
-
- // ensure the trailing bit is 1 (i.e. must be odd)
- b[nBytes - 1] |= (byte)1;
-
- this.magnitude = makeMagnitude(b, 1);
- this.nBits = -1;
- this.mQuote = 0;
-
- if (certainty < 1)
- break;
-
- if (this.isProbablePrime(certainty))
- break;
-
- if (bitLength > 32)
- {
- for (int rep = 0; rep < 10000; ++rep)
- {
- int n = 33 + (rnd.nextInt() >>> 1) % (bitLength - 2);
- this.magnitude[this.magnitude.length - (n >>> 5)] ^= (1 << (n & 31));
- this.magnitude[this.magnitude.length - 1] ^= (rnd.nextInt() << 1);
- this.mQuote = 0;
-
- if (this.isProbablePrime(certainty))
- return;
- }
- }
- }
- }
-
- public BigInteger abs()
- {
- return (sign >= 0) ? this : this.negate();
- }
-
- /**
- * return a = a + b - b preserved.
- */
- private int[] add(int[] a, int[] b)
- {
- int tI = a.length - 1;
- int vI = b.length - 1;
- long m = 0;
-
- while (vI >= 0)
- {
- m += (((long)a[tI]) & IMASK) + (((long)b[vI--]) & IMASK);
- a[tI--] = (int)m;
- m >>>= 32;
- }
-
- while (tI >= 0 && m != 0)
- {
- m += (((long)a[tI]) & IMASK);
- a[tI--] = (int)m;
- m >>>= 32;
- }
-
- return a;
- }
-
- /**
- * return a = a + 1.
- */
- private int[] inc(int[] a)
- {
- int tI = a.length - 1;
- long m = 0;
-
- m = (((long)a[tI]) & IMASK) + 1L;
- a[tI--] = (int)m;
- m >>>= 32;
-
- while (tI >= 0 && m != 0)
- {
- m += (((long)a[tI]) & IMASK);
- a[tI--] = (int)m;
- m >>>= 32;
- }
-
- return a;
- }
-
- public BigInteger add(BigInteger val) throws ArithmeticException
- {
- if (val.sign == 0 || val.magnitude.length == 0)
- return this;
- if (this.sign == 0 || this.magnitude.length == 0)
- return val;
-
- if (val.sign < 0)
- {
- if (this.sign > 0)
- return this.subtract(val.negate());
- }
- else
- {
- if (this.sign < 0)
- return val.subtract(this.negate());
- }
-
- return addToMagnitude(val.magnitude);
- }
-
- private BigInteger addToMagnitude(
- int[] magToAdd)
- {
- int[] big, small;
- if (this.magnitude.length < magToAdd.length)
- {
- big = magToAdd;
- small = this.magnitude;
- }
- else
- {
- big = this.magnitude;
- small = magToAdd;
- }
-
- // Conservatively avoid over-allocation when no overflow possible
- int limit = Integer.MAX_VALUE;
- if (big.length == small.length)
- limit -= small[0];
-
- boolean possibleOverflow = (big[0] ^ (1 << 31)) >= limit;
- int extra = possibleOverflow ? 1 : 0;
-
- int[] bigCopy = new int[big.length + extra];
- System.arraycopy(big, 0, bigCopy, extra, big.length);
-
- bigCopy = add(bigCopy, small);
-
- return new BigInteger(this.sign, bigCopy);
- }
-
- public BigInteger and(
- BigInteger value)
- {
- if (this.sign == 0 || value.sign == 0)
- {
- return ZERO;
- }
-
- int[] aMag = this.sign > 0
- ? this.magnitude
- : add(ONE).magnitude;
-
- int[] bMag = value.sign > 0
- ? value.magnitude
- : value.add(ONE).magnitude;
-
- boolean resultNeg = sign < 0 && value.sign < 0;
- int resultLength = Math.max(aMag.length, bMag.length);
- int[] resultMag = new int[resultLength];
-
- int aStart = resultMag.length - aMag.length;
- int bStart = resultMag.length - bMag.length;
-
- for (int i = 0; i < resultMag.length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
-
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
-
- if (value.sign < 0)
- {
- bWord = ~bWord;
- }
-
- resultMag[i] = aWord & bWord;
-
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
-
- BigInteger result = new BigInteger(1, resultMag);
-
- // TODO Optimise this case
- if (resultNeg)
- {
- result = result.not();
- }
-
- return result;
- }
-
- public BigInteger andNot(
- BigInteger value)
- {
- return and(value.not());
- }
-
- public int bitCount()
- {
- if (nBits == -1)
- {
- if (sign < 0)
- {
- // TODO Optimise this case
- nBits = not().bitCount();
- }
- else
- {
- int sum = 0;
- for (int i = 0; i < magnitude.length; i++)
- {
- sum += bitCounts[magnitude[i] & 0xff];
- sum += bitCounts[(magnitude[i] >> 8) & 0xff];
- sum += bitCounts[(magnitude[i] >> 16) & 0xff];
- sum += bitCounts[(magnitude[i] >> 24) & 0xff];
- }
- nBits = sum;
- }
- }
-
- return nBits;
- }
-
- private static int calcBitLength(int sign, int indx, int[] mag)
- {
- if (mag.length == 0)
- {
- return 0;
- }
-
- while (indx != mag.length && mag[indx] == 0)
- {
- indx++;
- }
-
- if (indx == mag.length)
- {
- return 0;
- }
-
- // bit length for everything after the first int
- int bitLength = 32 * ((mag.length - indx) - 1);
-
- // and determine bitlength of first int
- bitLength += bitLen(mag[indx]);
-
- if (sign < 0)
- {
- // Check if magnitude is a power of two
- boolean pow2 = ((bitCounts[mag[indx] & 0xff])
- + (bitCounts[(mag[indx] >> 8) & 0xff])
- + (bitCounts[(mag[indx] >> 16) & 0xff])
- + (bitCounts[(mag[indx] >> 24) & 0xff])) == 1;
-
- for (int i = indx + 1; i < mag.length && pow2; i++)
- {
- pow2 = (mag[i] == 0);
- }
-
- bitLength -= (pow2 ? 1 : 0);
- }
-
- return bitLength;
- }
-
- public int bitLength()
- {
- if (nBitLength == -1)
- {
- if (sign == 0)
- {
- nBitLength = 0;
- }
- else
- {
- nBitLength = calcBitLength(sign, 0, magnitude);
- }
- }
-
- return nBitLength;
- }
-
- //
- // bitLen(value) is the number of bits in value.
- //
- private static int bitLen(int w)
- {
- int t = w >>> 24;
- if (t != 0)
- {
- return 24 + bitLengths[t];
- }
- t = w >>> 16;
- if (t != 0)
- {
- return 16 + bitLengths[t];
- }
- t = w >>> 8;
- if (t != 0)
- {
- return 8 + bitLengths[t];
- }
- return bitLengths[w];
- }
-
- private boolean quickPow2Check()
- {
- return sign > 0 && nBits == 1;
- }
-
- public int compareTo(Object o)
- {
- return compareTo((BigInteger)o);
- }
-
- /**
- * unsigned comparison on two arrays - note the arrays may
- * start with leading zeros.
- */
- private static int compareTo(int xIndx, int[] x, int yIndx, int[] y)
- {
- while (xIndx != x.length && x[xIndx] == 0)
- {
- xIndx++;
- }
-
- while (yIndx != y.length && y[yIndx] == 0)
- {
- yIndx++;
- }
-
- return compareNoLeadingZeroes(xIndx, x, yIndx, y);
- }
-
- private static int compareNoLeadingZeroes(int xIndx, int[] x, int yIndx, int[] y)
- {
- int diff = (x.length - y.length) - (xIndx - yIndx);
-
- if (diff != 0)
- {
- return diff < 0 ? -1 : 1;
- }
-
- // lengths of magnitudes the same, test the magnitude values
-
- while (xIndx < x.length)
- {
- int v1 = x[xIndx++];
- int v2 = y[yIndx++];
-
- if (v1 != v2)
- {
- return (v1 ^ Integer.MIN_VALUE) < (v2 ^ Integer.MIN_VALUE) ? -1 : 1;
- }
- }
-
- return 0;
- }
-
- public int compareTo(BigInteger val)
- {
- if (sign < val.sign)
- return -1;
- if (sign > val.sign)
- return 1;
- if (sign == 0)
- return 0;
-
- return sign * compareTo(0, magnitude, 0, val.magnitude);
- }
-
- /**
- * return z = x / y - done in place (z value preserved, x contains the
- * remainder)
- */
- private int[] divide(int[] x, int[] y)
- {
- int xyCmp = compareTo(0, x, 0, y);
- int[] count;
-
- if (xyCmp > 0)
- {
- int[] c;
-
- int shift = calcBitLength(1, 0, x) - calcBitLength(1, 0, y);
-
- if (shift > 1)
- {
- c = shiftLeft(y, shift - 1);
- count = shiftLeft(ONE.magnitude, shift - 1);
- if (shift % 32 == 0)
- {
- // Special case where the shift is the size of an int.
- int countSpecial[] = new int[shift / 32 + 1];
- System.arraycopy(count, 0, countSpecial, 1, countSpecial.length - 1);
- countSpecial[0] = 0;
- count = countSpecial;
- }
- }
- else
- {
- c = new int[x.length];
- count = new int[1];
-
- System.arraycopy(y, 0, c, c.length - y.length, y.length);
- count[0] = 1;
- }
-
- int[] iCount = new int[count.length];
-
- subtract(0, x, 0, c);
- System.arraycopy(count, 0, iCount, 0, count.length);
-
- int xStart = 0;
- int cStart = 0;
- int iCountStart = 0;
-
- for (; ; )
- {
- int cmp = compareTo(xStart, x, cStart, c);
-
- while (cmp >= 0)
- {
- subtract(xStart, x, cStart, c);
- add(count, iCount);
- cmp = compareTo(xStart, x, cStart, c);
- }
-
- xyCmp = compareTo(xStart, x, 0, y);
-
- if (xyCmp > 0)
- {
- if (x[xStart] == 0)
- {
- xStart++;
- }
-
- shift = calcBitLength(1, cStart, c) - calcBitLength(1, xStart, x);
-
- if (shift == 0)
- {
- shiftRightOneInPlace(cStart, c);
- shiftRightOneInPlace(iCountStart, iCount);
- }
- else
- {
- shiftRightInPlace(cStart, c, shift);
- shiftRightInPlace(iCountStart, iCount, shift);
- }
-
- if (c[cStart] == 0)
- {
- cStart++;
- }
-
- if (iCount[iCountStart] == 0)
- {
- iCountStart++;
- }
- }
- else if (xyCmp == 0)
- {
- add(count, ONE.magnitude);
- for (int i = xStart; i != x.length; i++)
- {
- x[i] = 0;
- }
- break;
- }
- else
- {
- break;
- }
- }
- }
- else if (xyCmp == 0)
- {
- count = new int[1];
- count[0] = 1;
- Arrays.fill(x, 0);
- }
- else
- {
- count = new int[1];
- count[0] = 0;
- }
-
- return count;
- }
-
- public BigInteger divide(BigInteger val) throws ArithmeticException
- {
- if (val.sign == 0)
- {
- throw new ArithmeticException("Divide by zero");
- }
-
- if (sign == 0)
- {
- return BigInteger.ZERO;
- }
-
- if (val.compareTo(BigInteger.ONE) == 0)
- {
- return this;
- }
-
- int[] mag = new int[this.magnitude.length];
- System.arraycopy(this.magnitude, 0, mag, 0, mag.length);
-
- return new BigInteger(this.sign * val.sign, divide(mag, val.magnitude));
- }
-
- public BigInteger[] divideAndRemainder(BigInteger val) throws ArithmeticException
- {
- if (val.sign == 0)
- {
- throw new ArithmeticException("Divide by zero");
- }
-
- BigInteger biggies[] = new BigInteger[2];
-
- if (sign == 0)
- {
- biggies[0] = biggies[1] = BigInteger.ZERO;
-
- return biggies;
- }
-
- if (val.compareTo(BigInteger.ONE) == 0)
- {
- biggies[0] = this;
- biggies[1] = BigInteger.ZERO;
-
- return biggies;
- }
-
- int[] remainder = new int[this.magnitude.length];
- System.arraycopy(this.magnitude, 0, remainder, 0, remainder.length);
-
- int[] quotient = divide(remainder, val.magnitude);
-
- biggies[0] = new BigInteger(this.sign * val.sign, quotient);
- biggies[1] = new BigInteger(this.sign, remainder);
-
- return biggies;
- }
-
- public boolean equals(Object val)
- {
- if (val == this)
- return true;
-
- if (!(val instanceof BigInteger))
- return false;
- BigInteger biggie = (BigInteger)val;
-
- return sign == biggie.sign && isEqualMagnitude(biggie);
- }
-
- private boolean isEqualMagnitude(BigInteger x)
- {
- if (magnitude.length != x.magnitude.length)
- {
- return false;
- }
- for (int i = 0; i < magnitude.length; i++)
- {
- if (magnitude[i] != x.magnitude[i])
- {
- return false;
- }
- }
- return true;
- }
-
- public BigInteger gcd(BigInteger val)
- {
- if (val.sign == 0)
- return this.abs();
- else if (sign == 0)
- return val.abs();
-
- BigInteger r;
- BigInteger u = this;
- BigInteger v = val;
-
- while (v.sign != 0)
- {
- r = u.mod(v);
- u = v;
- v = r;
- }
-
- return u;
- }
-
- public int hashCode()
- {
- int hc = magnitude.length;
-
- if (magnitude.length > 0)
- {
- hc ^= magnitude[0];
-
- if (magnitude.length > 1)
- {
- hc ^= magnitude[magnitude.length - 1];
- }
- }
-
- return sign < 0 ? ~hc : hc;
- }
-
- public int intValue()
- {
- if (sign == 0)
- {
- return 0;
- }
-
- int n = magnitude.length;
-
- int val = magnitude[n - 1];
-
- return sign < 0 ? -val : val;
- }
-
- public byte byteValue()
- {
- return (byte)intValue();
- }
-
- /**
- * return whether or not a BigInteger is probably prime with a
- * probability of 1 - (1/2)**certainty.
- * <p>
- * From Knuth Vol 2, pg 395.
- */
- public boolean isProbablePrime(int certainty)
- {
- if (certainty <= 0)
- return true;
-
- if (sign == 0)
- return false;
-
- BigInteger n = this.abs();
-
- if (!n.testBit(0))
- return n.equals(TWO);
-
- if (n.equals(ONE))
- return false;
-
- // Try to reduce the penalty for really small numbers
- int numLists = Math.min(n.bitLength() - 1, primeLists.length);
-
- for (int i = 0; i < numLists; ++i)
- {
- int test = n.remainder(primeProducts[i]);
-
- int[] primeList = primeLists[i];
- for (int j = 0; j < primeList.length; ++j)
- {
- int prime = primeList[j];
- int qRem = test % prime;
- if (qRem == 0)
- {
- // We may find small numbers in the list
- return n.bitLength() < 16 && n.intValue() == prime;
- }
- }
- }
-
- //
- // let n = 1 + 2^kq
- //
- int s = n.getLowestSetBitMaskFirst(-1 << 1);
- BigInteger r = n.shiftRight(s);
-
- Random random = new Random();
-
- // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead
-
- BigInteger montRadix = ONE.shiftLeft(32 * n.magnitude.length).remainder(n);
- BigInteger minusMontRadix = n.subtract(montRadix);
-
- do
- {
- BigInteger a;
-
- do
- {
- a = new BigInteger(n.bitLength(), random);
- }
- while (a.sign == 0 || a.compareTo(n) >= 0
- || a.isEqualMagnitude(montRadix) || a.isEqualMagnitude(minusMontRadix));
-
- BigInteger y = modPowMonty(a, r, n, false);
-
- if (!y.equals(montRadix))
- {
- int j = 0;
- while (!y.equals(minusMontRadix))
- {
- if (++j == s)
- {
- return false;
- }
-
- y = modPowMonty(y, TWO, n, false);
-
- if (y.equals(montRadix))
- {
- return false;
- }
- }
- }
-
- certainty -= 2; // composites pass for only 1/4 possible 'a'
- }
- while (certainty > 0);
-
- return true;
- }
-
- public long longValue()
- {
- if (sign == 0)
- {
- return 0;
- }
-
- int n = magnitude.length;
-
- long val = magnitude[n - 1] & IMASK;
- if (n > 1)
- {
- val |= (magnitude[n - 2] & IMASK) << 32;
- }
-
- return sign < 0 ? -val : val;
- }
-
- public BigInteger max(BigInteger val)
- {
- return (compareTo(val) > 0) ? this : val;
- }
-
- public BigInteger min(BigInteger val)
- {
- return (compareTo(val) < 0) ? this : val;
- }
-
- public BigInteger mod(BigInteger m) throws ArithmeticException
- {
- if (m.sign <= 0)
- {
- throw new ArithmeticException("BigInteger: modulus is not positive");
- }
-
- BigInteger biggie = this.remainder(m);
-
- return (biggie.sign >= 0 ? biggie : biggie.add(m));
- }
-
- public BigInteger modInverse(BigInteger m) throws ArithmeticException
- {
- if (m.sign < 1)
- {
- throw new ArithmeticException("Modulus must be positive");
- }
-
- if (m.quickPow2Check())
- {
- return modInversePow2(m);
- }
-
- BigInteger d = this.remainder(m);
- BigInteger x = new BigInteger();
- BigInteger gcd = BigInteger.extEuclid(d, m, x, null);
-
- if (!gcd.equals(BigInteger.ONE))
- {
- throw new ArithmeticException("Numbers not relatively prime.");
- }
-
- if (x.compareTo(BigInteger.ZERO) < 0)
- {
- x = x.add(m);
- }
-
- return x;
- }
-
- private BigInteger modInversePow2(BigInteger m)
- {
-// assert m.signum() > 0;
-// assert m.bitCount() == 1;
-
- if (!testBit(0))
- {
- throw new ArithmeticException("Numbers not relatively prime.");
- }
-
- int pow = m.bitLength() - 1;
-
- long inv64 = modInverse64(longValue());
- if (pow < 64)
- {
- inv64 &= ((1L << pow) - 1);
- }
-
- BigInteger x = BigInteger.valueOf(inv64);
-
- if (pow > 64)
- {
- BigInteger d = this.remainder(m);
- int bitsCorrect = 64;
-
- do
- {
- BigInteger t = x.multiply(d).remainder(m);
- x = x.multiply(TWO.subtract(t)).remainder(m);
- bitsCorrect <<= 1;
- }
- while (bitsCorrect < pow);
-
- if (x.sign < 0)
- {
- x = x.add(m);
- }
- }
-
- return x;
- }
-
- private static int modInverse32(int d)
- {
- // Newton-Raphson division (roughly)
- int x = d; // d.x == 1 mod 2**3
- x *= 2 - d * x; // d.x == 1 mod 2**6
- x *= 2 - d * x; // d.x == 1 mod 2**12
- x *= 2 - d * x; // d.x == 1 mod 2**24
- x *= 2 - d * x; // d.x == 1 mod 2**48
-// assert d * x == 1;
- return x;
- }
-
- private static long modInverse64(long d)
- {
- // Newton's method with initial estimate "correct to 4 bits"
- long x = d + (((d + 1L) & 4L) << 1); // d.x == 1 mod 2**4
- x *= 2 - d * x; // d.x == 1 mod 2**8
- x *= 2 - d * x; // d.x == 1 mod 2**16
- x *= 2 - d * x; // d.x == 1 mod 2**32
- x *= 2 - d * x; // d.x == 1 mod 2**64
-// assert d * x == 1L;
- return x;
- }
-
- /**
- * Calculate the numbers u1, u2, and u3 such that:
- *
- * u1 * a + u2 * b = u3
- *
- * where u3 is the greatest common divider of a and b.
- * a and b using the extended Euclid algorithm (refer p. 323
- * of The Art of Computer Programming vol 2, 2nd ed).
- * This also seems to have the side effect of calculating
- * some form of multiplicative inverse.
- *
- * @param a First number to calculate gcd for
- * @param b Second number to calculate gcd for
- * @param u1Out the return object for the u1 value
- * @param u2Out the return object for the u2 value
- * @return The greatest common divisor of a and b
- */
- private static BigInteger extEuclid(BigInteger a, BigInteger b, BigInteger u1Out,
- BigInteger u2Out)
- {
- BigInteger u1 = BigInteger.ONE;
- BigInteger u3 = a;
- BigInteger v1 = BigInteger.ZERO;
- BigInteger v3 = b;
-
- while (v3.sign > 0)
- {
- BigInteger[] q = u3.divideAndRemainder(v3);
-
- BigInteger tn = u1.subtract(v1.multiply(q[0]));
- u1 = v1;
- v1 = tn;
-
- u3 = v3;
- v3 = q[1];
- }
-
- if (u1Out != null)
- {
- u1Out.sign = u1.sign;
- u1Out.magnitude = u1.magnitude;
- }
-
- if (u2Out != null)
- {
- BigInteger res = u3.subtract(u1.multiply(a)).divide(b);
- u2Out.sign = res.sign;
- u2Out.magnitude = res.magnitude;
- }
-
- return u3;
- }
-
- /**
- * zero out the array x
- */
- private static void zero(int[] x)
- {
- for (int i = 0; i != x.length; i++)
- {
- x[i] = 0;
- }
- }
-
- public BigInteger modPow(BigInteger e, BigInteger m)
- {
- if (m.sign < 1)
- {
- throw new ArithmeticException("Modulus must be positive");
- }
-
- if (m.equals(ONE))
- {
- return ZERO;
- }
-
- if (e.sign == 0)
- {
- return ONE;
- }
-
- if (sign == 0)
- {
- return ZERO;
- }
-
- boolean negExp = e.sign < 0;
- if (negExp)
- {
- e = e.negate();
- }
-
- BigInteger result = this.mod(m);
- if (!e.equals(ONE))
- {
- if ((m.magnitude[m.magnitude.length - 1] & 1) == 0)
- {
- result = modPowBarrett(result, e, m);
- }
- else
- {
- result = modPowMonty(result, e, m, true);
- }
- }
-
- if (negExp)
- {
- result = result.modInverse(m);
- }
-
- return result;
- }
-
- private static BigInteger modPowBarrett(BigInteger b, BigInteger e, BigInteger m)
- {
- int k = m.magnitude.length;
- BigInteger mr = ONE.shiftLeft((k + 1) << 5);
- BigInteger yu = ONE.shiftLeft(k << 6).divide(m);
-
- // Sliding window from MSW to LSW
- int extraBits = 0, expLength = e.bitLength();
- while (expLength > EXP_WINDOW_THRESHOLDS[extraBits])
- {
- ++extraBits;
- }
-
- int numPowers = 1 << extraBits;
- BigInteger[] oddPowers = new BigInteger[numPowers];
- oddPowers[0] = b;
-
- BigInteger b2 = reduceBarrett(b.square(), m, mr, yu);
-
- for (int i = 1; i < numPowers; ++i)
- {
- oddPowers[i] = reduceBarrett(oddPowers[i - 1].multiply(b2), m, mr, yu);
- }
-
- int[] windowList = getWindowList(e.magnitude, extraBits);
-// assert windowList.size() > 0;
-
- int window = windowList[0];
- int mult = window & 0xFF, lastZeroes = window >>> 8;
-
- BigInteger y;
- if (mult == 1)
- {
- y = b2;
- --lastZeroes;
- }
- else
- {
- y = oddPowers[mult >>> 1];
- }
-
- int windowPos = 1;
- while ((window = windowList[windowPos++]) != -1)
- {
- mult = window & 0xFF;
-
- int bits = lastZeroes + bitLengths[mult];
- for (int j = 0; j < bits; ++j)
- {
- y = reduceBarrett(y.square(), m, mr, yu);
- }
-
- y = reduceBarrett(y.multiply(oddPowers[mult >>> 1]), m, mr, yu);
-
- lastZeroes = window >>> 8;
- }
-
- for (int i = 0; i < lastZeroes; ++i)
- {
- y = reduceBarrett(y.square(), m, mr, yu);
- }
-
- return y;
- }
-
- private static BigInteger reduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu)
- {
- int xLen = x.bitLength(), mLen = m.bitLength();
- if (xLen < mLen)
- {
- return x;
- }
-
- if (xLen - mLen > 1)
- {
- int k = m.magnitude.length;
-
- BigInteger q1 = x.divideWords(k - 1);
- BigInteger q2 = q1.multiply(yu); // TODO Only need partial multiplication here
- BigInteger q3 = q2.divideWords(k + 1);
-
- BigInteger r1 = x.remainderWords(k + 1);
- BigInteger r2 = q3.multiply(m); // TODO Only need partial multiplication here
- BigInteger r3 = r2.remainderWords(k + 1);
-
- x = r1.subtract(r3);
- if (x.sign < 0)
- {
- x = x.add(mr);
- }
- }
-
- while (x.compareTo(m) >= 0)
- {
- x = x.subtract(m);
- }
-
- return x;
- }
-
- private static BigInteger modPowMonty(BigInteger b, BigInteger e, BigInteger m, boolean convert)
- {
- int n = m.magnitude.length;
- int powR = 32 * n;
- boolean smallMontyModulus = m.bitLength() + 2 <= powR;
- int mDash = m.getMQuote();
-
- // tmp = this * R mod m
- if (convert)
- {
- b = b.shiftLeft(powR).remainder(m);
- }
-
- int[] yAccum = new int[n + 1];
-
- int[] zVal = b.magnitude;
-// assert zVal.length <= n;
- if (zVal.length < n)
- {
- int[] tmp = new int[n];
- System.arraycopy(zVal, 0, tmp, n - zVal.length, zVal.length);
- zVal = tmp;
- }
-
- // Sliding window from MSW to LSW
-
- int extraBits = 0;
-
- // Filter the common case of small RSA exponents with few bits set
- if (e.magnitude.length > 1 || e.bitCount() > 2)
- {
- int expLength = e.bitLength();
- while (expLength > EXP_WINDOW_THRESHOLDS[extraBits])
- {
- ++extraBits;
- }
- }
-
- int numPowers = 1 << extraBits;
- int[][] oddPowers = new int[numPowers][];
- oddPowers[0] = zVal;
-
- int[] zSquared = Arrays.clone(zVal);
- squareMonty(yAccum, zSquared, m.magnitude, mDash, smallMontyModulus);
-
- for (int i = 1; i < numPowers; ++i)
- {
- oddPowers[i] = Arrays.clone(oddPowers[i - 1]);
- multiplyMonty(yAccum, oddPowers[i], zSquared, m.magnitude, mDash, smallMontyModulus);
- }
-
- int[] windowList = getWindowList(e.magnitude, extraBits);
-// assert windowList.size() > 0;
-
- int window = windowList[0];
- int mult = window & 0xFF, lastZeroes = window >>> 8;
-
- int[] yVal;
- if (mult == 1)
- {
- yVal = zSquared;
- --lastZeroes;
- }
- else
- {
- yVal = Arrays.clone(oddPowers[mult >>> 1]);
- }
-
- int windowPos = 1;
- while ((window = windowList[windowPos++]) != -1)
- {
- mult = window & 0xFF;
-
- int bits = lastZeroes + bitLengths[mult];
- for (int j = 0; j < bits; ++j)
- {
- squareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
- }
-
- multiplyMonty(yAccum, yVal, oddPowers[mult >>> 1], m.magnitude, mDash, smallMontyModulus);
-
- lastZeroes = window >>> 8;
- }
-
- for (int i = 0; i < lastZeroes; ++i)
- {
- squareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
- }
-
- if (convert)
- {
- // Return y * R^(-1) mod m
- reduceMonty(yVal, m.magnitude, mDash);
- }
- else if (smallMontyModulus && compareTo(0, yVal, 0, m.magnitude) >= 0)
- {
- subtract(0, yVal, 0, m.magnitude);
- }
-
- return new BigInteger(1, yVal);
- }
-
- private static int[] getWindowList(int[] mag, int extraBits)
- {
- int v = mag[0];
-// assert v != 0;
- int leadingBits = bitLen(v);
-
- int resultSize = (((mag.length - 1) << 5) + leadingBits) / (1 + extraBits) + 2;
- int[] result = new int[resultSize];
- int resultPos = 0;
-
- int bitPos = 33 - leadingBits;
- v <<= bitPos;
-
- int mult = 1, multLimit = 1 << extraBits;
- int zeroes = 0;
-
- int i = 0;
- for (; ; )
- {
- for (; bitPos < 32; ++bitPos)
- {
- if (mult < multLimit)
- {
- mult = (mult << 1) | (v >>> 31);
- }
- else if (v < 0)
- {
- result[resultPos++] = createWindowEntry(mult, zeroes);
- mult = 1;
- zeroes = 0;
- }
- else
- {
- ++zeroes;
- }
-
- v <<= 1;
- }
-
- if (++i == mag.length)
- {
- result[resultPos++] = createWindowEntry(mult, zeroes);
- break;
- }
-
- v = mag[i];
- bitPos = 0;
- }
-
- result[resultPos] = -1;
- return result;
- }
-
- private static int createWindowEntry(int mult, int zeroes)
- {
- while ((mult & 1) == 0)
- {
- mult >>>= 1;
- ++zeroes;
- }
-
- return mult | (zeroes << 8);
- }
-
- /**
- * return w with w = x * x - w is assumed to have enough space.
- */
- private static int[] square(int[] w, int[] x)
- {
- // Note: this method allows w to be only (2 * x.Length - 1) words if result will fit
-// if (w.length != 2 * x.length)
-// {
-// throw new IllegalArgumentException("no I don't think so...");
-// }
-
- long c;
-
- int wBase = w.length - 1;
-
- for (int i = x.length - 1; i != 0; --i)
- {
- long v = x[i] & IMASK;
-
- c = v * v + (w[wBase] & IMASK);
- w[wBase] = (int)c;
- c >>>= 32;
-
- for (int j = i - 1; j >= 0; --j)
- {
- long prod = v * (x[j] & IMASK);
-
- c += (w[--wBase] & IMASK) + ((prod << 1) & IMASK);
- w[wBase] = (int)c;
- c = (c >>> 32) + (prod >>> 31);
- }
-
- c += w[--wBase] & IMASK;
- w[wBase] = (int)c;
-
- if (--wBase >= 0)
- {
- w[wBase] = (int)(c >> 32);
- }
- wBase += i;
- }
-
- c = x[0] & IMASK;
-
- c = c * c + (w[wBase] & IMASK);
- w[wBase] = (int)c;
-
- if (--wBase >= 0)
- {
- w[wBase] += (int)(c >> 32);
- }
-
- return w;
- }
-
- /**
- * return x with x = y * z - x is assumed to have enough space.
- */
- private static int[] multiply(int[] x, int[] y, int[] z)
- {
- int i = z.length;
-
- if (i < 1)
- {
- return x;
- }
-
- int xBase = x.length - y.length;
-
- for (;;)
- {
- long a = z[--i] & IMASK;
- long val = 0;
-
- for (int j = y.length - 1; j >= 0; j--)
- {
- val += a * (y[j] & IMASK) + (x[xBase + j] & IMASK);
-
- x[xBase + j] = (int)val;
-
- val >>>= 32;
- }
-
- --xBase;
-
- if (i < 1)
- {
- if (xBase >= 0)
- {
- x[xBase] = (int)val;
- }
- break;
- }
-
- x[xBase] = (int)val;
- }
-
- return x;
- }
-
- /**
- * Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size)
- */
- private int getMQuote()
- {
- if (mQuote != 0)
- {
- return mQuote; // already calculated
- }
-
-// assert this.sign > 0;
-
- int d = -magnitude[magnitude.length - 1];
-
-// assert (d & 1) != 0;
-
- return mQuote = modInverse32(d);
- }
-
- private static void reduceMonty(int[] x, int[] m, int mDash) // mDash = -m^(-1) mod b
- {
- // NOTE: Not a general purpose reduction (which would allow x up to twice the bitlength of m)
-// assert x.length == m.length;
-
- int n = m.length;
-
- for (int i = n - 1; i >= 0; --i)
- {
- int x0 = x[n - 1];
-
- long t = (x0 * mDash) & IMASK;
-
- long carry = t * (m[n - 1] & IMASK) + (x0 & IMASK);
-// assert (int)carry == 0;
- carry >>>= 32;
-
- for (int j = n - 2; j >= 0; --j)
- {
- carry += t * (m[j] & IMASK) + (x[j] & IMASK);
- x[j + 1] = (int)carry;
- carry >>>= 32;
- }
-
- x[0] = (int)carry;
-// assert carry >>> 32 == 0;
- }
-
- if (compareTo(0, x, 0, m) >= 0)
- {
- subtract(0, x, 0, m);
- }
- }
-
- /**
- * Montgomery multiplication: a = x * y * R^(-1) mod m
- * <br>
- * Based algorithm 14.36 of Handbook of Applied Cryptography.
- * <br>
- * <li> m, x, y should have length n </li>
- * <li> a should have length (n + 1) </li>
- * <li> b = 2^32, R = b^n </li>
- * <br>
- * The result is put in x
- * <br>
- * NOTE: the indices of x, y, m, a different in HAC and in Java
- */
- private static void multiplyMonty(int[] a, int[] x, int[] y, int[] m, int mDash, boolean smallMontyModulus)
- // mDash = -m^(-1) mod b
- {
- int n = m.length;
- long y_0 = y[n - 1] & IMASK;
-
- // 1. a = 0 (Notation: a = (a_{n} a_{n-1} ... a_{0})_{b} )
- for (int i = 0; i <= n; i++)
- {
- a[i] = 0;
- }
-
- // 2. for i from 0 to (n - 1) do the following:
- for (int i = n; i > 0; i--)
- {
- long a0 = a[n] & IMASK;
- long x_i = x[i - 1] & IMASK;
-
- long prod1 = x_i * y_0;
- long carry = (prod1 & IMASK) + a0;
-
- // 2.1 u = ((a[0] + (x[i] * y[0]) * mDash) mod b
- long u = ((int)carry * mDash) & IMASK;
-
- // 2.2 a = (a + x_i * y + u * m) / b
- long prod2 = u * (m[n - 1] & IMASK);
- carry += (prod2 & IMASK);
-// assert (int)carry == 0;
- carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
-
- for (int j = n - 2; j >= 0; j--)
- {
- prod1 = x_i * (y[j] & IMASK);
- prod2 = u * (m[j] & IMASK);
-
- carry += (prod1 & IMASK) + (prod2 & IMASK) + (a[j + 1] & IMASK);
- a[j + 2] = (int)carry;
- carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
- }
-
- carry += (a[0] & IMASK);
- a[1] = (int)carry;
- a[0] = (int)(carry >>> 32);
- }
-
- // 3. if x >= m the x = x - m
- if (!smallMontyModulus && compareTo(0, a, 0, m) >= 0)
- {
- subtract(0, a, 0, m);
- }
-
- // put the result in x
- System.arraycopy(a, 1, x, 0, n);
- }
-
- private static void squareMonty(int[] a, int[] x, int[] m, int mDash, boolean smallMontyModulus) // mDash = -m^(-1) mod b
- {
- int n = m.length;
-
- long x0 = x[n - 1] & IMASK;
-
- {
- long carry = x0 * x0;
- long u = ((int)carry * mDash) & IMASK;
-
- long prod1, prod2 = u * (m[n - 1] & IMASK);
- carry += (prod2 & IMASK);
-// assert (int)carry == 0;
- carry = (carry >>> 32) + (prod2 >>> 32);
-// assert carry <= (IMASK << 1);
-
- for (int j = n - 2; j >= 0; --j)
- {
- prod1 = x0 * (x[j] & IMASK);
- prod2 = u * (m[j] & IMASK);
-
- carry += ((prod1 << 1) & IMASK) + (prod2 & IMASK);
- a[j + 2] = (int)carry;
- carry = (carry >>> 32) + (prod1 >>> 31) + (prod2 >>> 32);
- }
-
- a[1] = (int)carry;
- a[0] = (int)(carry >>> 32);
- }
-
- for (int i = n - 2; i >= 0; --i)
- {
- int a0 = a[n];
- long u = (a0 * mDash) & IMASK;
-
- long carry = u * (m[n - 1] & IMASK) + (a0 & IMASK);
-// assert (int)carry == 0;
- carry >>>= 32;
-
- for (int j = n - 2; j > i; --j)
- {
- carry += u * (m[j] & IMASK) + (a[j + 1] & IMASK);
- a[j + 2] = (int)carry;
- carry >>>= 32;
- }
-
- long xi = x[i] & IMASK;
-
- {
- long prod1 = xi * xi;
- long prod2 = u * (m[i] & IMASK);
-
- carry += (prod1 & IMASK) + (prod2 & IMASK) + (a[i + 1] & IMASK);
- a[i + 2] = (int)carry;
- carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
- }
-
- for (int j = i - 1; j >= 0; --j)
- {
- long prod1 = xi * (x[j] & IMASK);
- long prod2 = u * (m[j] & IMASK);
-
- carry += ((prod1 << 1) & IMASK) + (prod2 & IMASK) + (a[j + 1] & IMASK);
- a[j + 2] = (int)carry;
- carry = (carry >>> 32) + (prod1 >>> 31) + (prod2 >>> 32);
- }
-
- carry += (a[0] & IMASK);
- a[1] = (int)carry;
- a[0] = (int)(carry >>> 32);
- }
-
- if (!smallMontyModulus && compareTo(0, a, 0, m) >= 0)
- {
- subtract(0, a, 0, m);
- }
-
- System.arraycopy(a, 1, x, 0, n);
- }
-
- public BigInteger multiply(BigInteger val)
- {
- if (val == this)
- return square();
-
- if ((sign & val.sign) == 0)
- return ZERO;
-
- if (val.quickPow2Check()) // val is power of two
- {
- BigInteger result = this.shiftLeft(val.abs().bitLength() - 1);
- return val.sign > 0 ? result : result.negate();
- }
-
- if (this.quickPow2Check()) // this is power of two
- {
- BigInteger result = val.shiftLeft(this.abs().bitLength() - 1);
- return this.sign > 0 ? result : result.negate();
- }
-
- int resLength = magnitude.length + val.magnitude.length;
- int[] res = new int[resLength];
-
- multiply(res, this.magnitude, val.magnitude);
-
- int resSign = sign ^ val.sign ^ 1;
- return new BigInteger(resSign, res);
- }
-
- public BigInteger square()
- {
- if (sign == 0)
- {
- return ZERO;
- }
- if (this.quickPow2Check())
- {
- return shiftLeft(abs().bitLength() - 1);
- }
- int resLength = magnitude.length << 1;
- if ((magnitude[0] >>> 16) == 0)
- {
- --resLength;
- }
- int[] res = new int[resLength];
- square(res, magnitude);
- return new BigInteger(1, res);
- }
-
- public BigInteger negate()
- {
- if (sign == 0)
- {
- return this;
- }
-
- return new BigInteger(-sign, magnitude);
- }
-
- public BigInteger not()
- {
- return add(ONE).negate();
- }
-
- public BigInteger pow(int exp) throws ArithmeticException
- {
- if (exp <= 0)
- {
- if (exp < 0)
- throw new ArithmeticException("Negative exponent");
-
- return ONE;
- }
-
- if (sign == 0)
- {
- return this;
- }
-
- if (quickPow2Check())
- {
- long powOf2 = (long)exp * (bitLength() - 1);
- if (powOf2 > Integer.MAX_VALUE)
- {
- throw new ArithmeticException("Result too large");
- }
- return ONE.shiftLeft((int)powOf2);
- }
-
- BigInteger y = BigInteger.ONE, z = this;
-
- while (exp != 0)
- {
- if ((exp & 0x1) == 1)
- {
- y = y.multiply(z);
- }
- exp >>= 1;
- if (exp != 0)
- {
- z = z.multiply(z);
- }
- }
-
- return y;
- }
-
- public static BigInteger probablePrime(
- int bitLength,
- Random random)
- {
- return new BigInteger(bitLength, 100, random);
- }
-
- private int remainder(int m)
- {
- long acc = 0;
- for (int pos = 0; pos < magnitude.length; ++pos)
- {
- acc = (acc << 32 | ((long)magnitude[pos] & 0xffffffffL)) % m;
- }
-
- return (int) acc;
- }
-
- /**
- * return x = x % y - done in place (y value preserved)
- */
- private static int[] remainder(int[] x, int[] y)
- {
- int xStart = 0;
- while (xStart < x.length && x[xStart] == 0)
- {
- ++xStart;
- }
-
- int yStart = 0;
- while (yStart < y.length && y[yStart] == 0)
- {
- ++yStart;
- }
-
- int xyCmp = compareNoLeadingZeroes(xStart, x, yStart, y);
-
- if (xyCmp > 0)
- {
- int yBitLength = calcBitLength(1, yStart, y);
- int xBitLength = calcBitLength(1, xStart, x);
- int shift = xBitLength - yBitLength;
-
- int[] c;
- int cStart = 0;
- int cBitLength = yBitLength;
- if (shift > 0)
- {
- c = shiftLeft(y, shift);
- cBitLength += shift;
- }
- else
- {
- int len = y.length - yStart;
- c = new int[len];
- System.arraycopy(y, yStart, c, 0, len);
- }
-
- for (;;)
- {
- if (cBitLength < xBitLength
- || compareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
- {
- subtract(xStart, x, cStart, c);
-
- while (x[xStart] == 0)
- {
- if (++xStart == x.length)
- {
- return x;
- }
- }
-
- xyCmp = compareNoLeadingZeroes(xStart, x, yStart, y);
-
- if (xyCmp <= 0)
- {
- break;
- }
-
- //xBitLength = bitLength(xStart, x);
- xBitLength = 32 * (x.length - xStart - 1) + bitLen(x[xStart]);
- }
-
- shift = cBitLength - xBitLength;
-
- if (shift < 2)
- {
- shiftRightOneInPlace(cStart, c);
- --cBitLength;
- }
- else
- {
- shiftRightInPlace(cStart, c, shift);
- cBitLength -= shift;
- }
-
-// cStart = c.length - ((cBitLength + 31) / 32);
- while (c[cStart] == 0)
- {
- ++cStart;
- }
- }
- }
-
- if (xyCmp == 0)
- {
- for (int i = xStart; i < x.length; ++i)
- {
- x[i] = 0;
- }
- }
-
- return x;
- }
-
- public BigInteger remainder(BigInteger n) throws ArithmeticException
- {
- if (n.sign == 0)
- {
- throw new ArithmeticException("BigInteger: Divide by zero");
- }
-
- if (sign == 0)
- {
- return BigInteger.ZERO;
- }
-
- // For small values, use fast remainder method
- if (n.magnitude.length == 1)
- {
- int val = n.magnitude[0];
-
- if (val > 0)
- {
- if (val == 1)
- return ZERO;
-
- int rem = remainder(val);
-
- return rem == 0
- ? ZERO
- : new BigInteger(sign, new int[]{ rem });
- }
- }
-
- if (compareTo(0, magnitude, 0, n.magnitude) < 0)
- return this;
-
- int[] res;
- if (n.quickPow2Check()) // n is power of two
- {
- // TODO Move before small values branch above?
- res = lastNBits(n.abs().bitLength() - 1);
- }
- else
- {
- res = new int[this.magnitude.length];
- System.arraycopy(this.magnitude, 0, res, 0, res.length);
- res = remainder(res, n.magnitude);
- }
-
- return new BigInteger(sign, res);
- }
-
- private int[] lastNBits(
- int n)
- {
- if (n < 1)
- {
- return ZERO_MAGNITUDE;
- }
-
- int numWords = (n + 31) / 32;
- numWords = Math.min(numWords, this.magnitude.length);
- int[] result = new int[numWords];
-
- System.arraycopy(this.magnitude, this.magnitude.length - numWords, result, 0, numWords);
-
- int excessBits = (numWords << 5) - n;
- if (excessBits > 0)
- {
- result[0] &= (-1 >>> excessBits);
- }
-
- return result;
- }
-
- private BigInteger divideWords(int w)
- {
-// assert w >= 0;
- int n = magnitude.length;
- if (w >= n)
- {
- return ZERO;
- }
- int[] mag = new int[n - w];
- System.arraycopy(magnitude, 0, mag, 0, n - w);
- return new BigInteger(sign, mag);
- }
-
- private BigInteger remainderWords(int w)
- {
-// assert w >= 0;
- int n = magnitude.length;
- if (w >= n)
- {
- return this;
- }
- int[] mag = new int[w];
- System.arraycopy(magnitude, n - w, mag, 0, w);
- return new BigInteger(sign, mag);
- }
-
- /**
- * do a left shift - this returns a new array.
- */
- private static int[] shiftLeft(int[] mag, int n)
- {
- int nInts = n >>> 5;
- int nBits = n & 0x1f;
- int magLen = mag.length;
- int newMag[] = null;
-
- if (nBits == 0)
- {
- newMag = new int[magLen + nInts];
- System.arraycopy(mag, 0, newMag, 0, magLen);
- }
- else
- {
- int i = 0;
- int nBits2 = 32 - nBits;
- int highBits = mag[0] >>> nBits2;
-
- if (highBits != 0)
- {
- newMag = new int[magLen + nInts + 1];
- newMag[i++] = highBits;
- }
- else
- {
- newMag = new int[magLen + nInts];
- }
-
- int m = mag[0];
- for (int j = 0; j < magLen - 1; j++)
- {
- int next = mag[j + 1];
-
- newMag[i++] = (m << nBits) | (next >>> nBits2);
- m = next;
- }
-
- newMag[i] = mag[magLen - 1] << nBits;
- }
-
- return newMag;
- }
-
- private static int shiftLeftOneInPlace(int[] x, int carry)
- {
-// assert carry == 0 || carry == 1;
- int pos = x.length;
- while (--pos >= 0)
- {
- int val = x[pos];
- x[pos] = (val << 1) | carry;
- carry = val >>> 31;
- }
- return carry;
- }
-
- public BigInteger shiftLeft(int n)
- {
- if (sign == 0 || magnitude.length == 0)
- {
- return ZERO;
- }
-
- if (n == 0)
- {
- return this;
- }
-
- if (n < 0)
- {
- return shiftRight( -n);
- }
-
- BigInteger result = new BigInteger(sign, shiftLeft(magnitude, n));
-
- if (this.nBits != -1)
- {
- result.nBits = sign > 0
- ? this.nBits
- : this.nBits + n;
- }
-
- if (this.nBitLength != -1)
- {
- result.nBitLength = this.nBitLength + n;
- }
-
- return result;
- }
-
- /**
- * do a right shift - this does it in place.
- */
- private static void shiftRightInPlace(int start, int[] mag, int n)
- {
- int nInts = (n >>> 5) + start;
- int nBits = n & 0x1f;
- int magEnd = mag.length - 1;
-
- if (nInts != start)
- {
- int delta = (nInts - start);
-
- for (int i = magEnd; i >= nInts; i--)
- {
- mag[i] = mag[i - delta];
- }
- for (int i = nInts - 1; i >= start; i--)
- {
- mag[i] = 0;
- }
- }
-
- if (nBits != 0)
- {
- int nBits2 = 32 - nBits;
- int m = mag[magEnd];
-
- for (int i = magEnd; i >= nInts + 1; i--)
- {
- int next = mag[i - 1];
-
- mag[i] = (m >>> nBits) | (next << nBits2);
- m = next;
- }
-
- mag[nInts] >>>= nBits;
- }
- }
-
- /**
- * do a right shift by one - this does it in place.
- */
- private static void shiftRightOneInPlace(int start, int[] mag)
- {
- int magEnd = mag.length - 1;
-
- int m = mag[magEnd];
-
- for (int i = magEnd; i > start; i--)
- {
- int next = mag[i - 1];
-
- mag[i] = (m >>> 1) | (next << 31);
- m = next;
- }
-
- mag[start] >>>= 1;
- }
-
- public BigInteger shiftRight(int n)
- {
- if (n == 0)
- {
- return this;
- }
-
- if (n < 0)
- {
- return shiftLeft( -n);
- }
-
- if (n >= bitLength())
- {
- return (this.sign < 0 ? valueOf( -1) : BigInteger.ZERO);
- }
-
- int[] res = new int[this.magnitude.length];
- System.arraycopy(this.magnitude, 0, res, 0, res.length);
- shiftRightInPlace(0, res, n);
-
- return new BigInteger(this.sign, res);
-
- // TODO Port C# version's optimisations...
- }
-
- public int signum()
- {
- return sign;
- }
-
- /**
- * returns x = x - y - we assume x is >= y
- */
- private static int[] subtract(int xStart, int[] x, int yStart, int[] y)
- {
- int iT = x.length;
- int iV = y.length;
- long m;
- int borrow = 0;
-
- do
- {
- m = ((long)x[--iT] & IMASK) - ((long)y[--iV] & IMASK) + borrow;
- x[iT] = (int)m;
-
-// borrow = (m < 0) ? -1 : 0;
- borrow = (int)(m >> 63);
- }
- while (iV > yStart);
-
- if (borrow != 0)
- {
- while (--x[--iT] == -1)
- {
- }
- }
-
- return x;
- }
-
- public BigInteger subtract(BigInteger val)
- {
- if (val.sign == 0 || val.magnitude.length == 0)
- {
- return this;
- }
- if (sign == 0 || magnitude.length == 0)
- {
- return val.negate();
- }
- if (this.sign != val.sign)
- {
- return this.add(val.negate());
- }
-
- int compare = compareTo(0, magnitude, 0, val.magnitude);
- if (compare == 0)
- {
- return ZERO;
- }
-
- BigInteger bigun, littlun;
- if (compare < 0)
- {
- bigun = val;
- littlun = this;
- }
- else
- {
- bigun = this;
- littlun = val;
- }
-
- int res[] = new int[bigun.magnitude.length];
-
- System.arraycopy(bigun.magnitude, 0, res, 0, res.length);
-
- return new BigInteger(this.sign * compare, subtract(0, res, 0, littlun.magnitude));
- }
-
- public byte[] toByteArray()
- {
- if (sign == 0)
- {
- return new byte[1];
- }
-
- int bitLength = bitLength();
- byte[] bytes = new byte[bitLength / 8 + 1];
-
- int magIndex = magnitude.length;
- int bytesIndex = bytes.length;
-
- if (sign > 0)
- {
- while (magIndex > 1)
- {
- int mag = magnitude[--magIndex];
- bytes[--bytesIndex] = (byte) mag;
- bytes[--bytesIndex] = (byte)(mag >>> 8);
- bytes[--bytesIndex] = (byte)(mag >>> 16);
- bytes[--bytesIndex] = (byte)(mag >>> 24);
- }
-
- int lastMag = magnitude[0];
- while ((lastMag & 0xFFFFFF00) != 0)
- {
- bytes[--bytesIndex] = (byte) lastMag;
- lastMag >>>= 8;
- }
-
- bytes[--bytesIndex] = (byte) lastMag;
- }
- else
- {
- boolean carry = true;
-
- while (magIndex > 1)
- {
- int mag = ~magnitude[--magIndex];
-
- if (carry)
- {
- carry = (++mag == 0);
- }
-
- bytes[--bytesIndex] = (byte) mag;
- bytes[--bytesIndex] = (byte)(mag >>> 8);
- bytes[--bytesIndex] = (byte)(mag >>> 16);
- bytes[--bytesIndex] = (byte)(mag >>> 24);
- }
-
- int lastMag = magnitude[0];
-
- if (carry)
- {
- // Never wraps because magnitude[0] != 0
- --lastMag;
- }
-
- while ((lastMag & 0xFFFFFF00) != 0)
- {
- bytes[--bytesIndex] = (byte) ~lastMag;
- lastMag >>>= 8;
- }
-
- bytes[--bytesIndex] = (byte) ~lastMag;
-
- if (bytesIndex > 0)
- {
- bytes[--bytesIndex] = (byte)0xFF;
- }
- }
-
- return bytes;
- }
-
- public BigInteger xor(BigInteger val)
- {
- if (this.sign == 0)
- {
- return val;
- }
-
- if (val.sign == 0)
- {
- return this;
- }
-
- int[] aMag = this.sign > 0
- ? this.magnitude
- : this.add(ONE).magnitude;
-
- int[] bMag = val.sign > 0
- ? val.magnitude
- : val.add(ONE).magnitude;
-
- boolean resultNeg = (sign < 0 && val.sign >= 0) || (sign >= 0 && val.sign < 0);
- int resultLength = Math.max(aMag.length, bMag.length);
- int[] resultMag = new int[resultLength];
-
- int aStart = resultMag.length - aMag.length;
- int bStart = resultMag.length - bMag.length;
-
- for (int i = 0; i < resultMag.length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
-
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
-
- if (val.sign < 0)
- {
- bWord = ~bWord;
- }
-
- resultMag[i] = aWord ^ bWord;
-
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
-
- BigInteger result = new BigInteger(1, resultMag);
-
- if (resultNeg)
- {
- result = result.not();
- }
-
- return result;
- }
-
- public BigInteger or(
- BigInteger value)
- {
- if (this.sign == 0)
- {
- return value;
- }
-
- if (value.sign == 0)
- {
- return this;
- }
-
- int[] aMag = this.sign > 0
- ? this.magnitude
- : this.add(ONE).magnitude;
-
- int[] bMag = value.sign > 0
- ? value.magnitude
- : value.add(ONE).magnitude;
-
- boolean resultNeg = sign < 0 || value.sign < 0;
- int resultLength = Math.max(aMag.length, bMag.length);
- int[] resultMag = new int[resultLength];
-
- int aStart = resultMag.length - aMag.length;
- int bStart = resultMag.length - bMag.length;
-
- for (int i = 0; i < resultMag.length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
-
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
-
- if (value.sign < 0)
- {
- bWord = ~bWord;
- }
-
- resultMag[i] = aWord | bWord;
-
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
-
- BigInteger result = new BigInteger(1, resultMag);
-
- if (resultNeg)
- {
- result = result.not();
- }
-
- return result;
- }
-
- public BigInteger setBit(int n)
- throws ArithmeticException
- {
- if (n < 0)
- {
- throw new ArithmeticException("Bit address less than zero");
- }
-
- if (testBit(n))
- {
- return this;
- }
-
- // TODO Handle negative values and zero
- if (sign > 0 && n < (bitLength() - 1))
- {
- return flipExistingBit(n);
- }
-
- return or(ONE.shiftLeft(n));
- }
-
- public BigInteger clearBit(int n)
- throws ArithmeticException
- {
- if (n < 0)
- {
- throw new ArithmeticException("Bit address less than zero");
- }
-
- if (!testBit(n))
- {
- return this;
- }
-
- // TODO Handle negative values
- if (sign > 0 && n < (bitLength() - 1))
- {
- return flipExistingBit(n);
- }
-
- return andNot(ONE.shiftLeft(n));
- }
-
- public BigInteger flipBit(int n)
- throws ArithmeticException
- {
- if (n < 0)
- {
- throw new ArithmeticException("Bit address less than zero");
- }
-
- // TODO Handle negative values and zero
- if (sign > 0 && n < (bitLength() - 1))
- {
- return flipExistingBit(n);
- }
-
- return xor(ONE.shiftLeft(n));
- }
-
- private BigInteger flipExistingBit(int n)
- {
- int[] mag = new int[this.magnitude.length];
- System.arraycopy(this.magnitude, 0, mag, 0, mag.length);
- mag[mag.length - 1 - (n >>> 5)] ^= (1 << (n & 31)); // Flip 0 bit to 1
- //mag[mag.Length - 1 - (n / 32)] |= (1 << (n % 32));
- return new BigInteger(this.sign, mag);
- }
-
- public String toString()
- {
- return toString(10);
- }
-
- public String toString(int rdx)
- {
- if (magnitude == null)
- {
- return "null";
- }
- if (sign == 0)
- {
- return "0";
- }
- if (rdx < Character.MIN_RADIX || rdx > Character.MAX_RADIX)
- {
- rdx = 10;
- }
-
-
- // NOTE: This *should* be unnecessary, since the magnitude *should* never have leading zero digits
- int firstNonZero = 0;
- while (firstNonZero < magnitude.length)
- {
- if (magnitude[firstNonZero] != 0)
- {
- break;
- }
- ++firstNonZero;
- }
-
- if (firstNonZero == magnitude.length)
- {
- return "0";
- }
-
-
- StringBuffer sb = new StringBuffer();
- if (sign == -1)
- {
- sb.append('-');
- }
-
- switch (rdx)
- {
- case 2:
- {
- int pos = firstNonZero;
- sb.append(Integer.toBinaryString(magnitude[pos]));
- while (++pos < magnitude.length)
- {
- appendZeroExtendedString(sb, Integer.toBinaryString(magnitude[pos]), 32);
- }
- break;
- }
- case 4:
- {
- int pos = firstNonZero;
- int mag = magnitude[pos];
- if (mag < 0)
- {
- sb.append(Integer.toString(mag >>> 30, 4));
- mag &= (1 << 30) - 1;
- appendZeroExtendedString(sb, Integer.toString(mag, 4), 15);
- }
- else
- {
- sb.append(Integer.toString(mag, 4));
- }
- int mask = (1 << 16) - 1;
- while (++pos < magnitude.length)
- {
- mag = magnitude[pos];
- appendZeroExtendedString(sb, Integer.toString(mag >>> 16, 4), 8);
- appendZeroExtendedString(sb, Integer.toString(mag & mask, 4), 8);
- }
- break;
- }
- case 8:
- {
- long mask = (1L << 63) - 1;
- BigInteger u = this.abs();
- int bits = u.bitLength();
- Stack S = new Stack();
- while (bits > 63)
- {
- S.push(Long.toString((u.longValue() & mask),8));
- u = u.shiftRight(63);
- bits -= 63;
- }
- sb.append(Long.toString(u.longValue(), 8));
- while (!S.empty())
- {
- appendZeroExtendedString(sb, (String)S.pop(), 21);
- }
- break;
- }
- case 16:
- {
- int pos = firstNonZero;
- sb.append(Integer.toHexString(magnitude[pos]));
- while (++pos < magnitude.length)
- {
- appendZeroExtendedString(sb, Integer.toHexString(magnitude[pos]), 8);
- }
- break;
- }
- default:
- {
- BigInteger q = this.abs();
- if (q.bitLength() < 64)
- {
- sb.append(Long.toString(q.longValue(), rdx));
- break;
- }
-
- // Based on algorithm 1a from chapter 4.4 in Seminumerical Algorithms (Knuth)
-
- // Work out the largest power of 'rdx' that is a positive 64-bit integer
- // TODO possibly cache power/exponent against radix?
- long limit = Long.MAX_VALUE / rdx;
- long power = rdx;
- int exponent = 1;
- while (power <= limit)
- {
- power *= rdx;
- ++exponent;
- }
-
- BigInteger bigPower = BigInteger.valueOf(power);
-
- Stack S = new Stack();
- while (q.compareTo(bigPower) >= 0)
- {
- BigInteger[] qr = q.divideAndRemainder(bigPower);
- S.push(Long.toString(qr[1].longValue(), rdx));
- q = qr[0];
- }
-
- sb.append(Long.toString(q.longValue(), rdx));
- while (!S.empty())
- {
- appendZeroExtendedString(sb, (String)S.pop(), exponent);
- }
- break;
- }
- }
-
- return sb.toString();
- }
-
- private static void appendZeroExtendedString(StringBuffer sb, String s, int minLength)
- {
- for (int len = s.length(); len < minLength; ++len)
- {
- sb.append('0');
- }
- sb.append(s);
- }
-
- public static BigInteger valueOf(long val)
- {
- if (val >= 0 && val < SMALL_CONSTANTS.length)
- {
- return SMALL_CONSTANTS[(int)val];
- }
-
- return createValueOf(val);
- }
-
- private static BigInteger createValueOf(long val)
- {
- if (val < 0)
- {
- if (val == Long.MIN_VALUE)
- {
- return valueOf(~val).not();
- }
-
- return valueOf(-val).negate();
- }
-
- // store val into a byte array
- byte[] b = new byte[8];
- for (int i = 0; i < 8; i++)
- {
- b[7 - i] = (byte)val;
- val >>= 8;
- }
-
- return new BigInteger(b);
- }
-
- public int getLowestSetBit()
- {
- if (this.sign == 0)
- {
- return -1;
- }
-
- return getLowestSetBitMaskFirst(-1);
- }
-
- private int getLowestSetBitMaskFirst(int firstWordMask)
- {
- int w = magnitude.length, offset = 0;
-
- int word = magnitude[--w] & firstWordMask;
-// assert magnitude[0] != 0;
-
- while (word == 0)
- {
- word = magnitude[--w];
- offset += 32;
- }
-
- while ((word & 0xFF) == 0)
- {
- word >>>= 8;
- offset += 8;
- }
-
- while ((word & 1) == 0)
- {
- word >>>= 1;
- ++offset;
- }
-
- return offset;
- }
-
- public boolean testBit(int n)
- throws ArithmeticException
- {
- if (n < 0)
- {
- throw new ArithmeticException("Bit position must not be negative");
- }
-
- if (sign < 0)
- {
- return !not().testBit(n);
- }
-
- int wordNum = n / 32;
- if (wordNum >= magnitude.length)
- return false;
-
- int word = magnitude[magnitude.length - 1 - wordNum];
- return ((word >> (n % 32)) & 1) > 0;
- }
-}