src/share/classes/java/math/BigInteger.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 1996, 2007, 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
--- 1,7 ----
/*
! * Copyright (c) 1996, 2011, 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
*** 351,390 ****
}
// Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude);
}
! // Constructs a new BigInteger using a char array with radix=10
! BigInteger(char[] val) {
int cursor = 0, numDigits;
- int len = val.length;
-
- // Check for leading minus sign
- int sign = 1;
- if (val[0] == '-') {
- if (len == 1)
- throw new NumberFormatException("Zero length BigInteger");
- sign = -1;
- cursor = 1;
- } else if (val[0] == '+') {
- if (len == 1)
- throw new NumberFormatException("Zero length BigInteger");
- cursor = 1;
- }
// Skip leading zeros and compute number of digits in magnitude
! while (cursor < len && Character.digit(val[cursor], 10) == 0)
cursor++;
if (cursor == len) {
signum = 0;
mag = ZERO.mag;
return;
}
numDigits = len - cursor;
signum = sign;
-
// Pre-allocate array of expected size
int numWords;
if (len < 10) {
numWords = 1;
} else {
--- 351,379 ----
}
// Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude);
}
! /*
! * Constructs a new BigInteger using a char array with radix=10.
! * Sign is precalculated outside and not allowed in the val.
! */
! BigInteger(char[] val, int sign, int len) {
int cursor = 0, numDigits;
// Skip leading zeros and compute number of digits in magnitude
! while (cursor < len && Character.digit(val[cursor], 10) == 0) {
cursor++;
+ }
if (cursor == len) {
signum = 0;
mag = ZERO.mag;
return;
}
numDigits = len - cursor;
signum = sign;
// Pre-allocate array of expected size
int numWords;
if (len < 10) {
numWords = 1;
} else {
*** 1056,1065 ****
--- 1045,1121 ----
return new BigInteger(resultMag, cmp == signum ? 1 : -1);
}
/**
+ * Package private methods used by BigDecimal code to add a BigInteger
+ * with a long. Assumes val is not equal to INFLATED.
+ */
+ BigInteger add(long val) {
+ if (val == 0)
+ return this;
+ if (signum == 0)
+ return valueOf(val);
+ if (Long.signum(val) == signum)
+ return new BigInteger(add(mag, Math.abs(val)), signum);
+ int cmp = compareMagnitude(val);
+ if (cmp == 0)
+ return ZERO;
+ int[] resultMag = (cmp > 0 ? subtract(mag, Math.abs(val)) : subtract(Math.abs(val), mag));
+ resultMag = trustedStripLeadingZeroInts(resultMag);
+ return new BigInteger(resultMag, cmp == signum ? 1 : -1);
+ }
+
+ /**
+ * Adds the contents of the int array x and long value val. This
+ * method allocates a new int array to hold the answer and returns
+ * a reference to that array. Assumes x.length > 0 and val is
+ * non-negative
+ */
+ private static int[] add(int[] x, long val) {
+ int[] y;
+ long sum = 0;
+ int xIndex = x.length;
+ int[] result;
+ int highWord = (int)(val >>> 32);
+ if (highWord==0) {
+ result = new int[xIndex];
+ sum = (x[--xIndex] & LONG_MASK) + val;
+ result[xIndex] = (int)sum;
+ } else {
+ if (xIndex == 1) {
+ result = new int[2];
+ sum = val + (x[0] & LONG_MASK);
+ result[1] = (int)sum;
+ result[0] = (int)(sum >>> 32);
+ return result;
+ } else {
+ result = new int[xIndex];
+ sum = (x[--xIndex] & LONG_MASK) + (val & LONG_MASK);
+ result[xIndex] = (int)sum;
+ sum = (x[--xIndex] & LONG_MASK) + (highWord & LONG_MASK) + (sum >>> 32);
+ result[xIndex] = (int)sum;
+ }
+ }
+ // Copy remainder of longer number while carry propagation is required
+ boolean carry = (sum >>> 32 != 0);
+ while (xIndex > 0 && carry)
+ carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
+ // Copy remainder of longer number
+ while (xIndex > 0)
+ result[--xIndex] = x[xIndex];
+ // Grow result if necessary
+ if (carry) {
+ int bigger[] = new int[result.length + 1];
+ System.arraycopy(result, 0, bigger, 1, result.length);
+ bigger[0] = 0x01;
+ return bigger;
+ }
+ return result;
+ }
+
+ /**
* Adds the contents of the int arrays x and y. This method allocates
* a new int array to hold the answer and returns a reference to that
* array.
*/
private static int[] add(int[] x, int[] y) {
*** 1072,1089 ****
int xIndex = x.length;
int yIndex = y.length;
int result[] = new int[xIndex];
long sum = 0;
!
// Add common parts of both numbers
while(yIndex > 0) {
sum = (x[--xIndex] & LONG_MASK) +
(y[--yIndex] & LONG_MASK) + (sum >>> 32);
result[xIndex] = (int)sum;
}
!
// Copy remainder of longer number while carry propagation is required
boolean carry = (sum >>> 32 != 0);
while (xIndex > 0 && carry)
carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
--- 1128,1148 ----
int xIndex = x.length;
int yIndex = y.length;
int result[] = new int[xIndex];
long sum = 0;
! if(yIndex==1) {
! sum = (x[--xIndex] & LONG_MASK) + (y[0] & LONG_MASK) ;
! result[xIndex] = (int)sum;
! } else {
// Add common parts of both numbers
while(yIndex > 0) {
sum = (x[--xIndex] & LONG_MASK) +
(y[--yIndex] & LONG_MASK) + (sum >>> 32);
result[xIndex] = (int)sum;
}
! }
// Copy remainder of longer number while carry propagation is required
boolean carry = (sum >>> 32 != 0);
while (xIndex > 0 && carry)
carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
*** 1099,1108 ****
--- 1158,1232 ----
return bigger;
}
return result;
}
+ private static int[] subtract(long val, int[] little) {
+ int highWord = (int)(val >>> 32);
+ if (highWord==0) {
+ int result[] = new int[1];
+ result[0] = (int)(val - (little[0] & LONG_MASK));
+ return result;
+ } else {
+ int result[] = new int[2];
+ if(little.length==1) {
+ long difference = ((int)val & LONG_MASK) - (little[0] & LONG_MASK);
+ result[1] = (int)difference;
+ // Subtract remainder of longer number while borrow propagates
+ boolean borrow = (difference >> 32 != 0);
+ if(borrow) {
+ result[0] = highWord - 1;
+ } else { // Copy remainder of longer number
+ result[0] = highWord;
+ }
+ return result;
+ } else { // little.length==2
+ long difference = ((int)val & LONG_MASK) - (little[1] & LONG_MASK);
+ result[1] = (int)difference;
+ difference = (highWord & LONG_MASK) - (little[0] & LONG_MASK) + (difference >> 32);
+ result[0] = (int)difference;
+ return result;
+ }
+ }
+ }
+
+ /**
+ * Subtracts the contents of the second argument (val) from the
+ * first (big). The first int array (big) must represent a larger number
+ * than the second. This method allocates the space necessary to hold the
+ * answer.
+ * assumes val >= 0
+ */
+ private static int[] subtract(int[] big, long val) {
+ int highWord = (int)(val >>> 32);
+ int bigIndex = big.length;
+ int result[] = new int[bigIndex];
+ long difference = 0;
+
+ if (highWord==0) {
+ difference = (big[--bigIndex] & LONG_MASK) - val;
+ result[bigIndex] = (int)difference;
+ } else {
+ difference = (big[--bigIndex] & LONG_MASK) - (val & LONG_MASK);
+ result[bigIndex] = (int)difference;
+ difference = (big[--bigIndex] & LONG_MASK) - (highWord & LONG_MASK) + (difference >> 32);
+ result[bigIndex] = (int)difference;
+ }
+
+
+ // Subtract remainder of longer number while borrow propagates
+ boolean borrow = (difference >> 32 != 0);
+ while (bigIndex > 0 && borrow)
+ borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1);
+
+ // Copy remainder of longer number
+ while (bigIndex > 0)
+ result[--bigIndex] = big[bigIndex];
+
+ return result;
+ }
+
/**
* Returns a BigInteger whose value is {@code (this - val)}.
*
* @param val value to be subtracted from this BigInteger.
* @return {@code this - val}
*** 1163,1177 ****
* @return {@code this * val}
*/
public BigInteger multiply(BigInteger val) {
if (val.signum == 0 || signum == 0)
return ZERO;
!
int[] result = multiplyToLen(mag, mag.length,
val.mag, val.mag.length, null);
result = trustedStripLeadingZeroInts(result);
! return new BigInteger(result, signum == val.signum ? 1 : -1);
}
/**
* Package private methods used by BigDecimal code to multiply a BigInteger
* with a long. Assumes v is not equal to INFLATED.
--- 1287,1329 ----
* @return {@code this * val}
*/
public BigInteger multiply(BigInteger val) {
if (val.signum == 0 || signum == 0)
return ZERO;
! int resultSign = signum == val.signum ? 1 : -1;
! if (val.mag.length == 1) {
! return multiplyByInt(mag,val.mag[0], resultSign);
! }
! if(mag.length == 1) {
! return multiplyByInt(val.mag,mag[0], resultSign);
! }
int[] result = multiplyToLen(mag, mag.length,
val.mag, val.mag.length, null);
result = trustedStripLeadingZeroInts(result);
! return new BigInteger(result, resultSign);
! }
!
! private static BigInteger multiplyByInt(int[] x, int y, int sign) {
! if(Integer.bitCount(y)==1) {
! return new BigInteger(shiftLeft(x,Integer.numberOfTrailingZeros(y)), sign);
! }
! int xlen = x.length;
! int[] rmag = new int[xlen + 1];
! long carry = 0;
! long yl = y & LONG_MASK;
! int rstart = rmag.length - 1;
! for (int i = xlen - 1; i >= 0; i--) {
! long product = (x[i] & LONG_MASK) * yl + carry;
! rmag[rstart--] = (int)product;
! carry = product >>> 32;
! }
! if (carry == 0L) {
! rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length);
! } else {
! rmag[rstart] = (int)carry;
! }
! return new BigInteger(rmag, sign);
}
/**
* Package private methods used by BigDecimal code to multiply a BigInteger
* with a long. Assumes v is not equal to INFLATED.
*** 1337,1348 ****
public BigInteger divide(BigInteger val) {
MutableBigInteger q = new MutableBigInteger(),
a = new MutableBigInteger(this.mag),
b = new MutableBigInteger(val.mag);
! a.divide(b, q);
! return q.toBigInteger(this.signum == val.signum ? 1 : -1);
}
/**
* Returns an array of two BigIntegers containing {@code (this / val)}
* followed by {@code (this % val)}.
--- 1489,1500 ----
public BigInteger divide(BigInteger val) {
MutableBigInteger q = new MutableBigInteger(),
a = new MutableBigInteger(this.mag),
b = new MutableBigInteger(val.mag);
! a.divide(b, q, false);
! return q.toBigInteger(this.signum * val.signum);
}
/**
* Returns an array of two BigIntegers containing {@code (this / val)}
* followed by {@code (this % val)}.
*** 2067,2077 ****
--- 2219,2234 ----
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
} else {
return shiftRight(-n);
}
}
+ int[] newMag = shiftLeft(mag,n);
+ return new BigInteger(newMag, signum);
+ }
+
+ private static int[] shiftLeft(int[] mag, int n) {
int nInts = n >>> 5;
int nBits = n & 0x1f;
int magLen = mag.length;
int newMag[] = null;
*** 2092,2103 ****
int j=0;
while (j < magLen-1)
newMag[i++] = mag[j++] << nBits | mag[j] >>> nBits2;
newMag[i] = mag[j] << nBits;
}
!
! return new BigInteger(newMag, signum);
}
/**
* Returns a BigInteger whose value is {@code (this >> n)}. Sign
* extension is performed. The shift distance, {@code n}, may be
--- 2249,2259 ----
int j=0;
while (j < magLen-1)
newMag[i++] = mag[j++] << nBits | mag[j] >>> nBits2;
newMag[i] = mag[j] << nBits;
}
! return newMag;
}
/**
* Returns a BigInteger whose value is {@code (this >> n)}. Sign
* extension is performed. The shift distance, {@code n}, may be
*** 2528,2537 ****
--- 2684,2736 ----
}
return 0;
}
/**
+ * Version of compareMagnitude that compares magnitude with long value.
+ * val can't be Long.MIN_VALUE.
+ */
+ final int compareMagnitude(long val) {
+ assert val != Long.MIN_VALUE;
+ int[] m1 = mag;
+ int len = m1.length;
+ if(len > 2) {
+ return 1;
+ }
+ if (val < 0) {
+ val = -val;
+ }
+ int highWord = (int)(val >>> 32);
+ if (highWord==0) {
+ if (len < 1)
+ return -1;
+ if (len > 1)
+ return 1;
+ int a = m1[0];
+ int b = (int)val;
+ if (a != b) {
+ return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1;
+ }
+ return 0;
+ } else {
+ if (len < 2)
+ return -1;
+ int a = m1[0];
+ int b = highWord;
+ if (a != b) {
+ return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1;
+ }
+ a = m1[1];
+ b = (int)val;
+ if (a != b) {
+ return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1;
+ }
+ return 0;
+ }
+ }
+
+ /**
* Compares this BigInteger with the specified Object for equality.
*
* @param x Object to which this BigInteger is to be compared.
* @return {@code true} if and only if the specified Object is a
* BigInteger whose value is numerically equal to this BigInteger.