Skip to content

Commit

Permalink
add bigInteger constructor BigInteger(byte[], int offset, int length)
Browse files Browse the repository at this point in the history
  • Loading branch information
vegegoku committed May 19, 2024
1 parent 9be7196 commit cb499e2
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 23 deletions.
70 changes: 47 additions & 23 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,40 @@ 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}.
* @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) {
throw new IndexOutOfBoundsException("Range check failed: offset=" + offset + ", length="
+ length + ", val.length=" + val.length);
}
if (length == 0) {
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 Down Expand Up @@ -309,7 +333,7 @@ public BigInteger(int signum, byte[] magnitude) {
digits = new int[] {0};
} else {
sign = signum;
putBytesPositiveToIntegers(magnitude);
putBytesPositiveToIntegers(magnitude, 0, magnitude.length);
cutOffLeadingZeroes();
}
}
Expand Down Expand Up @@ -1477,8 +1501,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 +1511,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 +1534,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 +1550,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
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,134 @@ public void testConstructorBytesPositive3() {
assertEquals("incorrect sign", 1, aNumber.signum());
}

/**
* Create a negative number from an array of bytes with offset and length.
* The number fits in an array of integers.
*/
public void testConstructorBytesOffsetLengthNegative1() {
byte aBytes[] = {0, 0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
byte rBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
BigInteger aNumber = new BigInteger(aBytes, 2, 14);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", -1, aNumber.signum());
}

/**
* Create a negative number from an array of bytes with offset and length.
* The number fits in an integer.
*/
public void testConstructorBytesOffsetLengthNegative2() {
byte aBytes[] = {127, 127, -12, 56, 100};
byte rBytes[] = {-12, 56, 100};
BigInteger aNumber = new BigInteger(aBytes, 2, 3);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", -1, aNumber.signum());
}

/**
* Create a negative number from an array of bytes with offset and length.
* The number of bytes is 4.
*/
public void testConstructorBytesOffsetLengthNegative3() {
byte aBytes[] = {0, 0, -128, -12, 56, 100};
byte rBytes[] = {-128, -12, 56, 100};
BigInteger aNumber = new BigInteger(aBytes, 2, 4);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", -1, aNumber.signum());
}

/**
* Create a negative number from an array of bytes with offset and length.
* The number of bytes is multiple of 4.
*/
public void testConstructorBytesOffsetLengthNegative4() {
byte aBytes[] = {127, 127, -128, -12, 56, 100, -13, 56, 93, -78};
byte rBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
BigInteger aNumber = new BigInteger(aBytes, 2, 8);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", -1, aNumber.signum());
}

/**
* Create a positive number from an array of bytes with offset and length.
* The number of bytes is multiple of 4.
*/
public void testConstructorBytesOffsetLengthPositive() {
byte aBytes[] = {0, 0, 127, 56, 100, -1, 14, 75, -24, -100};
byte rBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
BigInteger aNumber = new BigInteger(aBytes, 2, 8);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", 1, aNumber.signum());
}

/**
* Create a positive number from an array of bytes with offset and length.
* The number fits in an array of integers.
*/
public void testConstructorBytesOffsetLengthPositive1() {
byte aBytes[] = {127, 127, 12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
BigInteger aNumber = new BigInteger(aBytes, 2, 14);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", 1, aNumber.signum());
}

/**
* Create a positive number from an array of bytes with offset and length.
* The number fits in an integer.
*/
public void testConstructorBytesOffsetLengthPositive2() {
byte aBytes[] = {0, 0, 12, 56, 100};
byte rBytes[] = {12, 56, 100};
BigInteger aNumber = new BigInteger(aBytes, 2, 3);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", 1, aNumber.signum());
}

/**
* Create a positive number from an array of bytes with offset and length.
* The number of bytes is 4.
*/
public void testConstructorBytesOffsetLengthPositive3() {
byte aBytes[] = {127, 127, 127, 56, 100, -1};
byte rBytes[] = {127, 56, 100, -1};
BigInteger aNumber = new BigInteger(aBytes, 2, 4);
byte resBytes[] = new byte[rBytes.length];
resBytes = aNumber.toByteArray();
for (int i = 0; i < resBytes.length; i++) {
assertTrue(resBytes[i] == rBytes[i]);
}
assertEquals("incorrect sign", 1, aNumber.signum());
}

/**
* Create a zero number from an array of zero bytes.
*/
Expand Down Expand Up @@ -605,6 +733,56 @@ public void testConstructorSignBytesZeroNull3() {
assertEquals("incorrect sign", 0, aNumber.signum());
}

public void testConstructorWithZeroBytes_Offset_Length() {
byte[] aByte = {};
try {
new BigInteger(aByte, 2, 4);
fail("NumberFormatException has not been caught");
} catch (NumberFormatException e) {
}
}

public void testConstructorBytes_Offset_ZeroLength() {
byte[] aByte = {127, 127, 12, 34, 56, 78, 0, 0};
assertEquals(BigInteger.ZERO, new BigInteger(aByte, 2, 0));
}

public void testConstructorWithBytes_NegativeOffset_Length() {
byte[] aByte = {0, 0, 12, 34, 56, 78, 0, 0};
try {
new BigInteger(aByte, -1, 4);
fail("IndexOutOfBoundsException has not been caught");
} catch (IndexOutOfBoundsException e) {
}
}

public void testConstructorWithBytes_OffsetOutSideArray_Length() {
byte[] aByte = {0, 0, 12, 34, 56, 78, 0, 0};
try {
new BigInteger(aByte, 8, 4);
fail("IndexOutOfBoundsException has not been caught");
} catch (IndexOutOfBoundsException e) {
}
}

public void testConstructorWithBytes_Offset_NegativeLength() {
byte[] aByte = {0, 0, 12, 34, 56, 78, 0, 0};
try {
new BigInteger(aByte, 2, -4);
fail("IndexOutOfBoundsException has not been caught");
} catch (IndexOutOfBoundsException e) {
}
}

public void testConstructorWithBytes_Offset_Length_exceedingSize() {
byte[] aByte = {0, 0, 12, 34, 56, 78};
try {
new BigInteger(aByte, 2, 5);
fail("IndexOutOfBoundsException has not been caught");
} catch (IndexOutOfBoundsException e) {
}
}

/**
* Create a number from a string value and radix. Verify an exception thrown
* if a radix is out of range
Expand Down

0 comments on commit cb499e2

Please sign in to comment.