diff -r d9d491a5a169 -r dd6d609861f0 jdk/src/share/classes/java/math/BigInteger.java --- a/jdk/src/share/classes/java/math/BigInteger.java Thu May 21 23:32:46 2009 -0700 +++ b/jdk/src/share/classes/java/math/BigInteger.java Sun May 24 16:29:57 2009 -0700 @@ -105,7 +105,7 @@ * * @serial */ - int signum; + final int signum; /** * The magnitude of this BigInteger, in big-endian order: the @@ -116,61 +116,62 @@ * value. Note that this implies that the BigInteger zero has a * zero-length mag array. */ - int[] mag; + final int[] mag; // These "redundant fields" are initialized with recognizable nonsense // values, and cached the first time they are needed (or never, if they // aren't needed). - /** - * The bitCount of this BigInteger, as returned by bitCount(), or -1 - * (either value is acceptable). + /** + * One plus the bitCount of this BigInteger. Zeros means unitialized. * * @serial * @see #bitCount + * @deprecated Deprecated since logical value is offset from stored + * value and correction factor is applied in accessor method. */ - private int bitCount = -1; + @Deprecated + private int bitCount; /** - * The bitLength of this BigInteger, as returned by bitLength(), or -1 + * One plus the bitLength of this BigInteger. Zeros means unitialized. * (either value is acceptable). * * @serial * @see #bitLength() + * @deprecated Deprecated since logical value is offset from stored + * value and correction factor is applied in accessor method. */ - private int bitLength = -1; + @Deprecated + private int bitLength; /** - * The lowest set bit of this BigInteger, as returned by getLowestSetBit(), - * or -2 (either value is acceptable). + * Two plus the lowest set bit of this BigInteger, as returned by + * getLowestSetBit(). * * @serial * @see #getLowestSetBit + * @deprecated Deprecated since logical value is offset from stored + * value and correction factor is applied in accessor method. */ - private int lowestSetBit = -2; + @Deprecated + private int lowestSetBit; /** - * The index of the lowest-order byte in the magnitude of this BigInteger - * that contains a nonzero byte, or -2 (either value is acceptable). The - * least significant byte has int-number 0, the next byte in order of - * increasing significance has byte-number 1, and so forth. - * - * @serial + * Two plus the index of the lowest-order int in the magnitude of this + * BigInteger that contains a nonzero int, or -2 (either value is acceptable). + * The least significant int has int-number 0, the next int in order of + * increasing significance has int-number 1, and so forth. + * @deprecated Deprecated since logical value is offset from stored + * value and correction factor is applied in accessor method. */ - private int firstNonzeroByteNum = -2; - - /** - * The index of the lowest-order int in the magnitude of this BigInteger - * that contains a nonzero int, or -2 (either value is acceptable). The - * least significant int has int-number 0, the next int in order of - * increasing significance has int-number 1, and so forth. - */ - private int firstNonzeroIntNum = -2; + @Deprecated + private int firstNonzeroIntNum; /** * This mask is used to obtain the value of an int as if it were unsigned. */ - private final static long LONG_MASK = 0xffffffffL; + final static long LONG_MASK = 0xffffffffL; //Constructors @@ -295,7 +296,7 @@ throw new NumberFormatException("Zero length BigInteger"); // Check for at most one leading sign - signum = 1; + int sign = 1; int index1 = val.lastIndexOf('-'); int index2 = val.lastIndexOf('+'); if ((index1 + index2) <= -1) { @@ -306,7 +307,7 @@ throw new NumberFormatException("Zero length BigInteger"); } if (index1 == 0) - signum = -1; + sign = -1; } else throw new NumberFormatException("Illegal embedded sign character"); @@ -318,23 +319,24 @@ signum = 0; mag = ZERO.mag; return; - } else { - numDigits = len - cursor; } + numDigits = len - cursor; + signum = sign; + // Pre-allocate array of expected size. May be too large but can // never be too small. Typically exact. int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1); - int numWords = (numBits + 31) /32; - mag = new int[numWords]; + int numWords = (numBits + 31) >>> 5; + int[] magnitude = new int[numWords]; // Process first (potentially short) digit group int firstGroupLen = numDigits % digitsPerInt[radix]; if (firstGroupLen == 0) firstGroupLen = digitsPerInt[radix]; String group = val.substring(cursor, cursor += firstGroupLen); - mag[mag.length - 1] = Integer.parseInt(group, radix); - if (mag[mag.length - 1] < 0) + magnitude[numWords - 1] = Integer.parseInt(group, radix); + if (magnitude[numWords - 1] < 0) throw new NumberFormatException("Illegal digit"); // Process remaining digit groups @@ -345,10 +347,10 @@ groupVal = Integer.parseInt(group, radix); if (groupVal < 0) throw new NumberFormatException("Illegal digit"); - destructiveMulAdd(mag, superRadix, groupVal); + destructiveMulAdd(magnitude, superRadix, groupVal); } // Required for cases where the array was overallocated. - mag = trustedStripLeadingZeroInts(mag); + mag = trustedStripLeadingZeroInts(magnitude); } // Constructs a new BigInteger using a char array with radix=10 @@ -357,11 +359,11 @@ int len = val.length; // Check for leading minus sign - signum = 1; + int sign = 1; if (val[0] == '-') { if (len == 1) throw new NumberFormatException("Zero length BigInteger"); - signum = -1; + sign = -1; cursor = 1; } else if (val[0] == '+') { if (len == 1) @@ -376,32 +378,33 @@ signum = 0; mag = ZERO.mag; return; - } else { - numDigits = len - cursor; } + numDigits = len - cursor; + signum = sign; + // Pre-allocate array of expected size int numWords; if (len < 10) { numWords = 1; } else { int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1); - numWords = (numBits + 31) /32; + numWords = (numBits + 31) >>> 5; } - mag = new int[numWords]; + int[] magnitude = new int[numWords]; // Process first (potentially short) digit group int firstGroupLen = numDigits % digitsPerInt[10]; if (firstGroupLen == 0) firstGroupLen = digitsPerInt[10]; - mag[mag.length-1] = parseInt(val, cursor, cursor += firstGroupLen); + magnitude[numWords - 1] = parseInt(val, cursor, cursor += firstGroupLen); // Process remaining digit groups while (cursor < len) { int groupVal = parseInt(val, cursor, cursor += digitsPerInt[10]); - destructiveMulAdd(mag, intRadix[10], groupVal); + destructiveMulAdd(magnitude, intRadix[10], groupVal); } - mag = trustedStripLeadingZeroInts(mag); + mag = trustedStripLeadingZeroInts(magnitude); } // Create an integer with the digits between the two indexes @@ -842,26 +845,21 @@ u2 = u.multiply(v).mod(n); v2 = v.square().add(d.multiply(u.square())).mod(n); - if (v2.testBit(0)) { - v2 = n.subtract(v2); - v2.signum = - v2.signum; - } + if (v2.testBit(0)) + v2 = v2.subtract(n); + v2 = v2.shiftRight(1); u = u2; v = v2; if (k.testBit(i)) { u2 = u.add(v).mod(n); - if (u2.testBit(0)) { - u2 = n.subtract(u2); - u2.signum = - u2.signum; - } + if (u2.testBit(0)) + u2 = u2.subtract(n); + u2 = u2.shiftRight(1); - v2 = v.add(d.multiply(u)).mod(n); - if (v2.testBit(0)) { - v2 = n.subtract(v2); - v2.signum = - v2.signum; - } + if (v2.testBit(0)) + v2 = v2.subtract(n); v2 = v2.shiftRight(1); u = u2; v = v2; @@ -918,11 +916,11 @@ } /** - * This private constructor differs from its public cousin + * This internal constructor differs from its public cousin * with the arguments reversed in two ways: it assumes that its * arguments are correct, and it doesn't copy the magnitude array. */ - private BigInteger(int[] magnitude, int signum) { + BigInteger(int[] magnitude, int signum) { this.signum = (magnitude.length==0 ? 0 : signum); this.mag = magnitude; } @@ -936,22 +934,6 @@ this.mag = stripLeadingZeroBytes(magnitude); } - /** - * This private constructor is for internal use in converting - * from a MutableBigInteger object into a BigInteger. - */ - BigInteger(MutableBigInteger val, int sign) { - if (val.offset > 0 || val.value.length != val.intLen) { - mag = new int[val.intLen]; - for(int i=0; i0 ? subtract(mag, val.mag) + int[] resultMag = (cmp > 0 ? subtract(mag, val.mag) : subtract(val.mag, mag)); resultMag = trustedStripLeadingZeroInts(resultMag); - return new BigInteger(resultMag, cmp*signum); + return new BigInteger(resultMag, cmp == signum ? 1 : -1); } /** @@ -1112,12 +1093,10 @@ // Grow result if necessary if (carry) { - int newLen = result.length + 1; - int temp[] = new int[newLen]; - for (int i = 1; i0 ? subtract(mag, val.mag) + int[] resultMag = (cmp > 0 ? subtract(mag, val.mag) : subtract(val.mag, mag)); resultMag = trustedStripLeadingZeroInts(resultMag); - return new BigInteger(resultMag, cmp*signum); + return new BigInteger(resultMag, cmp == signum ? 1 : -1); } /** @@ -1191,12 +1169,54 @@ int[] result = multiplyToLen(mag, mag.length, val.mag, val.mag.length, null); result = trustedStripLeadingZeroInts(result); - return new BigInteger(result, signum*val.signum); + return new BigInteger(result, signum == val.signum ? 1 : -1); + } + + /** + * Package private methods used by BigDecimal code to multiply a BigInteger + * with a long. Assumes v is not equal to INFLATED. + */ + BigInteger multiply(long v) { + if (v == 0 || signum == 0) + return ZERO; + if (v == BigDecimal.INFLATED) + return multiply(BigInteger.valueOf(v)); + int rsign = (v > 0 ? signum : -signum); + if (v < 0) + v = -v; + long dh = v >>> 32; // higher order bits + long dl = v & LONG_MASK; // lower order bits + + int xlen = mag.length; + int[] value = mag; + int[] rmag = (dh == 0L) ? (new int[xlen + 1]) : (new int[xlen + 2]); + long carry = 0; + int rstart = rmag.length - 1; + for (int i = xlen - 1; i >= 0; i--) { + long product = (value[i] & LONG_MASK) * dl + carry; + rmag[rstart--] = (int)product; + carry = product >>> 32; + } + rmag[rstart] = (int)carry; + if (dh != 0L) { + carry = 0; + rstart = rmag.length - 2; + for (int i = xlen - 1; i >= 0; i--) { + long product = (value[i] & LONG_MASK) * dh + + (rmag[rstart] & LONG_MASK) + carry; + rmag[rstart--] = (int)product; + carry = product >>> 32; + } + rmag[0] = (int)carry; + } + if (carry == 0L) + rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length); + return new BigInteger(rmag, rsign); } /** * Multiplies int arrays x and y to the specified lengths and places - * the result into z. + * the result into z. There will be no leading zeros in the resultant array. */ private int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) { int xstart = xlen - 1; @@ -1316,12 +1336,11 @@ */ public BigInteger divide(BigInteger val) { MutableBigInteger q = new MutableBigInteger(), - r = new MutableBigInteger(), a = new MutableBigInteger(this.mag), b = new MutableBigInteger(val.mag); - a.divide(b, q, r); - return new BigInteger(q, this.signum * val.signum); + a.divide(b, q); + return q.toBigInteger(this.signum == val.signum ? 1 : -1); } /** @@ -1338,12 +1357,11 @@ public BigInteger[] divideAndRemainder(BigInteger val) { BigInteger[] result = new BigInteger[2]; MutableBigInteger q = new MutableBigInteger(), - r = new MutableBigInteger(), a = new MutableBigInteger(this.mag), b = new MutableBigInteger(val.mag); - a.divide(b, q, r); - result[0] = new BigInteger(q, this.signum * val.signum); - result[1] = new BigInteger(r, this.signum); + MutableBigInteger r = a.divide(b, q); + result[0] = q.toBigInteger(this.signum == val.signum ? 1 : -1); + result[1] = r.toBigInteger(this.signum); return result; } @@ -1357,12 +1375,10 @@ */ public BigInteger remainder(BigInteger val) { MutableBigInteger q = new MutableBigInteger(), - r = new MutableBigInteger(), a = new MutableBigInteger(this.mag), b = new MutableBigInteger(val.mag); - a.divide(b, q, r); - return new BigInteger(r, this.signum); + return a.divide(b, q).toBigInteger(this.signum); } /** @@ -1418,7 +1434,14 @@ MutableBigInteger result = a.hybridGCD(b); - return new BigInteger(result, 1); + return result.toBigInteger(1); + } + + /** + * Package private method to return bit length for an integer. + */ + static int bitLengthForInt(int n) { + return 32 - Integer.numberOfLeadingZeros(n); } /** @@ -1428,7 +1451,7 @@ private static int[] leftShift(int[] a, int len, int n) { int nInts = n >>> 5; int nBits = n&0x1F; - int bitsInHighWord = bitLen(a[0]); + int bitsInHighWord = bitLengthForInt(a[0]); // If shift can be done without recopy, do so if (n <= (32-bitsInHighWord)) { @@ -1481,9 +1504,9 @@ * assuming there are no leading zero ints. */ private static int bitLength(int[] val, int len) { - if (len==0) + if (len == 0) return 0; - return ((len-1)<<5) + bitLen(val[0]); + return ((len - 1) << 5) + bitLengthForInt(val[0]); } /** @@ -1710,11 +1733,10 @@ int[] a = leftShift(base, base.length, modLen << 5); MutableBigInteger q = new MutableBigInteger(), - r = new MutableBigInteger(), a2 = new MutableBigInteger(a), b2 = new MutableBigInteger(mod); - a2.divide(b2, q, r); + MutableBigInteger r= a2.divide(b2, q); table[0] = r.toIntArray(); // Pad table[0] with leading zeros so its length is at least modLen @@ -1976,7 +1998,7 @@ return this; // Copy remaining ints of mag - int numInts = (p+31)/32; + int numInts = (p + 31) >>> 5; int[] mag = new int[numInts]; for (int i=0; i= 0)) + if (signum < 0 || (this.compareMagnitude(m) >= 0)) modVal = this.mod(m); if (modVal.equals(ONE)) @@ -2016,7 +2038,7 @@ MutableBigInteger b = new MutableBigInteger(m); MutableBigInteger result = a.mutableModInverse(b); - return new BigInteger(result, 1); + return result.toBigInteger(1); } // Shift Operations @@ -2241,7 +2263,7 @@ if (n<0) throw new ArithmeticException("Negative bit address"); - return (getInt(n/32) & (1 << (n%32))) != 0; + return (getInt(n >>> 5) & (1 << (n & 31))) != 0; } /** @@ -2256,13 +2278,13 @@ if (n<0) throw new ArithmeticException("Negative bit address"); - int intNum = n/32; + int intNum = n >>> 5; int[] result = new int[Math.max(intLength(), intNum+2)]; for (int i=0; i>> 5; + int[] result = new int[Math.max(intLength(), ((n + 1) >>> 5) + 1)]; for (int i=0; i>> 5; int[] result = new int[Math.max(intLength(), intNum+2)]; for (int i=0; iexcluding a sign bit. */ public int bitLength() { - /* - * Initialize bitLength field the first time this method is executed. - * This method depends on the atomicity of int modifies; without - * this guarantee, it would have to be synchronized. - */ - if (bitLength == -1) { - if (signum == 0) { - bitLength = 0; - } else { + @SuppressWarnings("deprecation") int n = bitLength - 1; + if (n == -1) { // bitLength not initialized yet + int[] m = mag; + int len = m.length; + if (len == 0) { + n = 0; // offset by one to initialize + } else { // Calculate the bit length of the magnitude - int magBitLength = ((mag.length-1) << 5) + bitLen(mag[0]); - - if (signum < 0) { - // Check if magnitude is a power of two - boolean pow2 = (bitCnt(mag[0]) == 1); - for(int i=1; i>> 1; - val = (val & 0x33333333) + ((val >>> 2) & 0x33333333); - val = val + (val >>> 4) & 0x0f0f0f0f; - val += val >>> 8; - val += val >>> 16; - return val & 0xff; - } - - static int trailingZeroCnt(int val) { - // Loop unrolled for performance - int byteVal = val & 0xff; - if (byteVal != 0) - return trailingZeroTable[byteVal]; - - byteVal = (val >>> 8) & 0xff; - if (byteVal != 0) - return trailingZeroTable[byteVal] + 8; - - byteVal = (val >>> 16) & 0xff; - if (byteVal != 0) - return trailingZeroTable[byteVal] + 16; - - byteVal = (val >>> 24) & 0xff; - return trailingZeroTable[byteVal] + 24; + return bc; } // Primality Testing @@ -2536,29 +2474,41 @@ * to, or greater than {@code val}. */ public int compareTo(BigInteger val) { - return (signum==val.signum - ? signum*intArrayCmp(mag, val.mag) - : (signum>val.signum ? 1 : -1)); + if (signum == val.signum) { + switch (signum) { + case 1: + return compareMagnitude(val); + case -1: + return val.compareMagnitude(this); + default: + return 0; + } + } + return signum > val.signum ? 1 : -1; } - /* - * Returns -1, 0 or +1 as big-endian unsigned int array arg1 is - * less than, equal to, or greater than arg2. + /** + * Compares the magnitude array of this BigInteger with the specified + * BigInteger's. This is the version of compareTo ignoring sign. + * + * @param val BigInteger whose magnitude array to be compared. + * @return -1, 0 or 1 as this magnitude array is less than, equal to or + * greater than the magnitude aray for the specified BigInteger's. */ - private static int intArrayCmp(int[] arg1, int[] arg2) { - if (arg1.length < arg2.length) + final int compareMagnitude(BigInteger val) { + int[] m1 = mag; + int len1 = m1.length; + int[] m2 = val.mag; + int len2 = m2.length; + if (len1 < len2) return -1; - if (arg1.length > arg2.length) + if (len1 > len2) return 1; - - // Argument lengths are equal; compare the values - for (int i=0; i b2) - return 1; + for (int i = 0; i < len1; i++) { + int a = m1[i]; + int b = m2[i]; + if (a != b) + return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1; } return 0; } @@ -2577,13 +2527,19 @@ if (!(x instanceof BigInteger)) return false; + BigInteger xInt = (BigInteger) x; - - if (xInt.signum != signum || xInt.mag.length != mag.length) + if (xInt.signum != signum) return false; - for (int i=0; i 0) { - int result[] = new int[val.length - keep]; - for(int i=0; i>> 2; int[] result = new int[intLength]; int b = byteLength - 1; for (int i = intLength-1; i >= 0; i--) { result[i] = a[b--] & 0xff; int bytesRemaining = b - keep + 1; int bytesToTransfer = Math.min(3, bytesRemaining); - for (int j=8; j <= 8*bytesToTransfer; j += 8) + for (int j=8; j <= (bytesToTransfer << 3); j += 8) result[i] |= ((a[b--] & 0xff) << j); } return result; @@ -3037,7 +2979,7 @@ * including space for at least one sign bit. */ private int intLength() { - return bitLength()/32 + 1; + return (bitLength() >>> 5) + 1; } /* Returns sign bit */ @@ -3074,20 +3016,20 @@ * least significant). If the magnitude is zero, return value is undefined. */ private int firstNonzeroIntNum() { - /* - * Initialize firstNonzeroIntNum field the first time this method is - * executed. This method depends on the atomicity of int modifies; - * without this guarantee, it would have to be synchronized. - */ - if (firstNonzeroIntNum == -2) { - // Search for the first nonzero int - int i; - for (i=mag.length-1; i>=0 && mag[i]==0; i--) - ; - firstNonzeroIntNum = mag.length-i-1; - } - return firstNonzeroIntNum; - } + int fn = firstNonzeroIntNum - 2; + if (fn == -2) { // firstNonzeroIntNum not initialized yet + fn = 0; + + // Search for the first nonzero int + int i; + int mlen = mag.length; + for (i = mlen - 1; i >= 0 && mag[i] == 0; i--) + ; + fn = mlen - i - 1; + firstNonzeroIntNum = fn + 2; // offset by two to initialize + } + return fn; + } /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -8287574255936472291L; @@ -3121,6 +3063,12 @@ * deserialize it). The magnitude is read in as an array of bytes * for historical reasons, but it is converted to an array of ints * and the byte array is discarded. + * Note: + * The current convention is to initialize the cache fields, bitCount, + * bitLength and lowestSetBit, to 0 rather than some other marker value. + * Therefore, no explicit action to set these fields needs to be taken in + * readObject because those fields already have a 0 value be default since + * defaultReadObject is not being used. */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { @@ -3136,29 +3084,44 @@ ObjectInputStream.GetField fields = s.readFields(); // Read the alternate persistent fields that we care about - signum = fields.get("signum", -2); + int sign = fields.get("signum", -2); byte[] magnitude = (byte[])fields.get("magnitude", null); // Validate signum - if (signum < -1 || signum > 1) { + if (sign < -1 || sign > 1) { String message = "BigInteger: Invalid signum value"; if (fields.defaulted("signum")) message = "BigInteger: Signum not present in stream"; throw new java.io.StreamCorruptedException(message); } - if ((magnitude.length==0) != (signum==0)) { + if ((magnitude.length == 0) != (sign == 0)) { String message = "BigInteger: signum-magnitude mismatch"; if (fields.defaulted("magnitude")) message = "BigInteger: Magnitude not present in stream"; throw new java.io.StreamCorruptedException(message); } - // Set "cached computation" fields to their initial values - bitCount = bitLength = -1; - lowestSetBit = firstNonzeroByteNum = firstNonzeroIntNum = -2; + // Commit final fields via Unsafe + unsafe.putIntVolatile(this, signumOffset, sign); // Calculate mag field from magnitude and discard magnitude - mag = stripLeadingZeroBytes(magnitude); + unsafe.putObjectVolatile(this, magOffset, + stripLeadingZeroBytes(magnitude)); + } + + // Support for resetting final fields while deserializing + private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + private static final long signumOffset; + private static final long magOffset; + static { + try { + signumOffset = unsafe.objectFieldOffset + (BigInteger.class.getDeclaredField("signum")); + magOffset = unsafe.objectFieldOffset + (BigInteger.class.getDeclaredField("mag")); + } catch (Exception ex) { + throw new Error(ex); + } } /** @@ -3174,6 +3137,8 @@ ObjectOutputStream.PutField fields = s.putFields(); fields.put("signum", signum); fields.put("magnitude", magSerializedForm()); + // The values written for cached fields are compatible with older + // versions, but are ignored in readObject so don't otherwise matter. fields.put("bitCount", -1); fields.put("bitLength", -1); fields.put("lowestSetBit", -2); @@ -3187,12 +3152,13 @@ * Returns the mag array as an array of bytes. */ private byte[] magSerializedForm() { - int bitLen = (mag.length == 0 ? 0 : - ((mag.length - 1) << 5) + bitLen(mag[0])); - int byteLen = (bitLen + 7)/8; + int len = mag.length; + + int bitLen = (len == 0 ? 0 : ((len - 1) << 5) + bitLengthForInt(mag[0])); + int byteLen = (bitLen + 7) >>> 3; byte[] result = new byte[byteLen]; - for (int i=byteLen-1, bytesCopied=4, intIndex=mag.length-1, nextInt=0; + for (int i = byteLen - 1, bytesCopied = 4, intIndex = len - 1, nextInt = 0; i>=0; i--) { if (bytesCopied == 4) { nextInt = mag[intIndex--];