| /* | |
| * Copyright (c) 1999, 2024, 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; | |
| import static java.math.BigDecimal.INFLATED; | |
| import static java.math.BigInteger.LONG_MASK; | |
| import java.util.Arrays; | |
| /** | |
| * 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 | |
| * @author Timothy Buktu | |
| * @since 1.3 | |
| */ | |
| 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 final MutableBigInteger ONE = new MutableBigInteger(1); | |
| /** | |
| * The minimum {@code intLen} for cancelling powers of two before | |
| * dividing. | |
| * If the number of ints is less than this threshold, | |
| * {@code divideKnuth} does not eliminate common powers of two from | |
| * the dividend and divisor. | |
| */ | |
| static final int KNUTH_POW2_THRESH_LEN = 6; | |
| /** | |
| * The minimum number of trailing zero ints for cancelling powers of two | |
| * before dividing. | |
| * If the dividend and divisor don't share at least this many zero ints | |
| * at the end, {@code divideKnuth} does not eliminate common powers | |
| * of two from the dividend and divisor. | |
| */ | |
| static final int KNUTH_POW2_THRESH_ZEROS = 3; | |
| // Constructors | |
| /** | |
| * 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. | |
| */ | |
| MutableBigInteger(int val) { | |
| init(val); | |
| } | |
| /** | |
| * Construct a new MutableBigInteger with a magnitude specified by | |
| * the long val. | |
| */ | |
| MutableBigInteger(long val) { | |
| int hi = (int) (val >>> 32); | |
| if (hi == 0) { | |
| init((int) val); | |
| } else { | |
| value = new int[] { hi, (int) val }; | |
| intLen = 2; | |
| } | |
| } | |
| private void init(int val) { | |
| value = new int[] { val }; | |
| intLen = val != 0 ? 1 : 0; | |
| } | |
| /** | |
| * 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. | |
| */ | |
| 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. | |
| */ | |
| MutableBigInteger(MutableBigInteger val) { | |
| intLen = val.intLen; | |
| value = Arrays.copyOfRange(val.value, val.offset, val.offset + intLen); | |
| } | |
| /** | |
| * Makes this number an {@code n}-int number all of whose bits are ones. | |
| * Used by Burnikel-Ziegler division. | |
| * @param n number of ints in the {@code value} array | |
| */ | |
| private void ones(int n) { | |
| if (n > value.length) | |
| value = new int[n]; | |
| Arrays.fill(value, -1); | |
| offset = 0; | |
| intLen = n; | |
| } | |
| /** | |
| * 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) { | |
| // Shrink value to be the total magnitude | |
| int[] tmp = Arrays.copyOfRange(value, offset, offset + intLen); | |
| Arrays.fill(value, 0); | |
| offset = 0; | |
| intLen = tmp.length; | |
| value = tmp; | |
| } | |
| 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() { | |
| 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. | |
| */ | |
| BigInteger toBigInteger(int sign) { | |
| if (intLen == 0 || sign == 0) | |
| return BigInteger.ZERO; | |
| return new BigInteger(getMagnitudeArray(), sign); | |
| } | |
| /** | |
| * Converts this number to a nonnegative {@code BigInteger}. | |
| */ | |
| BigInteger toBigInteger() { | |
| normalize(); | |
| return toBigInteger(isZero() ? 0 : 1); | |
| } | |
| /** | |
| * 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.zeroValueOf(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 BigDecimal.valueOf(sign == -1 ? -v : v, scale); | |
| } | |
| /** | |
| * This is for internal use in converting from a MutableBigInteger | |
| * object into a long value given a specified sign. | |
| * returns INFLATED if value is not fit into long | |
| */ | |
| long toCompactValue(int sign) { | |
| if (intLen == 0 || sign == 0) | |
| return 0L; | |
| int[] mag = getMagnitudeArray(); | |
| int len = mag.length; | |
| int d = mag[0]; | |
| // If this MutableBigInteger can not be fitted into long, we need to | |
| // make a BigInteger object for the resultant BigDecimal object. | |
| if (len > 2 || (d < 0 && len == 2)) | |
| return INFLATED; | |
| long v = (len == 2) ? | |
| ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) : | |
| d & LONG_MASK; | |
| return sign == -1 ? -v : v; | |
| } | |
| /** | |
| * 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 {@code b}. | |
| * Assumes no leading unnecessary zeros. | |
| */ | |
| 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; | |
| } | |
| /** | |
| * Returns a value equal to what {@code b.leftShift(32*ints); return compare(b);} | |
| * would return, but doesn't change the value of {@code b}. | |
| * Assumes no leading unnecessary zeros. | |
| */ | |
| private int compareShifted(MutableBigInteger b, int ints) { | |
| int blen = b.intLen; | |
| int alen = intLen - ints; | |
| if (alen < blen) | |
| return -1; | |
| if (alen > 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 < alen + 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(). | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| 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]; | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| boolean isOne() { | |
| return (intLen == 1) && (value[offset] == 1); | |
| } | |
| /** | |
| * Returns true iff this MutableBigInteger has a value of zero. | |
| */ | |
| boolean isZero() { | |
| return (intLen == 0); | |
| } | |
| /** | |
| * 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. | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| */ | |
| public String toString() { | |
| BigInteger b = toBigInteger(1); | |
| return b.toString(); | |
| } | |
| /** | |
| * Like {@link #rightShift(int)} but {@code n} can be greater than the length of the number. | |
| */ | |
| void safeRightShift(int n) { | |
| if (n/32 >= intLen) { | |
| reset(); | |
| } else { | |
| rightShift(n); | |
| } | |
| } | |
| /** | |
| * Right shift this MutableBigInteger n bits. The MutableBigInteger is left | |
| * in normal form. | |
| * Assumes {@code Math.ceilDiv(n, 32) <= intLen || intLen == 0} | |
| */ | |
| 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); | |
| } | |
| } | |
| /** | |
| * Like {@link #leftShift(int)} but {@code n} can be zero. | |
| */ | |
| void safeLeftShift(int n) { | |
| if (n > 0) { | |
| leftShift(n); | |
| } | |
| } | |
| /** | |
| * 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 leadingZeros = Integer.numberOfLeadingZeros(value[offset]); | |
| // If shift can be done without moving words, do so | |
| if (n <= leadingZeros) { | |
| primitiveLeftShift(nBits); | |
| return; | |
| } | |
| int newLen = intLen + nInts; | |
| if (nBits > leadingZeros) | |
| newLen++; | |
| int[] result; | |
| final int newOffset; | |
| if (value.length < newLen) { // The array must grow | |
| result = new int[newLen]; | |
| newOffset = 0; | |
| } else { | |
| result = value; | |
| newOffset = value.length - offset >= newLen ? offset : 0; | |
| } | |
| int trailingZerosPos = newOffset + intLen; | |
| if (nBits != 0) { | |
| // Do primitive shift directly for speed | |
| if (nBits <= leadingZeros) { | |
| primitiveLeftShift(nBits, result, newOffset); // newOffset <= offset | |
| } else { | |
| int lastInt = value[offset + intLen - 1]; | |
| primitiveRightShift(32 - nBits, result, newOffset); // newOffset <= offset | |
| result[trailingZerosPos++] = lastInt << nBits; | |
| } | |
| } else if (result != value || newOffset != offset) { | |
| System.arraycopy(value, offset, result, newOffset, intLen); | |
| } | |
| // Add trailing zeros | |
| if (result == value) | |
| Arrays.fill(result, trailingZerosPos, newOffset + newLen, 0); | |
| value = result; | |
| intLen = newLen; | |
| offset = newOffset; | |
| } | |
| /** | |
| * 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. | |
| */ | |
| 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; | |
| } | |
| /** | |
| * The method is the same as mulsun, except the fact that q array is not | |
| * updated, the only result of the method is borrow flag. | |
| */ | |
| private int mulsubBorrow(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; | |
| 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 | |
| */ | |
| private void primitiveRightShift(int n) { | |
| primitiveRightShift(n, value, offset); | |
| } | |
| /** | |
| * Right shift this MutableBigInteger n bits, where n is | |
| * less than 32, placing the result in the specified array. | |
| * Assumes that intLen > 0, n > 0 for speed. | |
| * The result can be the value array of this MutableBigInteger, | |
| * but for speed the copy is not performed safely, so, in that case | |
| * the caller has to make sure that | |
| * {@code (resFrom <= offset || resFrom >= offset + intLen)}. | |
| */ | |
| private void primitiveRightShift(int n, int[] result, int resFrom) { | |
| int[] val = value; | |
| int n2 = 32 - n; | |
| int b = val[offset]; | |
| result[resFrom] = b >>> n; | |
| for (int i = 1; i < intLen; i++) { | |
| int c = b; | |
| b = val[offset + i]; | |
| result[resFrom + i] = (c << n2) | (b >>> 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) { | |
| primitiveLeftShift(n, value, offset); | |
| } | |
| /** | |
| * Left shift this MutableBigInteger n bits, where n is | |
| * less than 32, placing the result in the specified array. | |
| * Assumes that intLen > 0, n > 0 for speed. | |
| * The result can be the value array of this MutableBigInteger, | |
| * but for speed the copy is not performed safely, so, in that case | |
| * the caller has to make sure that | |
| * {@code (resFrom <= offset || resFrom >= offset + intLen)}. | |
| */ | |
| private void primitiveLeftShift(int n, int[] result, int resFrom) { | |
| int[] val = value; | |
| int n2 = 32 - n; | |
| final int m = intLen - 1; | |
| int b = val[offset]; | |
| for (int i = 0; i < m; i++) { | |
| int c = val[offset + i + 1]; | |
| result[resFrom + i] = (b << n) | (c >>> n2); | |
| b = c; | |
| } | |
| result[resFrom + m] = b << n; | |
| } | |
| /** | |
| * Returns a {@code BigInteger} equal to the {@code n} | |
| * low ints of this number. | |
| */ | |
| private BigInteger getLower(int n) { | |
| if (isZero()) { | |
| return BigInteger.ZERO; | |
| } else if (intLen < n) { | |
| return toBigInteger(1); | |
| } else { | |
| // strip zeros | |
| int len = n; | |
| while (len > 0 && value[offset+intLen-len] == 0) | |
| len--; | |
| int sign = len > 0 ? 1 : 0; | |
| return new BigInteger(Arrays.copyOfRange(value, offset+intLen-len, offset+intLen), sign); | |
| } | |
| } | |
| /** | |
| * Discards all ints whose index is greater than {@code n}. | |
| */ | |
| private void keepLower(int n) { | |
| if (intLen >= n) { | |
| offset += intLen - n; | |
| intLen = 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 = 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; | |
| } | |
| /** | |
| * Adds the value of {@code addend} shifted {@code n} ints to the left. | |
| * Has the same effect as {@code addend.leftShift(32*ints); add(addend);} | |
| * but doesn't change the value of {@code addend}. | |
| */ | |
| void addShifted(MutableBigInteger addend, int n) { | |
| if (addend.isZero()) { | |
| return; | |
| } | |
| int x = intLen; | |
| int y = addend.intLen + n; | |
| int resultLen = (intLen > y ? intLen : y); | |
| 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--; | |
| int bval = y+addend.offset < addend.value.length ? addend.value[y+addend.offset] : 0; | |
| sum = (value[x+offset] & LONG_MASK) + | |
| (bval & 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--; | |
| int bval = y+addend.offset < addend.value.length ? addend.value[y+addend.offset] : 0; | |
| sum = (bval & 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; | |
| } | |
| /** | |
| * Like {@link #addShifted(MutableBigInteger, int)} but {@code this.intLen} must | |
| * not be greater than {@code n}. In other words, concatenates {@code this} | |
| * and {@code addend}. | |
| */ | |
| void addDisjoint(MutableBigInteger addend, int n) { | |
| if (addend.isZero()) | |
| return; | |
| int x = intLen; | |
| int y = addend.intLen + n; | |
| int resultLen = (intLen > y ? intLen : y); | |
| int[] result; | |
| if (value.length < resultLen) | |
| result = new int[resultLen]; | |
| else { | |
| result = value; | |
| Arrays.fill(value, offset+intLen, value.length, 0); | |
| } | |
| int rstart = result.length-1; | |
| // copy from this if needed | |
| System.arraycopy(value, offset, result, rstart+1-x, x); | |
| y -= x; | |
| rstart -= x; | |
| int len = Math.min(y, addend.value.length-addend.offset); | |
| System.arraycopy(addend.value, addend.offset, result, rstart+1-y, len); | |
| // zero the gap | |
| for (int i=rstart+1-y+len; i < rstart+1; i++) | |
| result[i] = 0; | |
| value = result; | |
| intLen = resultLen; | |
| offset = result.length - resultLen; | |
| } | |
| /** | |
| * Adds the low {@code n} ints of {@code addend}. | |
| */ | |
| void addLower(MutableBigInteger addend, int n) { | |
| MutableBigInteger a = new MutableBigInteger(addend); | |
| if (a.offset + a.intLen >= n) { | |
| a.offset = a.offset + a.intLen - n; | |
| a.intLen = n; | |
| } | |
| a.normalize(); | |
| add(a); | |
| } | |
| /** | |
| * Shifts {@code this} of {@code n} ints to the left and adds {@code addend}. | |
| * Assumes {@code n > 0} for speed. | |
| */ | |
| void shiftAdd(MutableBigInteger addend, int n) { | |
| // Fast cases | |
| if (addend.intLen <= n) { | |
| shiftAddDisjoint(addend, n); | |
| } else if (intLen == 0) { | |
| copyValue(addend); | |
| } else { | |
| leftShift(n << 5); | |
| add(addend); | |
| } | |
| } | |
| /** | |
| * Shifts {@code this} of {@code n} ints to the left and adds {@code addend}. | |
| * Assumes {@code addend.intLen <= n}. | |
| */ | |
| void shiftAddDisjoint(MutableBigInteger addend, int n) { | |
| if (intLen == 0) { // Avoid unnormal values | |
| copyValue(addend); | |
| return; | |
| } | |
| int[] res; | |
| final int resLen = intLen + n, resOffset; | |
| if (resLen > value.length) { | |
| res = new int[resLen]; | |
| System.arraycopy(value, offset, res, 0, intLen); | |
| resOffset = 0; | |
| } else { | |
| res = value; | |
| if (offset + resLen > value.length) { | |
| System.arraycopy(value, offset, res, 0, intLen); | |
| resOffset = 0; | |
| } else { | |
| resOffset = offset; | |
| } | |
| // Clear words where necessary | |
| if (addend.intLen < n) | |
| Arrays.fill(res, resOffset + intLen, resOffset + resLen - addend.intLen, 0); | |
| } | |
| System.arraycopy(addend.value, addend.offset, res, resOffset + resLen - addend.intLen, addend.intLen); | |
| value = res; | |
| offset = resOffset; | |
| intLen = resLen; | |
| } | |
| /** | |
| * 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) + (diff >> 32); | |
| result[rstart--] = (int)diff; | |
| } | |
| // Subtract remainder of longer number | |
| while (x > 0) { | |
| x--; | |
| diff = (a.value[x+a.offset] & LONG_MASK) + (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) + (diff >> 32); | |
| a.value[a.offset+x] = (int)diff; | |
| } | |
| // Subtract remainder of longer number | |
| while (diff < 0 && x > 0) { | |
| x--; | |
| diff = (a.value[a.offset+ x] & LONG_MASK) + (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. | |
| * Assume {@code intLen > 0} | |
| */ | |
| 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. | |
| */ | |
| 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. | |
| * | |
| * @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) { | |
| int dividendValue = value[offset]; | |
| int q = Integer.divideUnsigned(dividendValue, divisor); | |
| int r = Integer.remainderUnsigned(dividendValue, divisor); | |
| 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; | |
| long rem = 0; | |
| for (int xlen = intLen; xlen > 0; xlen--) { | |
| long dividendEstimate = (rem << 32) | | |
| (value[offset + intLen - xlen] & LONG_MASK); | |
| int q = (int) Long.divideUnsigned(dividendEstimate, divisorLong); | |
| rem = Long.remainderUnsigned(dividendEstimate, divisorLong); | |
| quotient.value[intLen - xlen] = q; | |
| } | |
| quotient.normalize(); | |
| return (int)rem; | |
| } | |
| /** | |
| * Calculates the quotient of this div b and places the quotient in the | |
| * provided MutableBigInteger objects and the remainder object is returned. | |
| * | |
| */ | |
| MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient) { | |
| return divide(b,quotient,true); | |
| } | |
| MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient, boolean needRemainder) { | |
| if (b.intLen < BigInteger.BURNIKEL_ZIEGLER_THRESHOLD || | |
| intLen - b.intLen < BigInteger.BURNIKEL_ZIEGLER_OFFSET) { | |
| return divideKnuth(b, quotient, needRemainder); | |
| } else { | |
| return divideAndRemainderBurnikelZiegler(b, quotient); | |
| } | |
| } | |
| /** | |
| * @see #divideKnuth(MutableBigInteger, MutableBigInteger, boolean) | |
| */ | |
| MutableBigInteger divideKnuth(MutableBigInteger b, MutableBigInteger quotient) { | |
| return divideKnuth(b,quotient,true); | |
| } | |
| /** | |
| * 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 from Knuth TAOCP Vol. 2, 3rd edition, 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 divideKnuth(MutableBigInteger b, MutableBigInteger quotient, boolean needRemainder) { | |
| if (b.intLen == 0) | |
| throw new ArithmeticException("BigInteger divide by zero"); | |
| // Dividend is zero | |
| if (intLen == 0) { | |
| quotient.intLen = quotient.offset = 0; | |
| return needRemainder ? new MutableBigInteger() : null; | |
| } | |
| int cmp = compare(b); | |
| // Dividend less than divisor | |
| if (cmp < 0) { | |
| quotient.intLen = quotient.offset = 0; | |
| return needRemainder ? new MutableBigInteger(this) : null; | |
| } | |
| // Dividend equal to divisor | |
| if (cmp == 0) { | |
| quotient.value[0] = quotient.intLen = 1; | |
| quotient.offset = 0; | |
| return needRemainder ? new MutableBigInteger() : null; | |
| } | |
| quotient.clear(); | |
| // Special case one word divisor | |
| if (b.intLen == 1) { | |
| int r = divideOneWord(b.value[b.offset], quotient); | |
| if(needRemainder) { | |
| if (r == 0) | |
| return new MutableBigInteger(); | |
| return new MutableBigInteger(r); | |
| } else { | |
| return null; | |
| } | |
| } | |
| // Cancel common powers of two if we're above the KNUTH_POW2_* thresholds | |
| if (intLen >= KNUTH_POW2_THRESH_LEN) { | |
| int trailingZeroBits = Math.min(getLowestSetBit(), b.getLowestSetBit()); | |
| if (trailingZeroBits >= KNUTH_POW2_THRESH_ZEROS*32) { | |
| MutableBigInteger a = new MutableBigInteger(this); | |
| b = new MutableBigInteger(b); | |
| a.rightShift(trailingZeroBits); | |
| b.rightShift(trailingZeroBits); | |
| MutableBigInteger r = a.divideKnuth(b, quotient); | |
| r.leftShift(trailingZeroBits); | |
| return r; | |
| } | |
| } | |
| return divideMagnitude(b, quotient, needRemainder); | |
| } | |
| /** | |
| * Computes {@code this/b} and {@code this%b} using the | |
| * <a href="http://cr.yp.to/bib/1998/burnikel.ps"> Burnikel-Ziegler algorithm</a>. | |
| * This method implements algorithm 3 from pg. 9 of the Burnikel-Ziegler paper. | |
| * The parameter beta was chosen to b 2<sup>32</sup> so almost all shifts are | |
| * multiples of 32 bits.<br/> | |
| * {@code this} and {@code b} must be nonnegative. | |
| * @param b the divisor | |
| * @param quotient output parameter for {@code this/b} | |
| * @return the remainder | |
| */ | |
| MutableBigInteger divideAndRemainderBurnikelZiegler(MutableBigInteger b, MutableBigInteger quotient) { | |
| int r = intLen; | |
| int s = b.intLen; | |
| // Clear the quotient | |
| quotient.offset = quotient.intLen = 0; | |
| if (r < s) { | |
| return this; | |
| } else { | |
| // Unlike Knuth division, we don't check for common powers of two here because | |
| // BZ already runs faster if both numbers contain powers of two and cancelling them has no | |
| // additional benefit. | |
| // step 1: let m = min{2^k | (2^k)*BURNIKEL_ZIEGLER_THRESHOLD > s} | |
| int m = 1 << (32-Integer.numberOfLeadingZeros(s/BigInteger.BURNIKEL_ZIEGLER_THRESHOLD)); | |
| int j = (s+m-1) / m; // step 2a: j = ceil(s/m) | |
| int n = j * m; // step 2b: block length in 32-bit units | |
| long n32 = 32L * n; // block length in bits | |
| int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} | |
| MutableBigInteger bShifted = new MutableBigInteger(b); | |
| bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n | |
| MutableBigInteger aShifted = new MutableBigInteger (this); | |
| aShifted.safeLeftShift(sigma); // step 4b: shift a by the same amount | |
| // step 5: t is the number of blocks needed to accommodate a plus one additional bit | |
| int t = (int) ((aShifted.bitLength()+n32) / n32); | |
| if (t < 2) { | |
| t = 2; | |
| } | |
| // step 6: conceptually split a into blocks a[t-1], ..., a[0] | |
| MutableBigInteger a1 = aShifted.getBlock(t-1, t, n); // the most significant block of a | |
| // step 7: z[t-2] = [a[t-1], a[t-2]] | |
| MutableBigInteger z = aShifted.getBlock(t-2, t, n); // the second to most significant block | |
| z.addDisjoint(a1, n); // z[t-2] | |
| // do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers | |
| MutableBigInteger qi = new MutableBigInteger(); | |
| MutableBigInteger ri; | |
| for (int i=t-2; i > 0; i--) { | |
| // step 8a: compute (qi,ri) such that z=b*qi+ri | |
| ri = z.divide2n1n(bShifted, qi); | |
| // step 8b: z = [ri, a[i-1]] | |
| z = aShifted.getBlock(i-1, t, n); // a[i-1] | |
| z.addDisjoint(ri, n); | |
| quotient.addShifted(qi, i*n); // update q (part of step 9) | |
| } | |
| // final iteration of step 8: do the loop one more time for i=0 but leave z unchanged | |
| ri = z.divide2n1n(bShifted, qi); | |
| quotient.add(qi); | |
| ri.rightShift(sigma); // step 9: a and b were shifted, so shift back | |
| return ri; | |
| } | |
| } | |
| /** | |
| * This method implements algorithm 1 from pg. 4 of the Burnikel-Ziegler paper. | |
| * It divides a 2n-digit number by a n-digit number.<br/> | |
| * The parameter beta is 2<sup>32</sup> so all shifts are multiples of 32 bits. | |
| * <br/> | |
| * {@code this} must be a nonnegative number such that {@code this.bitLength() <= 2*b.bitLength()} | |
| * @param b a positive number such that {@code b.bitLength()} is even | |
| * @param quotient output parameter for {@code this/b} | |
| * @return {@code this%b} | |
| */ | |
| private MutableBigInteger divide2n1n(MutableBigInteger b, MutableBigInteger quotient) { | |
| int n = b.intLen; | |
| // step 1: base case | |
| if (n%2 != 0 || n < BigInteger.BURNIKEL_ZIEGLER_THRESHOLD) { | |
| return divideKnuth(b, quotient); | |
| } | |
| // step 2: view this as [a1,a2,a3,a4] where each ai is n/2 ints or less | |
| MutableBigInteger aUpper = new MutableBigInteger(this); | |
| aUpper.safeRightShift(32*(n/2)); // aUpper = [a1,a2,a3] | |
| keepLower(n/2); // this = a4 | |
| // step 3: q1=aUpper/b, r1=aUpper%b | |
| MutableBigInteger q1 = new MutableBigInteger(); | |
| MutableBigInteger r1 = aUpper.divide3n2n(b, q1); | |
| // step 4: quotient=[r1,this]/b, r2=[r1,this]%b | |
| addDisjoint(r1, n/2); // this = [r1,this] | |
| MutableBigInteger r2 = divide3n2n(b, quotient); | |
| // step 5: let quotient=[q1,quotient] and return r2 | |
| quotient.addDisjoint(q1, n/2); | |
| return r2; | |
| } | |
| /** | |
| * This method implements algorithm 2 from pg. 5 of the Burnikel-Ziegler paper. | |
| * It divides a 3n-digit number by a 2n-digit number.<br/> | |
| * The parameter beta is 2<sup>32</sup> so all shifts are multiples of 32 bits.<br/> | |
| * <br/> | |
| * {@code this} must be a nonnegative number such that {@code 2*this.bitLength() <= 3*b.bitLength()} | |
| * @param quotient output parameter for {@code this/b} | |
| * @return {@code this%b} | |
| */ | |
| private MutableBigInteger divide3n2n(MutableBigInteger b, MutableBigInteger quotient) { | |
| int n = b.intLen / 2; // half the length of b in ints | |
| // step 1: view this as [a1,a2,a3] where each ai is n ints or less; let a12=[a1,a2] | |
| MutableBigInteger a12 = new MutableBigInteger(this); | |
| a12.safeRightShift(32*n); | |
| // step 2: view b as [b1,b2] where each bi is n ints or less | |
| MutableBigInteger b1 = new MutableBigInteger(b); | |
| b1.safeRightShift(n * 32); | |
| BigInteger b2 = b.getLower(n); | |
| MutableBigInteger r; | |
| MutableBigInteger d; | |
| if (compareShifted(b, n) < 0) { | |
| // step 3a: if a1<b1, let quotient=a12/b1 and r=a12%b1 | |
| r = a12.divide2n1n(b1, quotient); | |
| // step 4: d=quotient*b2 | |
| d = new MutableBigInteger(quotient.toBigInteger().multiply(b2)); | |
| } else { | |
| // step 3b: if a1>=b1, let quotient=beta^n-1 and r=a12-b1*2^n+b1 | |
| quotient.ones(n); | |
| a12.add(b1); | |
| b1.leftShift(32*n); | |
| a12.subtract(b1); | |
| r = a12; | |
| // step 4: d=quotient*b2=(b2 << 32*n) - b2 | |
| d = new MutableBigInteger(b2); | |
| d.leftShift(32 * n); | |
| d.subtract(new MutableBigInteger(b2)); | |
| } | |
| // step 5: r = r*beta^n + a3 - d (paper says a4) | |
| // However, don't subtract d until after the while loop so r doesn't become negative | |
| r.leftShift(32 * n); | |
| r.addLower(this, n); | |
| // step 6: add b until r>=d | |
| while (r.compare(d) < 0) { | |
| r.add(b); | |
| quotient.subtract(MutableBigInteger.ONE); | |
| } | |
| r.subtract(d); | |
| return r; | |
| } | |
| /** | |
| * Returns a {@code MutableBigInteger} containing {@code blockLength} ints from | |
| * {@code this} number, starting at {@code index*blockLength}.<br/> | |
| * Used by Burnikel-Ziegler division. | |
| * @param index the block index | |
| * @param numBlocks the total number of blocks in {@code this} number | |
| * @param blockLength length of one block in units of 32 bits | |
| * @return | |
| */ | |
| private MutableBigInteger getBlock(int index, int numBlocks, int blockLength) { | |
| int blockStart = index * blockLength; | |
| if (blockStart >= intLen) { | |
| return new MutableBigInteger(); | |
| } | |
| int blockEnd; | |
| if (index == numBlocks-1) { | |
| blockEnd = intLen; | |
| } else { | |
| blockEnd = (index+1) * blockLength; | |
| } | |
| if (blockEnd > intLen) { | |
| return new MutableBigInteger(); | |
| } | |
| int[] newVal = Arrays.copyOfRange(value, offset+intLen-blockEnd, offset+intLen-blockStart); | |
| return new MutableBigInteger(newVal); | |
| } | |
| /** @see BigInteger#bitLength() */ | |
| long bitLength() { | |
| if (intLen == 0) | |
| return 0; | |
| return intLen*32L - Integer.numberOfLeadingZeros(value[offset]); | |
| } | |
| /** | |
| * 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 { | |
| return divideLongMagnitude(v, quotient).toLong(); | |
| } | |
| } | |
| /** | |
| * Divide this MutableBigInteger by the divisor. | |
| * The quotient will be placed into the provided quotient object & | |
| * the remainder object is returned. | |
| */ | |
| private MutableBigInteger divideMagnitude(MutableBigInteger div, | |
| MutableBigInteger quotient, | |
| boolean needRemainder ) { | |
| // assert div.intLen > 1 | |
| // D1 normalize the divisor | |
| int shift = Integer.numberOfLeadingZeros(div.value[div.offset]); | |
| // Copy divisor value to protect divisor | |
| final int dlen = div.intLen; | |
| int[] divisor; | |
| MutableBigInteger rem; // Remainder starts as dividend with space for a leading zero | |
| if (shift > 0) { | |
| divisor = new int[dlen]; | |
| div.primitiveLeftShift(shift, divisor, 0); | |
| if (Integer.numberOfLeadingZeros(value[offset]) >= shift) { | |
| int[] remarr = new int[intLen + 1]; | |
| rem = new MutableBigInteger(remarr); | |
| rem.intLen = intLen; | |
| rem.offset = 1; | |
| this.primitiveLeftShift(shift, remarr, 1); | |
| } else { | |
| int[] remarr = new int[intLen + 2]; | |
| rem = new MutableBigInteger(remarr); | |
| rem.intLen = intLen+1; | |
| rem.offset = 1; | |
| int rFrom = offset; | |
| int c=0; | |
| int n2 = 32 - shift; | |
| for (int i=1; i < intLen+1; i++,rFrom++) { | |
| int b = c; | |
| c = value[rFrom]; | |
| remarr[i] = (b << shift) | (c >>> n2); | |
| } | |
| remarr[intLen+1] = c << shift; | |
| } | |
| } else { | |
| divisor = Arrays.copyOfRange(div.value, div.offset, div.offset + div.intLen); | |
| 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 | |
| final 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; | |
| // Insert leading 0 in rem | |
| rem.offset = 0; | |
| rem.value[0] = 0; | |
| rem.intLen++; | |
| int dh = divisor[0]; | |
| long dhLong = dh & LONG_MASK; | |
| int dl = divisor[1]; | |
| // D2 Initialize j | |
| for (int j=0; j < limit-1; 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); | |
| qhat = (int) Long.divideUnsigned(nChunk, dhLong); | |
| qrem = (int) Long.remainderUnsigned(nChunk, dhLong); | |
| } | |
| 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 | |
| // D3 Calculate qhat | |
| // estimate qhat | |
| int qhat = 0; | |
| int qrem = 0; | |
| boolean skipCorrection = false; | |
| int nh = rem.value[limit - 1 + rem.offset]; | |
| int nh2 = nh + 0x80000000; | |
| int nm = rem.value[limit + rem.offset]; | |
| if (nh == dh) { | |
| qhat = ~0; | |
| qrem = nh + nm; | |
| skipCorrection = qrem + 0x80000000 < nh2; | |
| } else { | |
| long nChunk = (((long) nh) << 32) | (nm & LONG_MASK); | |
| qhat = (int) Long.divideUnsigned(nChunk, dhLong); | |
| qrem = (int) Long.remainderUnsigned(nChunk, dhLong); | |
| } | |
| if (qhat != 0) { | |
| if (!skipCorrection) { // Correct qhat | |
| long nl = rem.value[limit + 1 + 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 | |
| int borrow; | |
| rem.value[limit - 1 + rem.offset] = 0; | |
| if(needRemainder) | |
| borrow = mulsub(rem.value, divisor, qhat, dlen, limit - 1 + rem.offset); | |
| else | |
| borrow = mulsubBorrow(rem.value, divisor, qhat, dlen, limit - 1 + rem.offset); | |
| // D5 Test remainder | |
| if (borrow + 0x80000000 > nh2) { | |
| // D6 Add back | |
| if(needRemainder) | |
| divadd(divisor, rem.value, limit - 1 + 1 + rem.offset); | |
| qhat--; | |
| } | |
| // Store the quotient digit | |
| q[(limit - 1)] = qhat; | |
| } | |
| if (needRemainder) { | |
| // D8 Unnormalize | |
| if (shift > 0) | |
| rem.rightShift(shift); | |
| rem.normalize(); | |
| } | |
| quotient.normalize(); | |
| return needRemainder ? rem : null; | |
| } | |
| /** | |
| * Divide this MutableBigInteger by the divisor represented by positive long | |
| * value. The quotient will be placed into the provided quotient object & | |
| * the remainder object is returned. | |
| */ | |
| private MutableBigInteger divideLongMagnitude(long ldivisor, 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; | |
| int limit = nlen - 2 + 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 = Long.numberOfLeadingZeros(ldivisor); | |
| if (shift > 0) { | |
| ldivisor<<=shift; | |
| 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 = (int)(ldivisor >>> 32); | |
| long dhLong = dh & LONG_MASK; | |
| int dl = (int)(ldivisor & LONG_MASK); | |
| // 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); | |
| qhat = (int) Long.divideUnsigned(nChunk, dhLong); | |
| qrem = (int) Long.remainderUnsigned(nChunk, dhLong); | |
| } | |
| 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 = mulsubLong(rem.value, dh, dl, qhat, j + rem.offset); | |
| // D5 Test remainder | |
| if (borrow + 0x80000000 > nh2) { | |
| // D6 Add back | |
| divaddLong(dh,dl, 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; | |
| } | |
| /** | |
| * A primitive used for division by long. | |
| * Specialized version of the method divadd. | |
| * dh is a high part of the divisor, dl is a low part | |
| */ | |
| private int divaddLong(int dh, int dl, int[] result, int offset) { | |
| long carry = 0; | |
| long sum = (dl & LONG_MASK) + (result[1+offset] & LONG_MASK); | |
| result[1+offset] = (int)sum; | |
| sum = (dh & LONG_MASK) + (result[offset] & LONG_MASK) + carry; | |
| result[offset] = (int)sum; | |
| carry = sum >>> 32; | |
| return (int)carry; | |
| } | |
| /** | |
| * This method is used for division by long. | |
| * Specialized version of the method sulsub. | |
| * dh is a high part of the divisor, dl is a low part | |
| */ | |
| private int mulsubLong(int[] q, int dh, int dl, int x, int offset) { | |
| long xLong = x & LONG_MASK; | |
| offset += 2; | |
| long product = (dl & LONG_MASK) * xLong; | |
| long difference = q[offset] - product; | |
| q[offset--] = (int)difference; | |
| long carry = (product >>> 32) | |
| + (((difference & LONG_MASK) > | |
| (((~(int)product) & LONG_MASK))) ? 1:0); | |
| product = (dh & LONG_MASK) * xLong + carry; | |
| difference = q[offset] - product; | |
| q[offset--] = (int)difference; | |
| carry = (product >>> 32) | |
| + (((difference & LONG_MASK) > | |
| (((~(int)product) & LONG_MASK))) ? 1:0); | |
| return (int)carry; | |
| } | |
| /** | |
| * 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); | |
| } | |
| /** | |
| * Calculate the integer square root {@code floor(sqrt(this))} and the remainder | |
| * if needed, where {@code sqrt(.)} denotes the mathematical square root. | |
| * The contents of {@code this} are <em>not</em> changed. | |
| * The value of {@code this} is assumed to be non-negative. | |
| * | |
| * @return the integer square root of {@code this} and the remainder if needed | |
| */ | |
| MutableBigInteger[] sqrtRem(boolean needRemainder) { | |
| // Special cases. | |
| if (this.intLen <= 2) { | |
| final long x = this.toLong(); // unsigned | |
| long s = unsignedLongSqrt(x); | |
| return new MutableBigInteger[] { | |
| new MutableBigInteger((int) s), | |
| needRemainder ? new MutableBigInteger(x - s * s) : null | |
| }; | |
| } | |
| // Normalize | |
| MutableBigInteger x = this; | |
| final int shift = (Integer.numberOfLeadingZeros(x.value[x.offset]) & ~1) // shift must be even | |
| + ((x.intLen & 1) << 5); // x.intLen must be even | |
| if (shift != 0) { | |
| x = new MutableBigInteger(x); | |
| x.leftShift(shift); | |
| } | |
| // Compute sqrt and remainder | |
| MutableBigInteger[] sqrtRem = x.sqrtRemKaratsuba(x.intLen, needRemainder); | |
| // Unnormalize | |
| if (shift != 0) { | |
| final int halfShift = shift >> 1; | |
| if (needRemainder) { | |
| // shift <= 62, so s0 is at most 31 bit long | |
| final long s0 = sqrtRem[0].value[sqrtRem[0].offset + sqrtRem[0].intLen - 1] | |
| & (-1 >>> -halfShift); // Remove excess bits | |
| if (s0 != 0L) { // An optimization | |
| MutableBigInteger doubleProd = new MutableBigInteger(); | |
| sqrtRem[0].mul((int) (s0 << 1), doubleProd); | |
| sqrtRem[1].add(doubleProd); | |
| sqrtRem[1].subtract(new MutableBigInteger(s0 * s0)); | |
| } | |
| sqrtRem[1].rightShift(shift); | |
| } | |
| sqrtRem[0].primitiveRightShift(halfShift); | |
| } | |
| return sqrtRem; | |
| } | |
| private static long unsignedLongSqrt(long x) { | |
| /* For every long value s in [0, 2^32) such that x == s * s, | |
| * it is true that s - 1 <= (long) Math.sqrt(x >= 0 ? x : x + 0x1p64) <= s, | |
| * and if x == 2^64 - 1, then (long) Math.sqrt(x >= 0 ? x : x + 0x1p64) == 2^32. | |
| * Since both cast to long and `Math.sqrt()` are (weakly) increasing, | |
| * this means that the value returned by Math.sqrt() | |
| * for a long value in the range [0, 2^64) is either correct, | |
| * or rounded up/down by one if the value is too high | |
| * and too close to a perfect square. | |
| */ | |
| long s = (long) Math.sqrt(x >= 0 ? x : x + 0x1p64); | |
| long s2 = s * s; // overflows iff s == 2^32 | |
| return Long.compareUnsigned(x, s2) < 0 || s > LONG_MASK | |
| ? s - 1 | |
| : (Long.compareUnsigned(x, s2 + (s << 1)) <= 0 // x <= (s + 1)^2 - 1, does not overflow | |
| ? s | |
| : s + 1); | |
| } | |
| /** | |
| * Assumes {@code 2 <= len <= intLen && len % 2 == 0 | |
| * && Integer.numberOfLeadingZeros(value[offset]) <= 1} | |
| * @implNote The implementation is based on Zimmermann's works available | |
| * <a href="https://inria.hal.science/inria-00072854v1/document"> here</a> and | |
| * <a href="https://inria.hal.science/inria-00072113/document"> here</a> | |
| */ | |
| private MutableBigInteger[] sqrtRemKaratsuba(int len, boolean needRemainder) { | |
| if (len == 2) { // Base case | |
| long x = ((value[offset] & LONG_MASK) << 32) | (value[offset + 1] & LONG_MASK); | |
| long s = unsignedLongSqrt(x); | |
| // Allocate sufficient space to hold the final square root, assuming intLen % 2 == 0 | |
| MutableBigInteger sqrt = new MutableBigInteger(new int[intLen >> 1]); | |
| // Place the partial square root | |
| sqrt.intLen = 1; | |
| sqrt.value[0] = (int) s; | |
| return new MutableBigInteger[] { sqrt, new MutableBigInteger(x - s * s) }; | |
| } | |
| // Recursive step (len >= 4) | |
| final int halfLen = len >> 1; | |
| // Recursive invocation | |
| MutableBigInteger[] sr = sqrtRemKaratsuba(halfLen + (halfLen & 1), true); | |
| final int blockLen = halfLen >> 1; | |
| MutableBigInteger dividend = sr[1]; | |
| dividend.shiftAddDisjoint(getBlockForSqrt(1, len, blockLen), blockLen); | |
| // Compute dividend / (2*sqrt) | |
| MutableBigInteger sqrt = sr[0]; | |
| MutableBigInteger q = new MutableBigInteger(); | |
| MutableBigInteger u = dividend.divide(sqrt, q); | |
| if (q.isOdd()) | |
| u.add(sqrt); | |
| q.rightShift(1); | |
| sqrt.shiftAdd(q, blockLen); | |
| // Corresponds to ub + a_0 in the paper | |
| u.shiftAddDisjoint(getBlockForSqrt(0, len, blockLen), blockLen); | |
| BigInteger qBig = q.toBigInteger(); // Cast to BigInteger to use fast multiplication | |
| MutableBigInteger qSqr = new MutableBigInteger(qBig.multiply(qBig).mag); | |
| MutableBigInteger rem; | |
| if (needRemainder) { | |
| rem = u; | |
| if (rem.subtract(qSqr) < 0) { | |
| MutableBigInteger twiceSqrt = new MutableBigInteger(sqrt); | |
| twiceSqrt.leftShift(1); | |
| // Since subtract() performs an absolute difference, to get the correct algebraic sum | |
| // we must first add the sum of absolute values of addends concordant with the sign of rem | |
| // and then subtract the sum of absolute values of addends that are discordant | |
| rem.add(ONE); | |
| rem.subtract(twiceSqrt); | |
| sqrt.subtract(ONE); | |
| } | |
| } else { | |
| rem = null; | |
| if (u.compare(qSqr) < 0) | |
| sqrt.subtract(ONE); | |
| } | |
| sr[1] = rem; | |
| return sr; | |
| } | |
| /** | |
| * Returns a {@code MutableBigInteger} obtained by taking {@code blockLen} ints from | |
| * {@code this} number, ending at {@code blockIndex*blockLen} (exclusive).<br/> | |
| * Used in Karatsuba square root. | |
| * @param blockIndex the block index, starting from the lowest | |
| * @param len the logical length of the input value in units of 32 bits | |
| * @param blockLen the length of the block in units of 32 bits | |
| * | |
| * @return a {@code MutableBigInteger} obtained by taking {@code blockLen} ints from | |
| * {@code this} number, ending at {@code blockIndex*blockLen} (exclusive). | |
| */ | |
| private MutableBigInteger getBlockForSqrt(int blockIndex, int len, int blockLen) { | |
| final int to = offset + len - blockIndex * blockLen; | |
| // Skip leading zeros | |
| int from; | |
| for (from = to - blockLen; from < to && value[from] == 0; from++); | |
| return from == to | |
| ? new MutableBigInteger() | |
| : new MutableBigInteger(Arrays.copyOfRange(value, from, to)); | |
| } | |
| /** | |
| * 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. | |
| */ | |
| private MutableBigInteger binaryGCD(MutableBigInteger v) { | |
| // Algorithm B from Knuth TAOCP Vol. 2, 3rd edition, 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. | |
| */ | |
| 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. | |
| */ | |
| 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); | |
| oddPart.clear(); | |
| 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; | |
| } | |
| /** | |
| * Returns the multiplicative inverse of val mod 2^64. Assumes val is odd. | |
| */ | |
| static long inverseMod64(long val) { | |
| // Newton's iteration! | |
| long t = val; | |
| t *= 2 - val*t; | |
| t *= 2 - val*t; | |
| t *= 2 - val*t; | |
| t *= 2 - val*t; | |
| t *= 2 - val*t; | |
| assert(t * val == 1); | |
| 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 modulo mod, where the mod | |
| * argument 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; | |
| } | |
| if (c.compare(p) >= 0) { // c has a larger magnitude than p | |
| MutableBigInteger remainder = c.divide(p, | |
| new MutableBigInteger()); | |
| // The previous line ignores the sign so we copy the data back | |
| // into c which will restore the sign as needed (and converts | |
| // it back to a SignedMutableBigInteger) | |
| c.copyValue(remainder); | |
| } | |
| if (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!) | |
| if (c.compare(p) >= 0) | |
| c = c.divide(p, new MutableBigInteger()); | |
| 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; | |
| } | |
| } |