using System; using System.Text; using System.Diagnostics; using System.Globalization; namespace HH.WMS.Utils.NPOI.Util { public class BigInteger : IComparable { /** * The signum of this BigInteger: -1 for negative, 0 for zero, or * 1 for positive. Note that the BigInteger zero must have * a signum of 0. This is necessary to ensures that there is exactly one * representation for each BigInteger value. * * @serial */ private int _signum; /** * The magnitude of this BigInteger, in big-endian order: the * zeroth element of this array is the most-significant int of the * magnitude. The magnitude must be "minimal" in that the most-significant * int ({@code mag[0]}) must be non-zero. This is necessary to * ensure that there is exactly one representation for each BigInteger * value. Note that this implies that the BigInteger zero has a * zero-length mag array. */ internal int[] mag; // These "redundant fields" are initialized with recognizable nonsense // values, and cached the first time they are needed (or never, if they // aren't needed). /** * One plus the bitCount of this BigInteger. Zeros means unitialized. * * @serial * @see #bitCount * @deprecated Deprecated since logical value is offset from stored * value and correction factor is applied in accessor method. */ #if !HIDE_UNREACHABLE_CODE [Obsolete] #endif private int bitCount; /** * One plus the bitLength of this BigInteger. Zeros means unitialized. * (either value is acceptable). * * @serial * @see #bitLength() * @deprecated Deprecated since logical value is offset from stored * value and correction factor is applied in accessor method. */ #if !HIDE_UNREACHABLE_CODE [Obsolete] #endif private int bitLength; // /** // * Two plus the lowest set bit of this BigInteger, as returned by // * getLowestSetBit(). // * // * @serial // * @see #getLowestSetBit // * @deprecated Deprecated since logical value is offset from stored // * value and correction factor is applied in accessor method. // */ // [Obsolete] // never used private int lowestSetBit; /** * Two plus the index of the lowest-order int in the magnitude of this * BigInteger that contains a nonzero int, or -2 (either value is acceptable). * The least significant int has int-number 0, the next int in order of * increasing significance has int-number 1, and so forth. * @deprecated Deprecated since logical value is offset from stored * value and correction factor is applied in accessor method. */ #if !HIDE_UNREACHABLE_CODE [Obsolete] #endif private int firstNonzeroIntNum; /** * This mask is used to obtain the value of an int as if it were unsigned. */ public const long LONG_MASK = 0xffffffffL; public static long INFLATED = long.MinValue; public const int MIN_RADIX = 2; public const int MAX_RADIX = 36; private static String[] zeros = new String[64]; //Constructors static BigInteger() { for (int i = 1; i <= MAX_CONSTANT; i++) { int[] magnitude = new int[1]; magnitude[0] = i; posConst[i] = new BigInteger(magnitude, 1); negConst[i] = new BigInteger(magnitude, -1); } zeros[63] = "000000000000000000000000000000000000000000000000000000000000000"; for (int i = 0; i < 63; i++) zeros[i] = zeros[63].Substring(0, i); } /** * This internal constructor differs from its public cousin * with the arguments reversed in two ways: it assumes that its * arguments are correct, and it doesn't copy the magnitude array. */ public BigInteger(int[] magnitude, int signum) { this._signum = (magnitude.Length == 0 ? 0 : signum); this.mag = magnitude; } /** * Translates a byte array containing the two's-complement binary * representation of a BigInteger into a BigInteger. The input array is * assumed to be in big-endian byte-order: the most significant * byte is in the zeroth element. * * @param val big-endian two's-complement binary representation of * BigInteger. * @throws NumberFormatException {@code val} is zero bytes long. */ public BigInteger(byte[] val) { if (val.Length == 0) throw new ArgumentException("Zero length BigInteger"); if ((sbyte)val[0] < 0) { mag = makePositive(val); _signum = -1; } else { mag = stripLeadingZeroBytes(val); _signum = (mag.Length == 0 ? 0 : 1); } } /** * This private constructor translates an int array containing the * two's-complement binary representation of a BigInteger into a * BigInteger. The input array is assumed to be in big-endian * int-order: the most significant int is in the zeroth element. */ public BigInteger(int[] val) { if (val.Length == 0) throw new ArgumentException("Zero length BigInteger"); if (val[0] < 0) { mag = makePositive(val); _signum = -1; } else { mag = trustedStripLeadingZeroInts(val); _signum = (mag.Length == 0 ? 0 : 1); } } /** * Constructs a BigInteger with the specified value, which may not be zero. */ public BigInteger(long val) { if (val < 0) { val = -val; _signum = -1; } else { _signum = 1; } int highWord = (int)Operator.UnsignedRightShift(val, 32); if (highWord == 0) { mag = new int[1]; mag[0] = (int)val; } else { mag = new int[2]; mag[0] = highWord; mag[1] = (int)val; } } public BigInteger(String val, int radix) { int cursor = 0, numDigits; int len = val.Length; if (radix < MIN_RADIX || radix > MAX_RADIX) throw new FormatException("Radix out of range"); if (len == 0) throw new FormatException("Zero length BigInteger"); // Check for at most one leading sign int sign = 1; int index1 = val.LastIndexOf('-'); int index2 = val.LastIndexOf('+'); if ((index1 + index2) <= -1) { // No leading sign character or at most one leading sign character if (index1 == 0 || index2 == 0) { cursor = 1; if (len == 1) throw new FormatException("Zero length BigInteger"); } if (index1 == 0) sign = -1; } else throw new FormatException("Illegal embedded sign character"); // Skip leading zeros and compute number of digits in magnitude while (cursor < len && val[cursor] == '0') //now it can only process 10 radix //Character.digit(val.charAt(cursor), radix) == 0) // cursor++; if (cursor == len) { _signum = 0; mag = ZERO.mag; return; } numDigits = len - cursor; _signum = sign; // Pre-allocate array of expected size. May be too large but can // never be too small. Typically exact. int numBits = (int)(Operator.UnsignedRightShift((numDigits * bitsPerDigit[radix]), 10) + 1); int numWords = Operator.UnsignedRightShift(numBits + 31, 5); int[] magnitude = new int[numWords]; // Process first (potentially short) digit group int firstGroupLen = numDigits % digitsPerInt[radix]; if (firstGroupLen == 0) firstGroupLen = digitsPerInt[radix]; String group = val.Substring(cursor, cursor += firstGroupLen); //magnitude[numWords - 1] = Integer.parseInt(group, radix); magnitude[numWords - 1] = int.Parse(group, CultureInfo.InvariantCulture); if (magnitude[numWords - 1] < 0) throw new FormatException("Illegal digit"); // Process remaining digit groups int superRadix = intRadix[radix]; int groupVal = 0; while (cursor < len) { group = val.Substring(cursor, cursor += digitsPerInt[radix]); //groupVal = Integer.parseInt(group, radix); groupVal = int.Parse(group, CultureInfo.InvariantCulture); if (groupVal < 0) throw new FormatException("Illegal digit"); destructiveMulAdd(magnitude, superRadix, groupVal); } // Required for cases where the array was overallocated. mag = trustedStripLeadingZeroInts(magnitude); } /** * Returns the input array stripped of any leading zero bytes. * Since the source is trusted the copying may be skipped. */ private static int[] trustedStripLeadingZeroInts(int[] val) { int vlen = val.Length; int keep; // Find first nonzero byte for (keep = 0; keep < vlen && val[keep] == 0; keep++) ; return keep == 0 ? val : Arrays.CopyOfRange(val, keep, vlen); } // Multiply x array times word y in place, and add word z private static void destructiveMulAdd(int[] x, int y, int z) { // Perform the multiplication word by word long ylong = y & LONG_MASK; long zlong = z & LONG_MASK; int len = x.Length; long product = 0; long carry = 0; for (int i = len - 1; i >= 0; i--) { product = ylong * (x[i] & LONG_MASK) + carry; x[i] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } // Perform the addition long sum = (x[len - 1] & LONG_MASK) + zlong; x[len - 1] = (int)sum; carry = Operator.UnsignedRightShift(sum, 32); for (int i = len - 2; i >= 0; i--) { sum = (x[i] & LONG_MASK) + carry; x[i] = (int)sum; carry = Operator.UnsignedRightShift(sum, 32); } } /** * Returns the String representation of this BigInteger in the * given radix. If the radix is outside the range from {@link * Character#MIN_RADIX} to {@link Character#MAX_RADIX} inclusive, * it will default to 10 (as is the case for * {@code Integer.toString}). The digit-to-character mapping * provided by {@code Character.forDigit} is used, and a minus * sign is prepended if appropriate. (This representation is * compatible with the {@link #BigInteger(String, int) (String, * int)} constructor.) * * @param radix radix of the String representation. * @return String representation of this BigInteger in the given radix. * @see Integer#toString * @see Character#forDigit * @see #BigInteger(java.lang.String, int) */ public String ToString(int radix) { if (_signum == 0) return "0"; if (radix < MIN_RADIX || radix > MAX_RADIX) radix = 10; //now this method only support 10 radix rendering if (radix != 10) throw new ArgumentException("Only support 10 radix rendering"); // Compute upper bound on number of digit groups and allocate space int maxNumDigitGroups = (4 * mag.Length + 6) / 7; String[] digitGroup = new String[maxNumDigitGroups]; // Translate number to string, a digit group at a time BigInteger tmp = this.Abs(); int numGroups = 0; while (tmp._signum != 0) { BigInteger d = longRadix[radix]; MutableBigInteger q = new MutableBigInteger(), a = new MutableBigInteger(tmp.mag), b = new MutableBigInteger(d.mag); MutableBigInteger r = a.divide(b, q); BigInteger q2 = q.toBigInteger(tmp._signum * d._signum); BigInteger r2 = r.toBigInteger(tmp._signum * d._signum); //digitGroup[numGroups++] = Long.toString(r2.longValue(), radix); digitGroup[numGroups++] = r2.LongValue().ToString(CultureInfo.InvariantCulture); tmp = q2; } // Put sign (if any) and first digit group into result buffer StringBuilder buf = new StringBuilder(numGroups * digitsPerLong[radix] + 1); if (_signum < 0) buf.Append('-'); buf.Append(digitGroup[numGroups - 1]); // Append remaining digit groups padded with leading zeros for (int i = numGroups - 2; i >= 0; i--) { // Prepend (any) leading zeros for this digit group int numLeadingZeros = digitsPerLong[radix] - digitGroup[i].Length; if (numLeadingZeros != 0) buf.Append(zeros[numLeadingZeros]); buf.Append(digitGroup[i]); } return buf.ToString(); } /** * The BigInteger constant zero. * * @since 1.2 */ public static BigInteger ZERO = new BigInteger(new int[0], 0); /** * The BigInteger constant one. * * @since 1.2 */ public static BigInteger ONE = ValueOf(1); /** * The BigInteger constant two. (Not exported.) */ private static BigInteger TWO = ValueOf(2); /** * The BigInteger constant ten. * * @since 1.5 */ public static BigInteger TEN = ValueOf(10); /** * Returns a BigInteger whose value is equal to that of the * specified {@code long}. This "static factory method" is * provided in preference to a ({@code long}) constructor * because it allows for reuse of frequently used BigIntegers. * * @param val value of the BigInteger to return. * @return a BigInteger with the specified value. */ public static BigInteger ValueOf(long val) { // If -MAX_CONSTANT < val < MAX_CONSTANT, return stashed constant if (val == 0) return ZERO; if (val > 0 && val <= MAX_CONSTANT) return posConst[(int)val]; else if (val < 0 && val >= -MAX_CONSTANT) return negConst[(int)-val]; return new BigInteger(val); } private static int MAX_CONSTANT = 16; private static BigInteger[] posConst = new BigInteger[MAX_CONSTANT + 1]; private static BigInteger[] negConst = new BigInteger[MAX_CONSTANT + 1]; /** * Returns a BigInteger with the given two's complement representation. * Assumes that the input array will not be modified (the returned * BigInteger will reference the input array if feasible). */ private static BigInteger valueOf(int[] val) { return (val[0] > 0 ? new BigInteger(val, 1) : new BigInteger(val)); } /** * Package private method to return bit length for an integer. */ public static int BitLengthForInt(int n) { return 32 - NumberOfLeadingZeros(n); } // Miscellaneous Bit Operations /* * Returns the number of bits in the minimal two's-complement * representation of this BigInteger, excluding a sign bit. * For positive BigIntegers, this is equivalent to the number of bits in * the ordinary binary representation. (Computes * (ceil(log2(this << 0 ? -this : this+1))).) * * @return number of bits in the minimal two's-complement * representation of this BigInteger, excluding a sign bit. */ public int BitLength() { int n = bitLength - 1; if (n == -1) { // bitLength not initialized yet int[] m = mag; int len = m.Length; if (len == 0) { n = 0; // offset by one to initialize } else { // Calculate the bit length of the magnitude int magBitLength = ((len - 1) << 5) + BitLengthForInt(mag[0]); if (_signum < 0) { // Check if magnitude is a power of two bool pow2 = (BitCountForInt(mag[0]) == 1); for (int i = 1; i < len && pow2; i++) pow2 = (mag[i] == 0); n = (pow2 ? magBitLength - 1 : magBitLength); } else { n = magBitLength; } } bitLength = n + 1; } return n; } /** * Returns the number of bits in the two's complement representation * of this BigInteger that differ from its sign bit. This method is * useful when implementing bit-vector style sets atop BigIntegers. * * @return number of bits in the two's complement representation * of this BigInteger that differ from its sign bit. */ public int BitCount() { //@SuppressWarnings("deprecation") int bc = bitCount - 1; if (bc == -1) { // bitCount not initialized yet bc = 0; // offset by one to initialize // Count the bits in the magnitude for (int i = 0; i < mag.Length; i++) bc += BitCountForInt(mag[i]); if (_signum < 0) { // Count the trailing zeros in the magnitude int magTrailingZeroCount = 0, j; for (j = mag.Length - 1; mag[j] == 0; j--) magTrailingZeroCount += 32; magTrailingZeroCount += NumberOfTrailingZeros(mag[j]); bc += magTrailingZeroCount - 1; } bitCount = bc + 1; } return bc; } /** * Returns a BigInteger whose value is the absolute value of this * BigInteger. * * @return {@code abs(this)} */ public BigInteger Abs() { return (_signum >= 0 ? this : this.Negate()); } /** * Returns a BigInteger whose value is {@code (-this)}. * * @return {@code -this} */ public BigInteger Negate() { return new BigInteger(this.mag, -this._signum); } /** * Returns a BigInteger whose value is (thisexponent). * Note that {@code exponent} is an integer rather than a BigInteger. * * @param exponent exponent to which this BigInteger is to be raised. * @return thisexponent * @throws ArithmeticException {@code exponent} is negative. (This would * cause the operation to yield a non-integer value.) */ public BigInteger Pow(int exponent) { if (exponent < 0) throw new ArithmeticException("Negative exponent"); if (_signum == 0) return (exponent == 0 ? ONE : this); // Perform exponentiation using repeated squaring trick int newSign = (_signum < 0 && (exponent & 1) == 1 ? -1 : 1); int[] baseToPow2 = this.mag; int[] result = { 1 }; while (exponent != 0) { if ((exponent & 1) == 1) { result = multiplyToLen(result, result.Length, baseToPow2, baseToPow2.Length, null); result = trustedStripLeadingZeroInts(result); } exponent = Operator.UnsignedRightShift(exponent, 1); if (exponent != 0) { baseToPow2 = squareToLen(baseToPow2, baseToPow2.Length, null); baseToPow2 = trustedStripLeadingZeroInts(baseToPow2); } } return new BigInteger(result, newSign); } /** * Multiplies int arrays x and y to the specified lengths and places * the result into z. There will be no leading zeros in the resultant array. */ private int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) { int xstart = xlen - 1; int ystart = ylen - 1; if (z == null || z.Length < (xlen + ylen)) z = new int[xlen + ylen]; long carry = 0; for (int j = ystart, k = ystart + 1 + xstart; j >= 0; j--, k--) { long product = (y[j] & LONG_MASK) * (x[xstart] & LONG_MASK) + carry; z[k] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } z[xstart] = (int)carry; for (int i = xstart - 1; i >= 0; i--) { carry = 0; for (int j = ystart, k = ystart + 1 + i; j >= 0; j--, k--) { long product = (y[j] & LONG_MASK) * (x[i] & LONG_MASK) + (z[k] & LONG_MASK) + carry; z[k] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } z[i] = (int)carry; } return z; } /** * Multiply an array by one word k and add to result, return the carry */ static int mulAdd(int[] output, int[] input, int offset, int len, int k) { long kLong = k & LONG_MASK; long carry = 0; offset = output.Length - offset - 1; for (int j = len - 1; j >= 0; j--) { long product = (input[j] & LONG_MASK) * kLong + (output[offset] & LONG_MASK) + carry; output[offset--] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } return (int)carry; } /** * Squares the contents of the int array x. The result is placed into the * int array z. The contents of x are not changed. */ private static int[] squareToLen(int[] x, int len, int[] z) { /* * The algorithm used here is adapted from Colin Plumb's C library. * Technique: Consider the partial products in the multiplication * of "abcde" by itself: * * a b c d e * * a b c d e * ================== * ae be ce de ee * ad bd cd dd de * ac bc cc cd ce * ab bb bc bd be * aa ab ac ad ae * * Note that everything above the main diagonal: * ae be ce de = (abcd) * e * ad bd cd = (abc) * d * ac bc = (ab) * c * ab = (a) * b * * is a copy of everything below the main diagonal: * de * cd ce * bc bd be * ab ac ad ae * * Thus, the sum is 2 * (off the diagonal) + diagonal. * * This is accumulated beginning with the diagonal (which * consist of the squares of the digits of the input), which is then * divided by two, the off-diagonal added, and multiplied by two * again. The low bit is simply a copy of the low bit of the * input, so it doesn't need special care. */ int zlen = len << 1; if (z == null || z.Length < zlen) z = new int[zlen]; // Store the squares, right shifted one bit (i.e., divided by 2) int lastProductLowWord = 0; for (int j = 0, i = 0; j < len; j++) { long piece = (x[j] & LONG_MASK); long product = piece * piece; z[i++] = (lastProductLowWord << 31) | (int)Operator.UnsignedRightShift(product, 33); z[i++] = (int)Operator.UnsignedRightShift(product, 1); lastProductLowWord = (int)product; } // Add in off-diagonal sums for (int i = len, offset = 1; i > 0; i--, offset += 2) { int t = x[i - 1]; t = mulAdd(z, x, offset, i - 1, t); addOne(z, offset - 1, i, t); } // Shift back up and set low bit PrimitiveLeftShift(z, zlen, 1); z[zlen - 1] |= x[len - 1] & 1; return z; } // shifts a up to len left n bits assumes no leading zeros, 0<=n<32 public static void PrimitiveLeftShift(int[] a, int len, int n) { if (len == 0 || n == 0) return; int n2 = 32 - n; for (int i = 0, c = a[i], m = i + len - 1; i < m; i++) { int b = c; c = a[i + 1]; a[i] = (b << n) | Operator.UnsignedRightShift(c, n2); } a[len - 1] <<= n; } /** * Add one word to the number a mlen words into a. Return the resulting * carry. */ static int addOne(int[] a, int offset, int mlen, int carry) { offset = a.Length - 1 - mlen - offset; long t = (a[offset] & LONG_MASK) + (carry & LONG_MASK); a[offset] = (int)t; if ((t >> 32) == 0) return 0; while (--mlen >= 0) { if (--offset < 0) { // Carry out of number return 1; } else { a[offset]++; if (a[offset] != 0) return 0; } } return 1; } /** * Returns the signum function of this BigInteger. * * @return -1, 0 or 1 as the value of this BigInteger is negative, zero or * positive. */ public int Signum() { return this._signum; } /** * Returns a byte array containing the two's-complement * representation of this BigInteger. The byte array will be in * big-endian byte-order: the most significant byte is in * the zeroth element. The array will contain the minimum number * of bytes required to represent this BigInteger, including at * least one sign bit, which is {@code (ceil((this.bitLength() + * 1)/8))}. (This representation is compatible with the * {@link #BigInteger(byte[]) (byte[])} constructor.) * * @return a byte array containing the two's-complement representation of * this BigInteger. * @see #BigInteger(byte[]) */ public byte[] ToByteArray() { int byteLen = (BitLength() / 8 + 1); byte[] byteArray = new byte[byteLen]; for (int i = byteLen - 1, bytesCopied = 4, nextInt = 0, intIndex = 0; i >= 0; i--) { if (bytesCopied == 4) { nextInt = getInt(intIndex++); bytesCopied = 1; } else { nextInt = Operator.UnsignedRightShift(nextInt, 8); bytesCopied++; } byteArray[i] = (byte)nextInt; } return byteArray; } /** * Returns the length of the two's complement representation in ints, * including space for at least one sign bit. */ private int intLength() { return Operator.UnsignedRightShift(BitLength(), 5) + 1; } /* Returns sign bit */ private int signBit() { return _signum < 0 ? 1 : 0; } /* Returns an int of sign bits */ private int signInt() { return _signum < 0 ? -1 : 0; } /** * Returns the specified int of the little-endian two's complement * representation (int 0 is the least significant). The int number can * be arbitrarily high (values are logically preceded by infinitely many * sign ints). */ private int getInt(int n) { if (n < 0) return 0; if (n >= mag.Length) return signInt(); int magInt = mag[mag.Length - n - 1]; return (_signum >= 0 ? magInt : (n <= FirstNonzeroIntNum() ? -magInt : ~magInt)); } /** * Returns the index of the int that contains the first nonzero int in the * little-endian binary representation of the magnitude (int 0 is the * least significant). If the magnitude is zero, return value is undefined. */ private int FirstNonzeroIntNum() { int fn = firstNonzeroIntNum - 2; if (fn == -2) { // firstNonzeroIntNum not initialized yet fn = 0; // Search for the first nonzero int int i; int mlen = mag.Length; for (i = mlen - 1; i >= 0 && mag[i] == 0; i--) ; fn = mlen - i - 1; firstNonzeroIntNum = fn + 2; // offset by two to initialize } return fn; } /** * Returns a copy of the input array stripped of any leading zero bytes. */ private static int[] stripLeadingZeroBytes(byte[] a) { int byteLength = a.Length; int keep; // Find first nonzero byte for (keep = 0; keep < byteLength && a[keep] == 0; keep++) ; // Allocate new array and copy relevant part of input array int intLength = Operator.UnsignedRightShift((byteLength - keep) + 3, 2); int[] result = new int[intLength]; int b = byteLength - 1; for (int i = intLength - 1; i >= 0; i--) { result[i] = a[b--] & 0xff; int bytesRemaining = b - keep + 1; int bytesToTransfer = Math.Min(3, bytesRemaining); for (int j = 8; j <= (bytesToTransfer << 3); j += 8) result[i] |= ((a[b--] & 0xff) << j); } return result; } /** * Takes an array a representing a negative 2's-complement number and * returns the minimal (no leading zero bytes) unsigned whose value is -a. */ private static int[] makePositive(byte[] a) { int keep, k; int byteLength = a.Length; // Find first non-sign (0xff) byte of input for (keep = 0; (keep < byteLength) && ((sbyte)a[keep] == (sbyte)-1); keep++) ; /* Allocate output array. If all non-sign bytes are 0x00, we must * allocate space for one extra output byte. */ for (k = keep; k < byteLength && a[k] == 0; k++) ; int extraByte = (k == byteLength) ? 1 : 0; int intLength = ((byteLength - keep + extraByte) + 3) / 4; int[] result = new int[intLength]; /* Copy one's complement of input into output, leaving extra * byte (if it exists) == 0x00 */ int b = byteLength - 1; for (int i = intLength - 1; i >= 0; i--) { result[i] = a[b--] & 0xff; int numBytesToTransfer = Math.Min(3, b - keep + 1); if (numBytesToTransfer < 0) numBytesToTransfer = 0; for (int j = 8; j <= 8 * numBytesToTransfer; j += 8) result[i] |= ((a[b--] & 0xff) << j); // Mask indicates which bits must be complemented int mask = Operator.UnsignedRightShift(-1, (8 * (3 - numBytesToTransfer))); result[i] = ~result[i] & mask; } // Add one to one's complement to generate two's complement for (int i = result.Length - 1; i >= 0; i--) { result[i] = (int)((result[i] & LONG_MASK) + 1); if (result[i] != 0) break; } return result; } /* * The following two arrays are used for fast String conversions. Both * are indexed by radix. The first is the number of digits of the given * radix that can fit in a Java long without "going negative", i.e., the * highest integer n such that radix**n < 2**63. The second is the * "long radix" that tears each number into "long digits", each of which * consists of the number of digits in the corresponding element in * digitsPerLong (longRadix[i] = i**digitPerLong[i]). Both arrays have * nonsense values in their 0 and 1 elements, as radixes 0 and 1 are not * used. */ private static int[] digitsPerLong = {0, 0, 62, 39, 31, 27, 24, 22, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12}; private static BigInteger[] longRadix = {null, null, ValueOf(0x4000000000000000L), ValueOf(0x383d9170b85ff80bL), ValueOf(0x4000000000000000L), ValueOf(0x6765c793fa10079dL), ValueOf(0x41c21cb8e1000000L), ValueOf(0x3642798750226111L), ValueOf(0x1000000000000000L), ValueOf(0x12bf307ae81ffd59L), ValueOf( 0xde0b6b3a7640000L), ValueOf(0x4d28cb56c33fa539L), ValueOf(0x1eca170c00000000L), ValueOf(0x780c7372621bd74dL), ValueOf(0x1e39a5057d810000L), ValueOf(0x5b27ac993df97701L), ValueOf(0x1000000000000000L), ValueOf(0x27b95e997e21d9f1L), ValueOf(0x5da0e1e53c5c8000L), ValueOf( 0xb16a458ef403f19L), ValueOf(0x16bcc41e90000000L), ValueOf(0x2d04b7fdd9c0ef49L), ValueOf(0x5658597bcaa24000L), ValueOf( 0x6feb266931a75b7L), ValueOf( 0xc29e98000000000L), ValueOf(0x14adf4b7320334b9L), ValueOf(0x226ed36478bfa000L), ValueOf(0x383d9170b85ff80bL), ValueOf(0x5a3c23e39c000000L), ValueOf( 0x4e900abb53e6b71L), ValueOf( 0x7600ec618141000L), ValueOf( 0xaee5720ee830681L), ValueOf(0x1000000000000000L), ValueOf(0x172588ad4f5f0981L), ValueOf(0x211e44f7d02c1000L), ValueOf(0x2ee56725f06e5c71L), ValueOf(0x41c21cb8e1000000L)}; // bitsPerDigit in the given radix times 1024 // Rounded up to avoid underallocation. private static long[] bitsPerDigit = { 0, 0, 1024, 1624, 2048, 2378, 2648, 2875, 3072, 3247, 3402, 3543, 3672, 3790, 3899, 4001, 4096, 4186, 4271, 4350, 4426, 4498, 4567, 4633, 4696, 4756, 4814, 4870, 4923, 4975, 5025, 5074, 5120, 5166, 5210, 5253, 5295}; /* * These two arrays are the integer analogue of above. */ private static int[] digitsPerInt = {0, 0, 30, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5}; private static int[] intRadix = {0, 0, 0x40000000, 0x4546b3db, 0x40000000, 0x48c27395, 0x159fd800, 0x75db9c97, 0x40000000, 0x17179149, 0x3b9aca00, 0xcc6db61, 0x19a10000, 0x309f1021, 0x57f6c100, 0xa2f1b6f, 0x10000000, 0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d, 0x6c20a40, 0x8d2d931, 0xb640000, 0xe8d4a51, 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41, 0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x39aa400 }; /** * Takes an array a representing a negative 2's-complement number and * returns the minimal (no leading zero ints) unsigned whose value is -a. */ private static int[] makePositive(int[] a) { int keep, j; // Find first non-sign (0xffffffff) int of input for (keep = 0; keep < a.Length && a[keep] == -1; keep++) ; /* Allocate output array. If all non-sign ints are 0x00, we must * allocate space for one extra output int. */ for (j = keep; j < a.Length && a[j] == 0; j++) ; int extraInt = (j == a.Length ? 1 : 0); int[] result = new int[a.Length - keep + extraInt]; /* Copy one's complement of input into output, leaving extra * int (if it exists) == 0x00 */ for (int i = keep; i < a.Length; i++) result[i - keep + extraInt] = ~a[i]; // Add one to one's complement to generate two's complement for (int i = result.Length - 1; ++result[i] == 0; i--) ; return result; } #region Integer Method /** * Returns the number of zero bits preceding the highest-order * ("leftmost") one-bit in the two's complement binary representation * of the specified {@code int} value. Returns 32 if the * specified value has no one-bits in its two's complement representation, * in other words if it is equal to zero. * * Note that this method is closely related to the logarithm base 2. * For all positive {@code int} values x: * * * @return the number of zero bits preceding the highest-order * ("leftmost") one-bit in the two's complement binary representation * of the specified {@code int} value, or 32 if the value * is equal to zero. * @since 1.5 */ public static int NumberOfLeadingZeros(int i) { // HD, Figure 5-6 if (i == 0) return 32; int n = 1; if (Operator.UnsignedRightShift(i, 16) == 0) { n += 16; i <<= 16; } if (Operator.UnsignedRightShift(i, 24) == 0) { n += 8; i <<= 8; } if (Operator.UnsignedRightShift(i, 28) == 0) { n += 4; i <<= 4; } if (Operator.UnsignedRightShift(i, 30) == 0) { n += 2; i <<= 2; } n -= Operator.UnsignedRightShift(i, 31); return n; } /** * Returns the number of zero bits following the lowest-order ("rightmost") * one-bit in the two's complement binary representation of the specified * {@code int} value. Returns 32 if the specified value has no * one-bits in its two's complement representation, in other words if it is * equal to zero. * * @return the number of zero bits following the lowest-order ("rightmost") * one-bit in the two's complement binary representation of the * specified {@code int} value, or 32 if the value is equal * to zero. * @since 1.5 */ public static int NumberOfTrailingZeros(int i) { // HD, Figure 5-14 int y; if (i == 0) return 32; int n = 31; y = i << 16; if (y != 0) { n = n - 16; i = y; } y = i << 8; if (y != 0) { n = n - 8; i = y; } y = i << 4; if (y != 0) { n = n - 4; i = y; } y = i << 2; if (y != 0) { n = n - 2; i = y; } return n - Operator.UnsignedRightShift((i << 1), 31); } /** * Returns the number of one-bits in the two's complement binary * representation of the specified {@code int} value. This function is * sometimes referred to as the population count. * * @return the number of one-bits in the two's complement binary * representation of the specified {@code int} value. * @since 1.5 */ public static int BitCountForInt(int i) { // HD, Figure 5-2 uint x = (uint)i; x = x - ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0f0f0f0f; x = x + (x >> 8); x = x + (x >> 16); return (int)(x & 0x3f); } #endregion #region IComparable 成员 public int CompareTo(BigInteger val) { if (_signum == val._signum) { switch (_signum) { case 1: return compareMagnitude(val); case -1: return val.compareMagnitude(this); default: return 0; } } return _signum > val._signum ? 1 : -1; } /** * Compares the magnitude array of this BigInteger with the specified * BigInteger's. This is the version of compareTo ignoring sign. * * @param val BigInteger whose magnitude array to be compared. * @return -1, 0 or 1 as this magnitude array is less than, equal to or * greater than the magnitude aray for the specified BigInteger's. */ int compareMagnitude(BigInteger val) { int[] m1 = mag; int len1 = m1.Length; int[] m2 = val.mag; int len2 = m2.Length; if (len1 < len2) return -1; if (len1 > len2) return 1; for (int i = 0; i < len1; i++) { int a = m1[i]; int b = m2[i]; if (a != b) return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1; } return 0; } #endregion /** * Compares this BigInteger with the specified Object for equality. * * @param x Object to which this BigInteger is to be compared. * @return {@code true} if and only if the specified Object is a * BigInteger whose value is numerically equal to this BigInteger. */ public override bool Equals(object x) { // This test is just an optimization, which may or may not help //if (x == this) - avoid CS0252 by making the reference comparison explicit: if (Object.ReferenceEquals(x, this)) return true; if (!(x is BigInteger) || (null == x)) return false; BigInteger xInt = (BigInteger)x; if (xInt._signum != _signum) return false; int[] m = mag; int len = m.Length; int[] xm = xInt.mag; if (len != xm.Length) return false; for (int i = 0; i < len; i++) if (xm[i] != m[i]) return false; return true; } /** * Returns the minimum of this BigInteger and {@code val}. * * @param val value with which the minimum is to be computed. * @return the BigInteger whose value is the lesser of this BigInteger and * {@code val}. If they are equal, either may be returned. */ public BigInteger Min(BigInteger val) { return (CompareTo(val) < 0 ? this : val); } /** * Returns the maximum of this BigInteger and {@code val}. * * @param val value with which the maximum is to be computed. * @return the BigInteger whose value is the greater of this and * {@code val}. If they are equal, either may be returned. */ public BigInteger Max(BigInteger val) { return (CompareTo(val) > 0 ? this : val); } // Hash Function /** * Returns the hash code for this BigInteger. * * @return hash code for this BigInteger. */ public override int GetHashCode() { int hashCode = 0; for (int i = 0; i < mag.Length; i++) hashCode = (int)(31 * hashCode + (mag[i] & LONG_MASK)); return hashCode * _signum; } /** * Converts this BigInteger to an {@code int}. This * conversion is analogous to a * narrowing primitive conversion from {@code long} to * {@code int} as defined in section 5.1.3 of * The Java(TM) Language Specification: * if this BigInteger is too big to fit in an * {@code int}, only the low-order 32 bits are returned. * Note that this conversion can lose information about the * overall magnitude of the BigInteger value as well as return a * result with the opposite sign. * * @return this BigInteger converted to an {@code int}. */ public int IntValue() { int result = 0; result = getInt(0); return result; } public BigInteger ShiftLeft(int n) { if (_signum == 0) return ZERO; if (n == 0) return this; if (n < 0) { if (n == int.MinValue) { throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported."); } else { return ShiftRight(-n); } } int nInts = Operator.UnsignedRightShift(n, 5); int nBits = n & 0x1f; int magLen = mag.Length; int[] newMag = null; if (nBits == 0) { newMag = new int[magLen + nInts]; for (int i = 0; i < magLen; i++) newMag[i] = mag[i]; } else { int i = 0; int nBits2 = 32 - nBits; int highBits = Operator.UnsignedRightShift(mag[0], nBits2); if (highBits != 0) { newMag = new int[magLen + nInts + 1]; newMag[i++] = highBits; } else { newMag = new int[magLen + nInts]; } int j = 0; while (j < magLen - 1) newMag[i++] = mag[j++] << nBits | Operator.UnsignedRightShift(mag[j], nBits2); newMag[i] = mag[j] << nBits; } return new BigInteger(newMag, _signum); } /** * Converts this BigInteger to a {@code long}. This * conversion is analogous to a * narrowing primitive conversion from {@code long} to * {@code int} as defined in section 5.1.3 of * The Java(TM) Language Specification: * if this BigInteger is too big to fit in a * {@code long}, only the low-order 64 bits are returned. * Note that this conversion can lose information about the * overall magnitude of the BigInteger value as well as return a * result with the opposite sign. * * @return this BigInteger converted to a {@code long}. */ public long LongValue() { long result = 0; for (int i = 1; i >= 0; i--) result = (result << 32) + (getInt(i) & LONG_MASK); return result; } /** * Returns a BigInteger whose value is {@code (this >> n)}. Sign * extension is performed. The shift distance, {@code n}, may be * negative, in which case this method performs a left shift. * (Computes floor(this / 2n).) * * @param n shift distance, in bits. * @return {@code this >> n} * @throws ArithmeticException if the shift distance is {@code * Integer.MIN_VALUE}. * @see #shiftLeft */ public BigInteger ShiftRight(int n) { if (n == 0) return this; if (n < 0) { if (n == int.MinValue) { throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported."); } else { return ShiftLeft(-n); } } int nInts = Operator.UnsignedRightShift(n, 5); int nBits = n & 0x1f; int magLen = mag.Length; int[] newMag = null; // Special case: entire contents shifted off the end if (nInts >= magLen) return (_signum >= 0 ? ZERO : negConst[1]); if (nBits == 0) { int newMagLen = magLen - nInts; newMag = new int[newMagLen]; for (int i = 0; i < newMagLen; i++) newMag[i] = mag[i]; } else { int i = 0; int highBits = Operator.UnsignedRightShift(mag[0], nBits); if (highBits != 0) { newMag = new int[magLen - nInts]; newMag[i++] = highBits; } else { newMag = new int[magLen - nInts - 1]; } int nBits2 = 32 - nBits; int j = 0; while (j < magLen - nInts - 1) newMag[i++] = (mag[j++] << nBits2) | Operator.UnsignedRightShift(mag[j], nBits); } if (_signum < 0) { // Find out whether any one-bits were shifted off the end. bool onesLost = false; for (int i = magLen - 1, j = magLen - nInts; i >= j && !onesLost; i--) onesLost = (mag[i] != 0); if (!onesLost && nBits != 0) onesLost = (mag[magLen - nInts - 1] << (32 - nBits) != 0); if (onesLost) newMag = Increment(newMag); } return new BigInteger(newMag, _signum); } int[] Increment(int[] val) { int lastSum = 0; for (int i = val.Length - 1; i >= 0 && lastSum == 0; i--) lastSum = (val[i] += 1); if (lastSum == 0) { val = new int[val.Length + 1]; val[0] = 1; } return val; } public BigInteger and(BigInteger val) { int[] result = new int[Math.Max(intLength(), val.intLength())]; for (int i = 0; i < result.Length; i++) result[i] = (getInt(result.Length - i - 1) & val.getInt(result.Length - i - 1)); return valueOf(result); } /** * Returns a BigInteger whose value is {@code (~this)}. (This method * returns a negative value if and only if this BigInteger is * non-negative.) * * @return {@code ~this} */ public BigInteger Not() { int[] result = new int[intLength()]; for (int i = 0; i < result.Length; i++) result[i] = ~getInt(result.Length - i - 1); return valueOf(result); } /** * Returns a BigInteger whose value is {@code (this | val)}. (This method * returns a negative BigInteger if and only if either this or val is * negative.) * * @param val value to be OR'ed with this BigInteger. * @return {@code this | val} */ public BigInteger Or(BigInteger val) { int[] result = new int[Math.Max(intLength(), val.intLength())]; for (int i = 0; i < result.Length; i++) result[i] = (getInt(result.Length - i - 1) | val.getInt(result.Length - i - 1)); return valueOf(result); } /** * Package private methods used by BigDecimal code to multiply a BigInteger * with a long. Assumes v is not equal to INFLATED. */ BigInteger multiply(long v) { if (v == 0 || _signum == 0) return ZERO; if (v == INFLATED) return Multiply(BigInteger.ValueOf(v)); int rsign = (v > 0 ? _signum : -_signum); if (v < 0) v = -v; long dh = Operator.UnsignedRightShift(v, 32); // higher order bits long dl = v & LONG_MASK; // lower order bits int xlen = mag.Length; int[] value = mag; int[] rmag = (dh == 0L) ? (new int[xlen + 1]) : (new int[xlen + 2]); long carry = 0; int rstart = rmag.Length - 1; for (int i = xlen - 1; i >= 0; i--) { long product = (value[i] & LONG_MASK) * dl + carry; rmag[rstart--] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } rmag[rstart] = (int)carry; if (dh != 0L) { carry = 0; rstart = rmag.Length - 2; for (int i = xlen - 1; i >= 0; i--) { long product = (value[i] & LONG_MASK) * dh + (rmag[rstart] & LONG_MASK) + carry; rmag[rstart--] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } rmag[0] = (int)carry; } if (carry == 0L) rmag = Arrays.CopyOfRange(rmag, 1, rmag.Length); return new BigInteger(rmag, rsign); } /** * Returns a BigInteger whose value is {@code (this * val)}. * * @param val value to be multiplied by this BigInteger. * @return {@code this * val} */ public BigInteger Multiply(BigInteger val) { if (val._signum == 0 || _signum == 0) return ZERO; int[] result = multiplyToLen(mag, mag.Length, val.mag, val.mag.Length, null); result = trustedStripLeadingZeroInts(result); return new BigInteger(result, _signum == val._signum ? 1 : -1); } /** * Returns a BigInteger whose value is {@code (this + val)}. * * @param val value to be added to this BigInteger. * @return {@code this + val} */ public BigInteger Add(BigInteger val) { if (val._signum == 0) return this; if (_signum == 0) return val; if (val._signum == _signum) return new BigInteger(add(mag, val.mag), _signum); int cmp = compareMagnitude(val); if (cmp == 0) return ZERO; int[] resultMag = (cmp > 0 ? subtract(mag, val.mag) : subtract(val.mag, mag)); resultMag = trustedStripLeadingZeroInts(resultMag); return new BigInteger(resultMag, cmp == _signum ? 1 : -1); } /** * Adds the contents of the int arrays x and y. This method allocates * a new int array to hold the answer and returns a reference to that * array. */ private static int[] add(int[] x, int[] y) { // If x is shorter, swap the two arrays if (x.Length < y.Length) { int[] tmp = x; x = y; y = tmp; } int xIndex = x.Length; int yIndex = y.Length; int[] result = new int[xIndex]; long sum = 0; // Add common parts of both numbers while (yIndex > 0) { sum = (x[--xIndex] & LONG_MASK) + (y[--yIndex] & LONG_MASK) + Operator.UnsignedRightShift(sum, 32); result[xIndex] = (int)sum; } // Copy remainder of longer number while carry propagation is required bool carry = Operator.UnsignedRightShift(sum, 32) != 0; while (xIndex > 0 && carry) carry = ((result[--xIndex] = x[xIndex] + 1) == 0); // Copy remainder of longer number while (xIndex > 0) result[--xIndex] = x[xIndex]; // Grow result if necessary if (carry) { int[] bigger = new int[result.Length + 1]; Array.Copy(result, 0, bigger, 1, result.Length); bigger[0] = 0x01; return bigger; } return result; } /** * Returns a BigInteger whose value is {@code (this - val)}. * * @param val value to be subtracted from this BigInteger. * @return {@code this - val} */ public BigInteger Subtract(BigInteger val) { if (val._signum == 0) return this; if (_signum == 0) return val.Negate(); if (val._signum != _signum) return new BigInteger(add(mag, val.mag), _signum); int cmp = compareMagnitude(val); if (cmp == 0) return ZERO; int[] resultMag = (cmp > 0 ? subtract(mag, val.mag) : subtract(val.mag, mag)); resultMag = trustedStripLeadingZeroInts(resultMag); return new BigInteger(resultMag, cmp == _signum ? 1 : -1); } /** * Subtracts the contents of the second int arrays (little) from the * first (big). The first int array (big) must represent a larger number * than the second. This method allocates the space necessary to hold the * answer. */ private static int[] subtract(int[] big, int[] little) { int bigIndex = big.Length; int[] result = new int[bigIndex]; int littleIndex = little.Length; long difference = 0; // Subtract common parts of both numbers while (littleIndex > 0) { difference = (big[--bigIndex] & LONG_MASK) - (little[--littleIndex] & LONG_MASK) + (difference >> 32); result[bigIndex] = (int)difference; } // Subtract remainder of longer number while borrow propagates bool borrow = (difference >> 32 != 0); while (bigIndex > 0 && borrow) borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1); // Copy remainder of longer number while (bigIndex > 0) result[--bigIndex] = big[bigIndex]; return result; } /** * Returns a BigInteger whose value is {@code (this / val)}. * * @param val value by which this BigInteger is to be divided. * @return {@code this / val} * @throws ArithmeticException if {@code val} is zero. */ public BigInteger Divide(BigInteger val) { MutableBigInteger q = new MutableBigInteger(), a = new MutableBigInteger(this.mag), b = new MutableBigInteger(val.mag); a.divide(b, q); return q.toBigInteger(this._signum == val._signum ? 1 : -1); } #region operator overload //*********************************************************************** // Overloading of unary >> operators //*********************************************************************** public static BigInteger operator >>(BigInteger bi1, int shiftVal) { return bi1.ShiftRight(shiftVal); } //*********************************************************************** // Overloading of unary << operators //*********************************************************************** public static BigInteger operator <<(BigInteger bi1, int shiftVal) { return bi1.ShiftLeft(shiftVal); } //*********************************************************************** // Overloading of bitwise AND operator //*********************************************************************** public static BigInteger operator &(BigInteger bi1, BigInteger bi2) { return bi1.and(bi2); } //*********************************************************************** // Overloading of bitwise OR operator //*********************************************************************** public static BigInteger operator |(BigInteger bi1, BigInteger bi2) { return bi1.Or(bi2); } //*********************************************************************** // Overloading of bitwise mul operator //*********************************************************************** public static BigInteger operator *(BigInteger bi1, BigInteger bi2) { return bi1.Multiply(bi2); } //*********************************************************************** // Overloading of bitwise add operator //*********************************************************************** public static BigInteger operator +(BigInteger bi1, BigInteger bi2) { return bi1.Add(bi2); } //*********************************************************************** // Overloading of bitwise subtract operator //*********************************************************************** public static BigInteger operator -(BigInteger bi1, BigInteger bi2) { return bi1.Subtract(bi2); } public static bool operator <(BigInteger bi1, BigInteger bi2) { return bi1.CompareTo(bi2) < 0; } public static bool operator >(BigInteger bi1, BigInteger bi2) { return bi1.CompareTo(bi2) > 0; } public static BigInteger operator /(BigInteger bi1, BigInteger bi2) { return bi1.Divide(bi2); } public static bool operator ==(BigInteger bi1, BigInteger bi2) { return bi1.Equals(bi2); } public static bool operator !=(BigInteger bi1, BigInteger bi2) { return !(bi1 == bi2); } #endregion } internal class MutableBigInteger { /** * Holds the magnitude of this MutableBigInteger in big endian order. * The magnitude may start at an offset into the value array, and it may * end before the length of the value array. */ int[] _value; /** * The number of ints of the value array that are currently used * to hold the magnitude of this MutableBigInteger. The magnitude starts * at an offset and offset + intLen may be less than value.Length. */ int intLen; /** * The offset into the value array where the magnitude of this * MutableBigInteger begins. */ int offset = 0; // Constants /** * MutableBigInteger with one element value array with the value 1. Used by * BigDecimal divideAndRound to increment the quotient. Use this constant * only when the method is not going to modify this object. */ static MutableBigInteger ONE = new MutableBigInteger(1); // Constructors private const long LONG_MASK = BigInteger.LONG_MASK; private const long INFLATED = long.MinValue; /** * The default constructor. An empty MutableBigInteger is created with * a one word capacity. */ public MutableBigInteger() { _value = new int[1]; intLen = 0; } /** * Construct a new MutableBigInteger with a magnitude specified by * the int val. */ public MutableBigInteger(int val) { _value = new int[1]; intLen = 1; _value[0] = val; } /** * Construct a new MutableBigInteger with the specified value array * up to the length of the array supplied. */ public MutableBigInteger(int[] val) { _value = val; intLen = val.Length; } public static int[] ArraysCopyOf(int[] original, int newLength) { int[] copy = new int[newLength]; Array.Copy(original, 0, copy, 0, Math.Min(original.Length, newLength)); return copy; } public static long[] ArraysCopyOf(long[] original, int newLength) { long[] copy = new long[newLength]; Array.Copy(original, 0, copy, 0, Math.Min(original.Length, newLength)); return copy; } public static int[] ArraysCopyOfRange(int[] original, int from, int to) { int newLength = to - from; if (newLength < 0) throw new ArgumentException(from + " > " + to); int[] copy = new int[newLength]; Array.Copy(original, from, copy, 0, Math.Min(original.Length - from, newLength)); return copy; } public static long[] ArraysCopyOfRange(long[] original, int from, int to) { int newLength = to - from; if (newLength < 0) throw new ArgumentException(from + " > " + to); long[] copy = new long[newLength]; Array.Copy(original, from, copy, 0, Math.Min(original.Length - from, newLength)); return copy; } /** * Construct a new MutableBigInteger with a magnitude equal to the * specified BigInteger. */ MutableBigInteger(BigInteger b) { intLen = b.mag.Length; _value = ArraysCopyOf(b.mag, intLen); } /** * Construct a new MutableBigInteger with a magnitude equal to the * specified MutableBigInteger. */ MutableBigInteger(MutableBigInteger val) { intLen = val.intLen; _value = ArraysCopyOfRange(val._value, val.offset, val.offset + intLen); } /** * Internal helper method to return the magnitude array. The caller is not * supposed to modify the returned array. */ private int[] getMagnitudeArray() { if (offset > 0 || _value.Length != intLen) return ArraysCopyOfRange(_value, offset, offset + intLen); return _value; } /** * Convert this MutableBigInteger to a long value. The caller has to make * sure this MutableBigInteger can be fit into long. */ private long toLong() { Debug.Assert(intLen <= 2, "this MutableBigInteger exceeds the range of long"); if (intLen == 0) return 0; long d = _value[offset] & LONG_MASK; return (intLen == 2) ? d << 32 | (_value[offset + 1] & LONG_MASK) : d; } /** * Convert this MutableBigInteger to a BigInteger object. */ public BigInteger toBigInteger(int sign) { if (intLen == 0 || sign == 0) return BigInteger.ZERO; return new BigInteger(getMagnitudeArray(), sign); } /* * Convert this MutableBigInteger to BigDecimal object with the specified sign * and scale. */ //BigDecimal toBigDecimal(int sign, int scale) { // if (intLen == 0 || sign == 0) // return BigDecimal.valueOf(0, scale); // int[] mag = getMagnitudeArray(); // int len = mag.Length; // int d = mag[0]; // // If this MutableBigInteger can't be fit into long, we need to // // make a BigInteger object for the resultant BigDecimal object. // if (len > 2 || (d < 0 && len == 2)) // return new BigDecimal(new BigInteger(mag, sign), INFLATED, scale, 0); // long v = (len == 2) ? // ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) : // d & LONG_MASK; // return new BigDecimal(null, sign == -1 ? -v : v, scale, 0); //} /** * Clear out a MutableBigInteger for reuse. */ void clear() { offset = intLen = 0; for (int index = 0, n = _value.Length; index < n; index++) _value[index] = 0; } /** * Set a MutableBigInteger to zero, removing its offset. */ void reset() { offset = intLen = 0; } /** * Compare the magnitude of two MutableBigIntegers. Returns -1, 0 or 1 * as this MutableBigInteger is numerically less than, equal to, or * greater than b. */ int compare(MutableBigInteger b) { int blen = b.intLen; if (intLen < blen) return -1; if (intLen > blen) return 1; // Add Integer.MIN_VALUE to make the comparison act as unsigned integer // comparison. int[] bval = b._value; for (int i = offset, j = b.offset; i < intLen + offset; i++, j++) { int b1 = unchecked((int)(_value[i] + 0x80000000)); int b2 = unchecked((int)(bval[j] + 0x80000000)); if (b1 < b2) return -1; if (b1 > b2) return 1; } return 0; } /** * Compare this against half of a MutableBigInteger object (Needed for * remainder tests). * Assumes no leading unnecessary zeros, which holds for results * from divide(). */ int compareHalf(MutableBigInteger b) { int blen = b.intLen; int len = intLen; if (len <= 0) return blen <= 0 ? 0 : -1; if (len > blen) return 1; if (len < blen - 1) return -1; int[] bval = b._value; int bstart = 0; int carry = 0; // Only 2 cases left:len == blen or len == blen - 1 if (len != blen) { // len == blen - 1 if (bval[bstart] == 1) { ++bstart; carry = unchecked((int)0x80000000); } else return -1; } // compare values with right-shifted values of b, // carrying shifted-out bits across words int[] val = _value; for (int i = offset, j = bstart; i < len + offset; ) { int bv = bval[j++]; long hb = (Operator.UnsignedRightShift(bv, 1) + carry) & LONG_MASK; long v = val[i++] & LONG_MASK; if (v != hb) return v < hb ? -1 : 1; carry = (bv & 1) << 31; // carray will be either 0x80000000 or 0 } return carry == 0 ? 0 : -1; } /** * Return the index of the lowest set bit in this MutableBigInteger. If the * magnitude of this MutableBigInteger is zero, -1 is returned. */ private int getLowestSetBit() { if (intLen == 0) return -1; int j, b; for (j = intLen - 1; (j > 0) && (_value[j + offset] == 0); j--) ; b = _value[j + offset]; if (b == 0) return -1; return ((intLen - 1 - j) << 5) + BigInteger.NumberOfTrailingZeros(b); } /** * Return the int in use in this MutableBigInteger at the specified * index. This method is not used because it is not inlined on all * platforms. */ private int getInt(int index) { return _value[offset + index]; } /** * Return a long which is equal to the unsigned value of the int in * use in this MutableBigInteger at the specified index. This method is * not used because it is not inlined on all platforms. */ private long getLong(int index) { return _value[offset + index] & LONG_MASK; } /** * Ensure that the MutableBigInteger is in normal form, specifically * making sure that there are no leading zeros, and that if the * magnitude is zero, then intLen is zero. */ void normalize() { if (intLen == 0) { offset = 0; return; } int index = offset; if (_value[index] != 0) return; int indexBound = index + intLen; do { index++; } while (index < indexBound && _value[index] == 0); int numZeros = index - offset; intLen -= numZeros; offset = (intLen == 0 ? 0 : offset + numZeros); } /** * If this MutableBigInteger cannot hold len words, increase the size * of the value array to len words. */ private void ensureCapacity(int len) { if (_value.Length < len) { _value = new int[len]; offset = 0; intLen = len; } } /** * Convert this MutableBigInteger into an int array with no leading * zeros, of a length that is equal to this MutableBigInteger's intLen. */ int[] toIntArray() { int[] result = new int[intLen]; for (int i = 0; i < intLen; i++) result[i] = _value[offset + i]; return result; } /** * Sets the int at index+offset in this MutableBigInteger to val. * This does not get inlined on all platforms so it is not used * as often as originally intended. */ void setInt(int index, int val) { _value[offset + index] = val; } /** * Sets this MutableBigInteger's value array to the specified array. * The intLen is set to the specified length. */ void setValue(int[] val, int length) { _value = val; intLen = length; offset = 0; } /** * Sets this MutableBigInteger's value array to a copy of the specified * array. The intLen is set to the length of the new array. */ void copyValue(MutableBigInteger src) { int len = src.intLen; if (_value.Length < len) _value = new int[len]; Array.Copy(src._value, src.offset, _value, 0, len); intLen = len; offset = 0; } /** * Sets this MutableBigInteger's value array to a copy of the specified * array. The intLen is set to the length of the specified array. */ void copyValue(int[] val) { int len = val.Length; if (_value.Length < len) _value = new int[len]; Array.Copy(val, 0, _value, 0, len); intLen = len; offset = 0; } /** * Returns true iff this MutableBigInteger has a value of one. */ bool isOne() { return (intLen == 1) && (_value[offset] == 1); } /** * Returns true iff this MutableBigInteger has a value of zero. */ bool isZero() { return (intLen == 0); } /** * Returns true iff this MutableBigInteger is even. */ bool isEven() { return (intLen == 0) || ((_value[offset + intLen - 1] & 1) == 0); } /** * Returns true iff this MutableBigInteger is odd. */ bool isOdd() { return isZero() ? false : ((_value[offset + intLen - 1] & 1) == 1); } /** * Returns true iff this MutableBigInteger is in normal form. A * MutableBigInteger is in normal form if it has no leading zeros * after the offset, and intLen + offset <= value.Length. */ bool isNormal() { if (intLen + offset > _value.Length) return false; if (intLen == 0) return true; return (_value[offset] != 0); } /** * Returns a String representation of this MutableBigInteger in radix 10. */ public String toString() { BigInteger b = toBigInteger(1); return b.ToString(); } /** * Right shift this MutableBigInteger n bits. The MutableBigInteger is left * in normal form. */ void rightShift(int n) { if (intLen == 0) return; int nInts = Operator.UnsignedRightShift(n, 5); int nBits = n & 0x1F; this.intLen -= nInts; if (nBits == 0) return; int bitsInHighWord = BigInteger.BitLengthForInt(_value[offset]); if (nBits >= bitsInHighWord) { this.primitiveLeftShift(32 - nBits); this.intLen--; } else { primitiveRightShift(nBits); } } /** * Left shift this MutableBigInteger n bits. */ void leftShift(int n) { /* * If there is enough storage space in this MutableBigInteger already * the available space will be used. Space to the right of the used * ints in the value array is faster to utilize, so the extra space * will be taken from the right if possible. */ if (intLen == 0) return; int nInts = Operator.UnsignedRightShift(n, 5); int nBits = n & 0x1F; int bitsInHighWord = BigInteger.BitLengthForInt(_value[offset]); // If shift can be done without moving words, do so if (n <= (32 - bitsInHighWord)) { primitiveLeftShift(nBits); return; } int newLen = intLen + nInts + 1; if (nBits <= (32 - bitsInHighWord)) newLen--; if (_value.Length < newLen) { // The array must grow int[] result = new int[newLen]; for (int i = 0; i < intLen; i++) result[i] = _value[offset + i]; setValue(result, newLen); } else if (_value.Length - offset >= newLen) { // Use space on right for (int i = 0; i < newLen - intLen; i++) _value[offset + intLen + i] = 0; } else { // Must use space on left for (int i = 0; i < intLen; i++) _value[i] = _value[offset + i]; for (int i = intLen; i < newLen; i++) _value[i] = 0; offset = 0; } intLen = newLen; if (nBits == 0) return; if (nBits <= (32 - bitsInHighWord)) primitiveLeftShift(nBits); else primitiveRightShift(32 - nBits); } /** * A primitive used for division. This method adds in one multiple of the * divisor a back to the dividend result at a specified offset. It is used * when qhat was estimated too large, and must be adjusted. */ private int divadd(int[] a, int[] result, int offset) { long carry = 0; for (int j = a.Length - 1; j >= 0; j--) { long sum = (a[j] & LONG_MASK) + (result[j + offset] & LONG_MASK) + carry; result[j + offset] = (int)sum; carry = Operator.UnsignedRightShift(sum, 32); } return (int)carry; } /** * This method is used for division. It multiplies an n word input a by one * word input x, and subtracts the n word product from q. This is needed * when subtracting qhat*divisor from dividend. */ private int mulsub(int[] q, int[] a, int x, int len, int offset) { long xLong = x & LONG_MASK; long carry = 0; offset += len; for (int j = len - 1; j >= 0; j--) { long product = (a[j] & LONG_MASK) * xLong + carry; long difference = q[offset] - product; q[offset--] = (int)difference; carry = Operator.UnsignedRightShift(product, 32) + (((difference & LONG_MASK) > (((~(int)product) & LONG_MASK))) ? 1 : 0); } return (int)carry; } /** * Right shift this MutableBigInteger n bits, where n is * less than 32. * Assumes that intLen > 0, n > 0 for speed */ private void primitiveRightShift(int n) { int[] val = _value; int n2 = 32 - n; for (int i = offset + intLen - 1, c = val[i]; i > offset; i--) { int b = c; c = val[i - 1]; val[i] = (c << n2) | Operator.UnsignedRightShift(b, n); } val[offset] = Operator.UnsignedRightShift(val[offset], n); } /** * Left shift this MutableBigInteger n bits, where n is * less than 32. * Assumes that intLen > 0, n > 0 for speed */ private void primitiveLeftShift(int n) { int[] val = _value; int n2 = 32 - n; for (int i = offset, c = val[i], m = i + intLen - 1; i < m; i++) { int b = c; c = val[i + 1]; val[i] = (b << n) | Operator.UnsignedRightShift(c, n2); } val[offset + intLen - 1] <<= n; } /** * Adds the contents of two MutableBigInteger objects.The result * is placed within this MutableBigInteger. * The contents of the addend are not changed. */ void add(MutableBigInteger addend) { int x = intLen; int y = addend.intLen; int resultLen = (intLen > addend.intLen ? intLen : addend.intLen); int[] result = (_value.Length < resultLen ? new int[resultLen] : _value); int rstart = result.Length - 1; long sum; long carry = 0; // Add common parts of both numbers while (x > 0 && y > 0) { x--; y--; sum = (_value[x + offset] & LONG_MASK) + (addend._value[y + addend.offset] & LONG_MASK) + carry; result[rstart--] = (int)sum; carry = Operator.UnsignedRightShift(sum, 32); } // Add remainder of the longer number while (x > 0) { x--; if (carry == 0 && result == _value && rstart == (x + offset)) return; sum = (_value[x + offset] & LONG_MASK) + carry; result[rstart--] = (int)sum; carry = Operator.UnsignedRightShift(sum, 32); } while (y > 0) { y--; sum = (addend._value[y + addend.offset] & LONG_MASK) + carry; result[rstart--] = (int)sum; carry = Operator.UnsignedRightShift(sum, 32); } if (carry > 0) { // Result must grow in length resultLen++; if (result.Length < resultLen) { int[] temp = new int[resultLen]; // Result one word longer from carry-out; copy low-order // bits into new result. Array.Copy(result, 0, temp, 1, result.Length); temp[0] = 1; result = temp; } else { result[rstart--] = 1; } } _value = result; intLen = resultLen; offset = result.Length - resultLen; } /** * Subtracts the smaller of this and b from the larger and places the * result into this MutableBigInteger. */ int subtract(MutableBigInteger b) { MutableBigInteger a = this; int[] result = _value; int sign = a.compare(b); if (sign == 0) { reset(); return 0; } if (sign < 0) { MutableBigInteger tmp = a; a = b; b = tmp; } int resultLen = a.intLen; if (result.Length < resultLen) result = new int[resultLen]; long diff = 0; int x = a.intLen; int y = b.intLen; int rstart = result.Length - 1; // Subtract common parts of both numbers while (y > 0) { x--; y--; diff = (a._value[x + a.offset] & LONG_MASK) - (b._value[y + b.offset] & LONG_MASK) - ((int)-(diff >> 32)); result[rstart--] = (int)diff; } // Subtract remainder of longer number while (x > 0) { x--; diff = (a._value[x + a.offset] & LONG_MASK) - ((int)-(diff >> 32)); result[rstart--] = (int)diff; } _value = result; intLen = resultLen; offset = _value.Length - resultLen; normalize(); return sign; } /** * Subtracts the smaller of a and b from the larger and places the result * into the larger. Returns 1 if the answer is in a, -1 if in b, 0 if no * operation was performed. */ private int difference(MutableBigInteger b) { MutableBigInteger a = this; int sign = a.compare(b); if (sign == 0) return 0; if (sign < 0) { MutableBigInteger tmp = a; a = b; b = tmp; } long diff = 0; int x = a.intLen; int y = b.intLen; // Subtract common parts of both numbers while (y > 0) { x--; y--; diff = (a._value[a.offset + x] & LONG_MASK) - (b._value[b.offset + y] & LONG_MASK) - ((int)-(diff >> 32)); a._value[a.offset + x] = (int)diff; } // Subtract remainder of longer number while (x > 0) { x--; diff = (a._value[a.offset + x] & LONG_MASK) - ((int)-(diff >> 32)); a._value[a.offset + x] = (int)diff; } a.normalize(); return sign; } /** * Multiply the contents of two MutableBigInteger objects. The result is * placed into MutableBigInteger z. The contents of y are not changed. */ void multiply(MutableBigInteger y, MutableBigInteger z) { int xLen = intLen; int yLen = y.intLen; int newLen = xLen + yLen; // Put z into an appropriate state to receive product if (z._value.Length < newLen) z._value = new int[newLen]; z.offset = 0; z.intLen = newLen; // The first iteration is hoisted out of the loop to avoid extra add long carry = 0; for (int j = yLen - 1, k = yLen + xLen - 1; j >= 0; j--, k--) { long product = (y._value[j + y.offset] & LONG_MASK) * (_value[xLen - 1 + offset] & LONG_MASK) + carry; z._value[k] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } z._value[xLen - 1] = (int)carry; // Perform the multiplication word by word for (int i = xLen - 2; i >= 0; i--) { carry = 0; for (int j = yLen - 1, k = yLen + i; j >= 0; j--, k--) { long product = (y._value[j + y.offset] & LONG_MASK) * (_value[i + offset] & LONG_MASK) + (z._value[k] & LONG_MASK) + carry; z._value[k] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } z._value[i] = (int)carry; } // Remove leading zeros from product z.normalize(); } /** * Multiply the contents of this MutableBigInteger by the word y. The * result is placed into z. */ public void mul(int y, MutableBigInteger z) { if (y == 1) { z.copyValue(this); return; } if (y == 0) { z.clear(); return; } // Perform the multiplication word by word long ylong = y & LONG_MASK; int[] zval = (z._value.Length < intLen + 1 ? new int[intLen + 1] : z._value); long carry = 0; for (int i = intLen - 1; i >= 0; i--) { long product = ylong * (_value[i + offset] & LONG_MASK) + carry; zval[i + 1] = (int)product; carry = Operator.UnsignedRightShift(product, 32); } if (carry == 0) { z.offset = 1; z.intLen = intLen; } else { z.offset = 0; z.intLen = intLen + 1; zval[0] = (int)carry; } z._value = zval; } /** * This method is used for division of an n word dividend by a one word * divisor. The quotient is placed into quotient. The one word divisor is * specified by divisor. * * @return the remainder of the division is returned. * */ public int divideOneWord(int divisor, MutableBigInteger quotient) { long divisorLong = divisor & LONG_MASK; // Special case of one word dividend if (intLen == 1) { long dividendValue = _value[offset] & LONG_MASK; int q = (int)(dividendValue / divisorLong); int r = (int)(dividendValue - q * divisorLong); quotient._value[0] = q; quotient.intLen = (q == 0) ? 0 : 1; quotient.offset = 0; return r; } if (quotient._value.Length < intLen) quotient._value = new int[intLen]; quotient.offset = 0; quotient.intLen = intLen; // Normalize the divisor int shift = BigInteger.NumberOfLeadingZeros(divisor); int rem = _value[offset]; long remLong = rem & LONG_MASK; if (remLong < divisorLong) { quotient._value[0] = 0; } else { quotient._value[0] = (int)(remLong / divisorLong); rem = (int)(remLong - (quotient._value[0] * divisorLong)); remLong = rem & LONG_MASK; } int xlen = intLen; int[] qWord = new int[2]; while (--xlen > 0) { long dividendEstimate = (remLong << 32) | (_value[offset + intLen - xlen] & LONG_MASK); if (dividendEstimate >= 0) { qWord[0] = (int)(dividendEstimate / divisorLong); qWord[1] = (int)(dividendEstimate - qWord[0] * divisorLong); } else { divWord(qWord, dividendEstimate, divisor); } quotient._value[intLen - xlen] = qWord[0]; rem = qWord[1]; remLong = rem & LONG_MASK; } quotient.normalize(); // Unnormalize if (shift > 0) return rem % divisor; else return rem; } /** * Calculates the quotient of this div b and places the quotient in the * provided MutableBigInteger objects and the remainder object is returned. * * Uses Algorithm D in Knuth section 4.3.1. * Many optimizations to that algorithm have been adapted from the Colin * Plumb C library. * It special cases one word divisors for speed. The content of b is not * changed. * */ public MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient) { if (b.intLen == 0) throw new ArithmeticException("BigInteger divide by zero"); // Dividend is zero if (intLen == 0) { quotient.intLen = quotient.offset; return new MutableBigInteger(); } int cmp = compare(b); // Dividend less than divisor if (cmp < 0) { quotient.intLen = quotient.offset = 0; return new MutableBigInteger(this); } // Dividend equal to divisor if (cmp == 0) { quotient._value[0] = quotient.intLen = 1; quotient.offset = 0; return new MutableBigInteger(); } quotient.clear(); // Special case one word divisor if (b.intLen == 1) { int r = divideOneWord(b._value[b.offset], quotient); if (r == 0) return new MutableBigInteger(); return new MutableBigInteger(r); } // Copy divisor value to protect divisor int[] div = ArraysCopyOfRange(b._value, b.offset, b.offset + b.intLen); return divideMagnitude(div, quotient); } /** * Internally used to calculate the quotient of this div v and places the * quotient in the provided MutableBigInteger object and the remainder is * returned. * * @return the remainder of the division will be returned. */ public long divide(long v, MutableBigInteger quotient) { if (v == 0) throw new ArithmeticException("BigInteger divide by zero"); // Dividend is zero if (intLen == 0) { quotient.intLen = quotient.offset = 0; return 0; } if (v < 0) v = -v; int d = (int)Operator.UnsignedRightShift(v, 32); quotient.clear(); // Special case on word divisor if (d == 0) return divideOneWord((int)v, quotient) & LONG_MASK; else { int[] div = new int[] { d, (int)(v & LONG_MASK) }; return divideMagnitude(div, quotient).toLong(); } } /** * Divide this MutableBigInteger by the divisor represented by its magnitude * array. The quotient will be placed into the provided quotient object & * the remainder object is returned. */ private MutableBigInteger divideMagnitude(int[] divisor, MutableBigInteger quotient) { // Remainder starts as dividend with space for a leading zero MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]); Array.Copy(_value, offset, rem._value, 1, intLen); rem.intLen = intLen; rem.offset = 1; int nlen = rem.intLen; // Set the quotient size int dlen = divisor.Length; int limit = nlen - dlen + 1; if (quotient._value.Length < limit) { quotient._value = new int[limit]; quotient.offset = 0; } quotient.intLen = limit; int[] q = quotient._value; // D1 normalize the divisor int shift = BigInteger.NumberOfLeadingZeros(divisor[0]); if (shift > 0) { // First shift will not grow array BigInteger.PrimitiveLeftShift(divisor, dlen, shift); // But this one might rem.leftShift(shift); } // Must insert leading 0 in rem if its length did not change if (rem.intLen == nlen) { rem.offset = 0; rem._value[0] = 0; rem.intLen++; } int dh = divisor[0]; long dhLong = dh & LONG_MASK; int dl = divisor[1]; int[] qWord = new int[2]; // D2 Initialize j for (int j = 0; j < limit; j++) { // D3 Calculate qhat // estimate qhat int qhat = 0; int qrem = 0; bool skipCorrection = false; int nh = rem._value[j + rem.offset]; int nh2 = unchecked((int)(nh + 0x80000000)); int nm = rem._value[j + 1 + rem.offset]; if (nh == dh) { qhat = ~0; qrem = nh + nm; skipCorrection = qrem + 0x80000000 < nh2; } else { long nChunk = (((long)nh) << 32) | (nm & LONG_MASK); if (nChunk >= 0) { qhat = (int)(nChunk / dhLong); qrem = (int)(nChunk - (qhat * dhLong)); } else { divWord(qWord, nChunk, dh); qhat = qWord[0]; qrem = qWord[1]; } } if (qhat == 0) continue; if (!skipCorrection) { // Correct qhat long nl = rem._value[j + 2 + rem.offset] & LONG_MASK; long rs = ((qrem & LONG_MASK) << 32) | nl; long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK); if (unsignedLongCompare(estProduct, rs)) { qhat--; qrem = (int)((qrem & LONG_MASK) + dhLong); if ((qrem & LONG_MASK) >= dhLong) { estProduct -= (dl & LONG_MASK); rs = ((qrem & LONG_MASK) << 32) | nl; if (unsignedLongCompare(estProduct, rs)) qhat--; } } } // D4 Multiply and subtract rem._value[j + rem.offset] = 0; int borrow = mulsub(rem._value, divisor, qhat, dlen, j + rem.offset); // D5 Test remainder if ((int)(borrow + 0x80000000) > nh2) { // D6 Add back divadd(divisor, rem._value, j + 1 + rem.offset); qhat--; } // Store the quotient digit q[j] = qhat; } // D7 loop on j // D8 Unnormalize if (shift > 0) rem.rightShift(shift); quotient.normalize(); rem.normalize(); return rem; } /** * Compare two longs as if they were unsigned. * Returns true iff one is bigger than two. */ private bool unsignedLongCompare(long one, long two) { return (one + long.MinValue) > (two + long.MinValue); } /** * This method divides a long quantity by an int to estimate * qhat for two multi precision numbers. It is used when * the signed value of n is less than zero. */ private void divWord(int[] result, long n, int d) { long dLong = d & LONG_MASK; if (dLong == 1) { result[0] = (int)n; result[1] = 0; return; } // Approximate the quotient and remainder long q = Operator.UnsignedRightShift(n, 1) / Operator.UnsignedRightShift(dLong, 1); long r = n - q * dLong; // Correct the approximation while (r < 0) { r += dLong; q--; } while (r >= dLong) { r -= dLong; q++; } // n - q*dlong == r && 0 <= r = 0) { // steps B3 and B4 t.rightShift(lb); // step B5 if (tsign > 0) u = t; else v = t; // Special case one word numbers if (u.intLen < 2 && v.intLen < 2) { int x = u._value[u.offset]; int y = v._value[v.offset]; x = binaryGcd(x, y); r._value[0] = x; r.intLen = 1; r.offset = 0; if (k > 0) r.leftShift(k); return r; } // step B6 if ((tsign = u.difference(v)) == 0) break; t = (tsign >= 0) ? u : v; } if (k > 0) u.leftShift(k); return u; } /** * Calculate GCD of a and b interpreted as unsigned integers. */ static int binaryGcd(int a, int b) { if (b == 0) return a; if (a == 0) return b; // Right shift a & b till their last bits equal to 1. int aZeros = BigInteger.NumberOfTrailingZeros(a); int bZeros = BigInteger.NumberOfTrailingZeros(b); a = Operator.UnsignedRightShift(a, aZeros); b = Operator.UnsignedRightShift(b, bZeros); int t = (aZeros < bZeros ? aZeros : bZeros); while (a != b) { if ((a + 0x80000000) > (b + 0x80000000)) { // a > b as unsigned a -= b; a = Operator.UnsignedRightShift(a, BigInteger.NumberOfTrailingZeros(a)); } else { b -= a; b = Operator.UnsignedRightShift(b, BigInteger.NumberOfTrailingZeros(b)); } } return a << t; } /** * Returns the modInverse of this mod p. This and p are not affected by * the operation. */ MutableBigInteger mutableModInverse(MutableBigInteger p) { // Modulus is odd, use Schroeppel's algorithm if (p.isOdd()) return modInverse(p); // Base and modulus are even, throw exception if (isEven()) throw new ArithmeticException("BigInteger not invertible."); // Get even part of modulus expressed as a power of 2 int powersOf2 = p.getLowestSetBit(); // Construct odd part of modulus MutableBigInteger oddMod = new MutableBigInteger(p); oddMod.rightShift(powersOf2); if (oddMod.isOne()) return modInverseMP2(powersOf2); // Calculate 1/a mod oddMod MutableBigInteger oddPart = modInverse(oddMod); // Calculate 1/a mod evenMod MutableBigInteger evenPart = modInverseMP2(powersOf2); // Combine the results using Chinese Remainder Theorem MutableBigInteger y1 = modInverseBP2(oddMod, powersOf2); MutableBigInteger y2 = oddMod.modInverseMP2(powersOf2); MutableBigInteger temp1 = new MutableBigInteger(); MutableBigInteger temp2 = new MutableBigInteger(); MutableBigInteger result = new MutableBigInteger(); oddPart.leftShift(powersOf2); oddPart.multiply(y1, result); evenPart.multiply(oddMod, temp1); temp1.multiply(y2, temp2); result.add(temp2); return result.divide(p, temp1); } /* * Calculate the multiplicative inverse of this mod 2^k. */ MutableBigInteger modInverseMP2(int k) { if (isEven()) throw new ArithmeticException("Non-invertible. (GCD != 1)"); if (k > 64) return euclidModInverse(k); int t = inverseMod32(_value[offset + intLen - 1]); if (k < 33) { t = (k == 32 ? t : t & ((1 << k) - 1)); return new MutableBigInteger(t); } long pLong = (_value[offset + intLen - 1] & LONG_MASK); if (intLen > 1) pLong |= ((long)_value[offset + intLen - 2] << 32); long tLong = t & LONG_MASK; tLong = tLong * (2 - pLong * tLong); // 1 more Newton iter step tLong = (k == 64 ? tLong : tLong & ((1L << k) - 1)); MutableBigInteger result = new MutableBigInteger(new int[2]); result._value[0] = (int)Operator.UnsignedRightShift(tLong, 32); result._value[1] = (int)tLong; result.intLen = 2; result.normalize(); return result; } /* * Returns the multiplicative inverse of val mod 2^32. Assumes val is odd. */ static int inverseMod32(int val) { // Newton's iteration! int t = val; t *= 2 - val * t; t *= 2 - val * t; t *= 2 - val * t; t *= 2 - val * t; return t; } /* * Calculate the multiplicative inverse of 2^k mod mod, where mod is odd. */ static MutableBigInteger modInverseBP2(MutableBigInteger mod, int k) { // Copy the mod to protect original return fixup(new MutableBigInteger(1), new MutableBigInteger(mod), k); } /** * Calculate the multiplicative inverse of this mod mod, where mod is odd. * This and mod are not changed by the calculation. * * This method implements an algorithm due to Richard Schroeppel, that uses * the same intermediate representation as Montgomery Reduction * ("Montgomery Form"). The algorithm is described in an unpublished * manuscript entitled "Fast Modular Reciprocals." */ private MutableBigInteger modInverse(MutableBigInteger mod) { //TODO: to complete this method,we should implement SignedMutableBigInteger class throw new NotImplementedException("This method uses SignedMutableBigInteger class."); /*MutableBigInteger p = new MutableBigInteger(mod); MutableBigInteger f = new MutableBigInteger(this); MutableBigInteger g = new MutableBigInteger(p); SignedMutableBigInteger c = new SignedMutableBigInteger(1); SignedMutableBigInteger d = new SignedMutableBigInteger(); MutableBigInteger temp = null; SignedMutableBigInteger sTemp = null; int k = 0; // Right shift f k times until odd, left shift d k times if (f.isEven()) { int trailingZeros = f.getLowestSetBit(); f.rightShift(trailingZeros); d.leftShift(trailingZeros); k = trailingZeros; } // The Almost Inverse Algorithm while(!f.isOne()) { // If gcd(f, g) != 1, number is not invertible modulo mod if (f.isZero()) throw new ArithmeticException("BigInteger not invertible."); // If f < g exchange f, g and c, d if (f.compare(g) < 0) { temp = f; f = g; g = temp; sTemp = d; d = c; c = sTemp; } // If f == g (mod 4) if (((f.value[f.offset + f.intLen - 1] ^ g.value[g.offset + g.intLen - 1]) & 3) == 0) { f.subtract(g); c.signedSubtract(d); } else { // If f != g (mod 4) f.add(g); c.signedAdd(d); } // Right shift f k times until odd, left shift d k times int trailingZeros = f.getLowestSetBit(); f.rightShift(trailingZeros); d.leftShift(trailingZeros); k += trailingZeros; } while (c.sign < 0) c.signedAdd(p); return fixup(c, p, k);*/ } /* * The Fixup Algorithm * Calculates X such that X = C * 2^(-k) (mod P) * Assumes C

> 5; i < numWords; i++) { // V = R * c (mod 2^j) int v = r * c._value[c.offset + c.intLen - 1]; // c = c + (v * p) p.mul(v, temp); c.add(temp); // c = c / 2^j c.intLen--; } int numBits = k & 0x1f; if (numBits != 0) { // V = R * c (mod 2^j) int v = r * c._value[c.offset + c.intLen - 1]; v &= ((1 << numBits) - 1); // c = c + (v * p) p.mul(v, temp); c.add(temp); // c = c / 2^j c.rightShift(numBits); } // In theory, c may be greater than p at this point (Very rare!) while (c.compare(p) >= 0) c.subtract(p); return c; } /** * Uses the extended Euclidean algorithm to compute the modInverse of base * mod a modulus that is a power of 2. The modulus is 2^k. */ MutableBigInteger euclidModInverse(int k) { MutableBigInteger b = new MutableBigInteger(1); b.leftShift(k); MutableBigInteger mod = new MutableBigInteger(b); MutableBigInteger a = new MutableBigInteger(this); MutableBigInteger q = new MutableBigInteger(); MutableBigInteger r = b.divide(a, q); MutableBigInteger swapper = b; // swap b & r b = r; r = swapper; MutableBigInteger t1 = new MutableBigInteger(q); MutableBigInteger t0 = new MutableBigInteger(1); MutableBigInteger temp = new MutableBigInteger(); while (!b.isOne()) { r = a.divide(b, q); if (r.intLen == 0) throw new ArithmeticException("BigInteger not invertible."); swapper = r; a = swapper; if (q.intLen == 1) t1.mul(q._value[q.offset], temp); else q.multiply(t1, temp); swapper = q; q = temp; temp = swapper; t0.add(q); if (a.isOne()) return t0; r = b.divide(a, q); if (r.intLen == 0) throw new ArithmeticException("BigInteger not invertible."); swapper = b; b = r; if (q.intLen == 1) t0.mul(q._value[q.offset], temp); else q.multiply(t0, temp); swapper = q; q = temp; temp = swapper; t1.add(q); } mod.subtract(t1); return mod; } } }