BigInteger.java (BigInteger(String, int)): New constructor.

* java/math/BigInteger.java(BigInteger(String, int)): New constructor.
	(BigInteger(String)): New constructor.
	(not): Rewritten using version from Kawa's BitOps class.
	(valueOf): New private methods from Kawa's BitOps class.
	(swappedOp): ditto.
	(bitOp): ditto.
	(setBitOp): ditto.
	(and): Implemented.
	(or): Implemented.
	(xor): Implemented.
	(andNot): Implemented.
	(clearBit): Implemented.
	(setBit): Implemented.
	(bitCount): Implemented.
	(toByteArray): Implemented.

From-SVN: r31926
This commit is contained in:
Warren Levy 2000-02-11 19:09:03 +00:00 committed by Warren Levy
parent 9d381124d8
commit 136b5d77fc
2 changed files with 418 additions and 24 deletions

View File

@ -1,3 +1,21 @@
2000-02-04 Warren Levy <warrenl@cygnus.com>
* java/math/BigInteger.java(BigInteger(String, int)): New constructor.
(BigInteger(String)): New constructor.
(not): Rewritten using version from Kawa's BitOps class.
(valueOf): New private methods from Kawa's BitOps class.
(swappedOp): ditto.
(bitOp): ditto.
(setBitOp): ditto.
(and): Implemented.
(or): Implemented.
(xor): Implemented.
(andNot): Implemented.
(clearBit): Implemented.
(setBit): Implemented.
(bitCount): Implemented.
(toByteArray): Implemented.
2000-02-11 Tom Tromey <tromey@cygnus.com>
* java/io/File.java (nextValue): Now synchronized.

View File

@ -21,7 +21,7 @@ import java.util.Random;
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
*
* Based primarily on IntNum.java by Per Bothner <per@bothner.com>
* Based primarily on IntNum.java BitOps.java by Per Bothner <per@bothner.com>
* (found in Kawa 1.6.62).
*
* Status: Believed complete and correct.
@ -70,6 +70,18 @@ public class BigInteger extends Number implements Comparable
ival = value;
}
public BigInteger(String val, int radix)
{
BigInteger result = valueOf(val, radix);
this.ival = result.ival;
this.words = result.words;
}
public BigInteger(String val)
{
this(val, 10);
}
/* Create a new (non-shared) BigInteger, and initialize from a byte array. */
public BigInteger(byte[] val)
{
@ -184,7 +196,7 @@ public class BigInteger extends Number implements Comparable
word = (word << 8) | (((int) bytes[bptr]) & 0xff);
words[--nwords] = word;
// Elements remaining in byte[] is a multiple of 4.
// Elements remaining in byte[] are a multiple of 4.
while (nwords > 0)
words[--nwords] = bytes[bptr++] << 24 |
(((int) bytes[bptr++]) & 0xff) << 16 |
@ -339,13 +351,13 @@ public class BigInteger extends Number implements Comparable
return this;
}
/** Add two ints, yielding an BigInteger. */
/** Add two ints, yielding a BigInteger. */
private static final BigInteger add(int x, int y)
{
return BigInteger.make((long) x + (long) y);
}
/** Add an BigInteger and an int, yielding a new BigInteger. */
/** Add a BigInteger and an int, yielding a new BigInteger. */
private static BigInteger add(BigInteger x, int y)
{
if (x.words == null)
@ -1183,15 +1195,6 @@ public class BigInteger extends Number implements Comparable
}
}
public BigInteger not()
{
BigInteger result = new BigInteger();
result.ival = ival;
result.words = words;
result.setInvert();
return result;
}
private void setShiftLeft(BigInteger x, int count)
{
int[] xwords;
@ -1419,6 +1422,51 @@ public class BigInteger extends Number implements Comparable
return BigInteger.equals(this, (BigInteger) obj);
}
private static BigInteger valueOf(String s, int radix)
throws NumberFormatException
{
int len = s.length();
// Testing (len < MPN.chars_per_word(radix)) would be more accurate,
// but slightly more expensive, for little practical gain.
if (len <= 15 && radix <= 16)
return BigInteger.make(Long.parseLong(s, radix));
int byte_len = 0;
byte[] bytes = new byte[len];
boolean negative = false;
for (int i = 0; i < len; i++)
{
char ch = s.charAt(i);
if (ch == '-')
negative = true;
else if (ch == '_' || (byte_len == 0 && (ch == ' ' || ch == '\t')))
continue;
else
{
int digit = Character.digit(ch, radix);
if (digit < 0)
break;
bytes[byte_len++] = (byte) digit;
}
}
return valueOf(bytes, byte_len, negative, radix);
}
private static BigInteger valueOf(byte[] digits, int byte_len,
boolean negative, int radix)
{
int chars_per_word = MPN.chars_per_word(radix);
int[] words = new int[byte_len / chars_per_word + 1];
int size = MPN.set_str(words, digits, byte_len, radix);
if (size == 0)
return ZERO;
if (words[size-1] < 0)
words[size++] = 0;
if (negative)
negate(words, words, size);
return make(words, size);
}
public double doubleValue()
{
if (words == null)
@ -1632,21 +1680,307 @@ public class BigInteger extends Number implements Comparable
return MPN.intLength(words, ival);
}
/* TODO:
public byte[] toByteArray()
{
// Determine number of bytes needed. The method bitlength returns
// the size without the sign bit, so add one bit for that and then
// add 7 more to emulate the ceil function using integer math.
byte[] bytes = new byte[(bitLength() + 1 + 7) / 8];
int nbytes = bytes.length;
public BigInteger(String val, int radix)
int wptr = 0;
int word;
public BigInteger(String val)
// Deal with words array until one word or less is left to process.
// If BigInteger is an int, then it is in ival and nbytes will be <= 4.
while (nbytes > 4)
{
word = words[wptr++];
for (int i = 4; i > 0; --i, word >>= 8)
bytes[--nbytes] = (byte) word;
}
public BigInteger(int bitLength, int certainty, Random rnd)
// Deal with the last few bytes. If BigInteger is an int, use ival.
word = (words == null) ? ival : words[wptr];
for ( ; nbytes > 0; word >>= 8)
bytes[--nbytes] = (byte) word;
public BigInteger and(BigInteger val)
return bytes;
}
public BigInteger or(BigInteger val)
/** Return the boolean opcode (for bitOp) for swapped operands.
* I.e. bitOp(swappedOp(op), x, y) == bitOp(op, y, x).
*/
private static int swappedOp(int op)
{
return
"\000\001\004\005\002\003\006\007\010\011\014\015\012\013\016\017"
.charAt(op);
}
public BigInteger xor(BigInteger val
/** Do one the the 16 possible bit-wise operations of two BigIntegers. */
private static BigInteger bitOp(int op, BigInteger x, BigInteger y)
{
switch (op)
{
case 0: return ZERO;
case 1: return x.and(y);
case 3: return x;
case 5: return y;
case 15: return smallFixNums[-1 - minFixNum]; // Returns -1.
}
BigInteger result = new BigInteger();
setBitOp(result, op, x, y);
return result.canonicalize();
}
/** Do one the the 16 possible bit-wise operations of two BigIntegers. */
private static void setBitOp(BigInteger result, int op,
BigInteger x, BigInteger y)
{
if (y.words == null) ;
else if (x.words == null || x.ival < y.ival)
{
BigInteger temp = x; x = y; y = temp;
op = swappedOp(op);
}
int xi;
int yi;
int xlen, ylen;
if (y.words == null)
{
yi = y.ival;
ylen = 1;
}
else
{
yi = y.words[0];
ylen = y.ival;
}
if (x.words == null)
{
xi = x.ival;
xlen = 1;
}
else
{
xi = x.words[0];
xlen = x.ival;
}
if (xlen > 1)
result.realloc(xlen);
int[] w = result.words;
int i = 0;
// Code for how to handle the remainder of x.
// 0: Truncate to length of y.
// 1: Copy rest of x.
// 2: Invert rest of x.
int finish = 0;
int ni;
switch (op)
{
case 0: // clr
ni = 0;
break;
case 1: // and
for (;;)
{
ni = xi & yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi < 0) finish = 1;
break;
case 2: // andc2
for (;;)
{
ni = xi & ~yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi >= 0) finish = 1;
break;
case 3: // copy x
ni = xi;
finish = 1; // Copy rest
break;
case 4: // andc1
for (;;)
{
ni = ~xi & yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi < 0) finish = 2;
break;
case 5: // copy y
for (;;)
{
ni = yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
break;
case 6: // xor
for (;;)
{
ni = xi ^ yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
finish = yi < 0 ? 2 : 1;
break;
case 7: // ior
for (;;)
{
ni = xi | yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi >= 0) finish = 1;
break;
case 8: // nor
for (;;)
{
ni = ~(xi | yi);
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi >= 0) finish = 2;
break;
case 9: // eqv [exclusive nor]
for (;;)
{
ni = ~(xi ^ yi);
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
finish = yi >= 0 ? 2 : 1;
break;
case 10: // c2
for (;;)
{
ni = ~yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
break;
case 11: // orc2
for (;;)
{
ni = xi | ~yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi < 0) finish = 1;
break;
case 12: // c1
ni = ~xi;
finish = 2;
break;
case 13: // orc1
for (;;)
{
ni = ~xi | yi;
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi >= 0) finish = 2;
break;
case 14: // nand
for (;;)
{
ni = ~(xi & yi);
if (i+1 >= ylen) break;
w[i++] = ni; xi = x.words[i]; yi = y.words[i];
}
if (yi < 0) finish = 2;
break;
default:
case 15: // set
ni = -1;
break;
}
// Here i==ylen-1; w[0]..w[i-1] have the correct result;
// and ni contains the correct result for w[i+1].
if (i+1 == xlen)
finish = 0;
switch (finish)
{
case 0:
if (i == 0 && w == null)
{
result.ival = ni;
return;
}
w[i++] = ni;
break;
case 1: w[i] = ni; while (++i < xlen) w[i] = x.words[i]; break;
case 2: w[i] = ni; while (++i < xlen) w[i] = ~x.words[i]; break;
}
result.ival = i;
}
/** Return the logical (bit-wise) "and" of a BigInteger and an int. */
private static BigInteger and(BigInteger x, int y)
{
if (x.words == null)
return BigInteger.make(x.ival & y);
if (y >= 0)
return BigInteger.make(x.words[0] & y);
int len = x.ival;
int[] words = new int[len];
words[0] = x.words[0] & y;
while (--len > 0)
words[len] = x.words[len];
return BigInteger.make(words, x.ival);
}
/** Return the logical (bit-wise) "and" of two BigIntegers. */
public BigInteger and(BigInteger y)
{
if (y.words == null)
return and(this, y.ival);
else if (words == null)
return and(y, ival);
BigInteger x = this;
if (ival < y.ival)
{
BigInteger temp = this; x = y; y = temp;
}
int i;
int len = y.isNegative() ? x.ival : y.ival;
int[] words = new int[len];
for (i = 0; i < y.ival; i++)
words[i] = x.words[i] & y.words[i];
for ( ; i < len; i++)
words[i] = x.words[i];
return BigInteger.make(words, len);
}
/** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */
public BigInteger or(BigInteger y)
{
return bitOp(7, this, y);
}
/** Return the logical (bit-wise) "exclusive or" of two BigIntegers. */
public BigInteger xor(BigInteger y)
{
return bitOp(6, this, y);
}
/** Return the logical (bit-wise) negation of a BigInteger. */
public BigInteger not()
{
return bitOp(12, this, ZERO);
}
public BigInteger andNot(BigInteger val)
{
return and(val.not());
}
public BigInteger clearBit(int n)
{
@ -1664,20 +1998,62 @@ public class BigInteger extends Number implements Comparable
return or(ONE.shiftLeft(n));
}
// bit4count[I] is number of '1' bits in I.
private static final byte[] bit4_count = { 0, 1, 1, 2, 1, 2, 2, 3,
1, 2, 2, 3, 2, 3, 3, 4};
private static int bitCount(int i)
{
int count = 0;
while (i != 0)
{
count += bit4_count[i & 15];
i >>>= 4;
}
return count;
}
private static int bitCount(int[] x, int len)
{
int count = 0;
while (--len >= 0)
count += bitCount(x[len]);
return count;
}
/** Count one bits in a BigInteger.
* If argument is negative, count zero bits instead. */
public int bitCount()
{
int i, x_len;
int[] x_words = words;
if (x_words == null)
{
x_len = 1;
i = bitCount(ival);
}
else
{
x_len = ival;
i = bitCount(x_words, x_len);
}
return isNegative() ? x_len * 32 - i : i;
}
/* TODO:
public BigInteger(int bitLength, int certainty, Random rnd)
public boolean testBit(int n)
public BigInteger flipBit(int n)
public int getLowestSetBit()
public int bitCount()
public boolean isProbablePrime(int certainty)
public BigInteger min(BigInteger val)
public BigInteger max(BigInteger val)
public byte[] toByteArray()
*/
}