/*
 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.math;

/**
 * A class used to represent multiprecision integers that makes efficient
 * use of allocated space by allowing a number to occupy only part of
 * an array so that the arrays do not have to be reallocated as often.
 * When performing an operation with many iterations the array used to
 * hold a number is only reallocated when necessary and does not have to
 * be the same size as the number it represents. A mutable number allows
 * calculations to occur on the same number without having to create
 * a new number for every step of the calculation as occurs with
 * BigIntegers.
 *
 * @see     BigInteger
 * @author  Michael McCloskey
 * @since   1.3
 */

import java.util.Arrays;

import static java.math.BigInteger.LONG_MASK;
import static java.math.BigDecimal.INFLATED;

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.
/** * 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.
/** * 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.
/** * 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.
/** * 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 final MutableBigInteger ONE = new MutableBigInteger(1); // Constructors
The default constructor. An empty MutableBigInteger is created with a one word capacity.
/** * The default constructor. An empty MutableBigInteger is created with * a one word capacity. */
MutableBigInteger() { value = new int[1]; intLen = 0; }
Construct a new MutableBigInteger with a magnitude specified by the int val.
/** * Construct a new MutableBigInteger with a magnitude specified by * the int val. */
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.
/** * Construct a new MutableBigInteger with the specified value array * up to the length of the array supplied. */
MutableBigInteger(int[] val) { value = val; intLen = val.length; }
Construct a new MutableBigInteger with a magnitude equal to the specified BigInteger.
/** * Construct a new MutableBigInteger with a magnitude equal to the * specified BigInteger. */
MutableBigInteger(BigInteger b) { intLen = b.mag.length; value = Arrays.copyOf(b.mag, intLen); }
Construct a new MutableBigInteger with a magnitude equal to the specified MutableBigInteger.
/** * Construct a new MutableBigInteger with a magnitude equal to the * specified MutableBigInteger. */
MutableBigInteger(MutableBigInteger val) { intLen = val.intLen; value = Arrays.copyOfRange(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.
/** * 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 Arrays.copyOfRange(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.
/** * Convert this MutableBigInteger to a long value. The caller has to make * sure this MutableBigInteger can be fit into long. */
private long toLong() { 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.
/** * Convert this MutableBigInteger to a BigInteger object. */
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.
/** * 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.
/** * 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.
/** * 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.
/** * Compare the magnitude of two MutableBigIntegers. Returns -1, 0 or 1 * as this MutableBigInteger is numerically less than, equal to, or * greater than <tt>b</tt>. */
final 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 = value[i] + 0x80000000; int b2 = 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().
/** * Compare this against half of a MutableBigInteger object (Needed for * remainder tests). * Assumes no leading unnecessary zeros, which holds for results * from divide(). */
final 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 = 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 = ((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.
/** * Return the index of the lowest set bit in this MutableBigInteger. If the * magnitude of this MutableBigInteger is zero, -1 is returned. */
private final 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) + Integer.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.
/** * 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 final 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.
/** * 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 final 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.
/** * 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. */
final 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.
/** * If this MutableBigInteger cannot hold len words, increase the size * of the value array to len words. */
private final 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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]; System.arraycopy(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.
/** * 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]; System.arraycopy(val, 0, value, 0, len); intLen = len; offset = 0; }
Returns true iff this MutableBigInteger has a value of one.
/** * Returns true iff this MutableBigInteger has a value of one. */
boolean isOne() { return (intLen == 1) && (value[offset] == 1); }
Returns true iff this MutableBigInteger has a value of zero.
/** * Returns true iff this MutableBigInteger has a value of zero. */
boolean isZero() { return (intLen == 0); }
Returns true iff this MutableBigInteger is even.
/** * Returns true iff this MutableBigInteger is even. */
boolean isEven() { return (intLen == 0) || ((value[offset + intLen - 1] & 1) == 0); }
Returns true iff this MutableBigInteger is odd.
/** * Returns true iff this MutableBigInteger is odd. */
boolean 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.
/** * 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. */
boolean 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.
/** * 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.
/** * Right shift this MutableBigInteger n bits. The MutableBigInteger is left * in normal form. */
void rightShift(int n) { if (intLen == 0) return; int nInts = 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.
/** * 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 = 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.
/** * 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 = 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.
/** * 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 = (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
/** * Right shift this MutableBigInteger n bits, where n is * less than 32. * Assumes that intLen > 0, n > 0 for speed */
private final 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) | (b >>> n); } val[offset] >>>= n; }
Left shift this MutableBigInteger n bits, where n is less than 32. Assumes that intLen > 0, n > 0 for speed
/** * Left shift this MutableBigInteger n bits, where n is * less than 32. * Assumes that intLen > 0, n > 0 for speed */
private final 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) | (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.
/** * 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 = 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 = sum >>> 32; } while(y>0) { y--; sum = (addend.value[y+addend.offset] & LONG_MASK) + carry; result[rstart--] = (int)sum; carry = 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. System.arraycopy(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.
/** * 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.
/** * 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.
/** * 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 = 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 = 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.
/** * Multiply the contents of this MutableBigInteger by the word y. The * result is placed into z. */
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 = 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.
Returns:the remainder of the division is returned.
/** * 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. * */
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 = Integer.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.
/** * 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. * */
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 = Arrays.copyOfRange(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.
Returns:the remainder of the division will be returned.
/** * 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. */
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)(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.
/** * 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]); System.arraycopy(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 = Integer.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; boolean skipCorrection = false; int nh = rem.value[j+rem.offset]; int nh2 = 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 (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.
/** * Compare two longs as if they were unsigned. * Returns true iff one is bigger than two. */
private boolean unsignedLongCompare(long one, long two) { return (one+Long.MIN_VALUE) > (two+Long.MIN_VALUE); }
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.
/** * 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 = (n >>> 1) / (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 <dLong, hence we're done. result[0] = (int)q; result[1] = (int)r; }
Calculate GCD of this and b. This and b are changed by the computation.
/** * Calculate GCD of this and b. This and b are changed by the computation. */
MutableBigInteger hybridGCD(MutableBigInteger b) { // Use Euclid's algorithm until the numbers are approximately the // same length, then use the binary GCD algorithm to find the GCD. MutableBigInteger a = this; MutableBigInteger q = new MutableBigInteger(); while (b.intLen != 0) { if (Math.abs(a.intLen - b.intLen) < 2) return a.binaryGCD(b); MutableBigInteger r = a.divide(b, q); a = b; b = r; } return a; }
Calculate GCD of this and v. Assumes that this and v are not zero.
/** * Calculate GCD of this and v. * Assumes that this and v are not zero. */
private MutableBigInteger binaryGCD(MutableBigInteger v) { // Algorithm B from Knuth section 4.5.2 MutableBigInteger u = this; MutableBigInteger r = new MutableBigInteger(); // step B1 int s1 = u.getLowestSetBit(); int s2 = v.getLowestSetBit(); int k = (s1 < s2) ? s1 : s2; if (k != 0) { u.rightShift(k); v.rightShift(k); } // step B2 boolean uOdd = (k==s1); MutableBigInteger t = uOdd ? v: u; int tsign = uOdd ? -1 : 1; int lb; while ((lb = t.getLowestSetBit()) >= 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.
/** * 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 = Integer.numberOfTrailingZeros(a); int bZeros = Integer.numberOfTrailingZeros(b); a >>>= aZeros; b >>>= bZeros; int t = (aZeros < bZeros ? aZeros : bZeros); while (a != b) { if ((a+0x80000000) > (b+0x80000000)) { // a > b as unsigned a -= b; a >>>= Integer.numberOfTrailingZeros(a); } else { b -= a; b >>>= Integer.numberOfTrailingZeros(b); } } return a<<t; }
Returns the modInverse of this mod p. This and p are not affected by the operation.
/** * 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)(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."
/** * 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) { 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<P and P is odd. */ static MutableBigInteger fixup(MutableBigInteger c, MutableBigInteger p, int k) { MutableBigInteger temp = new MutableBigInteger(); // Set r to the multiplicative inverse of p mod 2^32 int r = -inverseMod32(p.value[p.offset+p.intLen-1]); for(int i=0, numWords = k >> 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.
/** * 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; } }