6910473: java.math.BigInteger.bitLength() may return negative "int" on large numbers
8021203: BigInteger.doubleValue/floatValue returns 0.0 instead of Infinity 8021204: Constructor BigInteger(String val, int radix) doesn't detect overflow 8022780: Incorrect BigInteger division because of MutableBigInteger.bitLength() overflow Prevent construction of overflowed BigIntegers. Reviewed-by: bpb, darcy, psandoz
This commit is contained in:
parent
5f3b001859
commit
9e7ba92bff
@ -97,6 +97,21 @@ import sun.misc.FloatConsts;
|
|||||||
* {@code NullPointerException} when passed
|
* {@code NullPointerException} when passed
|
||||||
* a null object reference for any input parameter.
|
* a null object reference for any input parameter.
|
||||||
*
|
*
|
||||||
|
* BigInteger must support values in the range
|
||||||
|
* -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
|
||||||
|
* +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive)
|
||||||
|
* and may support values outside of that range.
|
||||||
|
*
|
||||||
|
* The range of probable prime values is limited and may be less than
|
||||||
|
* the full supported positive range of {@code BigInteger}.
|
||||||
|
* The range must be at least 1 to 2<sup>500000000</sup>.
|
||||||
|
*
|
||||||
|
* @implNote
|
||||||
|
* BigInteger constructors and operations throw {@code ArithmeticException} when
|
||||||
|
* the result is out of the supported range of
|
||||||
|
* -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
|
||||||
|
* +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive).
|
||||||
|
*
|
||||||
* @see BigDecimal
|
* @see BigDecimal
|
||||||
* @author Josh Bloch
|
* @author Josh Bloch
|
||||||
* @author Michael McCloskey
|
* @author Michael McCloskey
|
||||||
@ -182,6 +197,18 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
*/
|
*/
|
||||||
final static long LONG_MASK = 0xffffffffL;
|
final static long LONG_MASK = 0xffffffffL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constant limits {@code mag.length} of BigIntegers to the supported
|
||||||
|
* range.
|
||||||
|
*/
|
||||||
|
private static final int MAX_MAG_LENGTH = Integer.MAX_VALUE / Integer.SIZE + 1; // (1 << 26)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bit lengths larger than this constant can cause overflow in searchLen
|
||||||
|
* calculation and in BitSieve.singleSearch method.
|
||||||
|
*/
|
||||||
|
private static final int PRIME_SEARCH_BIT_LENGTH_LIMIT = 500000000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The threshold value for using Karatsuba multiplication. If the number
|
* The threshold value for using Karatsuba multiplication. If the number
|
||||||
* of ints in both mag arrays are greater than this number, then
|
* of ints in both mag arrays are greater than this number, then
|
||||||
@ -256,6 +283,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
mag = stripLeadingZeroBytes(val);
|
mag = stripLeadingZeroBytes(val);
|
||||||
signum = (mag.length == 0 ? 0 : 1);
|
signum = (mag.length == 0 ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,6 +305,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
mag = trustedStripLeadingZeroInts(val);
|
mag = trustedStripLeadingZeroInts(val);
|
||||||
signum = (mag.length == 0 ? 0 : 1);
|
signum = (mag.length == 0 ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -306,6 +339,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
throw(new NumberFormatException("signum-magnitude mismatch"));
|
throw(new NumberFormatException("signum-magnitude mismatch"));
|
||||||
this.signum = signum;
|
this.signum = signum;
|
||||||
}
|
}
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,6 +363,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
throw(new NumberFormatException("signum-magnitude mismatch"));
|
throw(new NumberFormatException("signum-magnitude mismatch"));
|
||||||
this.signum = signum;
|
this.signum = signum;
|
||||||
}
|
}
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -359,17 +398,20 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
int sign = 1;
|
int sign = 1;
|
||||||
int index1 = val.lastIndexOf('-');
|
int index1 = val.lastIndexOf('-');
|
||||||
int index2 = val.lastIndexOf('+');
|
int index2 = val.lastIndexOf('+');
|
||||||
if ((index1 + index2) <= -1) {
|
if (index1 >= 0) {
|
||||||
// No leading sign character or at most one leading sign character
|
if (index1 != 0 || index2 >= 0) {
|
||||||
if (index1 == 0 || index2 == 0) {
|
throw new NumberFormatException("Illegal embedded sign character");
|
||||||
cursor = 1;
|
|
||||||
if (len == 1)
|
|
||||||
throw new NumberFormatException("Zero length BigInteger");
|
|
||||||
}
|
}
|
||||||
if (index1 == 0)
|
sign = -1;
|
||||||
sign = -1;
|
cursor = 1;
|
||||||
} else
|
} else if (index2 >= 0) {
|
||||||
throw new NumberFormatException("Illegal embedded sign character");
|
if (index2 != 0) {
|
||||||
|
throw new NumberFormatException("Illegal embedded sign character");
|
||||||
|
}
|
||||||
|
cursor = 1;
|
||||||
|
}
|
||||||
|
if (cursor == len)
|
||||||
|
throw new NumberFormatException("Zero length BigInteger");
|
||||||
|
|
||||||
// Skip leading zeros and compute number of digits in magnitude
|
// Skip leading zeros and compute number of digits in magnitude
|
||||||
while (cursor < len &&
|
while (cursor < len &&
|
||||||
@ -388,8 +430,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
|
|
||||||
// Pre-allocate array of expected size. May be too large but can
|
// Pre-allocate array of expected size. May be too large but can
|
||||||
// never be too small. Typically exact.
|
// never be too small. Typically exact.
|
||||||
int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1);
|
long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1;
|
||||||
int numWords = (numBits + 31) >>> 5;
|
if (numBits + 31 >= (1L << 32)) {
|
||||||
|
reportOverflow();
|
||||||
|
}
|
||||||
|
int numWords = (int) (numBits + 31) >>> 5;
|
||||||
int[] magnitude = new int[numWords];
|
int[] magnitude = new int[numWords];
|
||||||
|
|
||||||
// Process first (potentially short) digit group
|
// Process first (potentially short) digit group
|
||||||
@ -413,6 +458,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
}
|
}
|
||||||
// Required for cases where the array was overallocated.
|
// Required for cases where the array was overallocated.
|
||||||
mag = trustedStripLeadingZeroInts(magnitude);
|
mag = trustedStripLeadingZeroInts(magnitude);
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -439,8 +487,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
if (len < 10) {
|
if (len < 10) {
|
||||||
numWords = 1;
|
numWords = 1;
|
||||||
} else {
|
} else {
|
||||||
int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1);
|
long numBits = ((numDigits * bitsPerDigit[10]) >>> 10) + 1;
|
||||||
numWords = (numBits + 31) >>> 5;
|
if (numBits + 31 >= (1L << 32)) {
|
||||||
|
reportOverflow();
|
||||||
|
}
|
||||||
|
numWords = (int) (numBits + 31) >>> 5;
|
||||||
}
|
}
|
||||||
int[] magnitude = new int[numWords];
|
int[] magnitude = new int[numWords];
|
||||||
|
|
||||||
@ -456,6 +507,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
destructiveMulAdd(magnitude, intRadix[10], groupVal);
|
destructiveMulAdd(magnitude, intRadix[10], groupVal);
|
||||||
}
|
}
|
||||||
mag = trustedStripLeadingZeroInts(magnitude);
|
mag = trustedStripLeadingZeroInts(magnitude);
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an integer with the digits between the two indexes
|
// Create an integer with the digits between the two indexes
|
||||||
@ -575,7 +629,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
* this constructor is proportional to the value of this parameter.
|
* this constructor is proportional to the value of this parameter.
|
||||||
* @param rnd source of random bits used to select candidates to be
|
* @param rnd source of random bits used to select candidates to be
|
||||||
* tested for primality.
|
* tested for primality.
|
||||||
* @throws ArithmeticException {@code bitLength < 2}.
|
* @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
|
||||||
* @see #bitLength()
|
* @see #bitLength()
|
||||||
*/
|
*/
|
||||||
public BigInteger(int bitLength, int certainty, Random rnd) {
|
public BigInteger(int bitLength, int certainty, Random rnd) {
|
||||||
@ -607,7 +661,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
* @param rnd source of random bits used to select candidates to be
|
* @param rnd source of random bits used to select candidates to be
|
||||||
* tested for primality.
|
* tested for primality.
|
||||||
* @return a BigInteger of {@code bitLength} bits that is probably prime
|
* @return a BigInteger of {@code bitLength} bits that is probably prime
|
||||||
* @throws ArithmeticException {@code bitLength < 2}.
|
* @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
|
||||||
* @see #bitLength()
|
* @see #bitLength()
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
@ -677,7 +731,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
p.mag[p.mag.length-1] &= 0xfffffffe;
|
p.mag[p.mag.length-1] &= 0xfffffffe;
|
||||||
|
|
||||||
// Use a sieve length likely to contain the next prime number
|
// Use a sieve length likely to contain the next prime number
|
||||||
int searchLen = (bitLength / 20) * 64;
|
int searchLen = getPrimeSearchLen(bitLength);
|
||||||
BitSieve searchSieve = new BitSieve(p, searchLen);
|
BitSieve searchSieve = new BitSieve(p, searchLen);
|
||||||
BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
|
BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
|
||||||
|
|
||||||
@ -701,7 +755,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
*
|
*
|
||||||
* @return the first integer greater than this {@code BigInteger} that
|
* @return the first integer greater than this {@code BigInteger} that
|
||||||
* is probably prime.
|
* is probably prime.
|
||||||
* @throws ArithmeticException {@code this < 0}.
|
* @throws ArithmeticException {@code this < 0} or {@code this} is too large.
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public BigInteger nextProbablePrime() {
|
public BigInteger nextProbablePrime() {
|
||||||
@ -750,7 +804,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
result = result.subtract(ONE);
|
result = result.subtract(ONE);
|
||||||
|
|
||||||
// Looking for the next large prime
|
// Looking for the next large prime
|
||||||
int searchLen = (result.bitLength() / 20) * 64;
|
int searchLen = getPrimeSearchLen(result.bitLength());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
BitSieve searchSieve = new BitSieve(result, searchLen);
|
BitSieve searchSieve = new BitSieve(result, searchLen);
|
||||||
@ -762,6 +816,13 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getPrimeSearchLen(int bitLength) {
|
||||||
|
if (bitLength > PRIME_SEARCH_BIT_LENGTH_LIMIT + 1) {
|
||||||
|
throw new ArithmeticException("Prime search implementation restriction on bitLength");
|
||||||
|
}
|
||||||
|
return bitLength / 20 * 64;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if this BigInteger is probably prime,
|
* Returns {@code true} if this BigInteger is probably prime,
|
||||||
* {@code false} if it's definitely composite.
|
* {@code false} if it's definitely composite.
|
||||||
@ -965,6 +1026,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
BigInteger(int[] magnitude, int signum) {
|
BigInteger(int[] magnitude, int signum) {
|
||||||
this.signum = (magnitude.length == 0 ? 0 : signum);
|
this.signum = (magnitude.length == 0 ? 0 : signum);
|
||||||
this.mag = magnitude;
|
this.mag = magnitude;
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -974,6 +1038,25 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
private BigInteger(byte[] magnitude, int signum) {
|
private BigInteger(byte[] magnitude, int signum) {
|
||||||
this.signum = (magnitude.length == 0 ? 0 : signum);
|
this.signum = (magnitude.length == 0 ? 0 : signum);
|
||||||
this.mag = stripLeadingZeroBytes(magnitude);
|
this.mag = stripLeadingZeroBytes(magnitude);
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
checkRange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an {@code ArithmeticException} if the {@code BigInteger} would be
|
||||||
|
* out of the supported range.
|
||||||
|
*
|
||||||
|
* @throws ArithmeticException if {@code this} exceeds the supported range.
|
||||||
|
*/
|
||||||
|
private void checkRange() {
|
||||||
|
if (mag.length > MAX_MAG_LENGTH || mag.length == MAX_MAG_LENGTH && mag[0] < 0) {
|
||||||
|
reportOverflow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void reportOverflow() {
|
||||||
|
throw new ArithmeticException("BigInteger would overflow supported range");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Static Factory Methods
|
//Static Factory Methods
|
||||||
@ -2073,6 +2156,10 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
// The remaining part can then be exponentiated faster. The
|
// The remaining part can then be exponentiated faster. The
|
||||||
// powers of two will be multiplied back at the end.
|
// powers of two will be multiplied back at the end.
|
||||||
int powersOfTwo = partToSquare.getLowestSetBit();
|
int powersOfTwo = partToSquare.getLowestSetBit();
|
||||||
|
long bitsToShift = (long)powersOfTwo * exponent;
|
||||||
|
if (bitsToShift > Integer.MAX_VALUE) {
|
||||||
|
reportOverflow();
|
||||||
|
}
|
||||||
|
|
||||||
int remainingBits;
|
int remainingBits;
|
||||||
|
|
||||||
@ -2126,11 +2213,10 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
|
|
||||||
// Multiply back the powers of two (quickly, by shifting left)
|
// Multiply back the powers of two (quickly, by shifting left)
|
||||||
if (powersOfTwo > 0) {
|
if (powersOfTwo > 0) {
|
||||||
int bitsToShift = powersOfTwo*exponent;
|
|
||||||
if (bitsToShift + scaleFactor <= 62) { // Fits in long?
|
if (bitsToShift + scaleFactor <= 62) { // Fits in long?
|
||||||
return valueOf((result << bitsToShift) * newSign);
|
return valueOf((result << bitsToShift) * newSign);
|
||||||
} else {
|
} else {
|
||||||
return valueOf(result*newSign).shiftLeft(bitsToShift);
|
return valueOf(result*newSign).shiftLeft((int) bitsToShift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2375,8 +2461,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
BigInteger y1 = m2.modInverse(m1);
|
BigInteger y1 = m2.modInverse(m1);
|
||||||
BigInteger y2 = m1.modInverse(m2);
|
BigInteger y2 = m1.modInverse(m2);
|
||||||
|
|
||||||
result = a1.multiply(m2).multiply(y1).add
|
if (m.mag.length < MAX_MAG_LENGTH / 2) {
|
||||||
(a2.multiply(m1).multiply(y2)).mod(m);
|
result = a1.multiply(m2).multiply(y1).add(a2.multiply(m1).multiply(y2)).mod(m);
|
||||||
|
} else {
|
||||||
|
MutableBigInteger t1 = new MutableBigInteger();
|
||||||
|
new MutableBigInteger(a1.multiply(m2)).multiply(new MutableBigInteger(y1), t1);
|
||||||
|
MutableBigInteger t2 = new MutableBigInteger();
|
||||||
|
new MutableBigInteger(a2.multiply(m1)).multiply(new MutableBigInteger(y2), t2);
|
||||||
|
t1.add(t2);
|
||||||
|
MutableBigInteger q = new MutableBigInteger();
|
||||||
|
result = t1.divide(new MutableBigInteger(m), q).toBigInteger();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (invertResult ? result.modInverse(m) : result);
|
return (invertResult ? result.modInverse(m) : result);
|
||||||
@ -2797,27 +2892,31 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
*
|
*
|
||||||
* @param n shift distance, in bits.
|
* @param n shift distance, in bits.
|
||||||
* @return {@code this << n}
|
* @return {@code this << n}
|
||||||
* @throws ArithmeticException if the shift distance is {@code
|
|
||||||
* Integer.MIN_VALUE}.
|
|
||||||
* @see #shiftRight
|
* @see #shiftRight
|
||||||
*/
|
*/
|
||||||
public BigInteger shiftLeft(int n) {
|
public BigInteger shiftLeft(int n) {
|
||||||
if (signum == 0)
|
if (signum == 0)
|
||||||
return ZERO;
|
return ZERO;
|
||||||
if (n == 0)
|
if (n > 0) {
|
||||||
|
return new BigInteger(shiftLeft(mag, n), signum);
|
||||||
|
} else if (n == 0) {
|
||||||
return this;
|
return this;
|
||||||
if (n < 0) {
|
} else {
|
||||||
if (n == Integer.MIN_VALUE) {
|
// Possible int overflow in (-n) is not a trouble,
|
||||||
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
|
// because shiftRightImpl considers its argument unsigned
|
||||||
} else {
|
return shiftRightImpl(-n);
|
||||||
return shiftRight(-n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int[] newMag = shiftLeft(mag, n);
|
|
||||||
|
|
||||||
return new BigInteger(newMag, signum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a magnitude array whose value is {@code (mag << n)}.
|
||||||
|
* The shift distance, {@code n}, is considered unnsigned.
|
||||||
|
* (Computes <tt>this * 2<sup>n</sup></tt>.)
|
||||||
|
*
|
||||||
|
* @param mag magnitude, the most-significant int ({@code mag[0]}) must be non-zero.
|
||||||
|
* @param n unsigned shift distance, in bits.
|
||||||
|
* @return {@code mag << n}
|
||||||
|
*/
|
||||||
private static int[] shiftLeft(int[] mag, int n) {
|
private static int[] shiftLeft(int[] mag, int n) {
|
||||||
int nInts = n >>> 5;
|
int nInts = n >>> 5;
|
||||||
int nBits = n & 0x1f;
|
int nBits = n & 0x1f;
|
||||||
@ -2853,21 +2952,31 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
*
|
*
|
||||||
* @param n shift distance, in bits.
|
* @param n shift distance, in bits.
|
||||||
* @return {@code this >> n}
|
* @return {@code this >> n}
|
||||||
* @throws ArithmeticException if the shift distance is {@code
|
|
||||||
* Integer.MIN_VALUE}.
|
|
||||||
* @see #shiftLeft
|
* @see #shiftLeft
|
||||||
*/
|
*/
|
||||||
public BigInteger shiftRight(int n) {
|
public BigInteger shiftRight(int n) {
|
||||||
if (n == 0)
|
if (signum == 0)
|
||||||
|
return ZERO;
|
||||||
|
if (n > 0) {
|
||||||
|
return shiftRightImpl(n);
|
||||||
|
} else if (n == 0) {
|
||||||
return this;
|
return this;
|
||||||
if (n < 0) {
|
} else {
|
||||||
if (n == Integer.MIN_VALUE) {
|
// Possible int overflow in {@code -n} is not a trouble,
|
||||||
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
|
// because shiftLeft considers its argument unsigned
|
||||||
} else {
|
return new BigInteger(shiftLeft(mag, -n), signum);
|
||||||
return shiftLeft(-n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a BigInteger whose value is {@code (this >> n)}. The shift
|
||||||
|
* distance, {@code n}, is considered unsigned.
|
||||||
|
* (Computes <tt>floor(this * 2<sup>-n</sup>)</tt>.)
|
||||||
|
*
|
||||||
|
* @param n unsigned shift distance, in bits.
|
||||||
|
* @return {@code this >> n}
|
||||||
|
*/
|
||||||
|
private BigInteger shiftRightImpl(int n) {
|
||||||
int nInts = n >>> 5;
|
int nInts = n >>> 5;
|
||||||
int nBits = n & 0x1f;
|
int nBits = n & 0x1f;
|
||||||
int magLen = mag.length;
|
int magLen = mag.length;
|
||||||
@ -3899,7 +4008,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
;
|
;
|
||||||
|
|
||||||
int extraByte = (k == byteLength) ? 1 : 0;
|
int extraByte = (k == byteLength) ? 1 : 0;
|
||||||
int intLength = ((byteLength - keep + extraByte) + 3)/4;
|
int intLength = ((byteLength - keep + extraByte) + 3) >>> 2;
|
||||||
int result[] = new int[intLength];
|
int result[] = new int[intLength];
|
||||||
|
|
||||||
/* Copy one's complement of input into output, leaving extra
|
/* Copy one's complement of input into output, leaving extra
|
||||||
@ -4135,7 +4244,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
message = "BigInteger: Signum not present in stream";
|
message = "BigInteger: Signum not present in stream";
|
||||||
throw new java.io.StreamCorruptedException(message);
|
throw new java.io.StreamCorruptedException(message);
|
||||||
}
|
}
|
||||||
if ((magnitude.length == 0) != (sign == 0)) {
|
int[] mag = stripLeadingZeroBytes(magnitude);
|
||||||
|
if ((mag.length == 0) != (sign == 0)) {
|
||||||
String message = "BigInteger: signum-magnitude mismatch";
|
String message = "BigInteger: signum-magnitude mismatch";
|
||||||
if (fields.defaulted("magnitude"))
|
if (fields.defaulted("magnitude"))
|
||||||
message = "BigInteger: Magnitude not present in stream";
|
message = "BigInteger: Magnitude not present in stream";
|
||||||
@ -4146,7 +4256,14 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
UnsafeHolder.putSign(this, sign);
|
UnsafeHolder.putSign(this, sign);
|
||||||
|
|
||||||
// Calculate mag field from magnitude and discard magnitude
|
// Calculate mag field from magnitude and discard magnitude
|
||||||
UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude));
|
UnsafeHolder.putMag(this, mag);
|
||||||
|
if (mag.length >= MAX_MAG_LENGTH) {
|
||||||
|
try {
|
||||||
|
checkRange();
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for resetting final fields while deserializing
|
// Support for resetting final fields while deserializing
|
||||||
|
@ -1257,14 +1257,14 @@ class MutableBigInteger {
|
|||||||
|
|
||||||
int j = (s+m-1) / m; // step 2a: j = ceil(s/m)
|
int j = (s+m-1) / m; // step 2a: j = ceil(s/m)
|
||||||
int n = j * m; // step 2b: block length in 32-bit units
|
int n = j * m; // step 2b: block length in 32-bit units
|
||||||
int n32 = 32 * n; // block length in bits
|
long n32 = 32L * n; // block length in bits
|
||||||
int sigma = Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
|
int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
|
||||||
MutableBigInteger bShifted = new MutableBigInteger(b);
|
MutableBigInteger bShifted = new MutableBigInteger(b);
|
||||||
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
|
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
|
||||||
safeLeftShift(sigma); // step 4b: shift this by the same amount
|
safeLeftShift(sigma); // step 4b: shift this by the same amount
|
||||||
|
|
||||||
// step 5: t is the number of blocks needed to accommodate this plus one additional bit
|
// step 5: t is the number of blocks needed to accommodate this plus one additional bit
|
||||||
int t = (bitLength()+n32) / n32;
|
int t = (int) ((bitLength()+n32) / n32);
|
||||||
if (t < 2) {
|
if (t < 2) {
|
||||||
t = 2;
|
t = 2;
|
||||||
}
|
}
|
||||||
@ -1421,10 +1421,10 @@ class MutableBigInteger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @see BigInteger#bitLength() */
|
/** @see BigInteger#bitLength() */
|
||||||
int bitLength() {
|
long bitLength() {
|
||||||
if (intLen == 0)
|
if (intLen == 0)
|
||||||
return 0;
|
return 0;
|
||||||
return intLen*32 - Integer.numberOfLeadingZeros(value[offset]);
|
return intLen*32L - Integer.numberOfLeadingZeros(value[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
49
jdk/test/java/math/BigInteger/BitLengthOverflow.java
Normal file
49
jdk/test/java/math/BigInteger/BitLengthOverflow.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ test
|
||||||
|
* @bug 6910473
|
||||||
|
* @summary Test that bitLength() is not negative
|
||||||
|
* @author Dmitry Nadezhin
|
||||||
|
*/
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class BitLengthOverflow {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
BigInteger x = BigInteger.ONE.shiftLeft(Integer.MAX_VALUE); // x = pow(2,Integer.MAX_VALUE)
|
||||||
|
if (x.bitLength() != (1L << 31))
|
||||||
|
throw new RuntimeException("Incorrect bitLength() " + x.bitLength());
|
||||||
|
System.out.println("Surprisingly passed with correct bitLength() " + x.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
System.out.println("Overflow is reported by ArithmeticException, as expected");
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
// possible
|
||||||
|
System.out.println("OutOfMemoryError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
jdk/test/java/math/BigInteger/DivisionOverflow.java
Normal file
51
jdk/test/java/math/BigInteger/DivisionOverflow.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ test
|
||||||
|
* @bug 8022780
|
||||||
|
* @summary Test division of large values
|
||||||
|
* @author Dmitry Nadezhin
|
||||||
|
*/
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class DivisionOverflow {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
BigInteger a = BigInteger.ONE.shiftLeft(2147483646);
|
||||||
|
BigInteger b = BigInteger.ONE.shiftLeft(1568);
|
||||||
|
BigInteger[] qr = a.divideAndRemainder(b);
|
||||||
|
BigInteger q = qr[0];
|
||||||
|
BigInteger r = qr[1];
|
||||||
|
if (!r.equals(BigInteger.ZERO))
|
||||||
|
throw new RuntimeException("Incorrect singum() of remainder " + r.signum());
|
||||||
|
if (q.bitLength() != 2147482079)
|
||||||
|
throw new RuntimeException("Incorrect bitLength() of quotient " + q.bitLength());
|
||||||
|
System.out.println("Division of large values passed without overflow.");
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
// possible
|
||||||
|
System.out.println("OutOfMemoryError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
jdk/test/java/math/BigInteger/DoubleValueOverflow.java
Normal file
49
jdk/test/java/math/BigInteger/DoubleValueOverflow.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ test
|
||||||
|
* @bug 8021203
|
||||||
|
* @summary Test that doubleValue() doesn't overflow
|
||||||
|
* @author Dmitry Nadezhin
|
||||||
|
*/
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class DoubleValueOverflow {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
BigInteger x = BigInteger.valueOf(2).shiftLeft(Integer.MAX_VALUE); // x = pow(2,pow(2,31))
|
||||||
|
if (x.doubleValue() != Double.POSITIVE_INFINITY)
|
||||||
|
throw new RuntimeException("Incorrect doubleValue() " + x.doubleValue());
|
||||||
|
System.out.println("Passed with correct result");
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
System.out.println("Overflow is reported by ArithmeticException, as expected");
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
// possible
|
||||||
|
System.out.println("OutOfMemoryError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,22 +27,41 @@
|
|||||||
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
|
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
|
||||||
* @author Joseph D. Darcy
|
* @author Joseph D. Darcy
|
||||||
*/
|
*/
|
||||||
|
import java.math.BigInteger;
|
||||||
import static java.math.BigInteger.*;
|
import static java.math.BigInteger.*;
|
||||||
|
|
||||||
public class ExtremeShiftingTests {
|
public class ExtremeShiftingTests {
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
|
BigInteger bi = ONE.shiftLeft(Integer.MIN_VALUE);
|
||||||
|
if (!bi.equals(ZERO))
|
||||||
|
throw new RuntimeException("1 << " + Integer.MIN_VALUE);
|
||||||
|
|
||||||
|
bi = ZERO.shiftLeft(Integer.MIN_VALUE);
|
||||||
|
if (!bi.equals(ZERO))
|
||||||
|
throw new RuntimeException("0 << " + Integer.MIN_VALUE);
|
||||||
|
|
||||||
|
bi = BigInteger.valueOf(-1);
|
||||||
|
bi = bi.shiftLeft(Integer.MIN_VALUE);
|
||||||
|
if (!bi.equals(BigInteger.valueOf(-1)))
|
||||||
|
throw new RuntimeException("-1 << " + Integer.MIN_VALUE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ONE.shiftLeft(Integer.MIN_VALUE);
|
ONE.shiftRight(Integer.MIN_VALUE);
|
||||||
throw new RuntimeException("Should not reach here.");
|
throw new RuntimeException("1 >> " + Integer.MIN_VALUE);
|
||||||
} catch (ArithmeticException ae) {
|
} catch (ArithmeticException ae) {
|
||||||
; // Expected
|
; // Expected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bi = ZERO.shiftRight(Integer.MIN_VALUE);
|
||||||
|
if (!bi.equals(ZERO))
|
||||||
|
throw new RuntimeException("0 >> " + Integer.MIN_VALUE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ONE.shiftRight(Integer.MIN_VALUE);
|
BigInteger.valueOf(-1).shiftRight(Integer.MIN_VALUE);
|
||||||
throw new RuntimeException("Should not reach here.");
|
throw new RuntimeException("-1 >> " + Integer.MIN_VALUE);
|
||||||
} catch (ArithmeticException ae) {
|
} catch (ArithmeticException ae) {
|
||||||
; // Expected
|
; // Expected
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
59
jdk/test/java/math/BigInteger/StringConstructorOverflow.java
Normal file
59
jdk/test/java/math/BigInteger/StringConstructorOverflow.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ test
|
||||||
|
* @bug 8021204
|
||||||
|
* @summary Test constructor BigInteger(String val, int radix) on very long string
|
||||||
|
* @author Dmitry Nadezhin
|
||||||
|
*/
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class StringConstructorOverflow {
|
||||||
|
|
||||||
|
// String with hexadecimal value pow(2,pow(2,34))+1
|
||||||
|
private static String makeLongHexString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append('1');
|
||||||
|
for (int i = 0; i < (1 << 30) - 1; i++) {
|
||||||
|
sb.append('0');
|
||||||
|
}
|
||||||
|
sb.append('1');
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
BigInteger bi = new BigInteger(makeLongHexString(), 16);
|
||||||
|
if (bi.compareTo(BigInteger.ONE) <= 0)
|
||||||
|
throw new RuntimeException("Incorrect result " + bi.toString());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
System.out.println("Overflow is reported by ArithmeticException, as expected");
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
// possible
|
||||||
|
System.out.println("OutOfMemoryError");
|
||||||
|
System.out.println("Run jtreg with -javaoption:-Xmx8g");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
662
jdk/test/java/math/BigInteger/SymmetricRangeTests.java
Normal file
662
jdk/test/java/math/BigInteger/SymmetricRangeTests.java
Normal file
@ -0,0 +1,662 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This test is intentionally ignored because of huge memory requirements
|
||||||
|
* @ test
|
||||||
|
* @run main/timeout=180/othervm -Xmx8g SymmetricRangeTests
|
||||||
|
* @bug 6910473 8021204 8021203 9005933
|
||||||
|
* @summary Test range of BigInteger values
|
||||||
|
* @author Dmitry Nadezhin
|
||||||
|
*/
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class SymmetricRangeTests {
|
||||||
|
|
||||||
|
private static final BigInteger MAX_VALUE = makeMaxValue();
|
||||||
|
private static final BigInteger MIN_VALUE = MAX_VALUE.negate();
|
||||||
|
|
||||||
|
private static BigInteger makeMaxValue() {
|
||||||
|
byte[] ba = new byte[1 << 28];
|
||||||
|
Arrays.fill(ba, (byte) 0xFF);
|
||||||
|
ba[0] = (byte) 0x7F;
|
||||||
|
return new BigInteger(ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(String msg, BigInteger actual, BigInteger expected) {
|
||||||
|
if (!actual.equals(expected)) {
|
||||||
|
throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(String msg, double actual, double expected) {
|
||||||
|
if (actual != expected) {
|
||||||
|
throw new RuntimeException(msg + "=" + actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(String msg, float actual, float expected) {
|
||||||
|
if (actual != expected) {
|
||||||
|
throw new RuntimeException(msg + "=" + actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(String msg, long actual, long expected) {
|
||||||
|
if (actual != expected) {
|
||||||
|
throw new RuntimeException(msg + "=" + actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(String msg, int actual, int expected) {
|
||||||
|
if (actual != expected) {
|
||||||
|
throw new RuntimeException(msg + "=" + actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testOverflowInMakePositive() {
|
||||||
|
System.out.println("Testing overflow in BigInteger.makePositive");
|
||||||
|
byte[] ba = new byte[Integer.MAX_VALUE - 2];
|
||||||
|
ba[0] = (byte) 0x80;
|
||||||
|
try {
|
||||||
|
BigInteger actual = new BigInteger(ba);
|
||||||
|
throw new RuntimeException("new BigInteger(ba).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testBug8021204() {
|
||||||
|
System.out.println("Testing Bug 8021204");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append('1');
|
||||||
|
for (int i = 0; i < (1 << 30) - 1; i++) {
|
||||||
|
sb.append('0');
|
||||||
|
}
|
||||||
|
sb.append('1');
|
||||||
|
String s = sb.toString();
|
||||||
|
sb = null;
|
||||||
|
try {
|
||||||
|
BigInteger actual = new BigInteger(s, 16);
|
||||||
|
throw new RuntimeException("new BigInteger(\"1000...001\").bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testOverflowInBitSieve() {
|
||||||
|
System.out.println("Testing overflow in BitSieve.sieveSingle");
|
||||||
|
int bitLength = (5 << 27) - 1;
|
||||||
|
try {
|
||||||
|
Random rnd = new Random();
|
||||||
|
BigInteger actual = new BigInteger(bitLength, 0, rnd);
|
||||||
|
throw new RuntimeException("new BigInteger(bitLength, 0, null).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger bi = BigInteger.ONE.shiftLeft(bitLength - 1).subtract(BigInteger.ONE);
|
||||||
|
BigInteger actual = bi.nextProbablePrime();
|
||||||
|
throw new RuntimeException("bi.nextActualPrime().bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testAdd() {
|
||||||
|
System.out.println("Testing BigInteger.add");
|
||||||
|
try {
|
||||||
|
BigInteger actual = MAX_VALUE.add(BigInteger.ONE);
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.add(BigInteger.ONE).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testSubtract() {
|
||||||
|
System.out.println("Testing BigInteger.subtract");
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.subtract(BigInteger.ONE);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.subtract(BigInteger.ONE).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testMultiply() {
|
||||||
|
System.out.println("Testing BigInteger.multiply");
|
||||||
|
int py = 2000;
|
||||||
|
int px = Integer.MAX_VALUE - py;
|
||||||
|
BigInteger x = BigInteger.ONE.shiftLeft(px);
|
||||||
|
BigInteger y = BigInteger.ONE.shiftLeft(py);
|
||||||
|
try {
|
||||||
|
BigInteger actual = x.multiply(y);
|
||||||
|
throw new RuntimeException("(1 << " + px + " ) * (1 << " + py + ").bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testDivide() {
|
||||||
|
System.out.println("Testing BigInteger.divide");
|
||||||
|
check("BigInteger.MIN_VALUE.divide(BigInteger.valueOf(-1))",
|
||||||
|
MIN_VALUE.divide(BigInteger.valueOf(-1)), MAX_VALUE);
|
||||||
|
check("BigInteger.MIN_VALUE.divide(BigInteger.ONE)",
|
||||||
|
MIN_VALUE.divide(BigInteger.ONE), MIN_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testDivideAndRemainder(String msg, BigInteger dividend, BigInteger divisor,
|
||||||
|
BigInteger expectedQuotent, BigInteger expectedRemainder) {
|
||||||
|
BigInteger[] qr = dividend.divideAndRemainder(divisor);
|
||||||
|
check(msg + "[0]", qr[0], expectedQuotent);
|
||||||
|
check(msg + "[1]", qr[1], expectedRemainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testDivideAndRemainder() {
|
||||||
|
System.out.println("Testing BigInteger.divideAndRemainder");
|
||||||
|
testDivideAndRemainder("BigInteger.MIN_VALUE.divideAndRemainder(BigInteger.valueOf(-1))",
|
||||||
|
MIN_VALUE, BigInteger.valueOf(-1),
|
||||||
|
MAX_VALUE,
|
||||||
|
BigInteger.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testBug9005933() {
|
||||||
|
System.out.println("Testing Bug 9005933");
|
||||||
|
int dividendPow = 2147483646;
|
||||||
|
int divisorPow = 1568;
|
||||||
|
BigInteger dividend = BigInteger.ONE.shiftLeft(dividendPow);
|
||||||
|
BigInteger divisor = BigInteger.ONE.shiftLeft(divisorPow);
|
||||||
|
testDivideAndRemainder("(1 << " + dividendPow + ").divideAndRemainder(1 << " + divisorPow + ")",
|
||||||
|
dividend, divisor,
|
||||||
|
BigInteger.ONE.shiftLeft(dividendPow - divisorPow),
|
||||||
|
BigInteger.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testRemainder() {
|
||||||
|
System.out.println("Testing BigInteger.remainder");
|
||||||
|
check("BigInteger.MIN_VALUE.remainder(BigInteger.valueOf(-1))",
|
||||||
|
MIN_VALUE.remainder(BigInteger.valueOf(-1)), BigInteger.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testPow() {
|
||||||
|
System.out.println("Testing BigInteger.pow");
|
||||||
|
check("BigInteger.MIN_VALUE.pow(1)",
|
||||||
|
MIN_VALUE.pow(1), MIN_VALUE);
|
||||||
|
try {
|
||||||
|
BigInteger actual = BigInteger.valueOf(4).pow(Integer.MAX_VALUE);
|
||||||
|
throw new RuntimeException("BigInteger.valueOf(4).pow(Integer.MAX_VALUE).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testGcd() {
|
||||||
|
System.out.println("Testing BigInteger.gcd");
|
||||||
|
check("BigInteger.MIN_VALUE.gcd(BigInteger.MIN_VALUE)",
|
||||||
|
MIN_VALUE.gcd(MIN_VALUE), MAX_VALUE);
|
||||||
|
check("BigInteger.MIN_VALUE.gcd(BigInteger.ZERO)",
|
||||||
|
MIN_VALUE.gcd(BigInteger.ZERO), MAX_VALUE);
|
||||||
|
check("BigInteger.ZERO.gcd(MIN_VALUE)",
|
||||||
|
BigInteger.ZERO.gcd(MIN_VALUE), MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testAbs() {
|
||||||
|
System.out.println("Testing BigInteger.abs");
|
||||||
|
check("BigInteger.MIN_VALUE.abs()",
|
||||||
|
MIN_VALUE.abs(), MAX_VALUE);
|
||||||
|
check("BigInteger.MAX_VALUE.abs()",
|
||||||
|
MAX_VALUE.abs(), MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testNegate() {
|
||||||
|
System.out.println("Testing BigInteger.negate");
|
||||||
|
check("BigInteger.MIN_VALUE.negate()",
|
||||||
|
MIN_VALUE.negate(), MAX_VALUE);
|
||||||
|
check("BigInteger.MAX_VALUE.negate()",
|
||||||
|
MAX_VALUE.negate(), MIN_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testMod() {
|
||||||
|
System.out.println("Testing BigInteger.mod");
|
||||||
|
check("BigInteger.MIN_VALUE.mod(BigInteger.MAX_VALUE)",
|
||||||
|
MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO);
|
||||||
|
check("BigInteger.MAX_VALUE.mod(BigInteger.MAX_VALUE)",
|
||||||
|
MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testModPow() {
|
||||||
|
System.out.println("Testing BigInteger.modPow");
|
||||||
|
BigInteger x = BigInteger.valueOf(3);
|
||||||
|
BigInteger m = BigInteger.valueOf(-4).subtract(MIN_VALUE);
|
||||||
|
check("BigInteger.valueOf(3).modPow(BigInteger.ONE, m)",
|
||||||
|
x.modPow(BigInteger.ONE, m), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// slow test
|
||||||
|
private static void testModInverse() {
|
||||||
|
System.out.println("Testing BigInteger.modInverse");
|
||||||
|
check("BigInteger.MIN_VALUE.modInverse(BigInteger.MAX_VALUE)",
|
||||||
|
MIN_VALUE.modInverse(MAX_VALUE), MAX_VALUE.subtract(BigInteger.ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testShiftLeft() {
|
||||||
|
System.out.println("Testing BigInteger.shiftLeft");
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.shiftLeft(1);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger actual = MAX_VALUE.shiftLeft(1);
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testShiftRight() {
|
||||||
|
System.out.println("Testing BigInteger.shiftRight");
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.shiftRight(-1);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger actual = MAX_VALUE.shiftRight(-1);
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testAnd() {
|
||||||
|
System.out.println("Testing BigInteger.and");
|
||||||
|
check("BigInteger.MIN_VALUE.and(BigInteger.MIN_VALUE)",
|
||||||
|
MIN_VALUE.and(MIN_VALUE), MIN_VALUE);
|
||||||
|
check("BigInteger.MAX_VALUE.and(BigInteger.MAX_VALUE)",
|
||||||
|
MAX_VALUE.and(MAX_VALUE), MAX_VALUE);
|
||||||
|
check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)",
|
||||||
|
MIN_VALUE.and(MAX_VALUE), BigInteger.ONE);
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.and(BigInteger.valueOf(-2));
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.and(-2)).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testOr() {
|
||||||
|
System.out.println("Testing BigInteger.or");
|
||||||
|
check("BigInteger.MIN_VALUE.or(BigInteger.MIN_VALUE)",
|
||||||
|
MIN_VALUE.or(MIN_VALUE), MIN_VALUE);
|
||||||
|
check("BigInteger.MAX_VALUE.or(BigInteger.MAX_VALUE)",
|
||||||
|
MAX_VALUE.or(MAX_VALUE), MAX_VALUE);
|
||||||
|
check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)",
|
||||||
|
MIN_VALUE.or(MAX_VALUE), BigInteger.valueOf(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testXor() {
|
||||||
|
System.out.println("Testing BigInteger.xor");
|
||||||
|
check("BigInteger.MIN_VALUE.xor(BigInteger.MIN_VALUE)",
|
||||||
|
MIN_VALUE.xor(MIN_VALUE), BigInteger.ZERO);
|
||||||
|
check("BigInteger.MAX_VALUE.xor(BigInteger.MAX_VALUE)",
|
||||||
|
MAX_VALUE.xor(MAX_VALUE), BigInteger.ZERO);
|
||||||
|
check("BigInteger.MIN_VALUE.xor(BigInteger.MAX_VALUE)",
|
||||||
|
MIN_VALUE.xor(MAX_VALUE), BigInteger.valueOf(-2));
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.xor(BigInteger.ONE);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.xor(BigInteger.ONE)).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testNot() {
|
||||||
|
System.out.println("Testing BigInteger.not");
|
||||||
|
check("BigInteger.MIN_VALUE.not()",
|
||||||
|
MIN_VALUE.not(), MAX_VALUE.subtract(BigInteger.ONE));
|
||||||
|
try {
|
||||||
|
BigInteger actual = MAX_VALUE.not();
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.not()).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testSetBit() {
|
||||||
|
System.out.println("Testing BigInteger.setBit");
|
||||||
|
check("BigInteger.MIN_VALUE.setBit(" + Integer.MAX_VALUE + ")",
|
||||||
|
MIN_VALUE.setBit(Integer.MAX_VALUE), MIN_VALUE);
|
||||||
|
try {
|
||||||
|
BigInteger actual = MAX_VALUE.setBit(Integer.MAX_VALUE);
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.setBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testClearBit() {
|
||||||
|
System.out.println("Testing BigInteger.clearBit");
|
||||||
|
check("BigInteger.MAX_VALUE.clearBit(" + Integer.MAX_VALUE + ")",
|
||||||
|
MAX_VALUE.clearBit(Integer.MAX_VALUE), MAX_VALUE);
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.clearBit(Integer.MAX_VALUE);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.clearBit(0);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(0).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testFlipBit() {
|
||||||
|
System.out.println("Testing BigInteger.flipBit");
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.flipBit(Integer.MAX_VALUE);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger actual = MIN_VALUE.flipBit(0);
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(0).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger actual = MAX_VALUE.flipBit(Integer.MAX_VALUE);
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testGetLowestSetBit() {
|
||||||
|
System.out.println("Testing BigInteger.getLowestSetBit");
|
||||||
|
check("BigInteger.MIN_VALUE.getLowestSetBit()",
|
||||||
|
MIN_VALUE.getLowestSetBit(), 0);
|
||||||
|
check("BigInteger.MAX_VALUE.getLowestSetBit()",
|
||||||
|
MAX_VALUE.getLowestSetBit(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testBitLength() {
|
||||||
|
System.out.println("Testing BigInteger.bitLength");
|
||||||
|
check("BigInteger.MIN_NEXT.bitLength()",
|
||||||
|
MIN_VALUE.bitLength(), Integer.MAX_VALUE);
|
||||||
|
check("BigInteger.MAX_VALUE.bitLength()",
|
||||||
|
MAX_VALUE.bitLength(), Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testBitCount() {
|
||||||
|
System.out.println("Testing BigInteger.bitCount");
|
||||||
|
check("BigInteger.MIN_VALUE.bitCount()",
|
||||||
|
MIN_VALUE.bitCount(), Integer.MAX_VALUE - 1);
|
||||||
|
check("BigInteger.MAX_VALUE.bitCount()",
|
||||||
|
MAX_VALUE.bitCount(), Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testToString(String msg, int radix, BigInteger bi, int length, String startsWith, char c) {
|
||||||
|
String s = bi.toString(radix);
|
||||||
|
if (s.length() != length) {
|
||||||
|
throw new RuntimeException(msg + ".length=" + s.length());
|
||||||
|
}
|
||||||
|
if (!s.startsWith(startsWith)) {
|
||||||
|
throw new RuntimeException(msg + "[0]=" + s.substring(0, startsWith.length()));
|
||||||
|
}
|
||||||
|
for (int i = startsWith.length(); i < s.length(); i++) {
|
||||||
|
if (s.charAt(i) != c) {
|
||||||
|
throw new RuntimeException(msg + "[" + i + "]='" + s.charAt(i) + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testToString() {
|
||||||
|
System.out.println("Testing BigInteger.toString");
|
||||||
|
testToString("BigInteger.MIN_VALUE.toString(16)=", 16,
|
||||||
|
BigInteger.valueOf(-1).shiftLeft(Integer.MAX_VALUE - 1),
|
||||||
|
(1 << 29) + 1, "-4", '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testToByteArrayWithConstructor(String msg, BigInteger bi, int length, byte msb, byte b, byte lsb) {
|
||||||
|
byte[] ba = bi.toByteArray();
|
||||||
|
if (ba.length != length) {
|
||||||
|
throw new RuntimeException(msg + ".length=" + ba.length);
|
||||||
|
}
|
||||||
|
if (ba[0] != msb) {
|
||||||
|
throw new RuntimeException(msg + "[0]=" + ba[0]);
|
||||||
|
}
|
||||||
|
for (int i = 1; i < ba.length - 1; i++) {
|
||||||
|
if (ba[i] != b) {
|
||||||
|
throw new RuntimeException(msg + "[" + i + "]=" + ba[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ba[ba.length - 1] != lsb) {
|
||||||
|
throw new RuntimeException(msg + "[" + (ba.length - 1) + "]=" + ba[ba.length - 1]);
|
||||||
|
}
|
||||||
|
BigInteger actual = new BigInteger(ba);
|
||||||
|
if (!actual.equals(bi)) {
|
||||||
|
throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testToByteArrayWithConstructor() {
|
||||||
|
System.out.println("Testing BigInteger.toByteArray with constructor");
|
||||||
|
testToByteArrayWithConstructor("BigInteger.MIN_VALUE.toByteArray()",
|
||||||
|
MIN_VALUE, (1 << 28), (byte) 0x80, (byte) 0x00, (byte) 0x01);
|
||||||
|
testToByteArrayWithConstructor("BigInteger.MAX_VALUE.toByteArray()",
|
||||||
|
MAX_VALUE, (1 << 28), (byte) 0x7f, (byte) 0xff, (byte) 0xff);
|
||||||
|
|
||||||
|
byte[] ba = new byte[1 << 28];
|
||||||
|
ba[0] = (byte) 0x80;
|
||||||
|
try {
|
||||||
|
BigInteger actual = new BigInteger(-1, ba);
|
||||||
|
throw new RuntimeException("new BigInteger(-1, ba).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BigInteger actual = new BigInteger(1, ba);
|
||||||
|
throw new RuntimeException("new BigInteger(1, ba).bitLength()=" + actual.bitLength());
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testIntValue() {
|
||||||
|
System.out.println("Testing BigInteger.intValue");
|
||||||
|
check("BigInteger.MIN_VALUE.intValue()",
|
||||||
|
MIN_VALUE.intValue(), 1);
|
||||||
|
check("BigInteger.MAX_VALUE.floatValue()",
|
||||||
|
MAX_VALUE.intValue(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testLongValue() {
|
||||||
|
System.out.println("Testing BigInteger.longValue");
|
||||||
|
check("BigInteger.MIN_VALUE.longValue()",
|
||||||
|
MIN_VALUE.longValue(), 1L);
|
||||||
|
check("BigInteger.MAX_VALUE.longValue()",
|
||||||
|
MAX_VALUE.longValue(), -1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testFloatValue() {
|
||||||
|
System.out.println("Testing BigInteger.floatValue, Bug 8021203");
|
||||||
|
check("BigInteger.MIN_VALUE_.floatValue()",
|
||||||
|
MIN_VALUE.floatValue(), Float.NEGATIVE_INFINITY);
|
||||||
|
check("BigInteger.MAX_VALUE.floatValue()",
|
||||||
|
MAX_VALUE.floatValue(), Float.POSITIVE_INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testDoubleValue() {
|
||||||
|
System.out.println("Testing BigInteger.doubleValue, Bug 8021203");
|
||||||
|
check("BigInteger.MIN_VALUE.doubleValue()",
|
||||||
|
MIN_VALUE.doubleValue(), Double.NEGATIVE_INFINITY);
|
||||||
|
check("BigInteger.MAX_VALUE.doubleValue()",
|
||||||
|
MAX_VALUE.doubleValue(), Double.POSITIVE_INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testSerialization(String msg, BigInteger bi) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream baOut = new ByteArrayOutputStream((1 << 28) + 1000);
|
||||||
|
ObjectOutputStream out = new ObjectOutputStream(baOut);
|
||||||
|
out.writeObject(bi);
|
||||||
|
out.close();
|
||||||
|
out = null;
|
||||||
|
byte[] ba = baOut.toByteArray();
|
||||||
|
baOut = null;
|
||||||
|
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba));
|
||||||
|
BigInteger actual = (BigInteger) in.readObject();
|
||||||
|
if (!actual.equals(bi)) {
|
||||||
|
throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
|
||||||
|
}
|
||||||
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(msg + " raised exception ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testSerialization() {
|
||||||
|
System.out.println("Testing BigInteger serialization");
|
||||||
|
testSerialization("BigInteger.MIN_VALUE.intValue()",
|
||||||
|
MIN_VALUE);
|
||||||
|
testSerialization("BigInteger.MAX_VALUE.floatValue()",
|
||||||
|
MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testLongValueExact() {
|
||||||
|
System.out.println("Testing BigInteger.longValueExact");
|
||||||
|
try {
|
||||||
|
long actual = MIN_VALUE.longValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.longValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
long actual = MAX_VALUE.longValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.longValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testIntValueExact() {
|
||||||
|
System.out.println("Testing BigInteger.intValueExact");
|
||||||
|
try {
|
||||||
|
long actual = MIN_VALUE.intValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.intValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
long actual = MAX_VALUE.intValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.intValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testShortValueExact() {
|
||||||
|
System.out.println("Testing BigInteger.shortValueExact");
|
||||||
|
try {
|
||||||
|
long actual = MIN_VALUE.shortValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.shortValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
long actual = MAX_VALUE.shortValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.shortValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testByteValueExact() {
|
||||||
|
System.out.println("Testing BigInteger.byteValueExact");
|
||||||
|
try {
|
||||||
|
long actual = MIN_VALUE.byteValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MIN_VALUE.byteValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
long actual = MAX_VALUE.byteValueExact();
|
||||||
|
throw new RuntimeException("BigInteger.MAX_VALUE.byteValueExact()= " + actual);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
// excpected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
testOverflowInMakePositive();
|
||||||
|
testBug8021204();
|
||||||
|
testOverflowInBitSieve();
|
||||||
|
testAdd();
|
||||||
|
testSubtract();
|
||||||
|
testMultiply();
|
||||||
|
testDivide();
|
||||||
|
testDivideAndRemainder();
|
||||||
|
testBug9005933();
|
||||||
|
testRemainder();
|
||||||
|
testPow();
|
||||||
|
testGcd();
|
||||||
|
testAbs();
|
||||||
|
testNegate();
|
||||||
|
testMod();
|
||||||
|
testModPow();
|
||||||
|
// testModInverse();
|
||||||
|
testShiftLeft();
|
||||||
|
testShiftRight();
|
||||||
|
testAnd();
|
||||||
|
testOr();
|
||||||
|
testXor();
|
||||||
|
testNot();
|
||||||
|
testSetBit();
|
||||||
|
testClearBit();
|
||||||
|
testFlipBit();
|
||||||
|
testGetLowestSetBit();
|
||||||
|
testBitLength();
|
||||||
|
testBitCount();
|
||||||
|
testToString();
|
||||||
|
testToByteArrayWithConstructor();
|
||||||
|
testIntValue();
|
||||||
|
testLongValue();
|
||||||
|
testFloatValue();
|
||||||
|
testDoubleValue();
|
||||||
|
testSerialization();
|
||||||
|
testLongValueExact();
|
||||||
|
testIntValueExact();
|
||||||
|
testShortValueExact();
|
||||||
|
testByteValueExact();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user