Fixes incorrect handling of one-block loops. Fixes infinite loop

generation.
This commit is contained in:
konsoletyper 2014-06-27 22:44:16 +04:00
parent 2aa1774b25
commit 87262f2e97
4 changed files with 139 additions and 161 deletions

View File

@ -26,16 +26,15 @@ import java.io.Serializable;
* offer dedicated functionality like the generation of large prime numbers or * offer dedicated functionality like the generation of large prime numbers or
* the computation of modular inverse. * the computation of modular inverse.
* <p> * <p>
* Since the class was modeled to offer all the functionality as the {@link Integer} * Since the class was modeled to offer all the functionality as the
* class does, it provides even methods that operate bitwise on a two's * {@link Integer} class does, it provides even methods that operate bitwise on
* complement representation of large integers. Note however that the * a two's complement representation of large integers. Note however that the
* implementations favors an internal representation where magnitude and sign * implementations favors an internal representation where magnitude and sign
* are treated separately. Hence such operations are inefficient and should be * are treated separately. Hence such operations are inefficient and should be
* discouraged. In simple words: Do NOT implement any bit fields based on * discouraged. In simple words: Do NOT implement any bit fields based on
* BigInteger. * BigInteger.
*/ */
public class TBigInteger extends Number implements Comparable<TBigInteger>, public class TBigInteger extends Number implements Comparable<TBigInteger>, Serializable {
Serializable {
/** This is the serialVersionUID used by the sun implementation. */ /** This is the serialVersionUID used by the sun implementation. */
private static final long serialVersionUID = -8287574255936472291L; private static final long serialVersionUID = -8287574255936472291L;
@ -44,18 +43,17 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
/** /**
* The magnitude of this big integer. This array holds unsigned little * The magnitude of this big integer. This array holds unsigned little
* endian digits. For example: * endian digits. For example: {@code 13} is represented as [ 13 ]
* {@code 13} is represented as [ 13 ] * {@code -13} is represented as [ 13 ] {@code 2^32 + 13} is represented as
* {@code -13} is represented as [ 13 ] * [ 13, 1 ] {@code 2^64 + 13} is represented as [ 13, 0, 1 ] {@code 2^31}
* {@code 2^32 + 13} is represented as [ 13, 1 ] * is represented as [ Integer.MIN_VALUE ] The magnitude array may be longer
* {@code 2^64 + 13} is represented as [ 13, 0, 1 ] * than strictly necessary, which results in additional trailing zeros.
* {@code 2^31} is represented as [ Integer.MIN_VALUE ]
* The magnitude array may be longer than strictly necessary, which results
* in additional trailing zeros.
*/ */
transient int digits[]; transient int digits[];
/** The length of this in measured in ints. Can be less than digits.length(). */ /**
* The length of this in measured in ints. Can be less than digits.length().
*/
transient int numberLength; transient int numberLength;
/** The sign of this. */ /** The sign of this. */
@ -89,17 +87,16 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
static final int LESS = -1; static final int LESS = -1;
/** All the {@code BigInteger} numbers in the range [0,10] are cached. */ /** All the {@code BigInteger} numbers in the range [0,10] are cached. */
static final TBigInteger[] SMALL_VALUES = { ZERO, ONE, new TBigInteger(1, 2), static final TBigInteger[] SMALL_VALUES = { ZERO, ONE, new TBigInteger(1, 2), new TBigInteger(1, 3),
new TBigInteger(1, 3), new TBigInteger(1, 4), new TBigInteger(1, 5), new TBigInteger(1, 4), new TBigInteger(1, 5), new TBigInteger(1, 6), new TBigInteger(1, 7),
new TBigInteger(1, 6), new TBigInteger(1, 7), new TBigInteger(1, 8), new TBigInteger(1, 8), new TBigInteger(1, 9), TEN };
new TBigInteger(1, 9), TEN };
static final TBigInteger[] TWO_POWS; static final TBigInteger[] TWO_POWS;
static { static {
TWO_POWS = new TBigInteger[32]; TWO_POWS = new TBigInteger[32];
for(int i = 0; i < TWO_POWS.length; i++) { for (int i = 0; i < TWO_POWS.length; i++) {
TWO_POWS[i] = TBigInteger.valueOf(1L<<i); TWO_POWS[i] = TBigInteger.valueOf(1L << i);
} }
} }
@ -174,8 +171,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
* @throws NullPointerException * @throws NullPointerException
* if {@code val == null}. * if {@code val == null}.
* @throws NumberFormatException * @throws NumberFormatException
* if {@code val} is not a valid representation of a {@code * if {@code val} is not a valid representation of a
* BigInteger}. * {@code BigInteger}.
*/ */
public TBigInteger(String val) { public TBigInteger(String val) {
this(val, 10); this(val, 10);
@ -195,9 +192,9 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
* @throws NullPointerException * @throws NullPointerException
* if {@code val == null}. * if {@code val == null}.
* @throws NumberFormatException * @throws NumberFormatException
* if {@code val} is not a valid representation of a {@code * if {@code val} is not a valid representation of a
* BigInteger} or if {@code radix < Character.MIN_RADIX} or * {@code BigInteger} or if {@code radix < Character.MIN_RADIX}
* {@code radix > Character.MAX_RADIX}. * or {@code radix > Character.MAX_RADIX}.
*/ */
public TBigInteger(String val, int radix) { public TBigInteger(String val, int radix) {
if (val == null) { if (val == null) {
@ -258,8 +255,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
/** /**
* Constructs a new {@code BigInteger} from the given two's complement * Constructs a new {@code BigInteger} from the given two's complement
* representation. The most significant byte is the entry at index 0. The * representation. The most significant byte is the entry at index 0. The
* most significant bit of this entry determines the sign of the new {@code * most significant bit of this entry determines the sign of the new
* BigInteger} instance. The given array must not be empty. * {@code BigInteger} instance. The given array must not be empty.
* *
* @param val * @param val
* two's complement representation of the new {@code BigInteger}. * two's complement representation of the new {@code BigInteger}.
@ -328,10 +325,10 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
if ((val & 0xFFFFFFFF00000000L) == 0) { if ((val & 0xFFFFFFFF00000000L) == 0) {
// It fits in one 'int' // It fits in one 'int'
numberLength = 1; numberLength = 1;
digits = new int[] { (int) val }; digits = new int[] { (int)val };
} else { } else {
numberLength = 2; numberLength = 2;
digits = new int[] { (int) val, (int) (val >> 32) }; digits = new int[] { (int)val, (int)(val >> 32) };
} }
} }
@ -365,7 +362,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
} }
return MINUS_ONE; return MINUS_ONE;
} else if (val <= 10) { } else if (val <= 10) {
return SMALL_VALUES[(int) val]; return SMALL_VALUES[(int)val];
} else {// (val > 10) } else {// (val > 10)
return new TBigInteger(1, val); return new TBigInteger(1, val);
} }
@ -398,7 +395,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int hB; int hB;
if (bytesLen - (numberLength << 2) == 1) { if (bytesLen - (numberLength << 2) == 1) {
bytes[0] = (byte) ((sign < 0) ? -1 : 0); bytes[0] = (byte)((sign < 0) ? -1 : 0);
highBytes = 4; highBytes = 4;
firstByteNumber++; firstByteNumber++;
} else { } else {
@ -416,7 +413,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
bytesInInteger = highBytes; bytesInInteger = highBytes;
} }
for (int i = 0; i < bytesInInteger; i++, digit >>= 8) { for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
bytes[--bytesLen] = (byte) digit; bytes[--bytesLen] = (byte)digit;
} }
while (bytesLen > firstByteNumber) { while (bytesLen > firstByteNumber) {
digit = ~temp.digits[digitIndex]; digit = ~temp.digits[digitIndex];
@ -425,7 +422,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
bytesInInteger = highBytes; bytesInInteger = highBytes;
} }
for (int i = 0; i < bytesInInteger; i++, digit >>= 8) { for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
bytes[--bytesLen] = (byte) digit; bytes[--bytesLen] = (byte)digit;
} }
} }
} else { } else {
@ -436,7 +433,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
bytesInInteger = highBytes; bytesInInteger = highBytes;
} }
for (int i = 0; i < bytesInInteger; i++, digit >>= 8) { for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
bytes[--bytesLen] = (byte) digit; bytes[--bytesLen] = (byte)digit;
} }
} }
} }
@ -483,14 +480,11 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars); int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars);
int newDigit; int newDigit;
for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart +
+ charsPerInt) { charsPerInt) {
int bigRadixDigit = Integer.parseInt(val.substring(substrStart, int bigRadixDigit = Integer.parseInt(val.substring(substrStart, substrEnd), radix);
substrEnd), radix); newDigit = TMultiplication.multiplyByInt(digits, digitIndex, bigRadix);
newDigit = TMultiplication.multiplyByInt(digits, digitIndex, newDigit += TElementary.inplaceAdd(digits, digitIndex, bigRadixDigit);
bigRadix);
newDigit += TElementary
.inplaceAdd(digits, digitIndex, bigRadixDigit);
digits[digitIndex++] = newDigit; digits[digitIndex++] = newDigit;
} }
numberLength = digitIndex; numberLength = digitIndex;
@ -516,8 +510,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
* @return {@code -this}. * @return {@code -this}.
*/ */
public TBigInteger negate() { public TBigInteger negate() {
return ((sign == 0) ? this return ((sign == 0) ? this : new TBigInteger(-sign, numberLength, digits));
: new TBigInteger(-sign, numberLength, digits));
} }
/** /**
@ -549,8 +542,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
/** /**
* Returns the sign of this {@code BigInteger}. * Returns the sign of this {@code BigInteger}.
* *
* @return {@code -1} if {@code this < 0}, * @return {@code -1} if {@code this < 0}, {@code 0} if {@code this == 0},
* {@code 0} if {@code this == 0},
* {@code 1} if {@code this > 0}. * {@code 1} if {@code this > 0}.
*/ */
public int signum() { public int signum() {
@ -574,8 +566,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
if ((n == 0) || (sign == 0)) { if ((n == 0) || (sign == 0)) {
return this; return this;
} }
return ((n > 0) ? TBitLevel.shiftRight(this, n) : TBitLevel.shiftLeft( return ((n > 0) ? TBitLevel.shiftRight(this, n) : TBitLevel.shiftLeft(this, -n));
this, -n));
} }
/** /**
@ -596,8 +587,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
if ((n == 0) || (sign == 0)) { if ((n == 0) || (sign == 0)) {
return this; return this;
} }
return ((n > 0) ? TBitLevel.shiftLeft(this, n) : TBitLevel.shiftRight( return ((n > 0) ? TBitLevel.shiftLeft(this, n) : TBitLevel.shiftRight(this, -n));
this, -n));
} }
TBigInteger shiftLeftOneBit() { TBigInteger shiftLeftOneBit() {
@ -826,8 +816,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
/** /**
* Returns a new {@code BigInteger} whose value is {@code this & ~val}. * Returns a new {@code BigInteger} whose value is {@code this & ~val}.
* Evaluating {@code x.andNot(val)} returns the same result as {@code * Evaluating {@code x.andNot(val)} returns the same result as
* x.and(val.not())}. * {@code x.and(val.not())}.
* <p> * <p>
* <b>Implementation Note:</b> Usage of this method is not recommended as * <b>Implementation Note:</b> Usage of this method is not recommended as
* the current implementation is not efficient. * the current implementation is not efficient.
@ -861,8 +851,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
*/ */
@Override @Override
public long longValue() { public long longValue() {
long value = (numberLength > 1) ? (((long) digits[1]) << 32) long value = (numberLength > 1) ? (((long)digits[1]) << 32) | (digits[0] & 0xFFFFFFFFL)
| (digits[0] & 0xFFFFFFFFL) : (digits[0] & 0xFFFFFFFFL); : (digits[0] & 0xFFFFFFFFL);
return (sign * value); return (sign * value);
} }
@ -878,13 +868,13 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
*/ */
@Override @Override
public float floatValue() { public float floatValue() {
return (float) doubleValue(); return (float)doubleValue();
} }
/** /**
* Returns this {@code BigInteger} as an double value. If {@code this} is * Returns this {@code BigInteger} as an double value. If {@code this} is
* too big to be represented as an double, then {@code * too big to be represented as an double, then
* Double.POSITIVE_INFINITY} or {@code Double.NEGATIVE_INFINITY} is * {@code Double.POSITIVE_INFINITY} or {@code Double.NEGATIVE_INFINITY} is
* returned. Note, that not all integers x in the range [-Double.MAX_VALUE, * returned. Note, that not all integers x in the range [-Double.MAX_VALUE,
* Double.MAX_VALUE] can be represented as a double. The double * Double.MAX_VALUE] can be represented as a double. The double
* representation has a mantissa of length 53. For example, 2^53+1 = * representation has a mantissa of length 53. For example, 2^53+1 =
@ -923,8 +913,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
return -val.sign; return -val.sign;
} }
// Equal sign and equal numberLength // Equal sign and equal numberLength
return (sign * TElementary.compareArrays(digits, val.digits, return (sign * TElementary.compareArrays(digits, val.digits, numberLength));
numberLength));
} }
/** /**
@ -977,7 +966,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
* @param x * @param x
* object to be compared with {@code this}. * object to be compared with {@code this}.
* @return true if {@code x} is a BigInteger and {@code this == x}, * @return true if {@code x} is a BigInteger and {@code this == x},
* {@code false} otherwise. * {@code false} otherwise.
*/ */
@Override @Override
public boolean equals(Object x) { public boolean equals(Object x) {
@ -985,9 +974,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
return true; return true;
} }
if (x instanceof TBigInteger) { if (x instanceof TBigInteger) {
TBigInteger x1 = (TBigInteger) x; TBigInteger x1 = (TBigInteger)x;
return sign == x1.sign && numberLength == x1.numberLength return sign == x1.sign && numberLength == x1.numberLength && equalsArrays(x1.digits);
&& equalsArrays(x1.digits);
} }
return false; return false;
} }
@ -1012,8 +1000,9 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
} }
/** /**
* Returns a string containing a string representation of this {@code * Returns a string containing a string representation of this
* BigInteger} with base radix. If {@code radix < Character.MIN_RADIX} or * {@code BigInteger} with base radix. If
* {@code radix < Character.MIN_RADIX} or
* {@code radix > Character.MAX_RADIX} then a decimal representation is * {@code radix > Character.MAX_RADIX} then a decimal representation is
* returned. The characters of the string representation are generated with * returned. The characters of the string representation are generated with
* method {@code Character.forDigit}. * method {@code Character.forDigit}.
@ -1049,10 +1038,9 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
// Optimization for small operands // Optimization for small operands
// (op2.bitLength() < 64) and (op1.bitLength() < 64) // (op2.bitLength() < 64) and (op1.bitLength() < 64)
if (((val1.numberLength == 1) || ((val1.numberLength == 2) && (val1.digits[1] > 0))) if (((val1.numberLength == 1) || ((val1.numberLength == 2) && (val1.digits[1] > 0))) &&
&& (val2.numberLength == 1 || (val2.numberLength == 2 && val2.digits[1] > 0))) { (val2.numberLength == 1 || (val2.numberLength == 2 && val2.digits[1] > 0))) {
return TBigInteger.valueOf(TDivision.gcdBinary(val1.longValue(), val2 return TBigInteger.valueOf(TDivision.gcdBinary(val1.longValue(), val2.longValue()));
.longValue()));
} }
return TDivision.gcdBinary(val1.copy(), val2.copy()); return TDivision.gcdBinary(val1.copy(), val2.copy());
@ -1105,7 +1093,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
while (!testBit(x)) { while (!testBit(x)) {
x++; x++;
} }
return getPowerOfTwo(x*exp).multiply(this.shiftRight(x).pow(exp)); return getPowerOfTwo(x * exp).multiply(this.shiftRight(x).pow(exp));
} }
return TMultiplication.pow(this, exp); return TMultiplication.pow(this, exp);
} }
@ -1132,14 +1120,13 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int divisorLen = divisor.numberLength; int divisorLen = divisor.numberLength;
int[] divisorDigits = divisor.digits; int[] divisorDigits = divisor.digits;
if (divisorLen == 1) { if (divisorLen == 1) {
return TDivision.divideAndRemainderByInteger(this, divisorDigits[0], return TDivision.divideAndRemainderByInteger(this, divisorDigits[0], divisorSign);
divisorSign);
} }
// res[0] is a quotient and res[1] is a remainder: // res[0] is a quotient and res[1] is a remainder:
int[] thisDigits = digits; int[] thisDigits = digits;
int thisLen = numberLength; int thisLen = numberLength;
int cmp = (thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) int cmp = (thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : TElementary.compareArrays(thisDigits,
: TElementary.compareArrays(thisDigits, divisorDigits, thisLen); divisorDigits, thisLen);
if (cmp < 0) { if (cmp < 0) {
return new TBigInteger[] { ZERO, this }; return new TBigInteger[] { ZERO, this };
} }
@ -1148,12 +1135,10 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int remainderLength = divisorLen; int remainderLength = divisorLen;
int quotientSign = ((thisSign == divisorSign) ? 1 : -1); int quotientSign = ((thisSign == divisorSign) ? 1 : -1);
int quotientDigits[] = new int[quotientLength]; int quotientDigits[] = new int[quotientLength];
int remainderDigits[] = TDivision.divide(quotientDigits, quotientLength, int remainderDigits[] = TDivision.divide(quotientDigits, quotientLength, thisDigits, thisLen, divisorDigits,
thisDigits, thisLen, divisorDigits, divisorLen); divisorLen);
TBigInteger result0 = new TBigInteger(quotientSign, quotientLength, TBigInteger result0 = new TBigInteger(quotientSign, quotientLength, quotientDigits);
quotientDigits); TBigInteger result1 = new TBigInteger(thisSign, remainderLength, remainderDigits);
TBigInteger result1 = new TBigInteger(thisSign, remainderLength,
remainderDigits);
result0.cutOffLeadingZeroes(); result0.cutOffLeadingZeroes();
result1.cutOffLeadingZeroes(); result1.cutOffLeadingZeroes();
return new TBigInteger[] { result0, result1 }; return new TBigInteger[] { result0, result1 };
@ -1182,15 +1167,14 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int thisLen = numberLength; int thisLen = numberLength;
int divisorLen = divisor.numberLength; int divisorLen = divisor.numberLength;
if (thisLen + divisorLen == 2) { if (thisLen + divisorLen == 2) {
long val = (digits[0] & 0xFFFFFFFFL) long val = (digits[0] & 0xFFFFFFFFL) / (divisor.digits[0] & 0xFFFFFFFFL);
/ (divisor.digits[0] & 0xFFFFFFFFL);
if (thisSign != divisorSign) { if (thisSign != divisorSign) {
val = -val; val = -val;
} }
return valueOf(val); return valueOf(val);
} }
int cmp = ((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) int cmp = ((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : TElementary.compareArrays(digits,
: TElementary.compareArrays(digits, divisor.digits, thisLen)); divisor.digits, thisLen));
if (cmp == EQUALS) { if (cmp == EQUALS) {
return ((thisSign == divisorSign) ? ONE : MINUS_ONE); return ((thisSign == divisorSign) ? ONE : MINUS_ONE);
} }
@ -1201,11 +1185,9 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int resDigits[] = new int[resLength]; int resDigits[] = new int[resLength];
int resSign = ((thisSign == divisorSign) ? 1 : -1); int resSign = ((thisSign == divisorSign) ? 1 : -1);
if (divisorLen == 1) { if (divisorLen == 1) {
TDivision.divideArrayByInt(resDigits, digits, thisLen, TDivision.divideArrayByInt(resDigits, digits, thisLen, divisor.digits[0]);
divisor.digits[0]);
} else { } else {
TDivision.divide(resDigits, resLength, digits, thisLen, TDivision.divide(resDigits, resLength, digits, thisLen, divisor.digits, divisorLen);
divisor.digits, divisorLen);
} }
TBigInteger result = new TBigInteger(resSign, resLength, resDigits); TBigInteger result = new TBigInteger(resSign, resLength, resDigits);
result.cutOffLeadingZeroes(); result.cutOffLeadingZeroes();
@ -1231,19 +1213,17 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
} }
int thisLen = numberLength; int thisLen = numberLength;
int divisorLen = divisor.numberLength; int divisorLen = divisor.numberLength;
if (((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) if (((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : TElementary.compareArrays(digits,
: TElementary.compareArrays(digits, divisor.digits, thisLen)) == LESS) { divisor.digits, thisLen)) == LESS) {
return this; return this;
} }
int resLength = divisorLen; int resLength = divisorLen;
int resDigits[] = new int[resLength]; int resDigits[] = new int[resLength];
if (resLength == 1) { if (resLength == 1) {
resDigits[0] = TDivision.remainderArrayByInt(digits, thisLen, resDigits[0] = TDivision.remainderArrayByInt(digits, thisLen, divisor.digits[0]);
divisor.digits[0]);
} else { } else {
int qLen = thisLen - divisorLen + 1; int qLen = thisLen - divisorLen + 1;
resDigits = TDivision.divide(null, qLen, digits, thisLen, resDigits = TDivision.divide(null, qLen, digits, thisLen, divisor.digits, divisorLen);
divisor.digits, divisorLen);
} }
TBigInteger result = new TBigInteger(sign, resLength, resDigits); TBigInteger result = new TBigInteger(sign, resLength, resDigits);
result.cutOffLeadingZeroes(); result.cutOffLeadingZeroes();
@ -1324,8 +1304,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
exponent = exponent.negate(); exponent = exponent.negate();
} }
// From now on: (m > 0) and (exponent >= 0) // From now on: (m > 0) and (exponent >= 0)
TBigInteger res = (m.testBit(0)) ? TDivision.oddModPow(base.abs(), TBigInteger res = (m.testBit(0)) ? TDivision.oddModPow(base.abs(), exponent, m) : TDivision.evenModPow(
exponent, m) : TDivision.evenModPow(base.abs(), exponent, m); base.abs(), exponent, m);
if ((base.sign < 0) && exponent.testBit(0)) { if ((base.sign < 0) && exponent.testBit(0)) {
// -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m
res = m.subtract(TBigInteger.ONE).multiply(res).mod(m); res = m.subtract(TBigInteger.ONE).multiply(res).mod(m);
@ -1375,8 +1355,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
/** /**
* Returns the smallest integer x > {@code this} which is probably prime as * Returns the smallest integer x > {@code this} which is probably prime as
* a {@code BigInteger} instance. The probability that the returned {@code * a {@code BigInteger} instance. The probability that the returned
* BigInteger} is prime is beyond (1-1/2^80). * {@code BigInteger} is prime is beyond (1-1/2^80).
* *
* @return smallest integer > {@code this} which is robably prime. * @return smallest integer > {@code this} which is robably prime.
* @throws ArithmeticException * @throws ArithmeticException
@ -1384,7 +1364,7 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
*/ */
public TBigInteger nextProbablePrime() { public TBigInteger nextProbablePrime() {
if (sign < 0) { if (sign < 0) {
throw new ArithmeticException("start < 0: " + this); throw new ArithmeticException("start < 0: " + this);
} }
return TPrimality.nextProbablePrime(this); return TPrimality.nextProbablePrime(this);
} }
@ -1436,10 +1416,8 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
int i = 0; int i = 0;
// Put bytes to the int array starting from the end of the byte array // Put bytes to the int array starting from the end of the byte array
while (bytesLen > highBytes) { while (bytesLen > highBytes) {
digits[i++] = (byteValues[--bytesLen] & 0xFF) digits[i++] = (byteValues[--bytesLen] & 0xFF) | (byteValues[--bytesLen] & 0xFF) << 8 |
| (byteValues[--bytesLen] & 0xFF) << 8 (byteValues[--bytesLen] & 0xFF) << 16 | (byteValues[--bytesLen] & 0xFF) << 24;
| (byteValues[--bytesLen] & 0xFF) << 16
| (byteValues[--bytesLen] & 0xFF) << 24;
} }
// Put the first bytes in the highest element of the int array // Put the first bytes in the highest element of the int array
for (int j = 0; j < bytesLen; j++) { for (int j = 0; j < bytesLen; j++) {
@ -1461,19 +1439,15 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
digits[numberLength - 1] = -1; digits[numberLength - 1] = -1;
// Put bytes to the int array starting from the end of the byte array // Put bytes to the int array starting from the end of the byte array
while (bytesLen > highBytes) { while (bytesLen > highBytes) {
digits[i] = (byteValues[--bytesLen] & 0xFF) digits[i] = (byteValues[--bytesLen] & 0xFF) | (byteValues[--bytesLen] & 0xFF) << 8 |
| (byteValues[--bytesLen] & 0xFF) << 8 (byteValues[--bytesLen] & 0xFF) << 16 | (byteValues[--bytesLen] & 0xFF) << 24;
| (byteValues[--bytesLen] & 0xFF) << 16
| (byteValues[--bytesLen] & 0xFF) << 24;
if (digits[i] != 0) { if (digits[i] != 0) {
digits[i] = -digits[i]; digits[i] = -digits[i];
firstNonzeroDigit = i; firstNonzeroDigit = i;
i++; i++;
while (bytesLen > highBytes) { while (bytesLen > highBytes) {
digits[i] = (byteValues[--bytesLen] & 0xFF) digits[i] = (byteValues[--bytesLen] & 0xFF) | (byteValues[--bytesLen] & 0xFF) << 8 |
| (byteValues[--bytesLen] & 0xFF) << 8 (byteValues[--bytesLen] & 0xFF) << 16 | (byteValues[--bytesLen] & 0xFF) << 24;
| (byteValues[--bytesLen] & 0xFF) << 16
| (byteValues[--bytesLen] & 0xFF) << 24;
digits[i] = ~digits[i]; digits[i] = ~digits[i];
i++; i++;
} }
@ -1526,14 +1500,13 @@ public class TBigInteger extends Number implements Comparable<TBigInteger>,
} }
static TBigInteger getPowerOfTwo(int exp) { static TBigInteger getPowerOfTwo(int exp) {
if(exp < TWO_POWS.length) { if (exp < TWO_POWS.length) {
return TWO_POWS[exp]; return TWO_POWS[exp];
} }
int intCount = exp >> 5; int intCount = exp >> 5;
int bitN = exp & 31; int bitN = exp & 31;
int resDigits[] = new int[intCount+1]; int resDigits[] = new int[intCount + 1];
resDigits[intCount] = 1 << bitN; resDigits[intCount] = 1 << bitN;
return new TBigInteger(1, intCount+1, resDigits); return new TBigInteger(1, intCount + 1, resDigits);
} }
} }

View File

@ -35,7 +35,8 @@ package org.teavm.classlib.java.math;
class TBitLevel { class TBitLevel {
/** Just to denote that this class can't be instantiated. */ /** Just to denote that this class can't be instantiated. */
private TBitLevel() {} private TBitLevel() {
}
/** @see TBigInteger#bitLength() */ /** @see TBigInteger#bitLength() */
static int bitLength(TBigInteger val) { static int bitLength(TBigInteger val) {
@ -67,7 +68,7 @@ class TBitLevel {
int i = val.getFirstNonzeroDigit(); int i = val.getFirstNonzeroDigit();
if (val.sign > 0) { if (val.sign > 0) {
for ( ; i < val.numberLength; i++) { for (; i < val.numberLength; i++) {
bCount += Integer.bitCount(val.digits[i]); bCount += Integer.bitCount(val.digits[i]);
} }
} else {// (sign < 0) } else {// (sign < 0)
@ -94,7 +95,8 @@ class TBitLevel {
/** /**
* Check if there are 1s in the lowest bits of this BigInteger * Check if there are 1s in the lowest bits of this BigInteger
* *
* @param numberOfBits the number of the lowest bits to check * @param numberOfBits
* the number of the lowest bits to check
* @return false if all bits are 0s, true otherwise * @return false if all bits are 0s, true otherwise
*/ */
static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) { static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) {
@ -112,8 +114,7 @@ class TBitLevel {
static TBigInteger shiftLeft(TBigInteger source, int count) { static TBigInteger shiftLeft(TBigInteger source, int count) {
int intCount = count >> 5; int intCount = count >> 5;
count &= 31; // %= 32 count &= 31; // %= 32
int resLength = source.numberLength + intCount int resLength = source.numberLength + intCount + ((count == 0) ? 0 : 1);
+ ( ( count == 0 ) ? 0 : 1 );
int resDigits[] = new int[resLength]; int resDigits[] = new int[resLength];
shiftLeft(resDigits, source.digits, intCount, count); shiftLeft(resDigits, source.digits, intCount, count);
@ -128,10 +129,8 @@ class TBitLevel {
// val should have enough place (and one digit more) // val should have enough place (and one digit more)
static void inplaceShiftLeft(TBigInteger val, int count) { static void inplaceShiftLeft(TBigInteger val, int count) {
int intCount = count >> 5; // count of integers int intCount = count >> 5; // count of integers
val.numberLength += intCount val.numberLength += intCount +
+ ( Integer (Integer.numberOfLeadingZeros(val.digits[val.numberLength - 1]) - (count & 31) >= 0 ? 0 : 1);
.numberOfLeadingZeros(val.digits[val.numberLength - 1])
- ( count & 31 ) >= 0 ? 0 : 1 );
shiftLeft(val.digits, val.digits, intCount, count & 31); shiftLeft(val.digits, val.digits, intCount, count & 31);
val.cutOffLeadingZeroes(); val.cutOffLeadingZeroes();
val.unCache(); val.unCache();
@ -141,15 +140,18 @@ class TBitLevel {
* Abstractly shifts left an array of integers in little endian (i.e. shift * Abstractly shifts left an array of integers in little endian (i.e. shift
* it right). Total shift distance in bits is intCount * 32 + count * it right). Total shift distance in bits is intCount * 32 + count
* *
* @param result the destination array * @param result
* @param source the source array * the destination array
* @param intCount the shift distance in integers * @param source
* @param count an additional shift distance in bits * the source array
* @param intCount
* the shift distance in integers
* @param count
* an additional shift distance in bits
*/ */
static void shiftLeft(int result[], int source[], int intCount, int count) { static void shiftLeft(int result[], int source[], int intCount, int count) {
if (count == 0) { if (count == 0) {
System.arraycopy(source, 0, result, intCount, result.length System.arraycopy(source, 0, result, intCount, result.length - intCount);
- intCount);
} else { } else {
int rightShiftCount = 32 - count; int rightShiftCount = 32 - count;
@ -169,13 +171,17 @@ class TBitLevel {
* Shifts the source digits left one bit, creating a value whose magnitude * Shifts the source digits left one bit, creating a value whose magnitude
* is doubled. * is doubled.
* *
* @param result an array of digits that will hold the computed result when * @param result
* this method returns. The size of this array is {@code srcLen + 1}, * an array of digits that will hold the computed result when
* and the format is the same as {@link TBigInteger#digits}. * this method returns. The size of this array is
* @param source the array of digits to shift left, in the same format as * {@code srcLen + 1}, and the format is the same as
* {@link TBigInteger#digits}. * {@link TBigInteger#digits}.
* @param srcLen the length of {@code source}; may be less than {@code * @param source
* source.length} * the array of digits to shift left, in the same format as
* {@link TBigInteger#digits}.
* @param srcLen
* the length of {@code source}; may be less than
* {@code source.length}
*/ */
static void shiftLeftOneBit(int result[], int source[], int srcLen) { static void shiftLeftOneBit(int result[], int source[], int srcLen) {
int carry = 0; int carry = 0;
@ -218,8 +224,7 @@ class TBitLevel {
// do nothing // do nothing
} }
// If the remainder is not zero, add 1 to the result // If the remainder is not zero, add 1 to the result
if ((i < intCount) if ((i < intCount) || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) {
|| ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) {
for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) { for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) {
resDigits[i] = 0; resDigits[i] = 0;
} }
@ -243,12 +248,10 @@ class TBitLevel {
return; return;
int intCount = count >> 5; // count of integers int intCount = count >> 5; // count of integers
val.numberLength -= intCount; val.numberLength -= intCount;
if (!shiftRight(val.digits, val.numberLength, val.digits, intCount, if (!shiftRight(val.digits, val.numberLength, val.digits, intCount, count & 31) && sign < 0) {
count & 31)
&& sign < 0) {
// remainder not zero: add one to the result // remainder not zero: add one to the result
int i; int i;
for (i = 0; ( i < val.numberLength ) && ( val.digits[i] == -1 ); i++) { for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
val.digits[i] = 0; val.digits[i] = 0;
} }
if (i == val.numberLength) { if (i == val.numberLength) {
@ -276,38 +279,40 @@ class TBitLevel {
* the number of bits to be shifted * the number of bits to be shifted
* @return dropped bit's are all zero (i.e. remaider is zero) * @return dropped bit's are all zero (i.e. remaider is zero)
*/ */
static boolean shiftRight(int result[], int resultLen, int source[], static boolean shiftRight(int result[], int resultLen, int source[], int intCount, int count) {
int intCount, int count) {
int i; int i;
boolean allZero = true; boolean allZero = true;
for (i = 0; i < intCount; i++) for (i = 0; i < intCount; i++) {
allZero &= source[i] == 0; allZero &= source[i] == 0;
}
if (count == 0) { if (count == 0) {
System.arraycopy(source, intCount, result, 0, resultLen); System.arraycopy(source, intCount, result, 0, resultLen);
i = resultLen; i = resultLen;
} else { } else {
int leftShiftCount = 32 - count; int leftShiftCount = 32 - count;
allZero &= ( source[i] << leftShiftCount ) == 0; allZero &= (source[i] << leftShiftCount) == 0;
for (i = 0; i < resultLen - 1; i++) { for (i = 0; i < resultLen - 1; i++) {
result[i] = ( source[i + intCount] >>> count ) result[i] = (source[i + intCount] >>> count) | (source[i + intCount + 1] << leftShiftCount);
| ( source[i + intCount + 1] << leftShiftCount );
} }
result[i] = ( source[i + intCount] >>> count ); result[i] = (source[i + intCount] >>> count);
i++; i++;
} }
return allZero; return allZero;
} }
/** /**
* Performs a flipBit on the BigInteger, returning a BigInteger with the the * Performs a flipBit on the BigInteger, returning a BigInteger with the the
* specified bit flipped. * specified bit flipped.
* @param intCount: the index of the element of the digits array where the operation will be performed *
* @param bitNumber: the bit's position in the intCount element * @param intCount
* : the index of the element of the digits array where the
* operation will be performed
* @param bitNumber
* : the bit's position in the intCount element
*/ */
static TBigInteger flipBit(TBigInteger val, int n){ static TBigInteger flipBit(TBigInteger val, int n) {
int resSign = (val.sign == 0) ? 1 : val.sign; int resSign = (val.sign == 0) ? 1 : val.sign;
int intCount = n >> 5; int intCount = n >> 5;
int bitN = n & 31; int bitN = n & 31;
@ -322,28 +327,28 @@ class TBitLevel {
if (intCount >= val.numberLength) { if (intCount >= val.numberLength) {
resDigits[intCount] = bitNumber; resDigits[intCount] = bitNumber;
} else { } else {
//val.sign<0 y intCount < val.numberLength // val.sign<0 y intCount < val.numberLength
int firstNonZeroDigit = val.getFirstNonzeroDigit(); int firstNonZeroDigit = val.getFirstNonzeroDigit();
if (intCount > firstNonZeroDigit) { if (intCount > firstNonZeroDigit) {
resDigits[intCount] ^= bitNumber; resDigits[intCount] ^= bitNumber;
} else if (intCount < firstNonZeroDigit) { } else if (intCount < firstNonZeroDigit) {
resDigits[intCount] = -bitNumber; resDigits[intCount] = -bitNumber;
for (i=intCount + 1; i < firstNonZeroDigit; i++) { for (i = intCount + 1; i < firstNonZeroDigit; i++) {
resDigits[i]=-1; resDigits[i] = -1;
} }
resDigits[i] = resDigits[i]--; resDigits[i] = resDigits[i]--;
} else { } else {
i = intCount; i = intCount;
resDigits[i] = -((-resDigits[intCount]) ^ bitNumber); resDigits[i] = -((-resDigits[intCount]) ^ bitNumber);
if (resDigits[i] == 0) { if (resDigits[i] == 0) {
for (i++; resDigits[i] == -1 ; i++) { for (i++; resDigits[i] == -1; i++) {
resDigits[i] = 0; resDigits[i] = 0;
} }
resDigits[i]++; resDigits[i]++;
} }
} }
} }
} else {//case where val is positive } else {// case where val is positive
resDigits[intCount] ^= bitNumber; resDigits[intCount] ^= bitNumber;
} }
TBigInteger result = new TBigInteger(resSign, resLength, resDigits); TBigInteger result = new TBigInteger(resSign, resLength, resDigits);

View File

@ -357,7 +357,7 @@ public class Decompiler {
} }
for (int node = 0; node < sz; ++node) { for (int node = 0; node < sz; ++node) {
if (isSingleBlockLoop(node)) { if (isSingleBlockLoop(node)) {
ranges.add(new RangeTree.Range(node, node)); ranges.add(new RangeTree.Range(node, node + 1));
} }
} }
codeTree = new RangeTree(sz + 1, ranges); codeTree = new RangeTree(sz + 1, ranges);

View File

@ -574,7 +574,7 @@ class StatementGenerator implements InstructionVisitor {
} }
Statement generateJumpStatement(BasicBlock target) { Statement generateJumpStatement(BasicBlock target) {
if (nextBlock == target) { if (nextBlock == target && blockMap[target.getIndex()] == null) {
return null; return null;
} }
Decompiler.Block block = blockMap[target.getIndex()]; Decompiler.Block block = blockMap[target.getIndex()];