Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Java 9 BigInteger constructors #9953

Merged
merged 4 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 77 additions & 25 deletions user/super/com/google/gwt/emul/java/math/BigInteger.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,16 +260,42 @@ private static void setFromString(BigInteger bi, String val, int radix) {
* @throws NumberFormatException if the length of {@code val} is zero.
*/
public BigInteger(byte[] val) {
this(val, 0, val.length);
}

/**
* Constructs a new {@code BigInteger} from the given two's complement
* 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
* BigInteger} instance. The given array must not be empty.
*
* @param val two's complement representation of the new {@code BigInteger}.
* @param offset the start offset of the binary representation.
* @param length the number of bytes to use.
* @throws NullPointerException if {@code val == null}.
* @throws NumberFormatException if the length of {@code val} is zero.
*/
public BigInteger(byte[] val, int offset, int length) {
if (val.length == 0) {
// math.12=Zero length BigInteger
throw new NumberFormatException("Zero length BigInteger"); //$NON-NLS-1$
}
if (val[0] < 0) {
if (length < 0 || offset < 0 || val.length < 0 || length > val.length - offset) {
vegegoku marked this conversation as resolved.
Show resolved Hide resolved
throw new IndexOutOfBoundsException("Range check failed: offset=" + offset + ", length="
+ length + ", val.length=" + val.length);
}
if (length == 0) {
niloc132 marked this conversation as resolved.
Show resolved Hide resolved
sign = 0;
numberLength = 1;
digits = new int[] {0};
return;
}
if (val[offset] < 0) {
sign = -1;
putBytesNegativeToIntegers(val);
putBytesNegativeToIntegers(val, offset, length);
} else {
sign = 1;
putBytesPositiveToIntegers(val);
putBytesPositiveToIntegers(val, offset, length);
}
cutOffLeadingZeroes();
}
Expand All @@ -289,27 +315,53 @@ public BigInteger(byte[] val) {
* sign is zero and the magnitude contains non-zero entries.
*/
public BigInteger(int signum, byte[] magnitude) {
this(signum, magnitude, 0, magnitude.length);
}

/**
* Constructs a new {@code BigInteger} instance with the given sign and the
* given magnitude. The sign is given as an integer (-1 for negative, 0 for
* zero, 1 for positive). The magnitude is specified as a byte array. The most
* significant byte is the entry at index 0.
*
* @param signum sign of the new {@code BigInteger} (-1 for negative, 0 for
* zero, 1 for positive).
* @param magnitude magnitude of the new {@code BigInteger} with the most
* significant byte first.
* @param offset the start offset of the binary representation.
* @param length the number of bytes to use.
* @throws NullPointerException if {@code magnitude == null}.
* @throws NumberFormatException if the sign is not one of -1, 0, 1 or if the
* sign is zero and the magnitude contains non-zero entries.
*/
public BigInteger(int signum, byte[] magnitude, int offset, int length) {
checkNotNull(magnitude);

if (length < 0 || offset < 0 || magnitude.length < 0 || length > magnitude.length - offset) {
vegegoku marked this conversation as resolved.
Show resolved Hide resolved
throw new IndexOutOfBoundsException("Range check failed: offset=" + offset + ", length="
+ length + ", val.length=" + magnitude.length);
}

if ((signum < -1) || (signum > 1)) {
// math.13=Invalid signum value
throw new NumberFormatException("Invalid signum value"); //$NON-NLS-1$
}
if (signum == 0) {
for (byte element : magnitude) {
for (int index = offset; index < offset + length; index++) {
byte element = magnitude[index];
if (element != 0) {
// math.14=signum-magnitude mismatch
throw new NumberFormatException("signum-magnitude mismatch"); //$NON-NLS-1$
}
}
}
if (magnitude.length == 0) {
if (length == 0) {
sign = 0;
numberLength = 1;
digits = new int[] {0};
} else {
sign = signum;
putBytesPositiveToIntegers(magnitude);
putBytesPositiveToIntegers(magnitude, offset, length);
cutOffLeadingZeroes();
}
}
Expand Down Expand Up @@ -1477,8 +1529,8 @@ void unCache() {
/**
* Puts a big-endian byte array into a little-endian applying two complement.
*/
private void putBytesNegativeToIntegers(byte[] byteValues) {
int bytesLen = byteValues.length;
private void putBytesNegativeToIntegers(byte[] byteValues, int offset, int length) {
int bytesLen = length;
int highBytes = bytesLen & 3;
numberLength = (bytesLen >> 2) + ((highBytes == 0) ? 0 : 1);
digits = new int[numberLength];
Expand All @@ -1487,19 +1539,19 @@ private void putBytesNegativeToIntegers(byte[] byteValues) {
digits[numberLength - 1] = -1;
// Put bytes to the int array starting from the end of the byte array
while (bytesLen > highBytes) {
digits[i] = (byteValues[--bytesLen] & 0xFF)
| (byteValues[--bytesLen] & 0xFF) << 8
| (byteValues[--bytesLen] & 0xFF) << 16
| (byteValues[--bytesLen] & 0xFF) << 24;
digits[i] = (byteValues[--bytesLen + offset] & 0xFF)
| (byteValues[--bytesLen + offset] & 0xFF) << 8
| (byteValues[--bytesLen + offset] & 0xFF) << 16
| (byteValues[--bytesLen + offset] & 0xFF) << 24;
if (digits[i] != 0) {
digits[i] = -digits[i];
firstNonzeroDigit = i;
i++;
while (bytesLen > highBytes) {
digits[i] = (byteValues[--bytesLen] & 0xFF)
| (byteValues[--bytesLen] & 0xFF) << 8
| (byteValues[--bytesLen] & 0xFF) << 16
| (byteValues[--bytesLen] & 0xFF) << 24;
digits[i] = (byteValues[--bytesLen + offset] & 0xFF)
| (byteValues[--bytesLen + offset] & 0xFF) << 8
| (byteValues[--bytesLen + offset] & 0xFF) << 16
| (byteValues[--bytesLen + offset] & 0xFF) << 24;
digits[i] = ~digits[i];
i++;
}
Expand All @@ -1510,12 +1562,12 @@ private void putBytesNegativeToIntegers(byte[] byteValues) {
if (highBytes != 0) {
// Put the first bytes in the highest element of the int array
if (firstNonzeroDigit != -2) {
for (int j = 0; j < bytesLen; j++) {
for (int j = offset; j < bytesLen + offset; j++) {
digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
}
digits[i] = ~digits[i];
} else {
for (int j = 0; j < bytesLen; j++) {
for (int j = offset; j < bytesLen + offset; j++) {
digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
}
digits[i] = -digits[i];
Expand All @@ -1526,21 +1578,21 @@ private void putBytesNegativeToIntegers(byte[] byteValues) {
/**
* Puts a big-endian byte array into a little-endian int array.
*/
private void putBytesPositiveToIntegers(byte[] byteValues) {
int bytesLen = byteValues.length;
private void putBytesPositiveToIntegers(byte[] byteValues, int offset, int length) {
int bytesLen = length;
int highBytes = bytesLen & 3;
numberLength = (bytesLen >> 2) + ((highBytes == 0) ? 0 : 1);
digits = new int[numberLength];
int i = 0;
// Put bytes to the int array starting from the end of the byte array
while (bytesLen > highBytes) {
digits[i++] = (byteValues[--bytesLen] & 0xFF)
| (byteValues[--bytesLen] & 0xFF) << 8
| (byteValues[--bytesLen] & 0xFF) << 16
| (byteValues[--bytesLen] & 0xFF) << 24;
digits[i++] = (byteValues[--bytesLen + offset] & 0xFF)
| (byteValues[--bytesLen + offset] & 0xFF) << 8
| (byteValues[--bytesLen + offset] & 0xFF) << 16
| (byteValues[--bytesLen + offset] & 0xFF) << 24;
}
// Put the first bytes in the highest element of the int array
for (int j = 0; j < bytesLen; j++) {
for (int j = offset; j < bytesLen + offset; j++) {
digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
}
}
Expand Down
Loading