diff --git a/gwt/.classpath b/gwt/.classpath
new file mode 100644
index 0000000..1d11b4c
--- /dev/null
+++ b/gwt/.classpath
@@ -0,0 +1,21 @@
+
+BufferedInputStream
is a class which takes an input stream and
+ * buffers the input. In this way, costly interaction with the
+ * original input stream can be minimized by reading buffered amounts of data
+ * infrequently. The drawback is that extra space is required to hold the buffer
+ * and that copying takes place when reading that buffer.
+ *
+ * @see BufferedOutputStream
+ */
+public class BufferedInputStream extends FilterInputStream {
+ /**
+ * The buffer containing the current bytes read from the target InputStream.
+ */
+ protected byte[] buf;
+
+ /**
+ * The total number of bytes inside the byte array buf
.
+ */
+ protected int count;
+
+ /**
+ * The current limit, which when passed, invalidates the current mark.
+ */
+ protected int marklimit;
+
+ /**
+ * The currently marked position. -1 indicates no mark has been set or the
+ * mark has been invalidated.
+ */
+ protected int markpos = -1;
+
+ /**
+ * The current position within the byte array buf
.
+ */
+ protected int pos;
+
+ private boolean closed = false;
+
+ /**
+ * Constructs a new BufferedInputStream
on the InputStream
+ * in
. The default buffer size (8Kb) is allocated and all
+ * reads can now be filtered through this stream.
+ *
+ * @param in
+ * the InputStream to buffer reads on.
+ */
+ public BufferedInputStream(InputStream in) {
+ super(in);
+ buf = new byte[8192];
+ }
+
+ /**
+ * Constructs a new BufferedInputStream on the InputStream in
.
+ * The buffer size is specified by the parameter size
and all
+ * reads can now be filtered through this BufferedInputStream.
+ *
+ * @param in
+ * the InputStream to buffer reads on.
+ * @param size
+ * the size of buffer to allocate.
+ */
+ public BufferedInputStream(InputStream in, int size) {
+ super(in);
+ if (size <= 0) {
+ // K0058=size must be > 0
+ throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
+ }
+ buf = new byte[size];
+ }
+
+ /**
+ * Answers an int representing the number of bytes that are available before
+ * this BufferedInputStream will block. This method returns the number of
+ * bytes available in the buffer plus those available in the target stream.
+ *
+ * @return the number of bytes available before blocking.
+ *
+ * @throws IOException
+ * If an error occurs in this stream.
+ */
+ @Override
+ public synchronized int available() throws IOException {
+ if (buf == null) {
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+ return count - pos + in.available();
+ }
+
+ /**
+ * Close this BufferedInputStream. This implementation closes the target
+ * stream and releases any resources associated with it.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this stream.
+ */
+ @Override
+ public synchronized void close() throws IOException {
+ if (null != in) {
+ super.close();
+ in = null;
+ }
+ buf = null;
+ closed = true;
+ }
+
+ private int fillbuf() throws IOException {
+ if (markpos == -1 || (pos - markpos >= marklimit)) {
+ /* Mark position not set or exceeded readlimit */
+ int result = in.read(buf);
+ if (result > 0) {
+ markpos = -1;
+ pos = 0;
+ count = result == -1 ? 0 : result;
+ }
+ return result;
+ }
+ if (markpos == 0 && marklimit > buf.length) {
+ /* Increase buffer size to accomodate the readlimit */
+ int newLength = buf.length * 2;
+ if (newLength > marklimit) {
+ newLength = marklimit;
+ }
+ byte[] newbuf = new byte[newLength];
+ System.arraycopy(buf, 0, newbuf, 0, buf.length);
+ buf = newbuf;
+ } else if (markpos > 0) {
+ System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+ }
+ /* Set the new position and mark position */
+ pos -= markpos;
+ count = markpos = 0;
+ int bytesread = in.read(buf, pos, buf.length - pos);
+ count = bytesread <= 0 ? pos : pos + bytesread;
+ return bytesread;
+ }
+
+ /**
+ * Set a Mark position in this BufferedInputStream. The parameter
+ * readLimit
indicates how many bytes can be read before a
+ * mark is invalidated. Sending reset() will reposition the Stream back to
+ * the marked position provided readLimit
has not been
+ * surpassed. The underlying buffer may be increased in size to allow
+ * readlimit
number of bytes to be supported.
+ *
+ * @param readlimit
+ * the number of bytes to be able to read before invalidating the
+ * mark.
+ */
+ @Override
+ public synchronized void mark(int readlimit) {
+ marklimit = readlimit;
+ markpos = pos;
+ }
+
+ /**
+ * Answers a boolean indicating whether or not this BufferedInputStream
+ * supports mark() and reset(). This implementation answers
+ * true
.
+ *
+ * @return true
for BufferedInputStreams.
+ */
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ /**
+ * Reads a single byte from this BufferedInputStream and returns the result
+ * as an int. The low-order byte is returned or -1 of the end of stream was
+ * encountered. If the underlying buffer does not contain any available
+ * bytes then it is filled and the first byte is returned.
+ *
+ * @return the byte read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public synchronized int read() throws IOException {
+ if (in == null) {
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+
+ /* Are there buffered bytes available? */
+ if (pos >= count && fillbuf() == -1) {
+ return -1; /* no, fill buffer */
+ }
+
+ /* Did filling the buffer fail with -1 (EOF)? */
+ if (count - pos > 0) {
+ return buf[pos++] & 0xFF;
+ }
+ return -1;
+ }
+
+ /**
+ * Reads at most length
bytes from this BufferedInputStream
+ * and stores them in byte array buffer
starting at offset
+ * offset
. Answer the number of bytes actually read or -1 if
+ * no bytes were read and end of stream was encountered. If all the buffered
+ * bytes have been used, a mark has not been set, and the requested number
+ * of bytes is larger than the receiver's buffer size, this implementation
+ * bypasses the buffer and simply places the results directly into
+ * buffer
.
+ *
+ * @param buffer
+ * the byte array in which to store the read bytes.
+ * @param offset
+ * the offset in buffer
to store the read bytes.
+ * @param length
+ * the maximum number of bytes to store in buffer
.
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public synchronized int read(byte[] buffer, int offset, int length)
+ throws IOException {
+ if (closed) {
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+ // avoid int overflow
+ if (offset > buffer.length - length || offset < 0 || length < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (length == 0) {
+ return 0;
+ }
+ if (null == buf) {
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+
+ int required;
+ if (pos < count) {
+ /* There are bytes available in the buffer. */
+ int copylength = count - pos >= length ? length : count - pos;
+ System.arraycopy(buf, pos, buffer, offset, copylength);
+ pos += copylength;
+ if (copylength == length || in.available() == 0) {
+ return copylength;
+ }
+ offset += copylength;
+ required = length - copylength;
+ } else {
+ required = length;
+ }
+
+ while (true) {
+ int read;
+ /*
+ * If we're not marked and the required size is greater than the
+ * buffer, simply read the bytes directly bypassing the buffer.
+ */
+ if (markpos == -1 && required >= buf.length) {
+ read = in.read(buffer, offset, required);
+ if (read == -1) {
+ return required == length ? -1 : length - required;
+ }
+ } else {
+ if (fillbuf() == -1) {
+ return required == length ? -1 : length - required;
+ }
+ read = count - pos >= required ? required : count - pos;
+ System.arraycopy(buf, pos, buffer, offset, read);
+ pos += read;
+ }
+ required -= read;
+ if (required == 0) {
+ return length;
+ }
+ if (in.available() == 0) {
+ return length - required;
+ }
+ offset += read;
+ }
+ }
+
+ /**
+ * Reset this BufferedInputStream to the last marked location. If the
+ * readlimit
has been passed or no mark
has
+ * been set, throw IOException. This implementation resets the target
+ * stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+
+ @Override
+ public synchronized void reset() throws IOException {
+ if (closed) {
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+ if (-1 == markpos) {
+ // K005a=Mark has been invalidated.
+ throw new IOException(Msg.getString("K005a")); //$NON-NLS-1$
+ }
+ pos = markpos;
+ }
+
+ /**
+ * Skips amount
number of bytes in this BufferedInputStream.
+ * Subsequent read()
's will not return these bytes unless
+ * reset()
is used.
+ *
+ * @param amount
+ * the number of bytes to skip.
+ * @return the number of bytes actually skipped.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public synchronized long skip(long amount) throws IOException {
+ if (null == in) {
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+ if (amount < 1) {
+ return 0;
+ }
+
+ if (count - pos >= amount) {
+ pos += amount;
+ return amount;
+ }
+ long read = count - pos;
+ pos = count;
+
+ if (markpos != -1) {
+ if (amount <= marklimit) {
+ if (fillbuf() == -1) {
+ return read;
+ }
+ if (count - pos >= amount - read) {
+ pos += amount - read;
+ return amount;
+ }
+ // Couldn't get all the bytes, skip what we read
+ read += (count - pos);
+ pos = count;
+ return read;
+ }
+ markpos = -1;
+ }
+ return read + in.skip(amount - read);
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/BufferedReader.java b/gwt/jre/java/io/BufferedReader.java
new file mode 100644
index 0000000..7fb1152
--- /dev/null
+++ b/gwt/jre/java/io/BufferedReader.java
@@ -0,0 +1,485 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * BufferedReader is a buffered character input reader. Buffering allows reading
+ * from character streams more efficiently. If the default size of the buffer is
+ * not practical, another size may be specified. Reading a character from a
+ * Reader class usually involves reading a character from its Stream or
+ * subsequent Reader. It is advisable to wrap a BufferedReader around those
+ * Readers whose read operations may have high latency. For example, the
+ * following code
+ *
+ *
+ * BufferedReader inReader = new BufferedReader(new FileReader("file.java")); + *+ * + * will buffer input for the file
file.java
.
+ *
+ * @see BufferedWriter
+ * @since 1.1
+ */
+public class BufferedReader extends Reader {
+
+ private Reader in;
+
+ private char[] buf;
+
+ private int marklimit = -1;
+
+ private int count;
+
+ private int markpos = -1;
+
+ private int pos;
+
+ /**
+ * Constructs a new BufferedReader on the Reader in
. The
+ * default buffer size (8K) is allocated and all reads can now be filtered
+ * through this BufferedReader.
+ *
+ * @param in
+ * the Reader to buffer reads on.
+ */
+ public BufferedReader(Reader in) {
+ super(in);
+ this.in = in;
+ buf = new char[8192];
+ }
+
+ /**
+ * Constructs a new BufferedReader on the Reader in
. The
+ * buffer size is specified by the parameter size
and all
+ * reads can now be filtered through this BufferedReader.
+ *
+ * @param in
+ * the Reader to buffer reads on.
+ * @param size
+ * the size of buffer to allocate.
+ * @throws IllegalArgumentException
+ * if the size is <= 0
+ */
+ public BufferedReader(Reader in, int size) {
+ super(in);
+ if (size <= 0) {
+ throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
+ }
+ this.in = in;
+ buf = new char[size];
+ }
+
+ /**
+ * Close the Reader. This implementation closes the Reader being filtered
+ * and releases the buffer used by this reader. If this BufferedReader has
+ * already been closed, nothing is done.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this BufferedReader.
+ */
+ @Override
+ public void close() throws IOException {
+ synchronized (lock) {
+ if (!isClosed()) {
+ in.close();
+ buf = null;
+ }
+ }
+ }
+
+ private int fillbuf() throws IOException {
+ if (markpos == -1 || (pos - markpos >= marklimit)) {
+ /* Mark position not set or exceeded readlimit */
+ int result = in.read(buf, 0, buf.length);
+ if (result > 0) {
+ markpos = -1;
+ pos = 0;
+ count = result == -1 ? 0 : result;
+ }
+ return result;
+ }
+ if (markpos == 0 && marklimit > buf.length) {
+ /* Increase buffer size to accommodate the readlimit */
+ int newLength = buf.length * 2;
+ if (newLength > marklimit) {
+ newLength = marklimit;
+ }
+ char[] newbuf = new char[newLength];
+ System.arraycopy(buf, 0, newbuf, 0, buf.length);
+ buf = newbuf;
+ } else if (markpos > 0) {
+ System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+ }
+
+ /* Set the new position and mark position */
+ pos -= markpos;
+ count = markpos = 0;
+ int charsread = in.read(buf, pos, buf.length - pos);
+ count = charsread == -1 ? pos : pos + charsread;
+ return charsread;
+ }
+
+ /**
+ * Answer a boolean indicating whether or not this BufferedReader is closed.
+ *
+ * @return true
if this reader is closed, false
+ * otherwise
+ */
+ private boolean isClosed() {
+ return buf == null;
+ }
+
+ /**
+ * Set a Mark position in this BufferedReader. The parameter
+ * readLimit
indicates how many characters can be read before
+ * a mark is invalidated. Sending reset() will reposition the reader back to
+ * the marked position provided readLimit
has not been
+ * surpassed.
+ *
+ * @param readlimit
+ * an int representing how many characters must be read before
+ * invalidating the mark.
+ *
+ * @throws IOException
+ * If an error occurs attempting mark this BufferedReader.
+ * @throws IllegalArgumentException
+ * If readlimit is < 0
+ */
+ @Override
+ public void mark(int readlimit) throws IOException {
+ if (readlimit < 0) {
+ throw new IllegalArgumentException();
+ }
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ marklimit = readlimit;
+ markpos = pos;
+ }
+ }
+
+ /**
+ * Answers a boolean indicating whether or not this Reader supports mark()
+ * and reset(). This implementation answers true
.
+ *
+ * @return true
if mark() and reset() are supported,
+ * false
otherwise
+ */
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ /**
+ * Reads a single character from this reader and returns the result as an
+ * int. The 2 higher-order characters are set to 0. If the end of reader was
+ * encountered then return -1. This implementation either returns a
+ * character from the buffer or if there are no characters available, fill
+ * the buffer then return a character or -1.
+ *
+ * @return the character read or -1 if end of reader.
+ *
+ * @throws IOException
+ * If the BufferedReader is already closed or some other IO
+ * error occurs.
+ */
+ @Override
+ public int read() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ /* Are there buffered characters available? */
+ if (pos < count || fillbuf() != -1) {
+ return buf[pos++];
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Reads at most length
characters from this BufferedReader
+ * and stores them at offset
in the character array
+ * buffer
. Returns the number of characters actually read or
+ * -1 if the end of reader was encountered. If all the buffered characters
+ * have been used, a mark has not been set, and the requested number of
+ * characters is larger than this Readers buffer size, this implementation
+ * bypasses the buffer and simply places the results directly into
+ * buffer
.
+ *
+ * @param buffer
+ * character array to store the read characters
+ * @param offset
+ * offset in buf to store the read characters
+ * @param length
+ * maximum number of characters to read
+ * @return number of characters read or -1 if end of reader.
+ *
+ * @throws IOException
+ * If the BufferedReader is already closed or some other IO
+ * error occurs.
+ */
+ @Override
+ public int read(char[] buffer, int offset, int length) throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ if (offset < 0 || offset > buffer.length - length || length < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (length == 0) {
+ return 0;
+ }
+ int required;
+ if (pos < count) {
+ /* There are bytes available in the buffer. */
+ int copylength = count - pos >= length ? length : count - pos;
+ System.arraycopy(buf, pos, buffer, offset, copylength);
+ pos += copylength;
+ if (copylength == length || !in.ready()) {
+ return copylength;
+ }
+ offset += copylength;
+ required = length - copylength;
+ } else {
+ required = length;
+ }
+
+ while (true) {
+ int read;
+ /*
+ * If we're not marked and the required size is greater than the
+ * buffer, simply read the bytes directly bypassing the buffer.
+ */
+ if (markpos == -1 && required >= buf.length) {
+ read = in.read(buffer, offset, required);
+ if (read == -1) {
+ return required == length ? -1 : length - required;
+ }
+ } else {
+ if (fillbuf() == -1) {
+ return required == length ? -1 : length - required;
+ }
+ read = count - pos >= required ? required : count - pos;
+ System.arraycopy(buf, pos, buffer, offset, read);
+ pos += read;
+ }
+ required -= read;
+ if (required == 0) {
+ return length;
+ }
+ if (!in.ready()) {
+ return length - required;
+ }
+ offset += read;
+ }
+ }
+ }
+
+ /**
+ * Answers a String
representing the next line of text
+ * available in this BufferedReader. A line is represented by 0 or more
+ * characters followed by '\n'
, '\r'
,
+ * '\r\n'
or end of stream. The String
does
+ * not include the newline sequence.
+ *
+ * @return the contents of the line or null if no characters were read
+ * before end of stream.
+ *
+ * @throws IOException
+ * If the BufferedReader is already closed or some other IO
+ * error occurs.
+ */
+ public String readLine() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ /* Are there buffered characters available? */
+ if ((pos >= count) && (fillbuf() == -1)) {
+ return null;
+ }
+ for (int charPos = pos; charPos < count; charPos++) {
+ char ch = buf[charPos];
+ if (ch > '\r') {
+ continue;
+ }
+ if (ch == '\n') {
+ String res = new String(buf, pos, charPos - pos);
+ pos = charPos + 1;
+ return res;
+ } else if (ch == '\r') {
+ String res = new String(buf, pos, charPos - pos);
+ pos = charPos + 1;
+ if (((pos < count) || (fillbuf() != -1))
+ && (buf[pos] == '\n')) {
+ pos++;
+ }
+ return res;
+ }
+ }
+
+ char eol = '\0';
+ StringBuilder result = new StringBuilder(80);
+ /* Typical Line Length */
+
+ result.append(buf, pos, count - pos);
+ pos = count;
+ while (true) {
+ /* Are there buffered characters available? */
+ if (pos >= count) {
+ if (eol == '\n') {
+ return result.toString();
+ }
+ // attempt to fill buffer
+ if (fillbuf() == -1) {
+ // characters or null.
+ return result.length() > 0 || eol != '\0' ? result
+ .toString() : null;
+ }
+ }
+ for (int charPos = pos; charPos < count; charPos++) {
+ if (eol == '\0') {
+ if ((buf[charPos] == '\n' || buf[charPos] == '\r')) {
+ eol = buf[charPos];
+ }
+ } else if (eol == '\r' && (buf[charPos] == '\n')) {
+ if (charPos > pos) {
+ result.append(buf, pos, charPos - pos - 1);
+ }
+ pos = charPos + 1;
+ return result.toString();
+ } else if (eol != '\0') {
+ if (charPos > pos) {
+ result.append(buf, pos, charPos - pos - 1);
+ }
+ pos = charPos;
+ return result.toString();
+ }
+ }
+ if (eol == '\0') {
+ result.append(buf, pos, count - pos);
+ } else {
+ result.append(buf, pos, count - pos - 1);
+ }
+ pos = count;
+ }
+ }
+
+ }
+
+ /**
+ * Answers a boolean
indicating whether or not this Reader is
+ * ready to be read without blocking. If the result is true
,
+ * the next read()
will not block. If the result is
+ * false
this Reader may or may not block when
+ * read()
is sent.
+ *
+ * @return true
if the receiver will not block when
+ * read()
is called, false
if unknown
+ * or blocking will occur.
+ *
+ * @throws IOException
+ * If the BufferedReader is already closed or some other IO
+ * error occurs.
+ */
+ @Override
+ public boolean ready() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ return ((count - pos) > 0) || in.ready();
+ }
+ }
+
+ /**
+ * Reset this BufferedReader's position to the last mark()
+ * location. Invocations of read()/skip()
will occur from
+ * this new location. If this Reader was not marked, throw IOException.
+ *
+ * @throws IOException
+ * If a problem occurred, the receiver does not support
+ * mark()/reset()
, or no mark has been set.
+ */
+ @Override
+ public void reset() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ if (markpos == -1) {
+ throw new IOException(Msg.getString("K005c")); //$NON-NLS-1$
+ }
+ pos = markpos;
+ }
+ }
+
+ /**
+ * Skips amount
number of characters in this Reader.
+ * Subsequent read()
's will not return these characters
+ * unless reset()
is used. Skipping characters may invalidate
+ * a mark if marklimit is surpassed.
+ *
+ * @param amount
+ * the maximum number of characters to skip.
+ * @return the number of characters actually skipped.
+ *
+ * @throws IOException
+ * If the BufferedReader is already closed or some other IO
+ * error occurs.
+ * @throws IllegalArgumentException
+ * If amount is negative
+ */
+ @Override
+ public long skip(long amount) throws IOException {
+ if (amount < 0) {
+ throw new IllegalArgumentException();
+ }
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
+ }
+ if (amount < 1) {
+ return 0;
+ }
+ if (count - pos >= amount) {
+ pos += amount;
+ return amount;
+ }
+
+ long read = count - pos;
+ pos = count;
+ while (read < amount) {
+ if (fillbuf() == -1) {
+ return read;
+ }
+ if (count - pos >= amount - read) {
+ pos += amount - read;
+ return amount;
+ }
+ // Couldn't get all the characters, skip what we read
+ read += (count - pos);
+ pos = count;
+ }
+ return amount;
+ }
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/ByteArrayInputStream.java b/gwt/jre/java/io/ByteArrayInputStream.java
new file mode 100644
index 0000000..2b749b4
--- /dev/null
+++ b/gwt/jre/java/io/ByteArrayInputStream.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package java.io;
+
+public class ByteArrayInputStream extends InputStream {
+
+ protected byte[] buf;
+ protected int pos = 0;
+ protected int start = 0;
+ protected int mark = 0;
+ protected int count;
+
+ public ByteArrayInputStream(byte[] data) {
+ this.buf = data;
+ this.count = data.length;
+ }
+
+ public ByteArrayInputStream(byte[] data, int offset, int len) {
+ this.buf = data;
+ count = offset + len;
+ this.mark = this.start = this.pos = offset;
+ }
+
+ @Override
+ public int read() {
+ return pos < count ? (buf[pos++] & 0xFF) : -1;
+ }
+
+ @Override
+ public int available() {
+ return count - pos;
+ }
+
+ @Override
+ public long skip(long n) throws IOException, IllegalArgumentException {
+ // TODO Auto-generated method stub
+ pos += n;
+ return pos;
+ }
+
+ @Override
+ public void reset() throws IOException {
+ pos = mark;
+ }
+
+ @Override
+ public void mark(int readAheadLimit) {
+ mark = pos;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+}
diff --git a/gwt/jre/java/io/ByteArrayOutputStream.java b/gwt/jre/java/io/ByteArrayOutputStream.java
new file mode 100644
index 0000000..9a668a4
--- /dev/null
+++ b/gwt/jre/java/io/ByteArrayOutputStream.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package java.io;
+
+import core.util.Arrays;
+
+public class ByteArrayOutputStream extends OutputStream {
+
+ protected int count = 0;
+ protected byte[] buf;
+
+ public ByteArrayOutputStream() {
+ this(16);
+ }
+
+ public ByteArrayOutputStream(int initialSize) {
+ buf = new byte[initialSize];
+ }
+
+ public void write(int b) {
+ if (buf.length == count) {
+ byte[] newBuf = new byte[buf.length * 3 / 2];
+ Arrays.copyFromTo(buf, 0, newBuf, 0, count);
+ buf = newBuf;
+ }
+
+ buf[count++] = (byte)b;
+ }
+
+ public void write(byte[] ba, int start, int len) {
+ int end = start + len;
+ for (int i = start; i < end; i++) {
+ write(ba[i]);
+ }
+ }
+
+ public void write(byte[] ba)
+ {
+ write(ba,0, ba.length);
+ }
+
+ public byte[] toByteArray() {
+ return Arrays.copyOf(buf,count);
+ }
+
+
+ public int size() {
+ return count;
+ }
+
+ public void reset () {
+ count = 0;
+ }
+}
diff --git a/gwt/jre/java/io/DataInputStream.java b/gwt/jre/java/io/DataInputStream.java
new file mode 100644
index 0000000..5f1acb7
--- /dev/null
+++ b/gwt/jre/java/io/DataInputStream.java
@@ -0,0 +1,79 @@
+package java.io;
+
+public class DataInputStream extends FilterInputStream
+{
+ public DataInputStream(InputStream in)
+ {
+ super(in);
+ }
+
+
+ /**
+ * Reads bytes from the source stream into the byte array
+ * buffer
. The number of bytes actually read is returned.
+ *
+ * @param buffer
+ * the buffer to read bytes into
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If a problem occurs reading from this DataInputStream.
+ *
+ * @see DataOutput#write(byte[])
+ * @see DataOutput#write(byte[], int, int)
+ */
+ @Override
+ public final int read(byte[] buffer) throws IOException {
+ return in.read(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Reads a 32-bit integer value from this stream.
+ *
+ * @return the next int
value from the source stream.
+ *
+ * @throws IOException
+ * If a problem occurs reading from this DataInputStream.
+ *
+ * @see DataOutput#writeInt(int)
+ */
+ public final int readInt() throws IOException {
+ int b1 = in.read();
+ int b2 = in.read();
+ int b3 = in.read();
+ int b4 = in.read();
+
+ if ((b1 | b2 | b3 | b4) < 0) {
+ throw new EOFException();
+ }
+
+ return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
+ }
+
+ /**
+ * Read at most length
bytes from this DataInputStream and
+ * stores them in byte array buffer
starting at
+ * offset
. Answer the number of bytes actually read or -1 if
+ * no bytes were read and end of stream was encountered.
+ *
+ * @param buffer
+ * the byte array in which to store the read bytes.
+ * @param offset
+ * the offset in buffer
to store the read bytes.
+ * @param length
+ * the maximum number of bytes to store in buffer
.
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If a problem occurs reading from this DataInputStream.
+ *
+ * @see DataOutput#write(byte[])
+ * @see DataOutput#write(byte[], int, int)
+ */
+ @Override
+ public final int read(byte[] buffer, int offset, int length)
+ throws IOException {
+ return in.read(buffer, offset, length);
+ }
+
+}
diff --git a/gwt/jre/java/io/DataOutputStream.java b/gwt/jre/java/io/DataOutputStream.java
new file mode 100644
index 0000000..97c54e3
--- /dev/null
+++ b/gwt/jre/java/io/DataOutputStream.java
@@ -0,0 +1,49 @@
+package java.io;
+
+public class DataOutputStream extends FilterOutputStream {
+
+ protected int written;
+
+ public DataOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ public void close() throws IOException
+ {
+ super.close();
+ }
+
+ public void write(byte buffer[], int offset, int count) throws IOException {
+ if (buffer == null) {
+ throw new NullPointerException(); //$NON-NLS-1$
+ }
+ out.write(buffer, offset, count);
+ written += count;
+ }
+
+ public void write(byte buffer[]) throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Writes a 32-bit int to this output stream. The resulting output is the 4
+ * bytes, highest order first, of val.
+ *
+ * @param val
+ * the int to be written.
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this
+ * DataOutputStream.
+ *
+ * @see DataInput#readInt()
+ */
+ public final void writeInt(int val) throws IOException {
+ out.write((byte)(val >> 24));
+ out.write((byte)(val >> 16));
+ out.write((byte)(val >> 8));
+ out.write((byte)(val));
+ written += 4;
+ }
+}
diff --git a/gwt/jre/java/io/EOFException.java b/gwt/jre/java/io/EOFException.java
new file mode 100644
index 0000000..ccd3004
--- /dev/null
+++ b/gwt/jre/java/io/EOFException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * This End Of File (EOF) exception is thrown when a program encounters the end
+ * of a file or stream during an operation.
+ */
+public class EOFException extends IOException {
+
+ private static final long serialVersionUID = 6433858223774886977L;
+
+ /**
+ * Constructs a new instance of this class with its walkback filled in.
+ *
+ */
+ public EOFException() {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of this class with its walkback and message
+ * filled in.
+ *
+ * @param detailMessage
+ * The detail message for the exception.
+ */
+ public EOFException(String detailMessage) {
+ super(detailMessage);
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/FilterInputStream.java b/gwt/jre/java/io/FilterInputStream.java
new file mode 100644
index 0000000..30dfd25
--- /dev/null
+++ b/gwt/jre/java/io/FilterInputStream.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * FilteredInputStream is a class which takes an input stream and
+ * filters the input in some way. The filtered view may be a buffered
+ * view or one which uncompresses data before returning bytes read.
+ * FilterInputStreams are meant for byte streams.
+ *
+ * @see FilterOutputStream
+ */
+public class FilterInputStream extends InputStream {
+
+ /**
+ * The target InputStream which is being filtered.
+ */
+ protected InputStream in;
+
+ /**
+ * Constructs a new FilterInputStream on the InputStream in
.
+ * All reads are now filtered through this stream.
+ *
+ * @param in
+ * The non-null InputStream to filter reads on.
+ */
+ protected FilterInputStream(InputStream in) {
+ super();
+ this.in = in;
+ }
+
+ /**
+ * Answers a int representing the number of bytes that are available before
+ * this FilterInputStream will block. This method returns the number of
+ * bytes available in the target stream.
+ *
+ * @return the number of bytes available before blocking.
+ *
+ * @throws IOException
+ * If an error occurs in this stream.
+ */
+ @Override
+ public int available() throws IOException {
+ return in.available();
+ }
+
+ /**
+ * Close this FilterInputStream. This implementation closes the target
+ * stream.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this stream.
+ */
+ @Override
+ public void close() throws IOException {
+ in.close();
+ }
+
+ /**
+ * Set a Mark position in this FilterInputStream. The parameter
+ * readLimit
indicates how many bytes can be read before a
+ * mark is invalidated. Sending reset() will reposition the Stream back to
+ * the marked position provided readLimit
has not been
+ * surpassed.
+ *
+ * This implementation sets a mark in the target stream.
+ *
+ * @param readlimit
+ * the number of bytes to be able to read before invalidating the
+ * mark.
+ */
+ @Override
+ public synchronized void mark(int readlimit) {
+ in.mark(readlimit);
+ }
+
+ /**
+ * Answers a boolean indicating whether or not this FilterInputStream
+ * supports mark() and reset(). This implementation answers whether or not
+ * the target stream supports marking.
+ *
+ * @return true
if mark() and reset() are supported,
+ * false
otherwise.
+ */
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+
+ /**
+ * Reads a single byte from this FilterInputStream and returns the result as
+ * an int. The low-order byte is returned or -1 of the end of stream was
+ * encountered. This implementation returns a byte from the target stream.
+ *
+ * @return the byte read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public int read() throws IOException {
+ return in.read();
+ }
+
+ /**
+ * Reads bytes from this FilterInputStream and stores them in byte array
+ * buffer
. Answer the number of bytes actually read or -1 if
+ * no bytes were read and end of stream was encountered. This implementation
+ * reads bytes from the target stream.
+ *
+ * @param buffer
+ * the byte array in which to store the read bytes.
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public int read(byte[] buffer) throws IOException {
+ return read(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Reads at most count
bytes from this FilterInputStream and
+ * stores them in byte array buffer
starting at
+ * offset
. Answer the number of bytes actually read or -1 if
+ * no bytes were read and end of stream was encountered. This implementation
+ * reads bytes from the target stream.
+ *
+ * @param buffer
+ * the byte array in which to store the read bytes.
+ * @param offset
+ * the offset in buffer
to store the read bytes.
+ * @param count
+ * the maximum number of bytes to store in buffer
.
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public int read(byte[] buffer, int offset, int count) throws IOException {
+ return in.read(buffer, offset, count);
+ }
+
+ /**
+ * Reset this FilterInputStream to the last marked location. If the
+ * readlimit
has been passed or no mark
has
+ * been set, throw IOException. This implementation resets the target
+ * stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public synchronized void reset() throws IOException {
+ in.reset();
+ }
+
+ /**
+ * Skips count
number of bytes in this InputStream.
+ * Subsequent read()
's will not return these bytes unless
+ * reset()
is used. This implementation skips
+ * count
number of bytes in the target stream.
+ *
+ * @param count
+ * the number of bytes to skip.
+ * @return the number of bytes actually skipped.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public long skip(long count) throws IOException {
+ return in.skip(count);
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/FilterOutputStream.java b/gwt/jre/java/io/FilterOutputStream.java
new file mode 100644
index 0000000..4cf9a1d
--- /dev/null
+++ b/gwt/jre/java/io/FilterOutputStream.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * FilteredOutputStream is a class which takes an output stream and
+ * filters the output in some way. The filtered view may be a
+ * buffered output or one which compresses data before actually writing the
+ * bytes. FilterOutputStreams are meant for byte streams.
+ *
+ * @see FilterInputStream
+ */
+public class FilterOutputStream extends OutputStream {
+
+ /**
+ * The target OutputStream for this filter.
+ */
+ protected OutputStream out;
+
+ /**
+ * Constructs a new FilterOutputStream on the OutputStream out
.
+ * All writes are now filtered through this stream.
+ *
+ * @param out
+ * the target OutputStream to filter writes on.
+ */
+ public FilterOutputStream(OutputStream out) {
+ this.out = out;
+ }
+
+ /**
+ * Close this FilterOutputStream. This implementation closes the target
+ * stream.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this stream.
+ */
+ @Override
+ public void close() throws IOException {
+ try {
+ flush();
+ } catch (IOException e) {
+ // Ignored
+ }
+ /* Make sure we clean up this stream if exception fires */
+ out.close();
+ }
+
+ /**
+ * Flush this FilterOutputStream to ensure all pending data is sent out to
+ * the target OutputStream. This implementation flushes the target
+ * OutputStream.
+ *
+ * @throws IOException
+ * If an error occurs attempting to flush this
+ * FilterOutputStream.
+ */
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ /**
+ * Writes the entire contents of the byte array buffer
to
+ * this FilterOutputStream. This implementation writes the
+ * buffer
to the target stream.
+ *
+ * @param buffer
+ * the buffer to be written
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this
+ * FilterOutputStream.
+ */
+ @Override
+ public void write(byte buffer[]) throws IOException {
+ write(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Writes count
bytes
from the byte array
+ * buffer
starting at offset
to this
+ * FilterOutputStream. This implementation writes the buffer
+ * to the target OutputStream.
+ *
+ * @param buffer
+ * the buffer to be written
+ * @param offset
+ * offset in buffer to get bytes
+ * @param count
+ * number of bytes in buffer to write
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this
+ * FilterOutputStream.
+ * @throws IndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+ @Override
+ public void write(byte buffer[], int offset, int count) throws IOException {
+ // avoid int overflow, force null buffer check first
+ if (offset > buffer.length || offset < 0 || count < 0
+ || count > buffer.length - offset) {
+ throw new ArrayIndexOutOfBoundsException(); //$NON-NLS-1$
+ }
+ for (int i = 0; i < count; i++) {
+ // Call write() instead of out.write() since subclasses could
+ // override the write() method.
+ write(buffer[offset + i]);
+ }
+ }
+
+ /**
+ * Writes the specified byte oneByte
to this
+ * FilterOutputStream. Only the low order byte of oneByte
is
+ * written. This implementation writes the byte to the target OutputStream.
+ *
+ * @param oneByte
+ * the byte to be written
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this
+ * FilterOutputStream.
+ */
+ @Override
+ public void write(int oneByte) throws IOException {
+ out.write(oneByte);
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/IOException.java b/gwt/jre/java/io/IOException.java
new file mode 100644
index 0000000..46a66ee
--- /dev/null
+++ b/gwt/jre/java/io/IOException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package java.io;
+
+public class IOException extends Exception {
+
+ public IOException() {
+ super();
+ }
+
+ public IOException(String s) {
+ super(s);
+ }
+
+ public IOException(Exception e) {
+ super(e);
+ }
+}
diff --git a/gwt/jre/java/io/InputStream.java b/gwt/jre/java/io/InputStream.java
new file mode 100644
index 0000000..446a013
--- /dev/null
+++ b/gwt/jre/java/io/InputStream.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package java.io;
+
+public abstract class InputStream {
+ public abstract int read() throws IOException;
+
+ public int read(byte[]buf, int start, int len) throws IOException {
+
+ int end = start + len;
+ for (int i = start; i < end; i++) {
+ int r = read();
+ if (r == -1) {
+ return i == start ? -1 : i - start;
+ }
+ buf[i] = (byte) r;
+ }
+ return len;
+ }
+
+ public int read(byte[] buf) throws IOException {
+ return read(buf, 0, buf.length);
+ }
+
+ public void close() throws IOException {
+
+ }
+
+ public int available() throws IOException
+ {
+ return 0;
+ }
+
+ public void mark(int readAheadLimit){
+ }
+
+ public boolean markSupported() {
+ return false;
+ }
+
+ public long skip(long n) throws IOException, IllegalArgumentException { return 0; }
+
+ public void reset() throws IOException {}
+}
diff --git a/gwt/jre/java/io/InputStreamReader.java b/gwt/jre/java/io/InputStreamReader.java
new file mode 100644
index 0000000..99f406c
--- /dev/null
+++ b/gwt/jre/java/io/InputStreamReader.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+import core.util.Streams;
+
+/**
+ * InputStreamReader is class for turning a byte Stream into a character Stream.
+ * Data read from the source input stream is converted into characters by either
+ * a default or provided character converter. By default, the encoding is
+ * assumed to ISO8859_1. The InputStreamReader contains a buffer of bytes read
+ * from the source input stream and converts these into characters as needed.
+ * The buffer size is 8K.
+ *
+ * @see OutputStreamWriter
+ */
+public class InputStreamReader extends StringReader {
+
+ /**
+ * Constructs a new InputStreamReader on the InputStream in
.
+ * Now character reading can be filtered through this InputStreamReader.
+ * This constructor assumes the default conversion of ISO8859_1
+ * (ISO-Latin-1).
+ *
+ * @param in
+ * the InputStream to convert to characters.
+ * @throws IOException
+ */
+ public InputStreamReader(InputStream in) throws IOException {
+ super(Streams.readFullyString(in, "UTF-8"));
+ }
+
+ public InputStreamReader(InputStream in, String enc) throws IOException
+ {
+ super(Streams.readFullyString(in, enc));
+ }
+
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/Msg.java b/gwt/jre/java/io/Msg.java
new file mode 100644
index 0000000..b706d5c
--- /dev/null
+++ b/gwt/jre/java/io/Msg.java
@@ -0,0 +1,15 @@
+package java.io;
+
+public class Msg {
+
+ public static String getString(String string) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static String getString(String string, int offset) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+};
diff --git a/gwt/jre/java/io/OutputStream.java b/gwt/jre/java/io/OutputStream.java
new file mode 100644
index 0000000..d8d3aa9
--- /dev/null
+++ b/gwt/jre/java/io/OutputStream.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.io;
+
+public abstract class OutputStream {
+
+ // not abstact because of some gwt strangeness
+ public abstract void write(int b) throws IOException;
+
+ public void write(byte[] ba) throws IOException {
+ write(ba, 0, ba.length);
+ }
+
+ public void write(byte[] ba, int start, int len) throws IOException {
+ int end = start + len;
+ for (int i = start; i < end; i++) {
+ write(ba[i]);
+ }
+ }
+
+ public void close() throws IOException {
+ }
+
+ public void flush() throws IOException {
+ }
+
+}
diff --git a/gwt/jre/java/io/OutputStreamWriter.java b/gwt/jre/java/io/OutputStreamWriter.java
new file mode 100644
index 0000000..bb02ae0
--- /dev/null
+++ b/gwt/jre/java/io/OutputStreamWriter.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+import core.util.Strings;
+
+/**
+ * OutputStreamWriter is a class for turning a character output stream into a
+ * byte output stream. The conversion of Unicode characters to their byte
+ * equivalents is determined by the converter used. By default, the encoding is
+ * ISO8859_1 (ISO-Latin-1) but can be changed by calling the constructor which
+ * takes an encoding.
+ *
+ * @see InputStreamReader
+ */
+
+public class OutputStreamWriter extends Writer {
+
+ private OutputStream out;
+ String enc;
+
+ /**
+ * Constructs a new OutputStreamWriter using out
as the
+ * OutputStream to write converted characters to. The default character
+ * encoding is used (see class description).
+ *
+ * @param out
+ * the non-null OutputStream to write converted bytes to.
+ */
+ public OutputStreamWriter(OutputStream out) {
+ super(out);
+ this.out = out;
+ }
+
+ /**
+ * Constructs a new OutputStreamWriter using out
as the
+ * OutputStream to write converted characters to and enc
as
+ * the character encoding. If the encoding cannot be found, an
+ * UnsupportedEncodingException error is thrown.
+ *
+ * @param out
+ * the non-null OutputStream to write converted bytes to.
+ * @param enc
+ * the non-null String describing the desired character encoding.
+ *
+ * @throws UnsupportedEncodingException
+ * if the encoding cannot be found.
+ */
+ public OutputStreamWriter(OutputStream out, final String enc)
+ throws UnsupportedEncodingException {
+ super(out);
+ if (enc == null) {
+ throw new NullPointerException();
+ }
+ this.out = out;
+ this.enc = enc;
+ }
+
+ /**
+ * Close this OutputStreamWriter. This implementation first flushes the
+ * buffer and the target OutputStream. The OutputStream is then closed and
+ * the resources for the buffer and converter are freed.
+ *
+ * Only the first invocation of this method has any effect. Subsequent calls
+ * do no work.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this
+ * OutputStreamWriter.
+ */
+ @Override
+ public void close() throws IOException {
+ synchronized (lock) {
+ out.flush();
+ out.close();
+ }
+ }
+
+ /**
+ * Flush this OutputStreamWriter. This implementation ensures all buffered
+ * bytes are written to the target OutputStream. After writing the bytes,
+ * the target OutputStream is then flushed.
+ *
+ * @throws IOException
+ * If an error occurs attempting to flush this
+ * OutputStreamWriter.
+ */
+ @Override
+ public void flush() throws IOException {
+ synchronized (lock) {
+ out.flush();
+ }
+ }
+
+ private void checkStatus() throws IOException {
+ }
+
+ /**
+ * Answer the String which identifies the encoding used to convert
+ * characters to bytes. The value
+ * This default implementation simply throws IOException and concrete
+ * subclasses must provide their own implementations.
+ *
+ * @param readLimit
+ * an int representing how many characters must be read before
+ * invalidating the mark.
+ *
+ * @throws IOException
+ * If an error occurs attempting mark this Reader.
+ */
+ public void mark(int readLimit) throws IOException {
+ throw new IOException();
+ }
+
+ /**
+ * Answers a boolean indicating whether or not this Reader supports mark()
+ * and reset(). This class a default implementation which answers false.
+ *
+ * @return
+ * Note, that if the unscaled value has more than 53 significant digits, then
+ * this decimal cannot be represented exactly in a double variable. In this
+ * case the result is rounded.
+ *
+ * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be
+ * represented exactly as a double, and thus {@code x1.equals(new
+ * BigDecimal(x1.doubleValue())} returns {@code false} for this case.
+ *
+ * Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is
+ * converted to a double, the result is {@code 9.007199254740992E15}.
+ *
+ *
+ * @return this {@code BigDecimal} as a double value.
+ */
+ @Override
+ public double doubleValue() {
+ return Double.parseDouble(this.toString());
+ }
+
+ /**
+ * Returns {@code true} if {@code x} is a {@code BigDecimal} instance and if
+ * this instance is equal to this big decimal. Two big decimals are equal if
+ * their unscaled value and their scale is equal. For example, 1.0
+ * (10*10^(-1)) is not equal to 1.00 (100*10^(-2)). Similarly, zero instances
+ * are not equal if their scale differs.
+ *
+ * @param x object to be compared with {@code this}.
+ * @return true if {@code x} is a {@code BigDecimal} and {@code this == x}.
+ */
+ @Override
+ public boolean equals(Object x) {
+ if (this == x) {
+ return true;
+ }
+ if (x instanceof BigDecimal) {
+ BigDecimal x1 = (BigDecimal) x;
+ return x1.scale == scale
+ && (bitLength < SMALL_VALUE_BITS ? (x1.smallValue == smallValue)
+ : intVal.equals(x1.intVal));
+ }
+ return false;
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a float value. If {@code this} is too
+ * big to be represented as an float, then {@code Float.POSITIVE_INFINITY} or
+ * {@code Float.NEGATIVE_INFINITY} is returned.
+ *
+ * Note, that if the unscaled value has more than 24 significant digits, then
+ * this decimal cannot be represented exactly in a float variable. In this
+ * case the result is rounded.
+ *
+ * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be
+ * represented exactly as a float, and thus {@code x1.equals(new
+ * BigDecimal(x1.folatValue())} returns {@code false} for this case.
+ *
+ * Similarly, if the instance {@code new BigDecimal(16777217)} is converted to
+ * a float, the result is {@code 1.6777216E}7.
+ *
+ * @return this {@code BigDecimal} as a float value.
+ */
+ @Override
+ public float floatValue() {
+ /*
+ * A similar code like in doubleValue() could be repeated here, but this
+ * simple implementation is quite efficient.
+ */
+ float floatResult = signum();
+ double powerOfTwo = this.bitLength - (scale / LOG10_2);
+ if ((powerOfTwo < -149) || (floatResult == 0.0f)) {
+ // Cases which 'this' is very small
+ floatResult *= 0.0f;
+ } else if (powerOfTwo > 129) {
+ // Cases which 'this' is very large
+ floatResult *= Float.POSITIVE_INFINITY;
+ } else {
+ floatResult = (float) doubleValue();
+ }
+ return floatResult;
+ }
+
+ /**
+ * Returns a hash code for this {@code BigDecimal}.
+ *
+ * @return hash code for {@code this}.
+ */
+ @Override
+ public int hashCode() {
+ if (hashCode != 0) {
+ return hashCode;
+ }
+ if (bitLength < SMALL_VALUE_BITS) {
+ long longValue = (long) smallValue;
+ hashCode = (int) (longValue & 0xffffffff);
+ hashCode = 33 * hashCode + (int) ((longValue >> 32) & 0xffffffff);
+ hashCode = 17 * hashCode + (int) scale;
+ return hashCode;
+ }
+ hashCode = 17 * intVal.hashCode() + (int) scale;
+ return hashCode;
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as an int value. Any fractional part is
+ * discarded. If the integral part of {@code this} is too big to be
+ * represented as an int, then {@code this} % 2^32 is returned.
+ *
+ * @return this {@code BigDecimal} as a int value.
+ */
+ @Override
+ public int intValue() {
+ /*
+ * If scale <= -32 there are at least 32 trailing bits zero in 10^(-scale).
+ * If the scale is positive and very large the long value could be zero.
+ */
+ return ((scale <= -32) || (scale > approxPrecision()) ? 0
+ : toBigInteger().intValue());
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a int value if it has no fractional part
+ * and if its value fits to the int range ([-2^{31}..2^{31}-1]). If these
+ * conditions are not met, an {@code ArithmeticException} is thrown.
+ *
+ * @return this {@code BigDecimal} as a int value.
+ * @throws ArithmeticException if rounding is necessary or the number doesn't
+ * fit in a int.
+ */
+ public int intValueExact() {
+ return (int) valueExact(32);
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as an long value. Any fractional part is
+ * discarded. If the integral part of {@code this} is too big to be
+ * represented as an long, then {@code this} % 2^64 is returned.
+ *
+ * @return this {@code BigDecimal} as a long value.
+ */
+ @Override
+ public long longValue() {
+ /*
+ * If scale <= -64 there are at least 64 trailing bits zero in 10^(-scale).
+ * If the scale is positive and very large the long value could be zero.
+ */
+ return ((scale <= -64) || (scale > approxPrecision()) ? 0L
+ : toBigInteger().longValue());
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a long value if it has no fractional
+ * part and if its value fits to the int range ([-2^{63}..2^{63}-1]). If these
+ * conditions are not met, an {@code ArithmeticException} is thrown.
+ *
+ * @return this {@code BigDecimal} as a long value.
+ * @throws ArithmeticException if rounding is necessary or the number doesn't
+ * fit in a long.
+ */
+ public long longValueExact() {
+ return valueExact(64);
+ }
+
+ /**
+ * Returns the maximum of this {@code BigDecimal} and {@code val}.
+ *
+ * @param val value to be used to compute the maximum with this.
+ * @return {@code max(this, val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigDecimal max(BigDecimal val) {
+ return ((compareTo(val) >= 0) ? this : val);
+ }
+
+ /**
+ * Returns the minimum of this {@code BigDecimal} and {@code val}.
+ *
+ * @param val value to be used to compute the minimum with this.
+ * @return {@code min(this, val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigDecimal min(BigDecimal val) {
+ return ((compareTo(val) <= 0) ? this : val);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance where the decimal point has been
+ * moved {@code n} places to the left. If {@code n < 0} then the decimal point
+ * is moved {@code -n} places to the right.
+ *
+ * The result is obtained by changing its scale. If the scale of the result
+ * becomes negative, then its precision is increased such that the scale is
+ * zero.
+ *
+ * Note, that {@code movePointLeft(0)} returns a result which is
+ * mathematically equivalent, but which has {@code scale >= 0}.
+ *
+ * @param n number of placed the decimal point has to be moved.
+ * @return {@code this * 10^(-n}).
+ */
+ public BigDecimal movePointLeft(int n) {
+ return movePoint(scale + n);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance where the decimal point has been
+ * moved {@code n} places to the right. If {@code n < 0} then the decimal
+ * point is moved {@code -n} places to the left.
+ *
+ * The result is obtained by changing its scale. If the scale of the result
+ * becomes negative, then its precision is increased such that the scale is
+ * zero.
+ *
+ * Note, that {@code movePointRight(0)} returns a result which is
+ * mathematically equivalent, but which has scale >= 0.
+ *
+ * @param n number of placed the decimal point has to be moved.
+ * @return {@code this * 10^n}.
+ */
+ public BigDecimal movePointRight(int n) {
+ return movePoint(scale - n);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this * multiplicand}
+ * . The scale of the result is the sum of the scales of the two arguments.
+ *
+ * @param multiplicand value to be multiplied with {@code this}.
+ * @return {@code this * multiplicand}.
+ * @throws NullPointerException if {@code multiplicand == null}.
+ */
+ public BigDecimal multiply(BigDecimal multiplicand) {
+ double newScale = this.scale + multiplicand.scale;
+
+ if ((this.isZero()) || (multiplicand.isZero())) {
+ return zeroScaledBy(newScale);
+ }
+ /*
+ * Let be: this = [u1,s1] and multiplicand = [u2,s2] so: this x multiplicand
+ * = [ s1 * s2 , s1 + s2 ]
+ */
+ if (this.bitLength + multiplicand.bitLength < SMALL_VALUE_BITS) {
+ return valueOf(this.smallValue * multiplicand.smallValue,
+ toIntScale(newScale));
+ }
+ return new BigDecimal(this.getUnscaledValue().multiply(
+ multiplicand.getUnscaledValue()), toIntScale(newScale));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this * multiplicand}
+ * . The result is rounded according to the passed context {@code mc}.
+ *
+ * @param multiplicand value to be multiplied with {@code this}.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this * multiplicand}.
+ * @throws NullPointerException if {@code multiplicand == null} or {@code mc
+ * == null}.
+ */
+ public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
+ BigDecimal result = multiply(multiplicand);
+
+ result.inplaceRound(mc);
+ return result;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
+ * scale of the result is the same as the scale of this.
+ *
+ * @return {@code -this}
+ */
+ public BigDecimal negate() {
+ if (bitLength < SMALL_VALUE_BITS) {
+ return valueOf(-smallValue, scale);
+ }
+ return new BigDecimal(getUnscaledValue().negate(), scale);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
+ * result is rounded according to the passed context {@code mc}.
+ *
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code -this}
+ */
+ public BigDecimal negate(MathContext mc) {
+ return round(mc).negate();
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code +this}. The scale of
+ * the result is the same as the scale of this.
+ *
+ * @return {@code this}
+ */
+ public BigDecimal plus() {
+ return this;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code +this}. The result
+ * is rounded according to the passed context {@code mc}.
+ *
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this}, rounded
+ */
+ public BigDecimal plus(MathContext mc) {
+ return round(mc);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The scale
+ * of the result is {@code n} times the scales of {@code this}.
+ *
+ * {@code x.pow(0)} returns {@code 1}, even if {@code x == 0}.
+ *
+ * Implementation Note: The implementation is based on the ANSI standard
+ * X3.274-1996 algorithm.
+ *
+ * @param n exponent to which {@code this} is raised.
+ * @return {@code this ^ n}.
+ * @throws ArithmeticException if {@code n < 0} or {@code n > 999999999}.
+ */
+ public BigDecimal pow(int n) {
+ if (n == 0) {
+ return ONE;
+ }
+ if ((n < 0) || (n > 999999999)) {
+ // math.07=Invalid Operation
+ throw new ArithmeticException("Invalid Operation"); //$NON-NLS-1$
+ }
+ double newScale = scale * n;
+ // Let be: this = [u,s] so: this^n = [u^n, s*n]
+ return ((isZero()) ? zeroScaledBy(newScale) : new BigDecimal(
+ getUnscaledValue().pow(n), toIntScale(newScale)));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The
+ * result is rounded according to the passed context {@code mc}.
+ *
+ * Implementation Note: The implementation is based on the ANSI standard
+ * X3.274-1996 algorithm.
+ *
+ * @param n exponent to which {@code this} is raised.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this ^ n}.
+ * @throws ArithmeticException if {@code n < 0} or {@code n > 999999999}.
+ */
+ public BigDecimal pow(int n, MathContext mc) {
+ // The ANSI standard X3.274-1996 algorithm
+ int m = Math.abs(n);
+ int mcPrecision = mc.getPrecision();
+ int elength = (int) Math.log10(m) + 1; // decimal digits in 'n'
+ int oneBitMask; // mask of bits
+ BigDecimal accum; // the single accumulator
+ MathContext newPrecision = mc; // MathContext by default
+
+ // In particular cases, it reduces the problem to call the other 'pow()'
+ if ((n == 0) || ((isZero()) && (n > 0))) {
+ return pow(n);
+ }
+ if ((m > 999999999) || ((mcPrecision == 0) && (n < 0))
+ || ((mcPrecision > 0) && (elength > mcPrecision))) {
+ // math.07=Invalid Operation
+ throw new ArithmeticException("Invalid Operation"); //$NON-NLS-1$
+ }
+ if (mcPrecision > 0) {
+ newPrecision = new MathContext(mcPrecision + elength + 1,
+ mc.getRoundingMode());
+ }
+ // The result is calculated as if 'n' were positive
+ accum = round(newPrecision);
+ oneBitMask = Integer.highestOneBit(m) >> 1;
+
+ while (oneBitMask > 0) {
+ accum = accum.multiply(accum, newPrecision);
+ if ((m & oneBitMask) == oneBitMask) {
+ accum = accum.multiply(this, newPrecision);
+ }
+ oneBitMask >>= 1;
+ }
+ // If 'n' is negative, the value is divided into 'ONE'
+ if (n < 0) {
+ accum = ONE.divide(accum, newPrecision);
+ }
+ // The final value is rounded to the destination precision
+ accum.inplaceRound(mc);
+ return accum;
+ }
+
+ /**
+ * Returns the precision of this {@code BigDecimal}. The precision is the
+ * number of decimal digits used to represent this decimal. It is equivalent
+ * to the number of digits of the unscaled value. The precision of {@code 0}
+ * is {@code 1} (independent of the scale).
+ *
+ * @return the precision of this {@code BigDecimal}.
+ */
+ public int precision() {
+ // Checking if the precision already was calculated
+ if (precision > 0) {
+ return precision;
+ }
+ double decimalDigits = 1; // the precision to be calculated
+ double doubleUnsc = 1; // intVal in 'double'
+
+ if (bitLength < SMALL_VALUE_BITS) {
+ // To calculate the precision for small numbers
+ if (bitLength >= 1) {
+ doubleUnsc = smallValue;
+ }
+ decimalDigits += Math.log10(Math.abs(doubleUnsc));
+ } else {
+ // (bitLength >= 1024)
+ /*
+ * To calculate the precision for large numbers Note that: 2 ^(bitlength()
+ * - 1) <= intVal < 10 ^(precision())
+ */
+ decimalDigits += (bitLength - 1) * LOG10_2;
+ // If after division the number isn't zero, exists an aditional digit
+ if (getUnscaledValue().divide(Multiplication.powerOf10(decimalDigits)).signum() != 0) {
+ decimalDigits++;
+ }
+ }
+ precision = (int) decimalDigits;
+ return precision;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
+ *
+ * The remainder is defined as {@code this -
+ * this.divideToIntegralValue(divisor) * divisor}.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return {@code this % divisor}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ */
+ public BigDecimal remainder(BigDecimal divisor) {
+ return divideAndRemainder(divisor)[1];
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
+ *
+ * The remainder is defined as {@code this -
+ * this.divideToIntegralValue(divisor) * divisor}.
+ *
+ * The specified rounding mode {@code mc} is used for the division only.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param mc rounding mode and precision to be used.
+ * @return {@code this % divisor}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code mc.getPrecision() > 0} and the result
+ * of {@code this.divideToIntegralValue(divisor, mc)} requires more
+ * digits to be represented.
+ */
+ public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
+ return divideAndRemainder(divisor, mc)[1];
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this}, rounded
+ * according to the passed context {@code mc}.
+ *
+ * If {@code mc.precision = 0}, then no rounding is performed.
+ *
+ * If {@code mc.precision > 0} and {@code mc.roundingMode == UNNECESSARY},
+ * then an {@code ArithmeticException} is thrown if the result cannot be
+ * represented exactly within the given precision.
+ *
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this} rounded according to the passed context.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and this cannot be represented
+ * within the given precision.
+ */
+ public BigDecimal round(MathContext mc) {
+ BigDecimal thisBD = new BigDecimal(getUnscaledValue(), scale);
+
+ thisBD.inplaceRound(mc);
+ return thisBD;
+ }
+
+ /**
+ * Returns the scale of this {@code BigDecimal}. The scale is the number of
+ * digits behind the decimal point. The value of this {@code BigDecimal} is
+ * the unsignedValue * 10^(-scale). If the scale is negative, then this
+ * {@code BigDecimal} represents a big integer.
+ *
+ * @return the scale of this {@code BigDecimal}.
+ */
+ public int scale() {
+ return (int) scale;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this} 10^{@code n}.
+ * The scale of the result is {@code this.scale()} - {@code n}. The precision
+ * of the result is the precision of {@code this}.
+ *
+ * This method has the same effect as {@link #movePointRight}, except that the
+ * precision is not changed.
+ *
+ * @param n number of places the decimal point has to be moved.
+ * @return {@code this * 10^n}
+ */
+ public BigDecimal scaleByPowerOfTen(int n) {
+ double newScale = scale - n;
+ if (bitLength < SMALL_VALUE_BITS) {
+ // Taking care when a 0 is to be scaled
+ if (smallValue == 0) {
+ return zeroScaledBy(newScale);
+ }
+ return valueOf(smallValue, toIntScale(newScale));
+ }
+ return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance with the specified scale. If the
+ * new scale is greater than the old scale, then additional zeros are added to
+ * the unscaled value. If the new scale is smaller than the old scale, then
+ * trailing zeros are removed. If the trailing digits are not zeros then an
+ * ArithmeticException is thrown.
+ *
+ * If no exception is thrown, then the following equation holds: {@code
+ * x.setScale(s).compareTo(x) == 0}.
+ *
+ * @param newScale scale of the result returned.
+ * @return a new {@code BigDecimal} instance with the specified scale.
+ * @throws ArithmeticException if rounding would be necessary.
+ */
+ public BigDecimal setScale(int newScale) {
+ return setScale(newScale, RoundingMode.UNNECESSARY);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance with the specified scale.
+ *
+ * If the new scale is greater than the old scale, then additional zeros are
+ * added to the unscaled value. In this case no rounding is necessary.
+ *
+ * If the new scale is smaller than the old scale, then trailing digits are
+ * removed. If these trailing digits are not zero, then the remaining unscaled
+ * value has to be rounded. For this rounding operation the specified rounding
+ * mode is used.
+ *
+ * @param newScale scale of the result returned.
+ * @param roundingMode rounding mode to be used to round the result.
+ * @return a new {@code BigDecimal} instance with the specified scale.
+ * @throws IllegalArgumentException if {@code roundingMode} is not a valid
+ * rounding mode.
+ * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
+ * and rounding is necessary according to the given scale.
+ */
+ public BigDecimal setScale(int newScale, int roundingMode) {
+ return setScale(newScale, RoundingMode.valueOf(roundingMode));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance with the specified scale.
+ *
+ * If the new scale is greater than the old scale, then additional zeros are
+ * added to the unscaled value. In this case no rounding is necessary.
+ *
+ * If the new scale is smaller than the old scale, then trailing digits are
+ * removed. If these trailing digits are not zero, then the remaining unscaled
+ * value has to be rounded. For this rounding operation the specified rounding
+ * mode is used.
+ *
+ * @param newScale scale of the result returned.
+ * @param roundingMode rounding mode to be used to round the result.
+ * @return a new {@code BigDecimal} instance with the specified scale.
+ * @throws NullPointerException if {@code roundingMode == null}.
+ * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
+ * and rounding is necessary according to the given scale.
+ */
+ public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
+ if (roundingMode == null) {
+ throw new NullPointerException();
+ }
+ double diffScale = newScale - scale;
+ // Let be: 'this' = [u,s]
+ if (diffScale == 0) {
+ return this;
+ }
+ if (diffScale > 0) {
+ // return [u * 10^(s2 - s), newScale]
+ if (diffScale < DOUBLE_TEN_POW.length
+ && (this.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[
+ (int) diffScale]) < SMALL_VALUE_BITS) {
+ return valueOf(this.smallValue * DOUBLE_TEN_POW[(int) diffScale],
+ newScale);
+ }
+ return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),
+ (int) diffScale), newScale);
+ }
+ // diffScale < 0
+ // return [u,s] / [1,newScale] with the appropriate scale and rounding
+ if (this.bitLength < SMALL_VALUE_BITS
+ && -diffScale < DOUBLE_TEN_POW.length) {
+ return dividePrimitiveDoubles(this.smallValue,
+ DOUBLE_TEN_POW[(int) -diffScale], newScale, roundingMode);
+ }
+ return divideBigIntegers(this.getUnscaledValue(),
+ Multiplication.powerOf10(-diffScale), newScale, roundingMode);
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a short value if it has no fractional
+ * part and if its value fits to the short range ([-2^{15}..2^{15}-1]). If
+ * these conditions are not met, an {@code ArithmeticException} is thrown.
+ *
+ * @return this {@code BigDecimal} as a short value.
+ * @throws ArithmeticException if rounding is necessary of the number doesn't
+ * fit in a short.
+ */
+ public short shortValueExact() {
+ return (short) valueExact(16);
+ }
+
+ /**
+ * Returns the sign of this {@code BigDecimal}.
+ *
+ * @return {@code -1} if {@code this < 0}, {@code 0} if {@code this == 0},
+ * {@code 1} if {@code this > 0}.
+ */
+ public int signum() {
+ if (bitLength < SMALL_VALUE_BITS) {
+ return this.smallValue < 0 ? -1 : this.smallValue > 0 ? 1 : 0;
+ }
+ return getUnscaledValue().signum();
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance with the same value as {@code
+ * this} but with a unscaled value where the trailing zeros have been removed.
+ * If the unscaled value of {@code this} has n trailing zeros, then the scale
+ * and the precision of the result has been reduced by n.
+ *
+ * @return a new {@code BigDecimal} instance equivalent to this where the
+ * trailing zeros of the unscaled value have been removed.
+ */
+ public BigDecimal stripTrailingZeros() {
+ int i = 1; // 1 <= i <= 18
+ int lastPow = TEN_POW.length - 1;
+ double newScale = scale;
+
+ if (isZero()) {
+ return new BigDecimal("0");
+ }
+ BigInteger strippedBI = getUnscaledValue();
+ BigInteger[] quotAndRem;
+
+ // while the number is even...
+ while (!strippedBI.testBit(0)) {
+ // To divide by 10^i
+ quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
+ // To look the remainder
+ if (quotAndRem[1].signum() == 0) {
+ // To adjust the scale
+ newScale -= i;
+ if (i < lastPow) {
+ // To set to the next power
+ i++;
+ }
+ strippedBI = quotAndRem[0];
+ } else {
+ if (i == 1) {
+ // 'this' has no more trailing zeros
+ break;
+ }
+ // To set to the smallest power of ten
+ i = 1;
+ }
+ }
+ return new BigDecimal(strippedBI, toIntScale(newScale));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
+ * The scale of the result is the maximum of the scales of the two arguments.
+ *
+ * @param subtrahend value to be subtracted from {@code this}.
+ * @return {@code this - subtrahend}.
+ * @throws NullPointerException if {@code subtrahend == null}.
+ */
+ public BigDecimal subtract(BigDecimal subtrahend) {
+ double diffScale = this.scale - subtrahend.scale;
+ // Fast return when some operand is zero
+ if (this.isZero()) {
+ if (diffScale <= 0) {
+ return subtrahend.negate();
+ }
+ if (subtrahend.isZero()) {
+ return this;
+ }
+ } else if (subtrahend.isZero()) {
+ if (diffScale >= 0) {
+ return this;
+ }
+ }
+ // Let be: this = [u1,s1] and subtrahend = [u2,s2] so:
+ if (diffScale == 0) {
+ // case s1 = s2 : [u1 - u2 , s1]
+ if (Math.max(this.bitLength, subtrahend.bitLength) + 1
+ < SMALL_VALUE_BITS) {
+ return valueOf(this.smallValue - subtrahend.smallValue, this.scale);
+ }
+ return new BigDecimal(this.getUnscaledValue().subtract(
+ subtrahend.getUnscaledValue()), this.scale);
+ } else if (diffScale > 0) {
+ // case s1 > s2 : [ u1 - u2 * 10 ^ (s1 - s2) , s1 ]
+ if (diffScale < DOUBLE_TEN_POW.length
+ && Math.max(this.bitLength, subtrahend.bitLength
+ + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale]) + 1
+ < SMALL_VALUE_BITS) {
+ return valueOf(this.smallValue - subtrahend.smallValue
+ * DOUBLE_TEN_POW[(int) diffScale], this.scale);
+ }
+ return new BigDecimal(this.getUnscaledValue().subtract(
+ Multiplication.multiplyByTenPow(subtrahend.getUnscaledValue(),
+ (int) diffScale)), this.scale);
+ } else {
+ // case s2 > s1 : [ u1 * 10 ^ (s2 - s1) - u2 , s2 ]
+ diffScale = -diffScale;
+ if (diffScale < DOUBLE_TEN_POW.length
+ && Math.max(this.bitLength
+ + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale],
+ subtrahend.bitLength) + 1 < SMALL_VALUE_BITS) {
+ return valueOf(this.smallValue * DOUBLE_TEN_POW[(int) diffScale]
+ - subtrahend.smallValue, subtrahend.scale);
+ }
+ return new BigDecimal(Multiplication.multiplyByTenPow(
+ this.getUnscaledValue(), (int) diffScale).subtract(
+ subtrahend.getUnscaledValue()), subtrahend.scale);
+ }
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
+ * The result is rounded according to the passed context {@code mc}.
+ *
+ * @param subtrahend value to be subtracted from {@code this}.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this - subtrahend}.
+ * @throws NullPointerException if {@code subtrahend == null} or {@code mc ==
+ * null}.
+ */
+ public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
+ double diffScale = subtrahend.scale - this.scale;
+ int thisSignum;
+ BigDecimal leftOperand; // it will be only the left operand (this)
+ BigInteger tempBI;
+ // Some operand is zero or the precision is infinity
+ if ((subtrahend.isZero()) || (this.isZero()) || (mc.getPrecision() == 0)) {
+ return subtract(subtrahend).round(mc);
+ }
+ // Now: this != 0 and subtrahend != 0
+ if (subtrahend.approxPrecision() < diffScale - 1) {
+ // Cases where it is unnecessary to subtract two numbers with very
+ // different scales
+ if (mc.getPrecision() < this.approxPrecision()) {
+ thisSignum = this.signum();
+ if (thisSignum != subtrahend.signum()) {
+ tempBI = Multiplication.multiplyByPositiveInt(
+ this.getUnscaledValue(), 10).add(BigInteger.valueOf(thisSignum));
+ } else {
+ tempBI = this.getUnscaledValue().subtract(
+ BigInteger.valueOf(thisSignum));
+ tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10).add(
+ BigInteger.valueOf(thisSignum * 9));
+ }
+ // Rounding the improved subtracting
+ leftOperand = new BigDecimal(tempBI, this.scale + 1);
+ return leftOperand.round(mc);
+ }
+ }
+ // No optimization is done
+ return subtract(subtrahend).round(mc);
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a big integer instance. A fractional
+ * part is discarded.
+ *
+ * @return this {@code BigDecimal} as a big integer instance.
+ */
+ public BigInteger toBigInteger() {
+ if ((scale == 0) || (isZero())) {
+ return getUnscaledValue();
+ } else if (scale < 0) {
+ return getUnscaledValue().multiply(Multiplication.powerOf10(-scale));
+ } else {
+ // (scale > 0)
+ return getUnscaledValue().divide(Multiplication.powerOf10(scale));
+ }
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a big integer instance if it has no
+ * fractional part. If this {@code BigDecimal} has a fractional part, i.e. if
+ * rounding would be necessary, an {@code ArithmeticException} is thrown.
+ *
+ * @return this {@code BigDecimal} as a big integer value.
+ * @throws ArithmeticException if rounding is necessary.
+ */
+ public BigInteger toBigIntegerExact() {
+ if ((scale == 0) || (isZero())) {
+ return getUnscaledValue();
+ } else if (scale < 0) {
+ return getUnscaledValue().multiply(Multiplication.powerOf10(-scale));
+ } else {
+ // (scale > 0)
+ BigInteger[] integerAndFraction;
+ // An optimization before do a heavy division
+ if ((scale > approxPrecision())
+ || (scale > getUnscaledValue().getLowestSetBit())) {
+ // math.08=Rounding necessary
+ throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
+ }
+ integerAndFraction = getUnscaledValue().divideAndRemainder(
+ Multiplication.powerOf10(scale));
+ if (integerAndFraction[1].signum() != 0) {
+ // It exists a non-zero fractional part
+ // math.08=Rounding necessary
+ throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
+ }
+ return integerAndFraction[0];
+ }
+ }
+
+ /**
+ * Returns a string representation of this {@code BigDecimal}. This
+ * representation always prints all significant digits of this value.
+ *
+ * If the scale is negative or if {@code scale - precision >= 6} then
+ * engineering notation is used. Engineering notation is similar to the
+ * scientific notation except that the exponent is made to be a multiple of 3
+ * such that the integer part is >= 1 and < 1000.
+ *
+ * @return a string representation of {@code this} in engineering notation if
+ * necessary.
+ */
+ public String toEngineeringString() {
+ String intString = getUnscaledValue().toString();
+ if (scale == 0) {
+ return intString;
+ }
+ int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
+ int end = intString.length();
+ double exponent = -scale + end - begin;
+ StringBuilder result = new StringBuilder(intString);
+
+ if ((scale > 0) && (exponent >= -6)) {
+ if (exponent >= 0) {
+ result.insert(end - (int) scale, '.');
+ } else {
+ result.insert(begin - 1, "0."); //$NON-NLS-1$
+ result.insert(begin + 1, CH_ZEROS, 0, -(int) exponent - 1);
+ }
+ } else {
+ int delta = end - begin;
+ int rem = (int) (exponent % 3);
+
+ if (rem != 0) {
+ // adjust exponent so it is a multiple of three
+ if (getUnscaledValue().signum() == 0) {
+ // zero value
+ rem = (rem < 0) ? -rem : 3 - rem;
+ exponent += rem;
+ } else {
+ // nonzero value
+ rem = (rem < 0) ? rem + 3 : rem;
+ exponent -= rem;
+ begin += rem;
+ }
+ if (delta < 3) {
+ for (int i = rem - delta; i > 0; i--) {
+ result.insert(end++, '0');
+ }
+ }
+ }
+ if (end - begin >= 1) {
+ result.insert(begin, '.');
+ end++;
+ }
+ if (exponent != 0) {
+ result.insert(end, 'E');
+ if (exponent > 0) {
+ result.insert(++end, '+');
+ }
+ result.insert(++end, Long.toString((long) exponent));
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns a string representation of this {@code BigDecimal}. No scientific
+ * notation is used. This methods adds zeros where necessary.
+ *
+ * If this string representation is used to create a new instance, this
+ * instance is generally not identical to {@code this} as the precision
+ * changes.
+ *
+ * {@code x.equals(new BigDecimal(x.toPlainString())} usually returns {@code
+ * false}.
+ *
+ * {@code x.compareTo(new BigDecimal(x.toPlainString())} returns {@code 0}.
+ *
+ * @return a string representation of {@code this} without exponent part.
+ */
+ public String toPlainString() {
+ String intStr = getUnscaledValue().toString();
+ if ((scale == 0) || ((isZero()) && (scale < 0))) {
+ return intStr;
+ }
+ int begin = (signum() < 0) ? 1 : 0;
+ double delta = scale;
+ // We take space for all digits, plus a possible decimal point, plus 'scale'
+ StringBuilder result = new StringBuilder(intStr.length() + 1
+ + Math.abs((int) scale));
+
+ if (begin == 1) {
+ // If the number is negative, we insert a '-' character at front
+ result.append('-');
+ }
+ if (scale > 0) {
+ delta -= (intStr.length() - begin);
+ if (delta >= 0) {
+ result.append("0."); //$NON-NLS-1$
+ // To append zeros after the decimal point
+ for (; delta > CH_ZEROS.length; delta -= CH_ZEROS.length) {
+ result.append(CH_ZEROS);
+ }
+ result.append(CH_ZEROS, 0, (int) delta);
+ result.append(intStr.substring(begin));
+ } else {
+ delta = begin - delta;
+ result.append(intStr.substring(begin, (int) delta));
+ result.append('.');
+ result.append(intStr.substring((int) delta));
+ }
+ } else {
+ // (scale <= 0)
+ result.append(intStr.substring(begin));
+ // To append trailing zeros
+ for (; delta < -CH_ZEROS.length; delta += CH_ZEROS.length) {
+ result.append(CH_ZEROS);
+ }
+ result.append(CH_ZEROS, 0, (int) -delta);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns a canonical string representation of this {@code BigDecimal}. If
+ * necessary, scientific notation is used. This representation always prints
+ * all significant digits of this value.
+ *
+ * If the scale is negative or if {@code scale - precision >= 6} then
+ * scientific notation is used.
+ *
+ * @return a string representation of {@code this} in scientific notation if
+ * necessary.
+ */
+ @Override
+ public String toString() {
+ if (toStringImage != null) {
+ return toStringImage;
+ }
+ if (bitLength < 32) {
+ // TODO convert to double math dont cast to long :-(
+ toStringImage = Conversion.toDecimalScaledString((long) smallValue,
+ (int) scale);
+ return toStringImage;
+ }
+ String intString = getUnscaledValue().toString();
+ if (scale == 0) {
+ return intString;
+ }
+ int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
+ int end = intString.length();
+ double exponent = -scale + end - begin;
+ StringBuilder result = new StringBuilder();
+
+ result.append(intString);
+ if ((scale > 0) && (exponent >= -6)) {
+ if (exponent >= 0) {
+ result.insert(end - (int) scale, '.');
+ } else {
+ result.insert(begin - 1, "0."); //$NON-NLS-1$
+ result.insert(begin + 1, CH_ZEROS, 0, -(int) exponent - 1);
+ }
+ } else {
+ if (end - begin >= 1) {
+ result.insert(begin, '.');
+ end++;
+ }
+ result.insert(end, 'E');
+ if (exponent > 0) {
+ result.insert(++end, '+');
+ }
+ result.insert(++end, Long.toString((long) exponent));
+ }
+ toStringImage = result.toString();
+ return toStringImage;
+ }
+
+ /**
+ * Returns the unit in the last place (ULP) of this {@code BigDecimal}
+ * instance. An ULP is the distance to the nearest big decimal with the same
+ * precision.
+ *
+ * The amount of a rounding error in the evaluation of a floating-point
+ * operation is often expressed in ULPs. An error of 1 ULP is often seen as a
+ * tolerable error.
+ *
+ * For class {@code BigDecimal}, the ULP of a number is simply 10^(-scale).
+ *
+ * For example, {@code new BigDecimal(0.1).ulp()} returns {@code 1E-55}.
+ *
+ * @return unit in the last place (ULP) of this {@code BigDecimal} instance.
+ */
+ public BigDecimal ulp() {
+ return valueOf(1, scale);
+ }
+
+ /**
+ * Returns the unscaled value (mantissa) of this {@code BigDecimal} instance
+ * as a {@code BigInteger}. The unscaled value can be computed as {@code this}
+ * 10^(scale).
+ *
+ * @return unscaled value (this * 10^(scale)).
+ */
+ public BigInteger unscaledValue() {
+ return getUnscaledValue();
+ }
+
+ /**
+ * If the precision already was calculated it returns that value, otherwise it
+ * calculates a very good approximation efficiently . Note that this value
+ * will be {@code precision()} or {@code precision()-1} in the worst case.
+ *
+ * @return an approximation of {@code precision()} value
+ */
+ private double approxPrecision() {
+ return (precision > 0) ? precision
+ : Math.floor((this.bitLength - 1) * LOG10_2) + 1;
+ }
+
+ private BigInteger getUnscaledValue() {
+ if (intVal == null) {
+ intVal = BigInteger.valueOf(smallValue);
+ }
+ return intVal;
+ }
+
+ private void initFrom(String val) {
+ int begin = 0; // first index to be copied
+ int offset = 0;
+ int last = val.length(); // one past the last index to be copied
+ String scaleString = null; // buffer for scale
+ StringBuilder unscaledBuffer; // buffer for unscaled value
+
+ unscaledBuffer = new StringBuilder(val.length());
+ // To skip a possible '+' symbol
+ if ((offset < last) && (val.charAt(offset) == '+')) {
+ offset++;
+ begin++;
+
+ // Fail if the next character is another sign.
+ if ((offset < last)
+ && (val.charAt(offset) == '+' || val.charAt(offset) == '-')) {
+ throw new NumberFormatException("For input string: \"" + val + "\"");
+ }
+ }
+ int counter = 0;
+ boolean wasNonZero = false;
+ // Accumulating all digits until a possible decimal point
+ for (; (offset < last) && (val.charAt(offset) != '.')
+ && (val.charAt(offset) != 'e') && (val.charAt(offset) != 'E'); offset++) {
+ if (!wasNonZero) {
+ if (val.charAt(offset) == '0') {
+ counter++;
+ } else {
+ wasNonZero = true;
+ }
+ }
+ }
+ unscaledBuffer.append(val, begin, offset);
+ // A decimal point was found
+ if ((offset < last) && (val.charAt(offset) == '.')) {
+ offset++;
+ // Accumulating all digits until a possible exponent
+ begin = offset;
+ for (; (offset < last) && (val.charAt(offset) != 'e')
+ && (val.charAt(offset) != 'E'); offset++) {
+ if (!wasNonZero) {
+ if (val.charAt(offset) == '0') {
+ counter++;
+ } else {
+ wasNonZero = true;
+ }
+ }
+ }
+ scale = offset - begin;
+ unscaledBuffer.append(val, begin, offset);
+ } else {
+ scale = 0;
+ }
+ // An exponent was found
+ if ((offset < last)
+ && ((val.charAt(offset) == 'e') || (val.charAt(offset) == 'E'))) {
+ offset++;
+ // Checking for a possible sign of scale
+ begin = offset;
+ if ((offset < last) && (val.charAt(offset) == '+')) {
+ offset++;
+ if ((offset < last) && (val.charAt(offset) != '-')) {
+ begin++;
+ }
+ }
+ // Accumulating all remaining digits
+ scaleString = val.substring(begin, last);
+ // Checking if the scale is defined
+ scale = scale - Integer.parseInt(scaleString);
+ if (scale != (int) scale) {
+ // math.02=Scale out of range.
+ throw new NumberFormatException("Scale out of range."); //$NON-NLS-1$
+ }
+ }
+ // Parsing the unscaled value
+ String unscaled = unscaledBuffer.toString();
+ if (unscaled.length() < 16) {
+ smallValue = parseUnscaled(unscaled);
+ if (Double.isNaN(smallValue)) {
+ throw new NumberFormatException("For input string: \"" + val + "\"");
+ }
+ bitLength = bitLength(smallValue);
+ } else {
+ setUnscaledValue(new BigInteger(unscaled));
+ }
+ precision = unscaledBuffer.length() - counter;
+ // Don't count leading zeros in the precision
+ for (int i = 0; i < unscaledBuffer.length(); ++i) {
+ char ch = unscaledBuffer.charAt(i);
+ if (ch != '-' && ch != '0') {
+ break;
+ }
+ --precision;
+ }
+ }
+
+ /**
+ * It does all rounding work of the public method {@code round(MathContext)},
+ * performing an inplace rounding without creating a new object.
+ *
+ * @param mc the {@code MathContext} for perform the rounding.
+ * @see #round(MathContext)
+ */
+ private void inplaceRound(MathContext mc) {
+ int mcPrecision = mc.getPrecision();
+ if (approxPrecision() - mcPrecision < 0 || mcPrecision == 0) {
+ return;
+ }
+ int discardedPrecision = precision() - mcPrecision;
+ // If no rounding is necessary it returns immediately
+ if ((discardedPrecision <= 0)) {
+ return;
+ }
+ // When the number is small perform an efficient rounding
+ if (this.bitLength < SMALL_VALUE_BITS) {
+ smallRound(mc, discardedPrecision);
+ return;
+ }
+ // Getting the integer part and the discarded fraction
+ BigInteger sizeOfFraction = Multiplication.powerOf10(discardedPrecision);
+ BigInteger[] integerAndFraction = getUnscaledValue().divideAndRemainder(
+ sizeOfFraction);
+ double newScale = scale - discardedPrecision;
+ int compRem;
+ BigDecimal tempBD;
+ // If the discarded fraction is non-zero, perform rounding
+ if (integerAndFraction[1].signum() != 0) {
+ // To check if the discarded fraction >= 0.5
+ compRem = (integerAndFraction[1].abs().shiftLeftOneBit().compareTo(sizeOfFraction));
+ // To look if there is a carry
+ compRem = roundingBehavior(integerAndFraction[0].testBit(0) ? 1 : 0,
+ integerAndFraction[1].signum() * (5 + compRem), mc.getRoundingMode());
+ if (compRem != 0) {
+ integerAndFraction[0] = integerAndFraction[0].add(BigInteger.valueOf(compRem));
+ }
+ tempBD = new BigDecimal(integerAndFraction[0]);
+ // If after to add the increment the precision changed, we normalize the
+ // size
+ if (tempBD.precision() > mcPrecision) {
+ integerAndFraction[0] = integerAndFraction[0].divide(BigInteger.TEN);
+ newScale--;
+ }
+ }
+ // To update all internal fields
+ scale = toIntScale(newScale);
+ precision = mcPrecision;
+ setUnscaledValue(integerAndFraction[0]);
+ }
+
+ private boolean isZero() {
+ return bitLength == 0 && this.smallValue != -1;
+ }
+
+ private BigDecimal movePoint(double newScale) {
+ if (isZero()) {
+ return zeroScaledBy(Math.max(newScale, 0));
+ }
+ /*
+ * When: 'n'== Integer.MIN_VALUE isn't possible to call to
+ * movePointRight(-n) since -Integer.MIN_VALUE == Integer.MIN_VALUE
+ */
+ if (newScale >= 0) {
+ if (bitLength < SMALL_VALUE_BITS) {
+ return valueOf(smallValue, toIntScale(newScale));
+ }
+ return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
+ }
+ if (-newScale < DOUBLE_TEN_POW.length
+ && bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) -newScale]
+ < SMALL_VALUE_BITS) {
+ return valueOf(smallValue * DOUBLE_TEN_POW[(int) -newScale], 0);
+ }
+ return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),
+ (int) -newScale), 0);
+ }
+
+ private void setUnscaledValue(BigInteger unscaledValue) {
+ this.intVal = unscaledValue;
+ this.bitLength = unscaledValue.bitLength();
+ if (this.bitLength < SMALL_VALUE_BITS) {
+ this.smallValue = unscaledValue.longValue();
+ }
+ }
+
+ /**
+ * This method implements an efficient rounding for numbers which unscaled
+ * value fits in the type {@code long}.
+ *
+ * @param mc the context to use
+ * @param discardedPrecision the number of decimal digits that are discarded
+ * @see #round(MathContext)
+ */
+ private void smallRound(MathContext mc, int discardedPrecision) {
+ long sizeOfFraction = (long) DOUBLE_TEN_POW[discardedPrecision];
+ long newScale = (long) scale - discardedPrecision;
+ long unscaledVal = (long) smallValue; // TODO convert to double math dont
+ // use longs
+ // Getting the integer part and the discarded fraction
+ long integer = unscaledVal / sizeOfFraction;
+ long fraction = unscaledVal % sizeOfFraction;
+ int compRem;
+ // If the discarded fraction is non-zero perform rounding
+ if (fraction != 0) {
+ // To check if the discarded fraction >= 0.5
+ compRem = longCompareTo(Math.abs(fraction) << 1, sizeOfFraction);
+ // To look if there is a carry
+ integer += roundingBehavior(((int) integer) & 1, Long.signum(fraction)
+ * (5 + compRem), mc.getRoundingMode());
+ // If after to add the increment the precision changed, we normalize the
+ // size
+ if (Math.log10(Math.abs(integer)) >= mc.getPrecision()) {
+ integer /= 10;
+ newScale--;
+ }
+ }
+ // To update all internal fields
+ scale = toIntScale(newScale);
+ precision = mc.getPrecision();
+ smallValue = integer;
+ bitLength = bitLength(integer);
+ intVal = null;
+ }
+
+ /**
+ * If {@code intVal} has a fractional part throws an exception, otherwise it
+ * counts the number of bits of value and checks if it's out of the range of
+ * the primitive type. If the number fits in the primitive type returns this
+ * number as {@code long}, otherwise throws an exception.
+ *
+ * @param bitLengthOfType number of bits of the type whose value will be
+ * calculated exactly
+ * @return the exact value of the integer part of {@code BigDecimal} when is
+ * possible
+ * @throws ArithmeticException when rounding is necessary or the number don't
+ * fit in the primitive type
+ */
+ private long valueExact(int bitLengthOfType) {
+ BigInteger bigInteger = toBigIntegerExact();
+
+ if (bigInteger.bitLength() < bitLengthOfType) {
+ // It fits in the primitive type
+ return bigInteger.longValue();
+ }
+ // math.08=Rounding necessary
+ throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
+ }
+}
diff --git a/gwt/jre/java/math/BigInteger.java b/gwt/jre/java/math/BigInteger.java
new file mode 100644
index 0000000..65287fa
--- /dev/null
+++ b/gwt/jre/java/math/BigInteger.java
@@ -0,0 +1,1553 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+import java.io.Serializable;
+import java.util.Random;
+
+/**
+ * This class represents immutable integer numbers of arbitrary length. Large
+ * numbers are typically used in security applications and therefore BigIntegers
+ * offer dedicated functionality like the generation of large prime numbers or
+ * the computation of modular inverse.
+ *
+ * Since the class was modeled to offer all the functionality as the
+ * {@link Integer} class does, it provides even methods that operate bitwise on
+ * a two's complement representation of large integers. Note however that the
+ * implementations favors an internal representation where magnitude and sign
+ * are treated separately. Hence such operations are inefficient and should be
+ * discouraged. In simple words: Do NOT implement any bit fields based on
+ * BigInteger.
+ */
+public class BigInteger extends Number implements Comparable
+ * Implementation Note: Currently {@code rnd} is ignored.
+ *
+ * @param bitLength length of the new {@code BigInteger} in bits.
+ * @param rnd random generator used to generate the new {@code BigInteger}.
+ * @return probably prime random {@code BigInteger} instance.
+ * @throws IllegalArgumentException if {@code bitLength < 2}.
+ */
+ public static BigInteger probablePrime(int bitLength, Random rnd) {
+ return new BigInteger(bitLength, 100, rnd);
+ }
+
+ public static BigInteger valueOf(long val) {
+ if (val < 0) {
+ if (val != -1) {
+ return new BigInteger(-1, -val);
+ }
+ return MINUS_ONE;
+ } else if (val <= 10) {
+ return SMALL_VALUES[(int) val];
+ } else {
+ // (val > 10)
+ return new BigInteger(1, val);
+ }
+ }
+
+ static BigInteger getPowerOfTwo(int exp) {
+ if (exp < TWO_POWS.length) {
+ return TWO_POWS[exp];
+ }
+ int intCount = exp >> 5;
+ int bitN = exp & 31;
+ int resDigits[] = new int[intCount + 1];
+ resDigits[intCount] = 1 << bitN;
+ return new BigInteger(1, intCount + 1, resDigits);
+ }
+
+ static BigInteger valueOf(double val) {
+ if (val < 0) {
+ if (val != -1) {
+ return new BigInteger(-1, -val);
+ }
+ return MINUS_ONE;
+ } else if (val <= 10) {
+ return SMALL_VALUES[(int) val];
+ } else {
+ // (val > 10)
+ return new BigInteger(1, val);
+ }
+ }
+
+ /**
+ * @see BigInteger#BigInteger(String, int)
+ */
+ private static void setFromString(BigInteger bi, String val, int radix) {
+ int sign;
+ int[] digits;
+ int numberLength;
+ int stringLength = val.length();
+ int startChar;
+ int endChar = stringLength;
+
+ if (val.charAt(0) == '-') {
+ sign = -1;
+ startChar = 1;
+ stringLength--;
+ } else {
+ sign = 1;
+ startChar = 0;
+ }
+ /*
+ * We use the following algorithm: split a string into portions of n
+ * characters and convert each portion to an integer according to the radix.
+ * Then convert an exp(radix, n) based number to binary using the
+ * multiplication method. See D. Knuth, The Art of Computer Programming,
+ * vol. 2.
+ */
+
+ int charsPerInt = Conversion.digitFitInInt[radix];
+ int bigRadixDigitsLength = stringLength / charsPerInt;
+ int topChars = stringLength % charsPerInt;
+
+ if (topChars != 0) {
+ bigRadixDigitsLength++;
+ }
+ digits = new int[bigRadixDigitsLength];
+ // Get the maximal power of radix that fits in int
+ int bigRadix = Conversion.bigRadices[radix - 2];
+ // Parse an input string and accumulate the BigInteger's magnitude
+ int digitIndex = 0; // index of digits array
+ int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars);
+ int newDigit;
+
+ for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart
+ + charsPerInt) {
+ int bigRadixDigit = Integer.parseInt(
+ val.substring(substrStart, substrEnd), radix);
+ newDigit = Multiplication.multiplyByInt(digits, digitIndex, bigRadix);
+ newDigit += Elementary.inplaceAdd(digits, digitIndex, bigRadixDigit);
+ digits[digitIndex++] = newDigit;
+ }
+ numberLength = digitIndex;
+ bi.sign = sign;
+ bi.numberLength = numberLength;
+ bi.digits = digits;
+ bi.cutOffLeadingZeroes();
+ }
+
+ /**
+ * Converts an integral double to an unsigned integer; ie 2^31 will be
+ * returned as 0x80000000.
+ *
+ * @param val
+ * @return val as an unsigned int
+ */
+ private static native int toUnsignedInt(double val) /*-{
+ return ~~val;
+ }-*/;
+
+ /**
+ * The magnitude of this big integer. This array is in little endian order and
+ * each "digit" is a 32-bit unsigned integer. For example: {@code 13} is
+ * represented as [ 13 ] {@code -13} is represented as [ 13 ] {@code 2^32 +
+ * 13} is represented as [ 13, 1 ] {@code 2^64 + 13} is represented as [ 13,
+ * 0, 1 ] {@code 2^31} is represented as [ Integer.MIN_VALUE ] The magnitude
+ * array may be longer than strictly necessary, which results in additional
+ * trailing zeros.
+ *
+ * TODO(jat): consider changing to 24-bit integers for better performance
+ * in browsers.
+ */
+ transient int digits[];
+
+ /**
+ * The length of this in measured in ints. Can be less than digits.length().
+ */
+ transient int numberLength;
+
+ /**
+ * The sign of this.
+ */
+ transient int sign;
+
+ private transient int firstNonzeroDigit = -2;
+
+ /**
+ * Cache for the hash code.
+ */
+ private transient int hashCode = 0;
+
+ /**
+ * 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) {
+ if (val.length == 0) {
+ // math.12=Zero length BigInteger
+ throw new NumberFormatException("Zero length BigInteger"); //$NON-NLS-1$
+ }
+ if (val[0] < 0) {
+ sign = -1;
+ putBytesNegativeToIntegers(val);
+ } else {
+ sign = 1;
+ putBytesPositiveToIntegers(val);
+ }
+ cutOffLeadingZeroes();
+ }
+
+ /**
+ * 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.
+ * @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) {
+ if (magnitude == null) {
+ throw new NullPointerException();
+ }
+ 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) {
+ if (element != 0) {
+ // math.14=signum-magnitude mismatch
+ throw new NumberFormatException("signum-magnitude mismatch"); //$NON-NLS-1$
+ }
+ }
+ }
+ if (magnitude.length == 0) {
+ sign = 0;
+ numberLength = 1;
+ digits = new int[] {0};
+ } else {
+ sign = signum;
+ putBytesPositiveToIntegers(magnitude);
+ cutOffLeadingZeroes();
+ }
+ }
+
+ /**
+ * Constructs a random {@code BigInteger} instance in the range [0,
+ * 2^(bitLength)-1] which is probably prime. The probability that the returned
+ * {@code BigInteger} is prime is beyond (1-1/2^certainty).
+ *
+ * @param bitLength length of the new {@code BigInteger} in bits.
+ * @param certainty tolerated primality uncertainty.
+ * @param rnd is an optional random generator to be used.
+ * @throws ArithmeticException if {@code bitLength} < 2.
+ */
+ public BigInteger(int bitLength, int certainty, Random rnd) {
+ if (bitLength < 2) {
+ // math.1C=bitLength < 2
+ throw new ArithmeticException("bitLength < 2"); //$NON-NLS-1$
+ }
+ BigInteger me = Primality.consBigInteger(bitLength, certainty, rnd);
+ sign = me.sign;
+ numberLength = me.numberLength;
+ digits = me.digits;
+ }
+
+ /**
+ * Constructs a random non-negative {@code BigInteger} instance in the range
+ * [0, 2^(numBits)-1].
+ *
+ * @param numBits maximum length of the new {@code BigInteger} in bits.
+ * @param rnd is an optional random generator to be used.
+ * @throws IllegalArgumentException if {@code numBits} < 0.
+ */
+ public BigInteger(int numBits, Random rnd) {
+ if (numBits < 0) {
+ // math.1B=numBits must be non-negative
+ throw new IllegalArgumentException("numBits must be non-negative"); //$NON-NLS-1$
+ }
+ if (numBits == 0) {
+ sign = 0;
+ numberLength = 1;
+ digits = new int[] {0};
+ } else {
+ sign = 1;
+ numberLength = (numBits + 31) >> 5;
+ digits = new int[numberLength];
+ for (int i = 0; i < numberLength; i++) {
+ digits[i] = rnd.nextInt();
+ }
+ // Using only the necessary bits
+ digits[numberLength - 1] >>>= (-numBits) & 31;
+ cutOffLeadingZeroes();
+ }
+ }
+
+ /**
+ * Constructs a new {@code BigInteger} instance from the string
+ * representation. The string representation consists of an optional minus
+ * sign followed by a non-empty sequence of decimal digits.
+ *
+ * @param val string representation of the new {@code BigInteger}.
+ * @throws NullPointerException if {@code val == null}.
+ * @throws NumberFormatException if {@code val} is not a valid representation
+ * of a {@code BigInteger}.
+ */
+ public BigInteger(String val) {
+ this(val, 10);
+ }
+
+ /**
+ * Constructs a new {@code BigInteger} instance from the string
+ * representation. The string representation consists of an optional minus
+ * sign followed by a non-empty sequence of digits in the specified radix. For
+ * the conversion the method {@code Character.digit(char, radix)} is used.
+ *
+ * @param val string representation of the new {@code BigInteger}.
+ * @param radix the base to be used for the conversion.
+ * @throws NullPointerException if {@code val == null}.
+ * @throws NumberFormatException if {@code val} is not a valid representation
+ * of a {@code BigInteger} or if {@code radix < Character.MIN_RADIX}
+ * or {@code radix > Character.MAX_RADIX}.
+ */
+ public BigInteger(String val, int radix) {
+ if (val == null) {
+ throw new NullPointerException();
+ }
+ if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX)) {
+ // math.11=Radix out of range
+ throw new NumberFormatException("Radix out of range"); //$NON-NLS-1$
+ }
+ if (val.length() == 0) {
+ // math.12=Zero length BigInteger
+ throw new NumberFormatException("Zero length BigInteger"); //$NON-NLS-1$
+ }
+ setFromString(this, val, radix);
+ }
+
+ /**
+ * Constructs a number which array is of size 1.
+ *
+ * @param sign the sign of the number
+ * @param value the only one digit of array
+ */
+ BigInteger(int sign, int value) {
+ this.sign = sign;
+ numberLength = 1;
+ digits = new int[] {value};
+ }
+
+ /**
+ * Creates a new {@code BigInteger} with the given sign and magnitude. This
+ * constructor does not create a copy, so any changes to the reference will
+ * affect the new number.
+ *
+ * @param signum The sign of the number represented by {@code digits}
+ * @param digits The magnitude of the number
+ */
+ BigInteger(int signum, int digits[]) {
+ if (digits.length == 0) {
+ sign = 0;
+ numberLength = 1;
+ this.digits = new int[] {0};
+ } else {
+ sign = signum;
+ numberLength = digits.length;
+ this.digits = digits;
+ cutOffLeadingZeroes();
+ }
+ }
+
+ /**
+ * Constructs a number without to create new space. This construct should be
+ * used only if the three fields of representation are known.
+ *
+ * @param sign the sign of the number
+ * @param numberLength the length of the internal array
+ * @param digits a reference of some array created before
+ */
+ BigInteger(int sign, int numberLength, int[] digits) {
+ this.sign = sign;
+ this.numberLength = numberLength;
+ this.digits = digits;
+ }
+
+ /**
+ * Creates a new {@code BigInteger} whose value is equal to the specified
+ * {@code long}.
+ *
+ * @param sign the sign of the number
+ * @param val the value of the new {@code BigInteger}.
+ */
+ BigInteger(int sign, long val) {
+ // PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
+ this.sign = sign;
+ if ((val & 0xFFFFFFFF00000000L) == 0) {
+ // It fits in one 'int'
+ numberLength = 1;
+ digits = new int[] {(int) val};
+ } else {
+ numberLength = 2;
+ digits = new int[] {(int) val, (int) (val >> 32)};
+ }
+ }
+
+ /**
+ * Creates a new {@code BigInteger} whose value is equal to the specified
+ * {@code double} (which must be an integral value).
+ *
+ * @param sign the sign of the number
+ * @param val the value of the new {@code BigInteger}.
+ */
+ private BigInteger(int sign, double val) {
+ // PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
+ // ~~ forces coercion to 32 bits
+ this.sign = sign;
+ if (val < POW32) {
+ // It fits in one 'int'
+ numberLength = 1;
+ digits = new int[] { toUnsignedInt(val) };
+ } else {
+ numberLength = 2;
+ digits = new int[] { toUnsignedInt(val % POW32),
+ toUnsignedInt(val / POW32)};
+ }
+ }
+
+ /**
+ * Returns a (new) {@code BigInteger} whose value is the absolute value of
+ * {@code this}.
+ *
+ * @return {@code abs(this)}.
+ */
+ public BigInteger abs() {
+ return ((sign < 0) ? new BigInteger(1, numberLength, digits) : this);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this + val}.
+ *
+ * @param val value to be added to {@code this}.
+ * @return {@code this + val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger add(BigInteger val) {
+ return Elementary.add(this, val);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this & val}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param val value to be and'ed with {@code this}.
+ * @return {@code this & val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger and(BigInteger val) {
+ return Logical.and(this, val);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this & ~val}.
+ * Evaluating {@code x.andNot(val)} returns the same result as {@code
+ * x.and(val.not())}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param val value to be not'ed and then and'ed with {@code this}.
+ * @return {@code this & ~val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger andNot(BigInteger val) {
+ return Logical.andNot(this, val);
+ }
+
+ /**
+ * Use {@code bitLength(0)} if you want to know the length of the binary value
+ * in bits.
+ *
+ * Returns the number of bits in the binary representation of {@code this}
+ * which differ from the sign bit. If {@code this} is positive the result is
+ * equivalent to the number of bits set in the binary representation of
+ * {@code this}. If {@code this} is negative the result is equivalent to the
+ * number of bits set in the binary representation of {@code -this-1}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @return number of bits in the binary representation of {@code this} which
+ * differ from the sign bit
+ */
+ public int bitCount() {
+ return BitLevel.bitCount(this);
+ }
+
+ /**
+ * Returns the length of the value's two's complement representation without
+ * leading zeros for positive numbers / without leading ones for negative
+ * values.
+ *
+ * The two's complement representation of {@code this} will be at least
+ * {@code bitLength() + 1} bits long.
+ *
+ * The value will fit into an {@code int} if {@code bitLength() < 32} or into
+ * a {@code long} if {@code bitLength() < 64}.
+ *
+ * @return the length of the minimal two's complement representation for
+ * {@code this} without the sign bit.
+ */
+ public int bitLength() {
+ return BitLevel.bitLength(this);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} which has the same binary representation
+ * as {@code this} but with the bit at position n cleared. The result is
+ * equivalent to {@code this & ~(2^n)}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param n position where the bit in {@code this} has to be cleared.
+ * @return {@code this & ~(2^n)}.
+ * @throws ArithmeticException if {@code n < 0}.
+ */
+ public BigInteger clearBit(int n) {
+ if (testBit(n)) {
+ return BitLevel.flipBit(this, n);
+ }
+ return this;
+ }
+
+ /**
+ * Compares this {@code BigInteger} with {@code val}. Returns one of the three
+ * values 1, 0, or -1.
+ *
+ * @param val value to be compared with {@code this}.
+ * @return {@code 1} if {@code this > val}, {@code -1} if {@code this < val} ,
+ * {@code 0} if {@code this == val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public int compareTo(BigInteger val) {
+ if (sign > val.sign) {
+ return GREATER;
+ }
+ if (sign < val.sign) {
+ return LESS;
+ }
+ if (numberLength > val.numberLength) {
+ return sign;
+ }
+ if (numberLength < val.numberLength) {
+ return -val.sign;
+ }
+ // Equal sign and equal numberLength
+ return (sign * Elementary.compareArrays(digits, val.digits, numberLength));
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this / divisor}.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return {@code this / divisor}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ */
+ public BigInteger divide(BigInteger divisor) {
+ if (divisor.sign == 0) {
+ // math.17=BigInteger divide by zero
+ throw new ArithmeticException("BigInteger divide by zero"); //$NON-NLS-1$
+ }
+ int divisorSign = divisor.sign;
+ if (divisor.isOne()) {
+ return ((divisor.sign > 0) ? this : this.negate());
+ }
+ int thisSign = sign;
+ int thisLen = numberLength;
+ int divisorLen = divisor.numberLength;
+ if (thisLen + divisorLen == 2) {
+ long val = (digits[0] & 0xFFFFFFFFL) / (divisor.digits[0] & 0xFFFFFFFFL);
+ if (thisSign != divisorSign) {
+ val = -val;
+ }
+ return valueOf(val);
+ }
+ int cmp = ((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1)
+ : Elementary.compareArrays(digits, divisor.digits, thisLen));
+ if (cmp == EQUALS) {
+ return ((thisSign == divisorSign) ? ONE : MINUS_ONE);
+ }
+ if (cmp == LESS) {
+ return ZERO;
+ }
+ int resLength = thisLen - divisorLen + 1;
+ int resDigits[] = new int[resLength];
+ int resSign = ((thisSign == divisorSign) ? 1 : -1);
+ if (divisorLen == 1) {
+ Division.divideArrayByInt(resDigits, digits, thisLen, divisor.digits[0]);
+ } else {
+ Division.divide(resDigits, resLength, digits, thisLen, divisor.digits,
+ divisorLen);
+ }
+ BigInteger result = new BigInteger(resSign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Returns a {@code BigInteger} array which contains {@code this / divisor} at
+ * index 0 and {@code this % divisor} at index 1.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return {@code [this / divisor, this % divisor]}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @see #divide
+ * @see #remainder
+ */
+ public BigInteger[] divideAndRemainder(BigInteger divisor) {
+ int divisorSign = divisor.sign;
+ if (divisorSign == 0) {
+ // math.17=BigInteger divide by zero
+ throw new ArithmeticException("BigInteger divide by zero"); //$NON-NLS-1$
+ }
+ int divisorLen = divisor.numberLength;
+ int[] divisorDigits = divisor.digits;
+ if (divisorLen == 1) {
+ return Division.divideAndRemainderByInteger(this, divisorDigits[0],
+ divisorSign);
+ }
+ // res[0] is a quotient and res[1] is a remainder:
+ int[] thisDigits = digits;
+ int thisLen = numberLength;
+ int cmp = (thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1)
+ : Elementary.compareArrays(thisDigits, divisorDigits, thisLen);
+ if (cmp < 0) {
+ return new BigInteger[] {ZERO, this};
+ }
+ int thisSign = sign;
+ int quotientLength = thisLen - divisorLen + 1;
+ int remainderLength = divisorLen;
+ int quotientSign = ((thisSign == divisorSign) ? 1 : -1);
+ int quotientDigits[] = new int[quotientLength];
+ int remainderDigits[] = Division.divide(quotientDigits, quotientLength,
+ thisDigits, thisLen, divisorDigits, divisorLen);
+ BigInteger result0 = new BigInteger(quotientSign, quotientLength,
+ quotientDigits);
+ BigInteger result1 = new BigInteger(thisSign, remainderLength,
+ remainderDigits);
+ result0.cutOffLeadingZeroes();
+ result1.cutOffLeadingZeroes();
+ return new BigInteger[] {result0, result1};
+ }
+
+ /**
+ * Returns this {@code BigInteger} as an double value. If {@code this} is too
+ * big to be represented as an double, then {@code Double.POSITIVE_INFINITY}
+ * or {@code Double.NEGATIVE_INFINITY} is returned. Note, that not all
+ * integers x in the range [-Double.MAX_VALUE, Double.MAX_VALUE] can be
+ * represented as a double. The double representation has a mantissa of length
+ * 53. For example, 2^53+1 = 9007199254740993 is returned as double
+ * 9007199254740992.0.
+ *
+ * @return this {@code BigInteger} as a double value
+ */
+ @Override
+ public double doubleValue() {
+ return Double.parseDouble(this.toString());
+ }
+
+ /**
+ * Returns {@code true} if {@code x} is a BigInteger instance and if this
+ * instance is equal to this {@code BigInteger}.
+ *
+ * @param x object to be compared with {@code this}.
+ * @return true if {@code x} is a BigInteger and {@code this == x}, {@code
+ * false} otherwise.
+ */
+ @Override
+ public boolean equals(Object x) {
+ if (this == x) {
+ return true;
+ }
+ if (x instanceof BigInteger) {
+ BigInteger x1 = (BigInteger) x;
+ return sign == x1.sign && numberLength == x1.numberLength
+ && equalsArrays(x1.digits);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a new {@code BigInteger} which has the same binary representation
+ * as {@code this} but with the bit at position n flipped. The result is
+ * equivalent to {@code this ^ 2^n}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param n position where the bit in {@code this} has to be flipped.
+ * @return {@code this ^ 2^n}.
+ * @throws ArithmeticException if {@code n < 0}.
+ */
+ public BigInteger flipBit(int n) {
+ if (n < 0) {
+ // math.15=Negative bit address
+ throw new ArithmeticException("Negative bit address"); //$NON-NLS-1$
+ }
+ return BitLevel.flipBit(this, n);
+ }
+
+ /**
+ * Returns this {@code BigInteger} as an float value. If {@code this} is too
+ * big to be represented as an float, then {@code Float.POSITIVE_INFINITY} or
+ * {@code Float.NEGATIVE_INFINITY} is returned. Note, that not all integers x
+ * in the range [-Float.MAX_VALUE, Float.MAX_VALUE] can be represented as a
+ * float. The float representation has a mantissa of length 24. For example,
+ * 2^24+1 = 16777217 is returned as float 16777216.0.
+ *
+ * @return this {@code BigInteger} as a float value.
+ */
+ @Override
+ public float floatValue() {
+ return Float.parseFloat(this.toString());
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is greatest common divisor of
+ * {@code this} and {@code val}. If {@code this==0} and {@code val==0} then
+ * zero is returned, otherwise the result is positive.
+ *
+ * @param val value with which the greatest common divisor is computed.
+ * @return {@code gcd(this, val)}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger gcd(BigInteger val) {
+ BigInteger val1 = this.abs();
+ BigInteger val2 = val.abs();
+ // To avoid a possible division by zero
+ if (val1.signum() == 0) {
+ return val2;
+ } else if (val2.signum() == 0) {
+ return val1;
+ }
+
+ // Optimization for small operands
+ // (op2.bitLength() < 64) and (op1.bitLength() < 64)
+ if (((val1.numberLength == 1) || ((val1.numberLength == 2) && (val1.digits[1] > 0)))
+ && (val2.numberLength == 1 || (val2.numberLength == 2 && val2.digits[1] > 0))) {
+ return BigInteger.valueOf(Division.gcdBinary(val1.longValue(),
+ val2.longValue()));
+ }
+
+ return Division.gcdBinary(val1.copy(), val2.copy());
+ }
+
+ /**
+ * Returns the position of the lowest set bit in the two's complement
+ * representation of this {@code BigInteger}. If all bits are zero (this=0)
+ * then -1 is returned as result.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @return position of lowest bit if {@code this != 0}, {@code -1} otherwise
+ */
+ public int getLowestSetBit() {
+ if (sign == 0) {
+ return -1;
+ }
+ // (sign != 0) implies that exists some non zero digit
+ int i = getFirstNonzeroDigit();
+ return ((i << 5) + Integer.numberOfTrailingZeros(digits[i]));
+ }
+
+ /**
+ * Returns a hash code for this {@code BigInteger}.
+ *
+ * @return hash code for {@code this}.
+ */
+ @Override
+ public int hashCode() {
+ if (hashCode != 0) {
+ return hashCode;
+ }
+ for (int i = 0; i < digits.length; i++) {
+ hashCode = (hashCode * 33 + (digits[i] & 0xffffffff));
+ }
+ hashCode = hashCode * sign;
+ return hashCode;
+ }
+
+ /**
+ * Returns this {@code BigInteger} as an int value. If {@code this} is too big
+ * to be represented as an int, then {@code this} % 2^32 is returned.
+ *
+ * @return this {@code BigInteger} as an int value.
+ */
+ @Override
+ public int intValue() {
+ return (sign * digits[0]);
+ }
+
+ /**
+ * Tests whether this {@code BigInteger} is probably prime. If {@code true} is
+ * returned, then this is prime with a probability beyond (1-1/2^certainty).
+ * If {@code false} is returned, then this is definitely composite. If the
+ * argument {@code certainty} <= 0, then this method returns true.
+ *
+ * @param certainty tolerated primality uncertainty.
+ * @return {@code true}, if {@code this} is probably prime, {@code false}
+ * otherwise.
+ */
+ public boolean isProbablePrime(int certainty) {
+ return Primality.isProbablePrime(abs(), certainty);
+ }
+
+ /**
+ * Returns this {@code BigInteger} as an long value. If {@code this} is too
+ * big to be represented as an long, then {@code this} % 2^64 is returned.
+ *
+ * @return this {@code BigInteger} as a long value.
+ */
+ @Override
+ public long longValue() {
+ long value = (numberLength > 1) ? (((long) digits[1]) << 32)
+ | (digits[0] & 0xFFFFFFFFL) : (digits[0] & 0xFFFFFFFFL);
+ return (sign * value);
+ }
+
+ /**
+ * Returns the maximum of this {@code BigInteger} and {@code val}.
+ *
+ * @param val value to be used to compute the maximum with {@code this}
+ * @return {@code max(this, val)}
+ * @throws NullPointerException if {@code val == null}
+ */
+ public BigInteger max(BigInteger val) {
+ return ((this.compareTo(val) == GREATER) ? this : val);
+ }
+
+ /**
+ * Returns the minimum of this {@code BigInteger} and {@code val}.
+ *
+ * @param val value to be used to compute the minimum with {@code this}.
+ * @return {@code min(this, val)}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger min(BigInteger val) {
+ return ((this.compareTo(val) == LESS) ? this : val);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this mod m}. The
+ * modulus {@code m} must be positive. The result is guaranteed to be in the
+ * interval {@code [0, m)} (0 inclusive, m exclusive). The behavior of this
+ * function is not equivalent to the behavior of the % operator defined for
+ * the built-in {@code int}'s.
+ *
+ * @param m the modulus.
+ * @return {@code this mod m}.
+ * @throws NullPointerException if {@code m == null}.
+ * @throws ArithmeticException if {@code m < 0}.
+ */
+ public BigInteger mod(BigInteger m) {
+ if (m.sign <= 0) {
+ // math.18=BigInteger: modulus not positive
+ throw new ArithmeticException("BigInteger: modulus not positive"); //$NON-NLS-1$
+ }
+ BigInteger rem = remainder(m);
+ return ((rem.sign < 0) ? rem.add(m) : rem);
+ }
+
+ // @Override
+ // public double doubleValue() {
+ // return Conversion.bigInteger2Double(this);
+ // }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code 1/this mod m}. The
+ * modulus {@code m} must be positive. The result is guaranteed to be in the
+ * interval {@code [0, m)} (0 inclusive, m exclusive). If {@code this} is not
+ * relatively prime to m, then an exception is thrown.
+ *
+ * @param m the modulus.
+ * @return {@code 1/this mod m}.
+ * @throws NullPointerException if {@code m == null}
+ * @throws ArithmeticException if {@code m < 0 or} if {@code this} is not
+ * relatively prime to {@code m}
+ */
+ public BigInteger modInverse(BigInteger m) {
+ if (m.sign <= 0) {
+ // math.18=BigInteger: modulus not positive
+ throw new ArithmeticException("BigInteger: modulus not positive"); //$NON-NLS-1$
+ }
+ // If both are even, no inverse exists
+ if (!(testBit(0) || m.testBit(0))) {
+ // math.19=BigInteger not invertible.
+ throw new ArithmeticException("BigInteger not invertible."); //$NON-NLS-1$
+ }
+ if (m.isOne()) {
+ return ZERO;
+ }
+
+ // From now on: (m > 1)
+ BigInteger res = Division.modInverseMontgomery(abs().mod(m), m);
+ if (res.sign == 0) {
+ // math.19=BigInteger not invertible.
+ throw new ArithmeticException("BigInteger not invertible."); //$NON-NLS-1$
+ }
+
+ res = ((sign < 0) ? m.subtract(res) : res);
+ return res;
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this^exponent mod m}
+ * . The modulus {@code m} must be positive. The result is guaranteed to be in
+ * the interval {@code [0, m)} (0 inclusive, m exclusive). If the exponent is
+ * negative, then {@code this.modInverse(m)^(-exponent) mod m)} is computed.
+ * The inverse of this only exists if {@code this} is relatively prime to m,
+ * otherwise an exception is thrown.
+ *
+ * @param exponent the exponent.
+ * @param m the modulus.
+ * @return {@code this^exponent mod val}.
+ * @throws NullPointerException if {@code m == null} or {@code exponent ==
+ * null}.
+ * @throws ArithmeticException if {@code m < 0} or if {@code exponent<0} and
+ * this is not relatively prime to {@code m}.
+ */
+ public BigInteger modPow(BigInteger exponent, BigInteger m) {
+ if (m.sign <= 0) {
+ // math.18=BigInteger: modulus not positive
+ throw new ArithmeticException("BigInteger: modulus not positive"); //$NON-NLS-1$
+ }
+ BigInteger base = this;
+
+ if (m.isOne() | (exponent.sign > 0 & base.sign == 0)) {
+ return BigInteger.ZERO;
+ }
+ if (base.sign == 0 && exponent.sign == 0) {
+ return BigInteger.ONE;
+ }
+ if (exponent.sign < 0) {
+ base = modInverse(m);
+ exponent = exponent.negate();
+ }
+ // From now on: (m > 0) and (exponent >= 0)
+ BigInteger res = (m.testBit(0)) ? Division.oddModPow(base.abs(), exponent,
+ m) : Division.evenModPow(base.abs(), exponent, m);
+ if ((base.sign < 0) && exponent.testBit(0)) {
+ // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m
+ res = m.subtract(BigInteger.ONE).multiply(res).mod(m);
+ }
+ // else exponent is even, so base^exp is positive
+ return res;
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this * val}.
+ *
+ * @param val value to be multiplied with {@code this}.
+ * @return {@code this * val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger multiply(BigInteger val) {
+ // This let us to throw NullPointerException when val == null
+ if (val.sign == 0) {
+ return ZERO;
+ }
+ if (sign == 0) {
+ return ZERO;
+ }
+ return Multiplication.multiply(this, val);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is the {@code -this}.
+ *
+ * @return {@code -this}.
+ */
+ public BigInteger negate() {
+ return ((sign == 0) ? this : new BigInteger(-sign, numberLength, digits));
+ }
+
+ /**
+ * Returns the smallest integer x > {@code this} which is probably prime as a
+ * {@code BigInteger} instance. The probability that the returned {@code
+ * BigInteger} is prime is beyond (1-1/2^80).
+ *
+ * @return smallest integer > {@code this} which is robably prime.
+ * @throws ArithmeticException if {@code this < 0}.
+ */
+ public BigInteger nextProbablePrime() {
+ if (sign < 0) {
+ // math.1A=start < 0: {0}
+ throw new ArithmeticException("start < 0: " + this); //$NON-NLS-1$
+ }
+ return Primality.nextProbablePrime(this);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code ~this}. The result
+ * of this operation is {@code -this-1}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @return {@code ~this}.
+ */
+ public BigInteger not() {
+ return Logical.not(this);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this | val}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param val value to be or'ed with {@code this}.
+ * @return {@code this | val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger or(BigInteger val) {
+ return Logical.or(this, val);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this ^ exp}.
+ *
+ * @param exp exponent to which {@code this} is raised.
+ * @return {@code this ^ exp}.
+ * @throws ArithmeticException if {@code exp < 0}.
+ */
+ public BigInteger pow(int exp) {
+ if (exp < 0) {
+ // math.16=Negative exponent
+ throw new ArithmeticException("Negative exponent"); //$NON-NLS-1$
+ }
+ if (exp == 0) {
+ return ONE;
+ } else if (exp == 1 || equals(ONE) || equals(ZERO)) {
+ return this;
+ }
+
+ // if even take out 2^x factor which we can
+ // calculate by shifting.
+ if (!testBit(0)) {
+ int x = 1;
+ while (!testBit(x)) {
+ x++;
+ }
+ return getPowerOfTwo(x * exp).multiply(this.shiftRight(x).pow(exp));
+ }
+ return Multiplication.pow(this, exp);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this % divisor}.
+ * Regarding signs this methods has the same behavior as the % operator on
+ * int's, i.e. the sign of the remainder is the same as the sign of this.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return {@code this % divisor}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ */
+ public BigInteger remainder(BigInteger divisor) {
+ if (divisor.sign == 0) {
+ // math.17=BigInteger divide by zero
+ throw new ArithmeticException("BigInteger divide by zero"); //$NON-NLS-1$
+ }
+ int thisLen = numberLength;
+ int divisorLen = divisor.numberLength;
+ if (((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1)
+ : Elementary.compareArrays(digits, divisor.digits, thisLen)) == LESS) {
+ return this;
+ }
+ int resLength = divisorLen;
+ int resDigits[] = new int[resLength];
+ if (resLength == 1) {
+ resDigits[0] = Division.remainderArrayByInt(digits, thisLen,
+ divisor.digits[0]);
+ } else {
+ int qLen = thisLen - divisorLen + 1;
+ resDigits = Division.divide(null, qLen, digits, thisLen, divisor.digits,
+ divisorLen);
+ }
+ BigInteger result = new BigInteger(sign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Returns a new {@code BigInteger} which has the same binary representation
+ * as {@code this} but with the bit at position n set. The result is
+ * equivalent to {@code this | 2^n}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param n position where the bit in {@code this} has to be set.
+ * @return {@code this | 2^n}.
+ * @throws ArithmeticException if {@code n < 0}.
+ */
+ public BigInteger setBit(int n) {
+ if (!testBit(n)) {
+ return BitLevel.flipBit(this, n);
+ }
+ return this;
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this << n}. The
+ * result is equivalent to {@code this * 2^n} if n >= 0. The shift distance
+ * may be negative which means that {@code this} is shifted right. The result
+ * then corresponds to {@code floor(this / 2^(-n))}.
+ *
+ * Implementation Note: Usage of this method on negative values is not
+ * recommended as the current implementation is not efficient.
+ *
+ * @param n shift distance.
+ * @return {@code this << n} if {@code n >= 0}; {@code this >> (-n)}.
+ * otherwise
+ */
+ public BigInteger shiftLeft(int n) {
+ if ((n == 0) || (sign == 0)) {
+ return this;
+ }
+ return ((n > 0) ? BitLevel.shiftLeft(this, n) : BitLevel.shiftRight(this,
+ -n));
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this >> n}. For
+ * negative arguments, the result is also negative. The shift distance may be
+ * negative which means that {@code this} is shifted left.
+ *
+ * Implementation Note: Usage of this method on negative values is not
+ * recommended as the current implementation is not efficient.
+ *
+ * @param n shift distance
+ * @return {@code this >> n} if {@code n >= 0}; {@code this << (-n)} otherwise
+ */
+ public BigInteger shiftRight(int n) {
+ if ((n == 0) || (sign == 0)) {
+ return this;
+ }
+ return ((n > 0) ? BitLevel.shiftRight(this, n) : BitLevel.shiftLeft(this,
+ -n));
+ }
+
+ /**
+ * Returns the sign of this {@code BigInteger}.
+ *
+ * @return {@code -1} if {@code this < 0}, {@code 0} if {@code this == 0},
+ * {@code 1} if {@code this > 0}.
+ */
+ public int signum() {
+ return sign;
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this - val}.
+ *
+ * @param val value to be subtracted from {@code this}.
+ * @return {@code this - val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public BigInteger subtract(BigInteger val) {
+ return Elementary.subtract(this, val);
+ }
+
+ /**
+ * Tests whether the bit at position n in {@code this} is set. The result is
+ * equivalent to {@code this & (2^n) != 0}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param n position where the bit in {@code this} has to be inspected.
+ * @return {@code this & (2^n) != 0}.
+ * @throws ArithmeticException if {@code n < 0}.
+ */
+ public boolean testBit(int n) {
+ if (n == 0) {
+ return ((digits[0] & 1) != 0);
+ }
+ if (n < 0) {
+ // math.15=Negative bit address
+ throw new ArithmeticException("Negative bit address"); //$NON-NLS-1$
+ }
+ int intCount = n >> 5;
+ if (intCount >= numberLength) {
+ return (sign < 0);
+ }
+ int digit = digits[intCount];
+ n = (1 << (n & 31)); // int with 1 set to the needed position
+ if (sign < 0) {
+ int firstNonZeroDigit = getFirstNonzeroDigit();
+ if (intCount < firstNonZeroDigit) {
+ return false;
+ } else if (firstNonZeroDigit == intCount) {
+ digit = -digit;
+ } else {
+ digit = ~digit;
+ }
+ }
+ return ((digit & n) != 0);
+ }
+
+ /**
+ * Returns the two's complement representation of this BigInteger in a byte
+ * array.
+ *
+ * @return two's complement representation of {@code this}.
+ */
+ public byte[] toByteArray() {
+ if (this.sign == 0) {
+ return new byte[] {0};
+ }
+ BigInteger temp = this;
+ int bitLen = bitLength();
+ int iThis = getFirstNonzeroDigit();
+ int bytesLen = (bitLen >> 3) + 1;
+ /*
+ * Puts the little-endian int array representing the magnitude of this
+ * BigInteger into the big-endian byte array.
+ */
+ byte[] bytes = new byte[bytesLen];
+ int firstByteNumber = 0;
+ int highBytes;
+ int digitIndex = 0;
+ int bytesInInteger = 4;
+ int digit;
+ int hB;
+
+ if (bytesLen - (numberLength << 2) == 1) {
+ bytes[0] = (byte) ((sign < 0) ? -1 : 0);
+ highBytes = 4;
+ firstByteNumber++;
+ } else {
+ hB = bytesLen & 3;
+ highBytes = (hB == 0) ? 4 : hB;
+ }
+
+ digitIndex = iThis;
+ bytesLen -= iThis << 2;
+
+ if (sign < 0) {
+ digit = -temp.digits[digitIndex];
+ digitIndex++;
+ if (digitIndex == numberLength) {
+ bytesInInteger = highBytes;
+ }
+ for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
+ bytes[--bytesLen] = (byte) digit;
+ }
+ while (bytesLen > firstByteNumber) {
+ digit = ~temp.digits[digitIndex];
+ digitIndex++;
+ if (digitIndex == numberLength) {
+ bytesInInteger = highBytes;
+ }
+ for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
+ bytes[--bytesLen] = (byte) digit;
+ }
+ }
+ } else {
+ while (bytesLen > firstByteNumber) {
+ digit = temp.digits[digitIndex];
+ digitIndex++;
+ if (digitIndex == numberLength) {
+ bytesInInteger = highBytes;
+ }
+ for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
+ bytes[--bytesLen] = (byte) digit;
+ }
+ }
+ }
+ return bytes;
+ }
+
+ /**
+ * Returns a string representation of this {@code BigInteger} in decimal form.
+ *
+ * @return a string representation of {@code this} in decimal form.
+ */
+ @Override
+ public String toString() {
+ return Conversion.toDecimalScaledString(this, 0);
+ }
+
+ /**
+ * Returns a string containing a string representation of this {@code
+ * BigInteger} with base radix. If {@code radix} is less than
+ * {@link Character#MIN_RADIX} or greater than {@link Character#MAX_RADIX}
+ * then a decimal representation is returned. The characters of the string
+ * representation are generated with method {@link Character#forDigit}.
+ *
+ * @param radix base to be used for the string representation.
+ * @return a string representation of this with radix 10.
+ */
+ public String toString(int radix) {
+ return Conversion.bigInteger2String(this, radix);
+ }
+
+ /**
+ * Returns a new {@code BigInteger} whose value is {@code this ^ val}.
+ *
+ * Implementation Note: Usage of this method is not recommended as the
+ * current implementation is not efficient.
+ *
+ * @param val value to be xor'ed with {@code this}
+ * @return {@code this ^ val}
+ * @throws NullPointerException if {@code val == null}
+ */
+ public BigInteger xor(BigInteger val) {
+ return Logical.xor(this, val);
+ }
+
+ /*
+ * Returns a copy of the current instance to achieve immutability
+ */
+ BigInteger copy() {
+ int[] copyDigits = new int[numberLength];
+ System.arraycopy(digits, 0, copyDigits, 0, numberLength);
+ return new BigInteger(sign, numberLength, copyDigits);
+ }
+
+ /* Private Methods */
+
+ /**
+ * Decreases {@code numberLength} if there are zero high elements.
+ */
+ final void cutOffLeadingZeroes() {
+ while ((numberLength > 0) && (digits[--numberLength] == 0)) {
+ // Empty
+ }
+ if (digits[numberLength++] == 0) {
+ sign = 0;
+ }
+ }
+
+ boolean equalsArrays(final int[] b) {
+ int i;
+ for (i = numberLength - 1; (i >= 0) && (digits[i] == b[i]); i--) {
+ // Empty
+ }
+ return i < 0;
+ }
+
+ int getFirstNonzeroDigit() {
+ if (firstNonzeroDigit == -2) {
+ int i;
+ if (this.sign == 0) {
+ i = -1;
+ } else {
+ for (i = 0; digits[i] == 0; i++) {
+ // Empty
+ }
+ }
+ firstNonzeroDigit = i;
+ }
+ return firstNonzeroDigit;
+ }
+
+ /**
+ * Tests if {@code this.abs()} is equals to {@code ONE}.
+ */
+ boolean isOne() {
+ return ((numberLength == 1) && (digits[0] == 1));
+ }
+
+ BigInteger shiftLeftOneBit() {
+ return (sign == 0) ? this : BitLevel.shiftLeftOneBit(this);
+ }
+
+ void unCache() {
+ firstNonzeroDigit = -2;
+ }
+
+ /**
+ * Puts a big-endian byte array into a little-endian applying two complement.
+ */
+ private void putBytesNegativeToIntegers(byte[] byteValues) {
+ int bytesLen = byteValues.length;
+ int highBytes = bytesLen & 3;
+ numberLength = (bytesLen >> 2) + ((highBytes == 0) ? 0 : 1);
+ digits = new int[numberLength];
+ int i = 0;
+ // Setting the sign
+ 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;
+ 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] = ~digits[i];
+ i++;
+ }
+ break;
+ }
+ i++;
+ }
+ 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++) {
+ digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
+ }
+ digits[i] = ~digits[i];
+ } else {
+ for (int j = 0; j < bytesLen; j++) {
+ digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
+ }
+ digits[i] = -digits[i];
+ }
+ }
+ }
+
+ /**
+ * Puts a big-endian byte array into a little-endian int array.
+ */
+ private void putBytesPositiveToIntegers(byte[] byteValues) {
+ int bytesLen = byteValues.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;
+ }
+ // Put the first bytes in the highest element of the int array
+ for (int j = 0; j < bytesLen; j++) {
+ digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
+ }
+ }
+}
diff --git a/gwt/jre/java/math/BitLevel.java b/gwt/jre/java/math/BitLevel.java
new file mode 100644
index 0000000..82e88c9
--- /dev/null
+++ b/gwt/jre/java/math/BitLevel.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+/**
+ * Static library that provides all the bit level operations for
+ * {@link BigInteger}. The operations are:
+ * The rounding mode is one of {@link RoundingMode#UP},
+ * {@link RoundingMode#DOWN}, {@link RoundingMode#CEILING},
+ * {@link RoundingMode#FLOOR}, {@link RoundingMode#HALF_UP},
+ * {@link RoundingMode#HALF_DOWN}, {@link RoundingMode#HALF_EVEN}, or
+ * {@link RoundingMode#UNNECESSARY}.
+ *
+ * @return the rounding mode.
+ */
+ public RoundingMode getRoundingMode() {
+ return roundingMode;
+ }
+
+ /**
+ * Returns the hash code for this {@code MathContext} instance.
+ *
+ * @return the hash code for this {@code MathContext}.
+ */
+ @Override
+ public int hashCode() {
+ // Make place for the necessary bits to represent 8 rounding modes
+ return ((precision << 3) | roundingMode.ordinal());
+ }
+
+ /**
+ * Returns the string representation for this {@code MathContext} instance.
+ * The string has the form {@code
+ * "precision=null
is returned if this
+ * Writer has been closed.
+ *
+ * @return the String describing the converter or null if this Writer is
+ * closed.
+ */
+
+ public String getEncoding() {
+ return enc;
+ }
+
+ /**
+ * Writes count
characters starting at offset
+ * in buf
to this Writer. The characters are immediately
+ * converted to bytes by the character converter and stored in a local
+ * buffer. If the buffer becomes full as a result of this write, this Writer
+ * is flushed.
+ *
+ * @param buf
+ * the non-null array containing characters to write.
+ * @param offset
+ * offset in buf to retrieve characters
+ * @param count
+ * maximum number of characters to write
+ *
+ * @throws IOException
+ * If this OutputStreamWriter has already been closed or some
+ * other IOException occurs.
+ * @throws IndexOutOfBoundsException
+ * If offset or count is outside of bounds.
+ */
+ @Override
+ public void write(char[] buf, int offset, int count) throws IOException {
+ char[] sb = new char[count];
+ for (int i=0; icount
characters starting at offset
+ * in str
to this Writer. The characters are immediately
+ * converted to bytes by the character converter and stored in a local
+ * buffer. If the buffer becomes full as a result of this write, this Writer
+ * is flushed.
+ *
+ * @param str
+ * the non-null String containing characters to write.
+ * @param offset
+ * offset in str to retrieve characters
+ * @param count
+ * maximum number of characters to write
+ *
+ * @throws IOException
+ * If this OutputStreamWriter has already been closed or some
+ * other IOException occurs.
+ * @throws IndexOutOfBoundsException
+ * If count is negative
+ * @throws StringIndexOutOfBoundsException
+ * If offset is negative or offset + count is outside of bounds
+ */
+ @Override
+ public void write(String str, int offset, int count) throws IOException {
+ synchronized (lock) {
+ char[] chars = new char[count];
+ str.getChars(0, count, chars, 0);
+
+ write(chars);
+ }
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/PushbackInputStream.java b/gwt/jre/java/io/PushbackInputStream.java
new file mode 100644
index 0000000..c4c2041
--- /dev/null
+++ b/gwt/jre/java/io/PushbackInputStream.java
@@ -0,0 +1,335 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * PushbackInputStream is a filter class which allows bytes read to be pushed
+ * back into the stream so that they can be reread. Parsers may find this
+ * useful. There is a progammable limit to the number of bytes which may be
+ * pushed back. If the buffer of pushed back bytes is empty, bytes are read from
+ * the source input stream.
+ */
+public class PushbackInputStream extends FilterInputStream {
+ /**
+ * The byte
array containing the bytes to read.
+ */
+ protected byte[] buf;
+
+ /**
+ * The current position within the byte array buf
. A value
+ * equal to buf.length indicates no bytes available. A value of 0 indicates
+ * the buffer is full.
+ */
+ protected int pos;
+
+ /**
+ * Constructs a new PushbackInputStream on the InputStream in
.
+ * The size of the pushback buffer is set to the default, or 1 byte.
+ *
+ * @param in
+ * the InputStream to allow pushback operations on.
+ */
+ public PushbackInputStream(InputStream in) {
+ super(in);
+ buf = (in == null) ? null : new byte[1];
+ pos = 1;
+ }
+
+ /**
+ * Constructs a new PushbackInputStream on the InputStream in
.
+ * The size of the pushback buffer is set to size
.
+ *
+ * @param in
+ * the InputStream to allow pushback operations on.
+ * @param size
+ * the size of the pushback buffer (size>=0
).
+ */
+ public PushbackInputStream(InputStream in, int size) {
+ super(in);
+ if (size <= 0) {
+ throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
+ }
+ buf = (in == null) ? null : new byte[size];
+ pos = size;
+ }
+
+ /**
+ * Answers a int representing then number of bytes that are available before
+ * this PushbackInputStream will block. This method returns the number of
+ * bytes available in the pushback buffer plus those available in the target
+ * stream.
+ *
+ * @return int the number of bytes available before blocking.
+ *
+ * @throws java.io.IOException
+ * If an error occurs in this stream.
+ */
+ @Override
+ public int available() throws IOException {
+ if (buf == null) {
+ throw new IOException();
+ }
+ return buf.length - pos + in.available();
+ }
+
+ /**
+ * Close this PushbackInputStream. This implementation closes the target
+ * stream.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this stream.
+ */
+ @Override
+ public void close() throws IOException {
+ if (in != null) {
+ in.close();
+ in = null;
+ buf = null;
+ }
+ }
+
+ /**
+ * Answers a boolean indicating whether or not this PushbackInputStream
+ * supports mark() and reset(). This implementation always answers false
+ * since PushbackInputStreams do not support mark/reset.
+ *
+ * @return boolean indicates whether or not mark() and reset() are
+ * supported.
+ */
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Reads a single byte from this PushbackInputStream and returns the result
+ * as an int. The low-order byte is returned or -1 of the end of stream was
+ * encountered. If the pushback buffer does not contain any available bytes
+ * then a byte from the target input stream is returned.
+ *
+ * @return int The byte read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If an IOException occurs.
+ */
+ @Override
+ public int read() throws IOException {
+ if (buf == null) {
+ throw new IOException();
+ }
+ // Is there a pushback byte available?
+ if (pos < buf.length) {
+ return (buf[pos++] & 0xFF);
+ }
+ // Assume read() in the InputStream will return low-order byte or -1
+ // if end of stream.
+ return in.read();
+ }
+
+ /**
+ * Reads at most length
bytes from this PushbackInputStream
+ * and stores them in byte array buffer
starting at
+ * offset
. Answer the number of bytes actually read or -1 if
+ * no bytes were read and end of stream was encountered. This implementation
+ * reads bytes from the pushback buffer first, then the target stream if
+ * more bytes are required to satisfy count
.
+ *
+ * @param buffer
+ * the byte array in which to store the read bytes.
+ * @param offset
+ * the offset in buffer
to store the read bytes.
+ * @param length
+ * the maximum number of bytes to store in buffer
.
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If an IOException occurs.
+ */
+ @Override
+ public int read(byte[] buffer, int offset, int length) throws IOException {
+ if (buf == null) {
+ throw new IOException();
+ }
+ if (buffer == null) {
+ throw new NullPointerException();
+ }
+ // avoid int overflow
+ if (offset < 0 || offset > buffer.length || length < 0
+ || length > buffer.length - offset) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ int copiedBytes = 0, copyLength = 0, newOffset = offset;
+ // Are there pushback bytes available?
+ if (pos < buf.length) {
+ copyLength = (buf.length - pos >= length) ? length : buf.length
+ - pos;
+ System.arraycopy(buf, pos, buffer, newOffset, copyLength);
+ newOffset += copyLength;
+ copiedBytes += copyLength;
+ // Use up the bytes in the local buffer
+ pos += copyLength;
+ }
+ // Have we copied enough?
+ if (copyLength == length) {
+ return length;
+ }
+ int inCopied = in.read(buffer, newOffset, length - copiedBytes);
+ if (inCopied > 0) {
+ return inCopied + copiedBytes;
+ }
+ if (copiedBytes == 0) {
+ return inCopied;
+ }
+ return copiedBytes;
+ }
+
+ /**
+ * Skips count
number of bytes in this PushbackInputStream.
+ * Subsequent read()
's will not return these bytes unless
+ * reset()
is used. This implementation skips
+ * count
number of bytes in the buffer and/or the target
+ * stream.
+ *
+ * @param count
+ * the number of bytes to skip.
+ * @return the number of bytes actually skipped.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ @Override
+ public long skip(long count) throws IOException {
+ if (in == null) {
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+ }
+ if (count <= 0) {
+ return 0;
+ }
+ int numSkipped = 0;
+ if (pos < buf.length) {
+ numSkipped += (count < buf.length - pos) ? count : buf.length - pos;
+ pos += numSkipped;
+ }
+ if (numSkipped < count) {
+ numSkipped += in.skip(count - numSkipped);
+ }
+ return numSkipped;
+ }
+
+ /**
+ * Push back all the bytes in buffer
. The bytes are pushed
+ * so that they would be read back buffer[0], buffer[1], etc. If the push
+ * back buffer cannot handle the entire contents of buffer
,
+ * an IOException will be thrown. Some of the buffer may already be in the
+ * buffer after the exception is thrown.
+ *
+ * @param buffer
+ * the byte array containing bytes to push back into the stream.
+ *
+ * @throws IOException
+ * If the pushback buffer becomes, or is, full.
+ */
+ public void unread(byte[] buffer) throws IOException {
+ unread(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Push back length
number of bytes in buffer
+ * starting at offset
. The bytes are pushed so that they
+ * would be read back buffer[offset], buffer[offset+1], etc. If the push
+ * back buffer cannot handle the bytes copied from buffer
,
+ * an IOException will be thrown. Some of the bytes may already be in the
+ * buffer after the exception is thrown.
+ *
+ * @param buffer
+ * the byte array containing bytes to push back into the stream.
+ * @param offset
+ * the location to start taking bytes to push back.
+ * @param length
+ * the number of bytes to push back.
+ *
+ * @throws IOException
+ * If the pushback buffer becomes, or is, full.
+ */
+ public void unread(byte[] buffer, int offset, int length)
+ throws IOException {
+ if (length > pos) {
+ // Pushback buffer full
+ throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
+ }
+ // avoid int overflow
+ if (offset < 0 || offset > buffer.length || length < 0
+ || length > buffer.length - offset) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ for (int i = offset + length - 1; i >= offset; i--) {
+ unread(buffer[i]);
+ }
+ }
+
+ /**
+ * Push back one byte
. Takes the byte oneByte
+ * and puts in in the local buffer of bytes to read back before accessing
+ * the target input stream.
+ *
+ * @param oneByte
+ * the byte to push back into the stream.
+ *
+ * @throws IOException
+ * If the pushback buffer is already full.
+ */
+ public void unread(int oneByte) throws IOException {
+ if (buf == null) {
+ throw new IOException();
+ }
+ if (pos == 0) {
+ throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
+ }
+ buf[--pos] = (byte) oneByte;
+ }
+
+ /**
+ * Make a mark of the current position in the stream but the mark method
+ * does nothing.
+ *
+ * @param readlimit
+ * the maximum number of bytes that are able to be read before
+ * the mark becomes invalid
+ * @override the method mark in FilterInputStream
+ */
+ @Override
+ public void mark(int readlimit) {
+ return;
+ }
+
+ /**
+ * Reset current position to the mark made previously int the stream, but
+ * the reset method will throw IOException and do nothing else if called.
+ *
+ * @override the method reset in FilterInputStream
+ * @throws IOException
+ * If the method is called
+ */
+ @Override
+ public void reset() throws IOException {
+ throw new IOException();
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/Reader.java b/gwt/jre/java/io/Reader.java
new file mode 100644
index 0000000..bba92c0
--- /dev/null
+++ b/gwt/jre/java/io/Reader.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * Reader is an Abstract class for reading Character Streams. Subclasses of
+ * Reader must implement the methods read(char[], int, int)
and
+ * close()
.
+ *
+ * @see Writer
+ */
+public abstract class Reader {
+ /**
+ * The object used to synchronize access to the reader.
+ */
+ protected Object lock;
+
+ /**
+ * Constructs a new character stream Reader using this
as the
+ * Object to synchronize critical regions around.
+ */
+ protected Reader() {
+ super();
+ lock = this;
+ }
+
+ /**
+ * Constructs a new character stream Reader using lock
as the
+ * Object to synchronize critical regions around.
+ *
+ * @param lock
+ * the Object
to synchronize critical regions
+ * around.
+ */
+ protected Reader(Object lock) {
+ if (lock == null) {
+ throw new NullPointerException();
+ }
+ this.lock = lock;
+ }
+
+ /**
+ * Close this Reader. This must be implemented by any concrete subclasses.
+ * The implementation should free any resources associated with the Reader.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this Reader.
+ */
+ public abstract void close() throws IOException;
+
+ /**
+ * Set a Mark position in this Reader. The parameter readLimit
+ * indicates how many characters can be read before a mark is invalidated.
+ * Sending reset() will reposition the reader back to the marked position
+ * provided readLimit
has not been surpassed.
+ * true
if mark() and reset() are supported,
+ * false
otherwise. This implementation returns
+ * false
.
+ */
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Reads a single character from this reader and returns the result as an
+ * int. The 2 higher-order characters are set to 0. If the end of reader was
+ * encountered then return -1.
+ *
+ * @return the character read or -1 if end of reader.
+ *
+ * @throws IOException
+ * If the Reader is already closed or some other IO error
+ * occurs.
+ */
+ public int read() throws IOException {
+ synchronized (lock) {
+ char charArray[] = new char[1];
+ if (read(charArray, 0, 1) != -1) {
+ return charArray[0];
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Reads characters from this Reader and stores them in the character array
+ * buf
starting at offset 0. Returns the number of characters
+ * actually read or -1 if the end of reader was encountered.
+ *
+ * @param buf
+ * character array to store the read characters
+ * @return how many characters were successfully read in or else -1 if the
+ * end of the reader was detected.
+ *
+ * @throws IOException
+ * If the Reader is already closed or some other IO error
+ * occurs.
+ */
+ public int read(char buf[]) throws IOException {
+ return read(buf, 0, buf.length);
+ }
+
+ /**
+ * Reads at most count
characters from this Reader and stores
+ * them at offset
in the character array buf
.
+ * Returns the number of characters actually read or -1 if the end of reader
+ * was encountered.
+ *
+ * @param buf
+ * character array to store the read characters
+ * @param offset
+ * offset in buf to store the read characters
+ * @param count
+ * how many characters should be read in
+ * @return how many characters were successfully read in or else -1 if the
+ * end of the reader was detected.
+ *
+ * @throws IOException
+ * If the Reader is already closed or some other IO error
+ * occurs.
+ */
+ public abstract int read(char buf[], int offset, int count)
+ throws IOException;
+
+ /**
+ * Answers a boolean
indicating whether or not this Reader is
+ * ready to be read without blocking. If the result is true
,
+ * the next read()
will not block. If the result is
+ * false
this Reader may or may not block when
+ * read()
is sent.
+ *
+ * @return true
if the receiver will not block when
+ * read()
is called, false
if unknown
+ * or blocking will occur.
+ *
+ * @throws IOException
+ * If the Reader is already closed or some other IO error
+ * occurs.
+ */
+ public boolean ready() throws IOException {
+ return false;
+ }
+
+ /**
+ * Reset this Readers position to the last mark()
location.
+ * Invocations of read()/skip()
will occur from this new
+ * location. If this Reader was not marked, the implementation of
+ * reset()
is implementation specific. See the comment for
+ * the specific Reader subclass for implementation details. The default
+ * action is to throw IOException
.
+ *
+ * @throws IOException
+ * If a problem occured or the receiver does not support
+ * mark()/reset()
.
+ */
+ public void reset() throws IOException {
+ throw new IOException();
+ }
+
+ /**
+ * Skips count
number of characters in this Reader.
+ * Subsequent read()
's will not return these characters
+ * unless reset()
is used. This method may perform multiple
+ * reads to read count
characters.
+ *
+ * @param count
+ * how many characters should be passed over
+ * @return how many characters were successfully passed over
+ *
+ * @throws IOException
+ * If the Reader is closed when the call is made or if an IO
+ * error occurs during the operation.
+ */
+ public long skip(long count) throws IOException {
+ if (count < 0) {
+ throw new IllegalArgumentException();
+ }
+ synchronized (lock) {
+ long skipped = 0;
+ int toRead = count < 512 ? (int) count : 512;
+ char charsSkipped[] = new char[toRead];
+ while (skipped < count) {
+ int read = read(charsSkipped, 0, toRead);
+ if (read == -1) {
+ return skipped;
+ }
+ skipped += read;
+ if (read < toRead) {
+ return skipped;
+ }
+ if (count - skipped < toRead) {
+ toRead = (int) (count - skipped);
+ }
+ }
+ return skipped;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/StringReader.java b/gwt/jre/java/io/StringReader.java
new file mode 100644
index 0000000..3b81233
--- /dev/null
+++ b/gwt/jre/java/io/StringReader.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * A specialized {@link Reader} that reads characters from a {@code String} in
+ * a sequential manner.
+ *
+ * @see StringWriter
+ */
+public class StringReader extends Reader {
+ private String str;
+
+ private int markpos = -1;
+
+ private int pos;
+
+ private int count;
+
+ /**
+ * Construct a new {@code StringReader} with {@code str} as source. The size
+ * of the reader is set to the {@code length()} of the string and the Object
+ * to synchronize access through is set to {@code str}.
+ *
+ * @param str
+ * the source string for this reader.
+ */
+ public StringReader(String str) {
+ super();
+ this.str = str;
+ this.count = str.length();
+ }
+
+ /**
+ * Closes this reader. Once it is closed, read operations on this reader
+ * will throw an {@code IOException}. Only the first invocation of this
+ * method has any effect.
+ */
+ @Override
+ public void close() {
+ str = null;
+ }
+
+ /**
+ * Returns a boolean indicating whether this reader is closed.
+ *
+ * @return {@code true} if closed, otherwise {@code false}.
+ */
+ private boolean isClosed() {
+ return str == null;
+ }
+
+ /**
+ * Sets a mark position in this reader. The parameter {@code readLimit} is
+ * ignored for this class. Calling {@code reset()} will reposition the
+ * reader back to the marked position.
+ *
+ * @param readLimit
+ * ignored for {@code StringReader} instances.
+ * @throws IllegalArgumentException
+ * if {@code readLimit < 0}.
+ * @throws IOException
+ * if this reader is closed.
+ * @see #markSupported()
+ * @see #reset()
+ */
+ @Override
+ public void mark(int readLimit) throws IOException {
+ if (readLimit < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
+ }
+ markpos = pos;
+ }
+ }
+
+ /**
+ * Indicates whether this reader supports the {@code mark()} and {@code
+ * reset()} methods. This implementation returns {@code true}.
+ *
+ * @return always {@code true}.
+ */
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ /**
+ * Reads a single character from the source string and returns it as an
+ * integer with the two higher-order bytes set to 0. Returns -1 if the end
+ * of the source string has been reached.
+ *
+ * @return the character read or -1 if the end of the source string has been
+ * reached.
+ * @throws IOException
+ * if this reader is closed.
+ */
+ @Override
+ public int read() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
+ }
+ if (pos != count) {
+ return str.charAt(pos++);
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Reads at most {@code len} characters from the source string and stores
+ * them at {@code offset} in the character array {@code buf}. Returns the
+ * number of characters actually read or -1 if the end of the source string
+ * has been reached.
+ *
+ * @param buf
+ * the character array to store the characters read.
+ * @param offset
+ * the initial position in {@code buffer} to store the characters
+ * read from this reader.
+ * @param len
+ * the maximum number of characters to read.
+ * @return the number of characters read or -1 if the end of the reader has
+ * been reached.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset < 0} or {@code len < 0}, or if
+ * {@code offset + len} is greater than the size of {@code buf}.
+ * @throws IOException
+ * if this reader is closed.
+ */
+ @Override
+ public int read(char buf[], int offset, int len) throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ // K0083=StringReader is closed.
+ throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
+ }
+ if (offset < 0 || offset > buf.length) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+ }
+ if (len < 0 || len > buf.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", len)); //$NON-NLS-1$
+ }
+ if (len == 0) {
+ return 0;
+ }
+ if (pos == this.count) {
+ return -1;
+ }
+ int end = pos + len > this.count ? this.count : pos + len;
+ str.getChars(pos, end, buf, offset);
+ int read = end - pos;
+ pos = end;
+ return read;
+ }
+ }
+
+ /**
+ * Indicates whether this reader is ready to be read without blocking. This
+ * implementation always returns {@code true}.
+ *
+ * @return always {@code true}.
+ * @throws IOException
+ * if this reader is closed.
+ * @see #read()
+ * @see #read(char[], int, int)
+ */
+ @Override
+ public boolean ready() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Resets this reader's position to the last {@code mark()} location.
+ * Invocations of {@code read()} and {@code skip()} will occur from this new
+ * location. If this reader has not been marked, it is reset to the
+ * beginning of the source string.
+ *
+ * @throws IOException
+ * if this reader is closed.
+ * @see #mark(int)
+ * @see #markSupported()
+ */
+ @Override
+ public void reset() throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
+ }
+ pos = markpos != -1 ? markpos : 0;
+ }
+ }
+
+ /**
+ * Moves {@code ns} characters in the source string. Unlike the {@link
+ * Reader#skip(long) overridden method}, this method may skip negative skip
+ * distances: this rewinds the input so that characters may be read again.
+ * When the end of the source string has been reached, the input cannot be
+ * rewound.
+ *
+ * @param ns
+ * the maximum number of characters to skip. Positive values skip
+ * forward; negative values skip backward.
+ * @return the number of characters actually skipped. This is bounded below
+ * by the number of characters already read and above by the
+ * number of characters remaining:
{@code -(num chars already
+ * read) <= distance skipped <= num chars remaining}.
+ * @throws IOException
+ * if this reader is closed.
+ * @see #mark(int)
+ * @see #markSupported()
+ * @see #reset()
+ */
+ @Override
+ public long skip(long ns) throws IOException {
+ synchronized (lock) {
+ if (isClosed()) {
+ throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
+ }
+
+ int minSkip = -pos;
+ int maxSkip = count - pos;
+
+ if (maxSkip == 0 || ns > maxSkip) {
+ ns = maxSkip; // no rewinding if we're at the end
+ } else if (ns < minSkip) {
+ ns = minSkip;
+ }
+
+ pos += ns;
+ return ns;
+ }
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/StringWriter.java b/gwt/jre/java/io/StringWriter.java
new file mode 100644
index 0000000..f399552
--- /dev/null
+++ b/gwt/jre/java/io/StringWriter.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * StringWriter is an class for writing Character Streams to a StringBuffer. The
+ * characters written can then be returned as a String. This is used for
+ * capturing output sent to a Writer by substituting a StringWriter.
+ *
+ * @see StringReader
+ */
+public class StringWriter extends Writer {
+
+ private StringBuffer buf;
+
+ /**
+ * Constructs a new StringWriter which has a StringBuffer allocated with the
+ * default size of 16 characters. The StringBuffer is also the
+ * lock
used to synchronize access to this Writer.
+ */
+ public StringWriter() {
+ super();
+ buf = new StringBuffer(16);
+ lock = buf;
+ }
+
+ /**
+ * Constructs a new StringWriter which has a StringBuffer allocated with the
+ * size of initialSize
characters. The StringBuffer is also
+ * the lock
used to synchronize access to this Writer.
+ *
+ * @param initialSize
+ * the intial number of characters
+ */
+ public StringWriter(int initialSize) {
+ if (initialSize < 0) {
+ throw new IllegalArgumentException();
+ }
+ buf = new StringBuffer(initialSize);
+ lock = buf;
+ }
+
+ /**
+ * Close this Writer. This is the concrete implementation required. This
+ * particular implementation does nothing.
+ *
+ * @throws IOException
+ * If an IO error occurs closing this StringWriter.
+ */
+ @Override
+ public void close() throws IOException {
+ /* empty */
+ }
+
+ /**
+ * Flush this Writer. This is the concrete implementation required. This
+ * particular implementation does nothing.
+ */
+ @Override
+ public void flush() {
+ /* empty */
+ }
+
+ /**
+ * Answer the contents of this StringWriter as a StringBuffer. Any changes
+ * made to the StringBuffer by the receiver or the caller are reflected in
+ * this StringWriter.
+ *
+ * @return this StringWriters local StringBuffer.
+ */
+ public StringBuffer getBuffer() {
+ synchronized (lock) {
+ return buf;
+ }
+ }
+
+ /**
+ * Answer the contents of this StringWriter as a String. Any changes made to
+ * the StringBuffer by the receiver after returning will not be reflected in
+ * the String returned to the caller.
+ *
+ * @return this StringWriters current contents as a String.
+ */
+ @Override
+ public String toString() {
+ synchronized (lock) {
+ return buf.toString();
+ }
+ }
+
+ /**
+ * Writes count
characters starting at offset
+ * in cbuf
to this StringWriter.
+ *
+ * @param cbuf
+ * the non-null array containing characters to write.
+ * @param offset
+ * offset in buf to retrieve characters
+ * @param count
+ * maximum number of characters to write
+ *
+ * @throws ArrayIndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+ @Override
+ public void write(char[] cbuf, int offset, int count) {
+ // avoid int overflow
+ if (offset < 0 || offset > cbuf.length || count < 0
+ || count > cbuf.length - offset) {
+ throw new IndexOutOfBoundsException();
+ }
+ synchronized (lock) {
+ this.buf.append(cbuf, offset, count);
+ }
+ }
+
+ /**
+ * Writes the specified character oneChar
to this
+ * StringWriter. This implementation writes the low order two bytes to the
+ * Stream.
+ *
+ * @param oneChar
+ * The character to write
+ */
+ @Override
+ public void write(int oneChar) {
+ synchronized (lock) {
+ buf.append((char) oneChar);
+ }
+ }
+
+ /**
+ * Writes the characters from the String str
to this
+ * StringWriter.
+ *
+ * @param str
+ * the non-null String containing the characters to write.
+ */
+ @Override
+ public void write(String str) {
+ synchronized (lock) {
+ buf.append(str);
+ }
+ }
+
+ /**
+ * Writes count
number of characters starting at
+ * offset
from the String str
to this
+ * StringWriter.
+ *
+ * @param str
+ * the non-null String containing the characters to write.
+ * @param offset
+ * the starting point to retrieve characters.
+ * @param count
+ * the number of characters to retrieve and write.
+ *
+ * @throws ArrayIndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+ @Override
+ public void write(String str, int offset, int count) {
+ String sub = str.substring(offset, offset + count);
+ synchronized (lock) {
+ buf.append(sub);
+ }
+ }
+
+ /**
+ * Append a char c
to the StringWriter. The
+ * StringWriter.append(c
) works the same way as
+ * StringWriter.write(c
).
+ *
+ * @param c
+ * The character appended to the StringWriter.
+ * @return The StringWriter.
+ */
+ @Override
+ public StringWriter append(char c) {
+ write(c);
+ return this;
+ }
+
+ /**
+ * Append a CharSequence csq
to the StringWriter. The
+ * StringWriter.append(csq
) works the same way as
+ * StringWriter.write(csq
.toString()). If csq
+ * is null, then "null" will be substituted for csq
.
+ *
+ * @param csq
+ * The CharSequence appended to the StringWriter.
+ * @return The StringWriter
+ */
+ @Override
+ public StringWriter append(CharSequence csq) {
+ if (null == csq) {
+ append(TOKEN_NULL, 0, TOKEN_NULL.length());
+ } else {
+ append(csq, 0, csq.length());
+ }
+ return this;
+ }
+
+ /**
+ * Append a subsequence of a CharSequence csq
to the
+ * StringWriter. The first char and the last char of the subsequnce is
+ * specified by the parameter start
and end
.
+ * The StringWriter.append(csq
) works the same way as
+ * StringWriter.write(csq
.subSequence(start
,end
).toString).If
+ * csq
is null, then "null" will be substituted for
+ * csq
. s
+ *
+ * @param csq
+ * The CharSequence appended to the StringWriter.
+ * @param start
+ * The index of the first char in the CharSequence appended to
+ * the StringWriter.
+ * @param end
+ * The index of the char after the last one in the CharSequence
+ * appended to the StringWriter.
+ * @return The StringWriter.
+ * @throws IndexOutOfBoundsException
+ * If start is less than end, end is greater than the length of
+ * the CharSequence, or start or end is negative.
+ */
+ @Override
+ public StringWriter append(CharSequence csq, int start, int end) {
+ if (null == csq) {
+ csq = TOKEN_NULL;
+ }
+ String output = csq.subSequence(start, end).toString();
+ write(output, 0, output.length());
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/io/Writer.java b/gwt/jre/java/io/Writer.java
new file mode 100644
index 0000000..3b7dce5
--- /dev/null
+++ b/gwt/jre/java/io/Writer.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+/**
+ * Writer is an Abstract class for writing Character Streams. Subclasses of
+ * writer must implement the methods write(char[], int, int)
,
+ * close()
and flush()
.
+ *
+ * @see Reader
+ */
+public abstract class Writer {
+
+ static final String TOKEN_NULL = "null"; //$NON-NLS-1$
+
+ /**
+ * The object used to synchronize access to the writer.
+ */
+ protected Object lock;
+
+ /**
+ * Constructs a new character stream Writer using this
as the
+ * Object to synchronize critical regions around.
+ */
+ protected Writer() {
+ super();
+ lock = this;
+ }
+
+ /**
+ * Constructs a new character stream Writer using lock
as the
+ * Object to synchronize critical regions around.
+ *
+ * @param lock
+ * the Object to synchronize critical regions around.
+ */
+ protected Writer(Object lock) {
+ if (lock == null) {
+ throw new NullPointerException();
+ }
+ this.lock = lock;
+ }
+
+ /**
+ * Close this Writer. This must be implemented by any concrete subclasses.
+ * The implementation should free any resources associated with the Writer.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this Writer.
+ */
+ public abstract void close() throws IOException;
+
+ /**
+ * Flush this Writer. This must be implemented by any concrete subclasses.
+ * The implementation should ensure all buffered characters are written out.
+ *
+ * @throws IOException
+ * If an error occurs attempting to flush this Writer.
+ */
+ public abstract void flush() throws IOException;
+
+ /**
+ * Writes the entire character buffer buf
to this Writer.
+ *
+ * @param buf
+ * the non-null array containing characters to write.
+ *
+ * @throws IOException
+ * If this Writer has already been closed or some other
+ * IOException occurs.
+ */
+ public void write(char buf[]) throws IOException {
+ write(buf, 0, buf.length);
+ }
+
+ /**
+ * Writes count
characters starting at offset
in
+ *
buf
to this Writer. This abstract method must be implemented
+ * by concrete subclasses.
+ *
+ * @param buf the non-null array containing characters to write.
+ * @param offset offset in buf to retrieve characters
+ * @param count maximum number of characters to write
+ *
+ * @throws IOException If this Writer has already been closed or some other IOException occurs.
+ * @throws ArrayIndexOutOfBoundsException If offset or count are outside of bounds.
+ */
+ public abstract void write(char buf[], int offset, int count)
+ throws IOException;
+
+ /**
+ * Writes the specified character oneChar
to this Writer.
+ * This implementation writes the low order two bytes of
+ * oneChar
to the Stream.
+ *
+ * @param oneChar
+ * The character to write
+ *
+ * @throws IOException
+ * If this Writer has already been closed or some other
+ * IOException occurs.
+ */
+ public void write(int oneChar) throws IOException {
+ synchronized (lock) {
+ char oneCharArray[] = new char[1];
+ oneCharArray[0] = (char) oneChar;
+ write(oneCharArray);
+ }
+ }
+
+ /**
+ * Writes the characters from the String str
to this Writer.
+ *
+ * @param str
+ * the non-null String containing the characters to write.
+ *
+ * @throws IOException
+ * If this Writer has already been closed or some other
+ * IOException occurs.
+ */
+ public void write(String str) throws IOException {
+ char buf[] = new char[str.length()];
+ str.getChars(0, buf.length, buf, 0);
+ synchronized (lock) {
+ write(buf);
+ }
+ }
+
+ /**
+ * Writes count
number of characters starting at
+ * offset
from the String str
to this Writer.
+ *
+ * @param str
+ * the non-null String containing the characters to write.
+ * @param offset
+ * the starting point to retrieve characters.
+ * @param count
+ * the number of characters to retrieve and write.
+ *
+ * @throws IOException
+ * If this Writer has already been closed or some other
+ * IOException occurs.
+ * @throws ArrayIndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+ public void write(String str, int offset, int count) throws IOException {
+ if (count < 0) { // other cases tested by getChars()
+ throw new StringIndexOutOfBoundsException();
+ }
+ char buf[] = new char[count];
+ str.getChars(offset, offset + count, buf, 0);
+
+ synchronized (lock) {
+ write(buf);
+ }
+ }
+
+ /**
+ * Append a char c
to the Writer. The Writer.append(c
)
+ * works the same as Writer.write(c
).
+ *
+ * @param c
+ * The character appended to the Writer.
+ * @return The Writer.
+ * @throws IOException
+ * If any IOException raises during the procedure.
+ */
+ public Writer append(char c) throws IOException {
+ write(c);
+ return this;
+ }
+
+ /**
+ * Append a CharSequence csq
to the Writer. The
+ * Writer.append(csq
) works the same way as Writer.write(csq
.toString()).
+ * If csq
is null, then "null" will be substituted for
+ * csq
.
+ *
+ * @param csq
+ * The CharSequence appended to the Writer.
+ * @return The Writer.
+ * @throws IOException
+ * If any IOException raises during the procedure.
+ */
+ public Writer append(CharSequence csq) throws IOException {
+ if (null == csq) {
+ write(TOKEN_NULL);
+ } else {
+ write(csq.toString());
+ }
+ return this;
+ }
+
+ /**
+ * Append a subsequence of a CharSequence csq
to the Writer.
+ * The first char and the last char of the subsequnce is specified by the
+ * parameter start
and end
. The
+ * Writer.append(csq
) works the same way as Writer.write (csq
csq.subSequence(start
,end
).toString).
+ * If csq
is null, then "null" will be substituted for
+ * csq
.
+ *
+ * @param csq
+ * The CharSequence appended to the Writaer.
+ * @param start
+ * The index of the first char in the CharSequence appended to
+ * the Writer.
+ * @param end
+ * The index of the char after the last one in the CharSequence
+ * appended to the Writer.
+ * @return The Writer.
+ * @throws IndexOutOfBoundsException
+ * If start is less than end, end is greater than the length of
+ * the CharSequence, or start or end is negative.
+ * @throws IOException
+ * If any IOException raises during the procedure.
+ */
+ public Writer append(CharSequence csq, int start, int end)
+ throws IOException {
+ if (null == csq) {
+ write(TOKEN_NULL.substring(start, end));
+ } else {
+ write(csq.subSequence(start, end).toString());
+ }
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/lang/ClassNotFoundException.java b/gwt/jre/java/lang/ClassNotFoundException.java
new file mode 100644
index 0000000..aa86717
--- /dev/null
+++ b/gwt/jre/java/lang/ClassNotFoundException.java
@@ -0,0 +1,18 @@
+package java.lang;
+
+public class ClassNotFoundException extends Exception {
+
+ public ClassNotFoundException()
+ {
+ }
+
+ public ClassNotFoundException(String s)
+ {
+ super(s);
+ }
+
+ public ClassNotFoundException(String s, Throwable ex)
+ {
+ super(s,ex);
+ }
+}
diff --git a/gwt/jre/java/lang/CloneNotSupportedException.java b/gwt/jre/java/lang/CloneNotSupportedException.java
new file mode 100644
index 0000000..abd3feb
--- /dev/null
+++ b/gwt/jre/java/lang/CloneNotSupportedException.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+
+/**
+ * This exception is thrown when a program attempts to clone an object which
+ * does not support the Cloneable interface.
+ *
+ * @see Cloneable
+ */
+public class CloneNotSupportedException extends Exception {
+
+ private static final long serialVersionUID = 5195511250079656443L;
+
+ /**
+ * Constructs a new instance of this class with its walkback filled in.
+ */
+ public CloneNotSupportedException() {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of this class with its walkback and message
+ * filled in.
+ *
+ * @param detailMessage
+ * String The detail message for the exception.
+ */
+ public CloneNotSupportedException(String detailMessage) {
+ super(detailMessage);
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/lang/InternalError.java b/gwt/jre/java/lang/InternalError.java
new file mode 100644
index 0000000..dc7a1aa
--- /dev/null
+++ b/gwt/jre/java/lang/InternalError.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+
+/**
+ * This error is thrown when the VM notices that it has gotten into a state
+ * which it does not understand.
+ */
+public class InternalError extends RuntimeException {
+
+ private static final long serialVersionUID = -9062593416125562365L;
+
+ /**
+ * Constructs a new instance of this class with its walkback filled in.
+ */
+ public InternalError() {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of this class with its walkback and message
+ * filled in.
+ *
+ * @param detailMessage
+ * String The detail message for the exception.
+ */
+ public InternalError(String detailMessage) {
+ super(detailMessage);
+ }
+}
\ No newline at end of file
diff --git a/gwt/jre/java/math/BigDecimal.java b/gwt/jre/java/math/BigDecimal.java
new file mode 100644
index 0000000..7cc988b
--- /dev/null
+++ b/gwt/jre/java/math/BigDecimal.java
@@ -0,0 +1,2845 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+import java.io.Serializable;
+
+/**
+ * This class represents immutable arbitrary precision decimal numbers. Each
+ * {@code BigDecimal} instance is represented with a unscaled arbitrary
+ * precision mantissa (the unscaled value) and a scale. The value of the {@code
+ * BigDecimal} is {@code unscaledValue} 10^(-{@code scale}).
+ */
+public class BigDecimal extends Number implements ComparableBigInteger
scaled by zero. (
+ * [0,0],[1,0],...,[10,0]
).
+ */
+ private static final BigDecimal BI_SCALED_BY_ZERO[] = new BigDecimal[BI_SCALED_BY_ZERO_LENGTH];
+
+ /**
+ * An array filled with characters '0'
.
+ */
+ private static final char[] CH_ZEROS = new char[100];
+
+ private static final double[] DOUBLE_FIVE_POW = new double[] {
+ 1D, 5D, 25D, 125D, 625D, 3125D, 15625D, 78125D, 390625D, 1953125D,
+ 9765625D, 48828125D, 244140625D, 1220703125D, 6103515625D, 30517578125D,
+ 152587890625D, 762939453125D, 3814697265625D, 19073486328125D,
+ 95367431640625D, 476837158203125D, 2384185791015625D,};
+
+ private static final int[] DOUBLE_FIVE_POW_BIT_LENGTH = new int[DOUBLE_FIVE_POW.length];
+
+ /**
+ * An array with powers of ten that fit in the type double
(
+ * 10^0,10^1,...,10^18
).
+ */
+ private static final double[] DOUBLE_TEN_POW = new double[] {
+ 1D, 10D, 100D, 1000D, 10000D, 100000D, 1000000D, 10000000D, 100000000D,
+ 1000000000D, 10000000000D, 100000000000D, 1000000000000D,
+ 10000000000000D, 100000000000000D, 1000000000000000D,
+ 10000000000000000D,};
+
+ private static final int[] DOUBLE_TEN_POW_BIT_LENGTH = new int[DOUBLE_TEN_POW.length];
+
+ /**
+ * An array with powers of five that fit in the type double
(
+ * 5^0,5^1,...,5^27
).
+ */
+ private static final BigInteger FIVE_POW[];
+
+ /**
+ * The double closest to Math.log(2.0d)
.
+ */
+ private static final double LOG2 = 0.6931471805599453d;
+
+ /**
+ * The double closest to Log10(2)
.
+ */
+ private static final double LOG10_2 = 0.3010299956639812;
+
+ /**
+ * The double closer to Math.pow(2, 47)
.
+ */
+ private static final double POW47 = 140737488355328d;
+
+ /**
+ * This is the serialVersionUID used by the sun implementation.
+ */
+ private static final long serialVersionUID = 6108874887143696463L;
+
+ /**
+ * An array with powers of ten that fit in the type double
(
+ * 10^0,10^1,...,10^18
).
+ */
+ private static final BigInteger TEN_POW[];
+
+ /**
+ * An array with the zero number scaled by the first positive scales. (
+ * 0*10^0, 0*10^1, ..., 0*10^10
).
+ */
+ private static final BigDecimal ZERO_SCALED_BY[] = new BigDecimal[11];
+
+ static {
+ // To fill all static arrays.
+ int i = 0;
+
+ for (; i < ZERO_SCALED_BY.length; i++) {
+ BI_SCALED_BY_ZERO[i] = new BigDecimal(i, 0);
+ ZERO_SCALED_BY[i] = new BigDecimal(0, i);
+ CH_ZEROS[i] = '0';
+ }
+
+ for (; i < CH_ZEROS.length; i++) {
+ CH_ZEROS[i] = '0';
+ }
+ for (int j = 0; j < DOUBLE_FIVE_POW_BIT_LENGTH.length; j++) {
+ DOUBLE_FIVE_POW_BIT_LENGTH[j] = bitLength(DOUBLE_FIVE_POW[j]);
+ }
+ for (int j = 0; j < DOUBLE_TEN_POW_BIT_LENGTH.length; j++) {
+ DOUBLE_TEN_POW_BIT_LENGTH[j] = bitLength(DOUBLE_TEN_POW[j]);
+ }
+
+ // Taking the references of useful powers.
+ TEN_POW = Multiplication.bigTenPows;
+ FIVE_POW = Multiplication.bigFivePows;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance whose value is equal to {@code
+ * val}. The new decimal is constructed as if the {@code BigDecimal(String)}
+ * constructor is called with an argument which is equal to {@code
+ * Double.toString(val)}. For example, {@code valueOf("0.1")} is converted to
+ * (unscaled=1, scale=1), although the double {@code 0.1} cannot be
+ * represented exactly as a double value. In contrast to that, a new {@code
+ * BigDecimal(0.1)} instance has the value {@code
+ * 0.1000000000000000055511151231257827021181583404541015625} with an unscaled
+ * value {@code 1000000000000000055511151231257827021181583404541015625} and
+ * the scale {@code 55}.
+ *
+ * @param val double value to be converted to a {@code BigDecimal}.
+ * @return {@code BigDecimal} instance with the value {@code val}.
+ * @throws NumberFormatException if {@code val} is infinite or {@code val} is
+ * not a number
+ */
+ public static BigDecimal valueOf(double val) {
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ // math.03=Infinity or NaN
+ throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
+ }
+ return new BigDecimal(Double.toString(val));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance whose value is equal to {@code
+ * unscaledVal}. The scale of the result is {@code 0}, and its unscaled value
+ * is {@code unscaledVal}.
+ *
+ * @param unscaledVal value to be converted to a {@code BigDecimal}.
+ * @return {@code BigDecimal} instance with the value {@code unscaledVal}.
+ */
+ public static BigDecimal valueOf(long unscaledVal) {
+ if ((unscaledVal >= 0) && (unscaledVal < BI_SCALED_BY_ZERO_LENGTH)) {
+ return BI_SCALED_BY_ZERO[(int) unscaledVal];
+ }
+ return new BigDecimal(unscaledVal, 0);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} instance whose value is equal to {@code
+ * unscaledVal} 10^(-{@code scale}). The scale of the result is {@code scale},
+ * and its unscaled value is {@code unscaledVal}.
+ *
+ * @param unscaledVal unscaled value to be used to construct the new {@code
+ * BigDecimal}.
+ * @param scale scale to be used to construct the new {@code BigDecimal}.
+ * @return {@code BigDecimal} instance with the value {@code unscaledVal}*
+ * 10^(-{@code unscaledVal}).
+ */
+ public static BigDecimal valueOf(long unscaledVal, int scale) {
+ if (scale == 0) {
+ return valueOf(unscaledVal);
+ }
+ if ((unscaledVal == 0) && (scale >= 0) && (scale < ZERO_SCALED_BY.length)) {
+ return ZERO_SCALED_BY[scale];
+ }
+ return new BigDecimal(unscaledVal, scale);
+ }
+
+ private static BigDecimal addAndMult10(BigDecimal thisValue,
+ BigDecimal augend, double diffScale) {
+ if (diffScale < DOUBLE_TEN_POW.length
+ && Math.max(thisValue.bitLength, augend.bitLength
+ + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale]) + 1
+ < SMALL_VALUE_BITS) {
+ return valueOf(thisValue.smallValue + augend.smallValue
+ * DOUBLE_TEN_POW[(int) diffScale], thisValue.scale);
+ }
+ return new BigDecimal(thisValue.getUnscaledValue().add(
+ Multiplication.multiplyByTenPow(augend.getUnscaledValue(),
+ (int) diffScale)), thisValue.scale);
+ }
+
+ private static int bitLength(double value) {
+ // if |value| is less than 2^47, use log
+ if (value > -POW47 && value < POW47) {
+ if (value == 0.0) {
+ // special-case zero, otherwise we get -INFINITY below
+ return 0;
+ }
+ boolean negative = (value < 0.0);
+ if (negative) {
+ value = -value;
+ }
+ int result = (int) Math.floor(Math.log(value) / LOG2);
+ if (!negative || value != Math.pow(2, result)) {
+ result++;
+ }
+ return result;
+ }
+ return bitLength((long) value);
+ }
+
+ private static int bitLength(long value) {
+ if (value < 0) {
+ value = ~value;
+ }
+ return 64 - Long.numberOfLeadingZeros(value);
+ }
+
+ private static BigDecimal divideBigIntegers(BigInteger scaledDividend,
+ BigInteger scaledDivisor, int scale, RoundingMode roundingMode) {
+
+ BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor); // quotient
+ // and
+ // remainder
+ // If after division there is a remainder...
+ BigInteger quotient = quotAndRem[0];
+ BigInteger remainder = quotAndRem[1];
+ if (remainder.signum() == 0) {
+ return new BigDecimal(quotient, scale);
+ }
+ int sign = scaledDividend.signum() * scaledDivisor.signum();
+ int compRem; // 'compare to remainder'
+ if (scaledDivisor.bitLength() < SMALL_VALUE_BITS) {
+ long rem = remainder.longValue();
+ long divisor = scaledDivisor.longValue();
+ compRem = longCompareTo(Math.abs(rem) << 1, Math.abs(divisor));
+ // To look if there is a carry
+ compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign
+ * (5 + compRem), roundingMode);
+
+ } else {
+ // Checking if: remainder * 2 >= scaledDivisor
+ compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs());
+ compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign
+ * (5 + compRem), roundingMode);
+ }
+ if (compRem != 0) {
+ if (quotient.bitLength() < SMALL_VALUE_BITS) {
+ return valueOf(quotient.longValue() + compRem, scale);
+ }
+ quotient = quotient.add(BigInteger.valueOf(compRem));
+ return new BigDecimal(quotient, scale);
+ }
+ // Constructing the result with the appropriate unscaled value
+ return new BigDecimal(quotient, scale);
+ }
+
+ private static BigDecimal dividePrimitiveDoubles(double scaledDividend,
+ double scaledDivisor, int scale, RoundingMode roundingMode) {
+ double quotient = intDivide(scaledDividend, scaledDivisor);
+ double remainder = scaledDividend % scaledDivisor;
+ int sign = Double.compare(scaledDividend * scaledDivisor, 0.0);
+ if (remainder != 0) {
+ // Checking if: remainder * 2 >= scaledDivisor
+ int compRem; // 'compare to remainder'
+ compRem = Double.compare(Math.abs(remainder) * 2,
+ Math.abs(scaledDivisor));
+ // To look if there is a carry
+ quotient += roundingBehavior(((int) quotient) & 1, sign * (5 + compRem),
+ roundingMode);
+ }
+ // Constructing the result with the appropriate unscaled value
+ return valueOf(quotient, scale);
+ }
+
+ private static double intDivide(double dividend, double divisor) {
+ double quotient = dividend / divisor;
+ return quotient > 0 ? Math.floor(quotient) : Math.ceil(quotient);
+ }
+
+ private static int longCompareTo(long a, long b) {
+ return Long.signum(a - b);
+ }
+
+ private static native double parseUnscaled(String str) /*-{
+ var unscaledRegex = @java.math.BigDecimal::unscaledRegex;
+ if (!unscaledRegex) {
+ unscaledRegex = @java.math.BigDecimal::unscaledRegex = /^[+-]?\d*$/i;
+ }
+ if (unscaledRegex.test(str)) {
+ return parseInt(str, 10);
+ } else {
+ return Number.NaN;
+ }
+ }-*/;
+
+ /**
+ * Return an increment that can be -1,0 or 1, depending of {@code
+ * roundingMode}.
+ *
+ * @param parityBit can be 0 or 1, it's only used in the case {@code
+ * HALF_EVEN}
+ * @param fraction the mantisa to be analyzed
+ * @param roundingMode the type of rounding
+ * @return the carry propagated after rounding
+ */
+ private static int roundingBehavior(int parityBit, int fraction,
+ RoundingMode roundingMode) {
+ int increment = 0; // the carry after rounding
+
+ switch (roundingMode) {
+ case UNNECESSARY:
+ if (fraction != 0) {
+ // math.08=Rounding necessary
+ throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
+ }
+ break;
+ case UP:
+ increment = Integer.signum(fraction);
+ break;
+ case DOWN:
+ break;
+ case CEILING:
+ increment = Math.max(Integer.signum(fraction), 0);
+ break;
+ case FLOOR:
+ increment = Math.min(Integer.signum(fraction), 0);
+ break;
+ case HALF_UP:
+ if (Math.abs(fraction) >= 5) {
+ increment = Integer.signum(fraction);
+ }
+ break;
+ case HALF_DOWN:
+ if (Math.abs(fraction) > 5) {
+ increment = Integer.signum(fraction);
+ }
+ break;
+ case HALF_EVEN:
+ if (Math.abs(fraction) + parityBit > 5) {
+ increment = Integer.signum(fraction);
+ }
+ break;
+ }
+ return increment;
+ }
+
+ /**
+ * It tests if a scale of type {@code long} fits in 32 bits. It returns the
+ * same scale being casted to {@code int} type when is possible, otherwise
+ * throws an exception.
+ *
+ * @param doubleScale a double bit scale
+ * @return a 32 bit scale when is possible
+ * @throws ArithmeticException when {@code scale} doesn't fit in {@code int}
+ * type
+ * @see #scale
+ */
+ private static int toIntScale(double doubleScale) {
+ if (doubleScale < Integer.MIN_VALUE) {
+ // math.09=Overflow
+ throw new ArithmeticException("Overflow"); //$NON-NLS-1$
+ } else if (doubleScale > Integer.MAX_VALUE) {
+ // math.0A=Underflow
+ throw new ArithmeticException("Underflow"); //$NON-NLS-1$
+ } else {
+ return (int) doubleScale;
+ }
+ }
+
+ /**
+ * Convert a double to a string with {@code digits} precision. The resulting
+ * string may still be in exponential notation.
+ *
+ * @param d double value
+ * @param digits number of digits of precision to include
+ * @return non-localized string representation of {@code d}
+ */
+ private static native String toPrecision(double d, int digits) /*-{
+ return d.toPrecision(digits);
+ }-*/;
+
+ private static BigDecimal valueOf(double smallValue, double scale) {
+ return new BigDecimal(smallValue, scale);
+ }
+
+ /**
+ * It returns the value 0 with the most approximated scale of type {@code int}
+ * . if {@code longScale > Integer.MAX_VALUE} the scale will be {@code
+ * Integer.MAX_VALUE}; if {@code longScale < Integer.MIN_VALUE} the scale will
+ * be {@code Integer.MIN_VALUE}; otherwise {@code longScale} is casted to the
+ * type {@code int}.
+ *
+ * @param doubleScale the scale to which the value 0 will be scaled.
+ * @return the value 0 scaled by the closer scale of type {@code int}.
+ * @see #scale
+ */
+ private static BigDecimal zeroScaledBy(double doubleScale) {
+ if (doubleScale == (int) doubleScale) {
+ return valueOf(0, (int) doubleScale);
+ }
+ if (doubleScale >= 0) {
+ return new BigDecimal(0, Integer.MAX_VALUE);
+ }
+ return new BigDecimal(0, Integer.MIN_VALUE);
+ }
+
+ private transient int bitLength;
+
+ /**
+ * Cache for the hash code.
+ */
+ private transient int hashCode;
+
+ /**
+ * The arbitrary precision integer (unscaled value) in the internal
+ * representation of {@code BigDecimal}.
+ */
+ private BigInteger intVal;
+
+ /**
+ * Represent the number of decimal digits in the unscaled value. This
+ * precision is calculated the first time, and used in the following calls of
+ * method precision()
. Note that some call to the private method
+ * inplaceRound()
could update this field.
+ *
+ * @see #precision()
+ * @see #inplaceRound(MathContext)
+ */
+ private transient int precision;
+
+ private double scale;
+
+ /**
+ * The unscaled integer value (stored in a double) if the number of bits is
+ * less than {@link #SMALL_VALUE_BITS}.
+ */
+ private transient double smallValue;
+
+ /**
+ * The String
representation is cached.
+ */
+ private transient String toStringImage;
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given big integer
+ * {@code val}. The scale of the result is {@code 0}.
+ *
+ * @param val {@code BigInteger} value to be converted to a {@code BigDecimal}
+ * instance.
+ */
+ public BigDecimal(BigInteger val) {
+ this(val, 0);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a given unscaled value
+ * {@code unscaledVal} and a given scale. The value of this instance is
+ * {@code unscaledVal} 10^(-{@code scale}).
+ *
+ * @param unscaledVal {@code BigInteger} representing the unscaled value of
+ * this {@code BigDecimal} instance.
+ * @param scale scale of this {@code BigDecimal} instance.
+ * @throws NullPointerException if {@code unscaledVal == null}.
+ */
+ public BigDecimal(BigInteger unscaledVal, int scale) {
+ if (unscaledVal == null) {
+ throw new NullPointerException();
+ }
+ this.scale = scale;
+ setUnscaledValue(unscaledVal);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a given unscaled value
+ * {@code unscaledVal} and a given scale. The value of this instance is
+ * {@code unscaledVal} 10^(-{@code scale}). The result is rounded according to
+ * the specified math context.
+ *
+ * @param unscaledVal {@code BigInteger} representing the unscaled value of
+ * this {@code BigDecimal} instance.
+ * @param scale scale of this {@code BigDecimal} instance.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ * @throws NullPointerException if {@code unscaledVal == null}.
+ */
+ public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
+ this(unscaledVal, scale);
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given big integer
+ * {@code val}. The scale of the result is {@code 0}.
+ *
+ * @param val {@code BigInteger} value to be converted to a {@code BigDecimal}
+ * instance.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(BigInteger val, MathContext mc) {
+ this(val);
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a string representation
+ * given as a character array.
+ *
+ * @param in array of characters containing the string representation of this
+ * {@code BigDecimal}.
+ * @throws NullPointerException if {@code in == null}.
+ * @throws NumberFormatException if {@code in} does not contain a valid string
+ * representation of a big decimal.
+ */
+ public BigDecimal(char[] in) {
+ this(in, 0, in.length);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a string representation
+ * given as a character array.
+ *
+ * @param in array of characters containing the string representation of this
+ * {@code BigDecimal}.
+ * @param offset first index to be copied.
+ * @param len number of characters to be used.
+ * @throws NullPointerException if {@code in == null}.
+ * @throws NumberFormatException if {@code offset < 0} or {@code len <= 0} or
+ * {@code offset+len-1 < 0} or {@code offset+len-1 >= in.length}.
+ * @throws NumberFormatException if in does not contain a valid string
+ * representation of a big decimal.
+ */
+ public BigDecimal(char[] in, int offset, int len) {
+ try {
+ initFrom(new String(in, offset, len));
+ } catch (StringIndexOutOfBoundsException e) {
+ throw new NumberFormatException(e.getMessage());
+ }
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a string representation
+ * given as a character array.
+ *
+ * @param in array of characters containing the string representation of this
+ * {@code BigDecimal}.
+ * @param offset first index to be copied.
+ * @param len number of characters to be used.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws NullPointerException if {@code in == null}.
+ * @throws NumberFormatException if {@code offset < 0} or {@code len <= 0} or
+ * {@code offset+len-1 < 0} or {@code offset+len-1 >= in.length}.
+ * @throws NumberFormatException if {@code in} does not contain a valid string
+ * representation of a big decimal.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(char[] in, int offset, int len, MathContext mc) {
+ this(in, offset, len);
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a string representation
+ * given as a character array. The result is rounded according to the
+ * specified math context.
+ *
+ * @param in array of characters containing the string representation of this
+ * {@code BigDecimal}.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws NullPointerException if {@code in == null}.
+ * @throws NumberFormatException if {@code in} does not contain a valid string
+ * representation of a big decimal.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(char[] in, MathContext mc) {
+ this(in, 0, in.length);
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given double {@code
+ * val}. The scale of the result is 0.
+ *
+ * @param val double value to be converted to a {@code BigDecimal} instance.
+ * @throws NumberFormatException if {@code val} is infinite or a NaN
+ */
+ public BigDecimal(double val) {
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ // math.03=Infinity or NaN
+ throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
+ }
+ initFrom(toPrecision(val, 20));
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given double {@code
+ * val}. The scale of the result is 0. The result is rounded according to the
+ * specified math context.
+ *
+ * @param val double value to be converted to a {@code BigDecimal} instance.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws NumberFormatException if {@code val} is infinite or a NaN
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(double val, MathContext mc) {
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ // math.03=Infinity or NaN
+ throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
+ }
+ initFrom(toPrecision(val, 20));
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given int {@code val}
+ * . The scale of the result is 0.
+ *
+ * @param val int value to be converted to a {@code BigDecimal} instance.
+ */
+ public BigDecimal(int val) {
+ this(val, 0);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given int {@code val}
+ * . The scale of the result is {@code 0}. The result is rounded according to
+ * the specified math context.
+ *
+ * @param val int value to be converted to a {@code BigDecimal} instance.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * c.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(int val, MathContext mc) {
+ this(val, 0);
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given long {@code
+ * val}. The scale of the result is {@code 0}.
+ *
+ * @param val long value to be converted to a {@code BigDecimal} instance.
+ */
+ public BigDecimal(long val) {
+ this(val, 0);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the given long {@code
+ * val}. The scale of the result is {@code 0}. The result is rounded according
+ * to the specified math context.
+ *
+ * @param val long value to be converted to a {@code BigDecimal} instance.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(long val, MathContext mc) {
+ this(val);
+ inplaceRound(mc);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a string representation.
+ *
+ * @param val string containing the string representation of this {@code
+ * BigDecimal}.
+ * @throws NumberFormatException if {@code val} does not contain a valid
+ * string representation of a big decimal.
+ */
+ public BigDecimal(String val) {
+ initFrom(val);
+ }
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from a string representation.
+ * The result is rounded according to the specified math context.
+ *
+ * @param val string containing the string representation of this {@code
+ * BigDecimal}.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @throws NumberFormatException if {@code val} does not contain a valid
+ * string representation of a big decimal.
+ * @throws ArithmeticException if {@code mc.precision > 0} and {@code
+ * mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
+ * represented within the given precision without rounding.
+ */
+ public BigDecimal(String val, MathContext mc) {
+ this(val.toCharArray(), 0, val.length());
+ inplaceRound(mc);
+ }
+
+ private BigDecimal(BigInteger unscaledVal, double scale) {
+ if (unscaledVal == null) {
+ throw new NullPointerException();
+ }
+ this.scale = scale;
+ setUnscaledValue(unscaledVal);
+ }
+
+ private BigDecimal(double smallValue, double scale) {
+ this.smallValue = smallValue;
+ this.scale = scale;
+ this.bitLength = bitLength(smallValue);
+ }
+
+ private BigDecimal(long smallValue, int scale) {
+ this.scale = scale;
+ this.bitLength = bitLength(smallValue);
+ if (bitLength < SMALL_VALUE_BITS) {
+ this.smallValue = smallValue;
+ } else {
+ this.intVal = BigInteger.valueOf(smallValue);
+ }
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is the absolute value of
+ * {@code this}. The scale of the result is the same as the scale of this.
+ *
+ * @return {@code abs(this)}
+ */
+ public BigDecimal abs() {
+ return ((signum() < 0) ? negate() : this);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is the absolute value of
+ * {@code this}. The result is rounded according to the passed context {@code
+ * mc}.
+ *
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code abs(this)}
+ */
+ public BigDecimal abs(MathContext mc) {
+ return round(mc).abs();
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this + augend}. The
+ * scale of the result is the maximum of the scales of the two arguments.
+ *
+ * @param augend value to be added to {@code this}.
+ * @return {@code this + augend}.
+ * @throws NullPointerException if {@code augend == null}.
+ */
+ public BigDecimal add(BigDecimal augend) {
+ double diffScale = this.scale - augend.scale;
+ // Fast return when some operand is zero
+ if (this.isZero()) {
+ if (diffScale <= 0) {
+ return augend;
+ }
+ if (augend.isZero()) {
+ return this;
+ }
+ } else if (augend.isZero()) {
+ if (diffScale >= 0) {
+ return this;
+ }
+ }
+ // Let be: this = [u1,s1] and augend = [u2,s2]
+ if (diffScale == 0) {
+ // case s1 == s2: [u1 + u2 , s1]
+ if (Math.max(this.bitLength, augend.bitLength) + 1 < SMALL_VALUE_BITS) {
+ return valueOf(this.smallValue + augend.smallValue, this.scale);
+ }
+ return new BigDecimal(this.getUnscaledValue().add(
+ augend.getUnscaledValue()), this.scale);
+ } else if (diffScale > 0) {
+ // case s1 > s2 : [(u1 + u2) * 10 ^ (s1 - s2) , s1]
+ return addAndMult10(this, augend, diffScale);
+ } else {
+ // case s2 > s1 : [(u2 + u1) * 10 ^ (s2 - s1) , s2]
+ return addAndMult10(augend, this, -diffScale);
+ }
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this + augend}. The
+ * result is rounded according to the passed context {@code mc}.
+ *
+ * @param augend value to be added to {@code this}.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this + augend}.
+ * @throws NullPointerException if {@code augend == null} or {@code mc ==
+ * null}.
+ */
+ public BigDecimal add(BigDecimal augend, MathContext mc) {
+ BigDecimal larger; // operand with the largest unscaled value
+ BigDecimal smaller; // operand with the smallest unscaled value
+ BigInteger tempBI;
+ double diffScale = this.scale - augend.scale;
+ int largerSignum;
+ // Some operand is zero or the precision is infinity
+ if ((augend.isZero()) || (this.isZero()) || (mc.getPrecision() == 0)) {
+ return add(augend).round(mc);
+ }
+ // Cases where there is room for optimizations
+ if (this.approxPrecision() < diffScale - 1) {
+ larger = augend;
+ smaller = this;
+ } else if (augend.approxPrecision() < -diffScale - 1) {
+ larger = this;
+ smaller = augend;
+ } else {
+ // No optimization is done
+ return add(augend).round(mc);
+ }
+ if (mc.getPrecision() >= larger.approxPrecision()) {
+ // No optimization is done
+ return add(augend).round(mc);
+ }
+ // Cases where it's unnecessary to add two numbers with very different
+ // scales
+ largerSignum = larger.signum();
+ if (largerSignum == smaller.signum()) {
+ tempBI = Multiplication.multiplyByPositiveInt(larger.getUnscaledValue(),
+ 10).add(BigInteger.valueOf(largerSignum));
+ } else {
+ tempBI = larger.getUnscaledValue().subtract(
+ BigInteger.valueOf(largerSignum));
+ tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10).add(
+ BigInteger.valueOf(largerSignum * 9));
+ }
+ // Rounding the improved adding
+ larger = new BigDecimal(tempBI, larger.scale + 1);
+ return larger.round(mc);
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a byte value if it has no fractional
+ * part and if its value fits to the byte range ([-128..127]). If these
+ * conditions are not met, an {@code ArithmeticException} is thrown.
+ *
+ * @return this {@code BigDecimal} as a byte value.
+ * @throws ArithmeticException if rounding is necessary or the number doesn't
+ * fit in a byte.
+ */
+ public byte byteValueExact() {
+ return (byte) valueExact(8);
+ }
+
+ /**
+ * Compares this {@code BigDecimal} with {@code val}. Returns one of the three
+ * values {@code 1}, {@code 0}, or {@code -1}. The method behaves as if
+ * {@code this.subtract(val)} is computed. If this difference is > 0 then 1 is
+ * returned, if the difference is < 0 then -1 is returned, and if the
+ * difference is 0 then 0 is returned. This means, that if two decimal
+ * instances are compared which are equal in value but differ in scale, then
+ * these two instances are considered as equal.
+ *
+ * @param val value to be compared with {@code this}.
+ * @return {@code 1} if {@code this > val}, {@code -1} if {@code this < val},
+ * {@code 0} if {@code this == val}.
+ * @throws NullPointerException if {@code val == null}.
+ */
+ public int compareTo(BigDecimal val) {
+ int thisSign = signum();
+ int valueSign = val.signum();
+
+ if (thisSign == valueSign) {
+ if (this.scale == val.scale && this.bitLength < SMALL_VALUE_BITS
+ && val.bitLength < SMALL_VALUE_BITS) {
+ return (smallValue < val.smallValue) ? -1
+ : (smallValue > val.smallValue) ? 1 : 0;
+ }
+ double diffScale = this.scale - val.scale;
+ double diffPrecision = this.approxPrecision() - val.approxPrecision();
+ if (diffPrecision > diffScale + 1) {
+ return thisSign;
+ } else if (diffPrecision < diffScale - 1) {
+ return -thisSign;
+ } else {
+ // thisSign == val.signum() and diffPrecision is aprox. diffScale
+ BigInteger thisUnscaled = this.getUnscaledValue();
+ BigInteger valUnscaled = val.getUnscaledValue();
+ // If any of both precision is bigger, append zeros to the shorter one
+ if (diffScale < 0) {
+ thisUnscaled = thisUnscaled.multiply(Multiplication.powerOf10(-diffScale));
+ } else if (diffScale > 0) {
+ valUnscaled = valUnscaled.multiply(Multiplication.powerOf10(diffScale));
+ }
+ return thisUnscaled.compareTo(valUnscaled);
+ }
+ } else if (thisSign < valueSign) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
+ * scale of the result is the difference of the scales of {@code this} and
+ * {@code divisor}. If the exact result requires more digits, then the scale
+ * is adjusted accordingly. For example, {@code 1/128 = 0.0078125} which has a
+ * scale of {@code 7} and precision {@code 5}.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return {@code this / divisor}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if the result cannot be represented exactly.
+ */
+ public BigDecimal divide(BigDecimal divisor) {
+ BigInteger p = this.getUnscaledValue();
+ BigInteger q = divisor.getUnscaledValue();
+ BigInteger gcd; // greatest common divisor between 'p' and 'q'
+ BigInteger quotAndRem[];
+ double diffScale = scale - divisor.scale;
+ int newScale; // the new scale for final quotient
+ int k; // number of factors "2" in 'q'
+ int l = 0; // number of factors "5" in 'q'
+ int i = 1;
+ int lastPow = FIVE_POW.length - 1;
+
+ if (divisor.isZero()) {
+ // math.04=Division by zero
+ throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
+ }
+ if (p.signum() == 0) {
+ return zeroScaledBy(diffScale);
+ }
+ // To divide both by the GCD
+ gcd = p.gcd(q);
+ p = p.divide(gcd);
+ q = q.divide(gcd);
+ // To simplify all "2" factors of q, dividing by 2^k
+ k = q.getLowestSetBit();
+ q = q.shiftRight(k);
+ // To simplify all "5" factors of q, dividing by 5^l
+ do {
+ quotAndRem = q.divideAndRemainder(FIVE_POW[i]);
+ if (quotAndRem[1].signum() == 0) {
+ l += i;
+ if (i < lastPow) {
+ i++;
+ }
+ q = quotAndRem[0];
+ } else {
+ if (i == 1) {
+ break;
+ }
+ i = 1;
+ }
+ } while (true);
+ // If abs(q) != 1 then the quotient is periodic
+ if (!q.abs().equals(BigInteger.ONE)) {
+ // math.05=Non-terminating decimal expansion; no exact representable
+ // decimal result.
+ throw new ArithmeticException(
+ "Non-terminating decimal expansion; no exact representable decimal result"); //$NON-NLS-1$
+ }
+ // The sign of the is fixed and the quotient will be saved in 'p'
+ if (q.signum() < 0) {
+ p = p.negate();
+ }
+ // Checking if the new scale is out of range
+ newScale = toIntScale(diffScale + Math.max(k, l));
+ // k >= 0 and l >= 0 implies that k - l is in the 32-bit range
+ i = k - l;
+
+ p = (i > 0) ? Multiplication.multiplyByFivePow(p, i) : p.shiftLeft(-i);
+ return new BigDecimal(p, newScale);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
+ * scale of the result is the scale of {@code this}. If rounding is required
+ * to meet the specified scale, then the specified rounding mode {@code
+ * roundingMode} is applied.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param roundingMode rounding mode to be used to round the result.
+ * @return {@code this / divisor} rounded according to the given rounding
+ * mode.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws IllegalArgumentException if {@code roundingMode} is not a valid
+ * rounding mode.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
+ * and rounding is necessary according to the scale of this.
+ */
+ public BigDecimal divide(BigDecimal divisor, int roundingMode) {
+ return divide(divisor, (int) scale, RoundingMode.valueOf(roundingMode));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. As
+ * scale of the result the parameter {@code scale} is used. If rounding is
+ * required to meet the specified scale, then the specified rounding mode
+ * {@code roundingMode} is applied.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param scale the scale of the result returned.
+ * @param roundingMode rounding mode to be used to round the result.
+ * @return {@code this / divisor} rounded according to the given rounding
+ * mode.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws IllegalArgumentException if {@code roundingMode} is not a valid
+ * rounding mode.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
+ * and rounding is necessary according to the given scale.
+ */
+ public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
+ return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. As
+ * scale of the result the parameter {@code scale} is used. If rounding is
+ * required to meet the specified scale, then the specified rounding mode
+ * {@code roundingMode} is applied.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param scale the scale of the result returned.
+ * @param roundingMode rounding mode to be used to round the result.
+ * @return {@code this / divisor} rounded according to the given rounding
+ * mode.
+ * @throws NullPointerException if {@code divisor == null} or {@code
+ * roundingMode == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code roundingMode ==
+ * RoundingMode.UNNECESSAR}Y and rounding is necessary according to
+ * the given scale and given precision.
+ */
+ public BigDecimal divide(BigDecimal divisor, int scale,
+ RoundingMode roundingMode) {
+ // Let be: this = [u1,s1] and divisor = [u2,s2]
+ if (roundingMode == null) {
+ throw new NullPointerException();
+ }
+ if (divisor.isZero()) {
+ // math.04=Division by zero
+ throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
+ }
+
+ double diffScale = this.scale - divisor.scale - scale;
+ if (this.bitLength < SMALL_VALUE_BITS
+ && divisor.bitLength < SMALL_VALUE_BITS) {
+ if (diffScale == 0) {
+ return dividePrimitiveDoubles(this.smallValue, divisor.smallValue,
+ scale, roundingMode);
+ } else if (diffScale > 0) {
+ if (diffScale < DOUBLE_TEN_POW.length
+ && divisor.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[
+ (int) diffScale] < SMALL_VALUE_BITS) {
+ return dividePrimitiveDoubles(this.smallValue, divisor.smallValue
+ * DOUBLE_TEN_POW[(int) diffScale], scale, roundingMode);
+ }
+ } else { // diffScale < 0
+ if (-diffScale < DOUBLE_TEN_POW.length
+ && this.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) -diffScale]
+ < SMALL_VALUE_BITS) {
+ return dividePrimitiveDoubles(this.smallValue
+ * DOUBLE_TEN_POW[(int) -diffScale], divisor.smallValue, scale,
+ roundingMode);
+ }
+ }
+ }
+
+ BigInteger scaledDividend = this.getUnscaledValue();
+ BigInteger scaledDivisor = divisor.getUnscaledValue(); // for scaling of
+ // 'u2'
+
+ if (diffScale > 0) {
+ // Multiply 'u2' by: 10^((s1 - s2) - scale)
+ scaledDivisor = Multiplication.multiplyByTenPow(scaledDivisor,
+ (int) diffScale);
+ } else if (diffScale < 0) {
+ // Multiply 'u1' by: 10^(scale - (s1 - s2))
+ scaledDividend = Multiplication.multiplyByTenPow(scaledDividend,
+ (int) -diffScale);
+ }
+ return divideBigIntegers(scaledDividend, scaledDivisor, scale, roundingMode);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
+ * result is rounded according to the passed context {@code mc}. If the passed
+ * math context specifies precision {@code 0}, then this call is equivalent to
+ * {@code this.divide(divisor)}.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param mc rounding mode and precision for the result of this operation.
+ * @return {@code this / divisor}.
+ * @throws NullPointerException if {@code divisor == null} or {@code mc ==
+ * null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code mc.getRoundingMode() == UNNECESSARY}
+ * and rounding is necessary according {@code mc.getPrecision()}.
+ */
+ public BigDecimal divide(BigDecimal divisor, MathContext mc) {
+ /*
+ * Calculating how many zeros must be append to 'dividend' to obtain a
+ * quotient with at least 'mc.precision()' digits
+ */
+ double traillingZeros = mc.getPrecision() + 2L + divisor.approxPrecision()
+ - approxPrecision();
+ double diffScale = scale - divisor.scale;
+ double newScale = diffScale; // scale of the final quotient
+ int compRem; // to compare the remainder
+ int i = 1; // index
+ int lastPow = TEN_POW.length - 1; // last power of ten
+ BigInteger integerQuot; // for temporal results
+ BigInteger quotAndRem[] = {getUnscaledValue()};
+ // In special cases it reduces the problem to call the dual method
+ if ((mc.getPrecision() == 0) || (this.isZero()) || (divisor.isZero())) {
+ return this.divide(divisor);
+ }
+ if (traillingZeros > 0) {
+ // To append trailing zeros at end of dividend
+ quotAndRem[0] = getUnscaledValue().multiply(
+ Multiplication.powerOf10(traillingZeros));
+ newScale += traillingZeros;
+ }
+ quotAndRem = quotAndRem[0].divideAndRemainder(divisor.getUnscaledValue());
+ integerQuot = quotAndRem[0];
+ // Calculating the exact quotient with at least 'mc.precision()' digits
+ if (quotAndRem[1].signum() != 0) {
+ // Checking if: 2 * remainder >= divisor ?
+ compRem = quotAndRem[1].shiftLeftOneBit().compareTo(
+ divisor.getUnscaledValue());
+ // quot := quot * 10 + r; with 'r' in {-6,-5,-4, 0,+4,+5,+6}
+ integerQuot = integerQuot.multiply(BigInteger.TEN).add(
+ BigInteger.valueOf(quotAndRem[0].signum() * (5 + compRem)));
+ newScale++;
+ } else {
+ // To strip trailing zeros until the preferred scale is reached
+ while (!integerQuot.testBit(0)) {
+ quotAndRem = integerQuot.divideAndRemainder(TEN_POW[i]);
+ if ((quotAndRem[1].signum() == 0) && (newScale - i >= diffScale)) {
+ newScale -= i;
+ if (i < lastPow) {
+ i++;
+ }
+ integerQuot = quotAndRem[0];
+ } else {
+ if (i == 1) {
+ break;
+ }
+ i = 1;
+ }
+ }
+ }
+ // To perform rounding
+ return new BigDecimal(integerQuot, toIntScale(newScale), mc);
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
+ * scale of the result is the scale of {@code this}. If rounding is required
+ * to meet the specified scale, then the specified rounding mode {@code
+ * roundingMode} is applied.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param roundingMode rounding mode to be used to round the result.
+ * @return {@code this / divisor} rounded according to the given rounding
+ * mode.
+ * @throws NullPointerException if {@code divisor == null} or {@code
+ * roundingMode == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code roundingMode ==
+ * RoundingMode.UNNECESSARY} and rounding is necessary according to
+ * the scale of this.
+ */
+ public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
+ return divide(divisor, (int) scale, roundingMode);
+ }
+
+ /**
+ * Returns a {@code BigDecimal} array which contains the integral part of
+ * {@code this / divisor} at index 0 and the remainder {@code this % divisor}
+ * at index 1. The quotient is rounded down towards zero to the next integer.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return {@code [this.divideToIntegralValue(divisor),
+ * this.remainder(divisor)]}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @see #divideToIntegralValue
+ * @see #remainder
+ */
+ public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
+ BigDecimal quotAndRem[] = new BigDecimal[2];
+
+ quotAndRem[0] = this.divideToIntegralValue(divisor);
+ quotAndRem[1] = this.subtract(quotAndRem[0].multiply(divisor));
+ return quotAndRem;
+ }
+
+ /**
+ * Returns a {@code BigDecimal} array which contains the integral part of
+ * {@code this / divisor} at index 0 and the remainder {@code this % divisor}
+ * at index 1. The quotient is rounded down towards zero to the next integer.
+ * The rounding mode passed with the parameter {@code mc} is not considered.
+ * But if the precision of {@code mc > 0} and the integral part requires more
+ * digits, then an {@code ArithmeticException} is thrown.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param mc math context which determines the maximal precision of the
+ * result.
+ * @return {@code [this.divideToIntegralValue(divisor),
+ * this.remainder(divisor)]}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @see #divideToIntegralValue
+ * @see #remainder
+ */
+ public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
+ BigDecimal quotAndRem[] = new BigDecimal[2];
+
+ quotAndRem[0] = this.divideToIntegralValue(divisor, mc);
+ quotAndRem[1] = this.subtract(quotAndRem[0].multiply(divisor));
+ return quotAndRem;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is the integral part of
+ * {@code this / divisor}. The quotient is rounded down towards zero to the
+ * next integer. For example, {@code 0.5/0.2 = 2}.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @return integral part of {@code this / divisor}.
+ * @throws NullPointerException if {@code divisor == null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ */
+ public BigDecimal divideToIntegralValue(BigDecimal divisor) {
+ BigInteger integralValue; // the integer of result
+ BigInteger powerOfTen; // some power of ten
+ BigInteger quotAndRem[] = {getUnscaledValue()};
+ double newScale = this.scale - divisor.scale;
+ double tempScale = 0;
+ int i = 1;
+ int lastPow = TEN_POW.length - 1;
+
+ if (divisor.isZero()) {
+ // math.04=Division by zero
+ throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
+ }
+ if ((divisor.approxPrecision() + newScale > this.approxPrecision() + 1L)
+ || (this.isZero())) {
+ /*
+ * If the divisor's integer part is greater than this's integer part, the
+ * result must be zero with the appropriate scale
+ */
+ integralValue = BigInteger.ZERO;
+ } else if (newScale == 0) {
+ integralValue = getUnscaledValue().divide(divisor.getUnscaledValue());
+ } else if (newScale > 0) {
+ powerOfTen = Multiplication.powerOf10(newScale);
+ integralValue = getUnscaledValue().divide(
+ divisor.getUnscaledValue().multiply(powerOfTen));
+ integralValue = integralValue.multiply(powerOfTen);
+ } else {
+ // (newScale < 0)
+ powerOfTen = Multiplication.powerOf10(-newScale);
+ integralValue = getUnscaledValue().multiply(powerOfTen).divide(
+ divisor.getUnscaledValue());
+ // To strip trailing zeros approximating to the preferred scale
+ while (!integralValue.testBit(0)) {
+ quotAndRem = integralValue.divideAndRemainder(TEN_POW[i]);
+ if ((quotAndRem[1].signum() == 0) && (tempScale - i >= newScale)) {
+ tempScale -= i;
+ if (i < lastPow) {
+ i++;
+ }
+ integralValue = quotAndRem[0];
+ } else {
+ if (i == 1) {
+ break;
+ }
+ i = 1;
+ }
+ }
+ newScale = tempScale;
+ }
+ return ((integralValue.signum() == 0) ? zeroScaledBy(newScale)
+ : new BigDecimal(integralValue, toIntScale(newScale)));
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is the integral part of
+ * {@code this / divisor}. The quotient is rounded down towards zero to the
+ * next integer. The rounding mode passed with the parameter {@code mc} is not
+ * considered. But if the precision of {@code mc > 0} and the integral part
+ * requires more digits, then an {@code ArithmeticException} is thrown.
+ *
+ * @param divisor value by which {@code this} is divided.
+ * @param mc math context which determines the maximal precision of the
+ * result.
+ * @return integral part of {@code this / divisor}.
+ * @throws NullPointerException if {@code divisor == null} or {@code mc ==
+ * null}.
+ * @throws ArithmeticException if {@code divisor == 0}.
+ * @throws ArithmeticException if {@code mc.getPrecision() > 0} and the result
+ * requires more digits to be represented.
+ */
+ public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
+ int mcPrecision = mc.getPrecision();
+ int diffPrecision = this.precision() - divisor.precision();
+ int lastPow = TEN_POW.length - 1;
+ double diffScale = this.scale - divisor.scale;
+ double newScale = diffScale;
+ double quotPrecision = diffPrecision - diffScale + 1;
+ BigInteger quotAndRem[] = new BigInteger[2];
+ // In special cases it call the dual method
+ if ((mcPrecision == 0) || (this.isZero()) || (divisor.isZero())) {
+ return this.divideToIntegralValue(divisor);
+ }
+ // Let be: this = [u1,s1] and divisor = [u2,s2]
+ if (quotPrecision <= 0) {
+ quotAndRem[0] = BigInteger.ZERO;
+ } else if (diffScale == 0) {
+ // CASE s1 == s2: to calculate u1 / u2
+ quotAndRem[0] = this.getUnscaledValue().divide(divisor.getUnscaledValue());
+ } else if (diffScale > 0) {
+ // CASE s1 >= s2: to calculate u1 / (u2 * 10^(s1-s2)
+ quotAndRem[0] = this.getUnscaledValue().divide(
+ divisor.getUnscaledValue().multiply(
+ Multiplication.powerOf10(diffScale)));
+ // To chose 10^newScale to get a quotient with at least 'mc.precision()'
+ // digits
+ newScale = Math.min(diffScale, Math.max(mcPrecision - quotPrecision + 1,
+ 0));
+ // To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
+ quotAndRem[0] = quotAndRem[0].multiply(Multiplication.powerOf10(newScale));
+ } else {
+ // CASE s2 > s1:
+ /*
+ * To calculate the minimum power of ten, such that the quotient (u1 *
+ * 10^exp) / u2 has at least 'mc.precision()' digits.
+ */
+ double exp = Math.min(-diffScale, Math.max((double) mcPrecision
+ - diffPrecision, 0));
+ double compRemDiv;
+ // Let be: (u1 * 10^exp) / u2 = [q,r]
+ quotAndRem = this.getUnscaledValue().multiply(
+ Multiplication.powerOf10(exp)).divideAndRemainder(
+ divisor.getUnscaledValue());
+ newScale += exp; // To fix the scale
+ exp = -newScale; // The remaining power of ten
+ // If after division there is a remainder...
+ if ((quotAndRem[1].signum() != 0) && (exp > 0)) {
+ // Log10(r) + ((s2 - s1) - exp) > mc.precision ?
+ compRemDiv = (new BigDecimal(quotAndRem[1])).precision() + exp
+ - divisor.precision();
+ if (compRemDiv == 0) {
+ // To calculate: (r * 10^exp2) / u2
+ quotAndRem[1] = quotAndRem[1].multiply(Multiplication.powerOf10(exp)).divide(
+ divisor.getUnscaledValue());
+ compRemDiv = Math.abs(quotAndRem[1].signum());
+ }
+ if (compRemDiv > 0) {
+ // The quotient won't fit in 'mc.precision()' digits
+ // math.06=Division impossible
+ throw new ArithmeticException("Division impossible"); //$NON-NLS-1$
+ }
+ }
+ }
+ // Fast return if the quotient is zero
+ if (quotAndRem[0].signum() == 0) {
+ return zeroScaledBy(diffScale);
+ }
+ BigInteger strippedBI = quotAndRem[0];
+ BigDecimal integralValue = new BigDecimal(quotAndRem[0]);
+ int resultPrecision = integralValue.precision();
+ int i = 1;
+ // To strip trailing zeros until the specified precision is reached
+ while (!strippedBI.testBit(0)) {
+ quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
+ if ((quotAndRem[1].signum() == 0)
+ && ((resultPrecision - i >= mcPrecision) || (newScale - i >= diffScale))) {
+ resultPrecision -= i;
+ newScale -= i;
+ if (i < lastPow) {
+ i++;
+ }
+ strippedBI = quotAndRem[0];
+ } else {
+ if (i == 1) {
+ break;
+ }
+ i = 1;
+ }
+ }
+ // To check if the result fit in 'mc.precision()' digits
+ if (resultPrecision > mcPrecision) {
+ // math.06=Division impossible
+ throw new ArithmeticException("Division impossible"); //$NON-NLS-1$
+ }
+ integralValue.scale = toIntScale(newScale);
+ integralValue.setUnscaledValue(strippedBI);
+ return integralValue;
+ }
+
+ /**
+ * Returns this {@code BigDecimal} as a double value. If {@code this} is too
+ * big to be represented as an float, then {@code Double.POSITIVE_INFINITY} or
+ * {@code Double.NEGATIVE_INFINITY} is returned.
+ *
All operations are provided in immutable way, and some in both mutable
+ * and immutable.
+ */
+class BitLevel {
+
+ /**
+ * @see BigInteger#bitCount()
+ * @param val
+ * @return
+ */
+ static int bitCount(BigInteger val) {
+ int bCount = 0;
+
+ if (val.sign == 0) {
+ return 0;
+ }
+
+ int i = val.getFirstNonzeroDigit();
+ if (val.sign > 0) {
+ for (; i < val.numberLength; i++) {
+ bCount += Integer.bitCount(val.digits[i]);
+ }
+ } else {
+ // (sign < 0)
+ // this digit absorbs the carry
+ bCount += Integer.bitCount(-val.digits[i]);
+ for (i++; i < val.numberLength; i++) {
+ bCount += Integer.bitCount(~val.digits[i]);
+ }
+ // We take the complement sum:
+ bCount = (val.numberLength << 5) - bCount;
+ }
+ return bCount;
+ }
+
+ /**
+ * @see BigInteger#bitLength()
+ * @param val
+ * @return
+ */
+ static int bitLength(BigInteger val) {
+ if (val.sign == 0) {
+ return 0;
+ }
+ int bLength = (val.numberLength << 5);
+ int highDigit = val.digits[val.numberLength - 1];
+
+ if (val.sign < 0) {
+ int i = val.getFirstNonzeroDigit();
+ // We reduce the problem to the positive case.
+ if (i == val.numberLength - 1) {
+ // ~~ is to handle int overflow
+ highDigit = ~~(highDigit - 1);
+ }
+ }
+ // Subtracting all sign bits
+ bLength -= Integer.numberOfLeadingZeros(highDigit);
+ return bLength;
+ }
+
+ /**
+ * Performs a flipBit on the BigInteger, returning a BigInteger with the the
+ * specified bit flipped.
+ *
+ * @param val BigInteger to operate on
+ * @param n the bit to flip
+ */
+ static BigInteger flipBit(BigInteger val, int n) {
+ int resSign = (val.sign == 0) ? 1 : val.sign;
+ int intCount = n >> 5;
+ int bitN = n & 31;
+ int resLength = Math.max(intCount + 1, val.numberLength) + 1;
+ int resDigits[] = new int[resLength];
+ int i;
+
+ int bitNumber = 1 << bitN;
+ System.arraycopy(val.digits, 0, resDigits, 0, val.numberLength);
+
+ if (val.sign < 0) {
+ if (intCount >= val.numberLength) {
+ resDigits[intCount] = bitNumber;
+ } else {
+ // val.sign<0 y intCount < val.numberLength
+ int firstNonZeroDigit = val.getFirstNonzeroDigit();
+ if (intCount > firstNonZeroDigit) {
+ resDigits[intCount] ^= bitNumber;
+ } else if (intCount < firstNonZeroDigit) {
+ resDigits[intCount] = -bitNumber;
+ for (i = intCount + 1; i < firstNonZeroDigit; i++) {
+ resDigits[i] = -1;
+ }
+ resDigits[i] = resDigits[i]--;
+ } else {
+ i = intCount;
+ resDigits[i] = -((-resDigits[intCount]) ^ bitNumber);
+ if (resDigits[i] == 0) {
+ for (i++; resDigits[i] == -1; i++) {
+ resDigits[i] = 0;
+ }
+ resDigits[i]++;
+ }
+ }
+ }
+ } else {
+ // case where val is positive
+ resDigits[intCount] ^= bitNumber;
+ }
+ BigInteger result = new BigInteger(resSign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Performs {@code val <<= count}.
+ */
+ // val should have enough place (and one digit more)
+ static void inplaceShiftLeft(BigInteger val, int count) {
+ int intCount = count >> 5; // count of integers
+ val.numberLength += intCount
+ + (Integer.numberOfLeadingZeros(val.digits[val.numberLength - 1])
+ - (count & 31) >= 0 ? 0 : 1);
+ shiftLeft(val.digits, val.digits, intCount, count & 31);
+ val.cutOffLeadingZeroes();
+ val.unCache();
+ }
+
+ /**
+ * Performs {@code val >>= count} where {@code val} is a positive number.
+ */
+ static void inplaceShiftRight(BigInteger val, int count) {
+ int sign = val.signum();
+ if (count == 0 || val.signum() == 0) {
+ return;
+ }
+ int intCount = count >> 5; // count of integers
+ val.numberLength -= intCount;
+ if (!shiftRight(val.digits, val.numberLength, val.digits, intCount,
+ count & 31)
+ && sign < 0) {
+ // remainder not zero: add one to the result
+ int i;
+ for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
+ val.digits[i] = 0;
+ }
+ if (i == val.numberLength) {
+ val.numberLength++;
+ }
+ val.digits[i]++;
+ }
+ val.cutOffLeadingZeroes();
+ val.unCache();
+ }
+
+ /**
+ * Check if there are 1s in the lowest bits of this BigInteger.
+ *
+ * @param numberOfBits the number of the lowest bits to check
+ * @return false if all bits are 0s, true otherwise
+ */
+ static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) {
+ int intCount = numberOfBits >> 5;
+ int bitCount = numberOfBits & 31;
+ int i;
+
+ for (i = 0; (i < intCount) && (digits[i] == 0); i++) {
+ }
+ return ((i != intCount) || (digits[i] << (32 - bitCount) != 0));
+ }
+
+ /**
+ * @see BigInteger#shiftLeft(int)
+ * @param source
+ * @param count
+ * @return
+ */
+ static BigInteger shiftLeft(BigInteger source, int count) {
+ int intCount = count >> 5;
+ count &= 31; // %= 32
+ int resLength = source.numberLength + intCount + ((count == 0) ? 0 : 1);
+ int resDigits[] = new int[resLength];
+
+ shiftLeft(resDigits, source.digits, intCount, count);
+ BigInteger result = new BigInteger(source.sign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Abstractly shifts left an array of integers in little endian (i.e.,
+ * shift it right). Total shift distance in bits is intCount * 32 + count
+ *
+ * @param result the destination array
+ * @param source 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) {
+ if (count == 0) {
+ System.arraycopy(source, 0, result, intCount, result.length - intCount);
+ } else {
+ int rightShiftCount = 32 - count;
+
+ result[result.length - 1] = 0;
+ for (int i = result.length - 1; i > intCount; i--) {
+ result[i] |= source[i - intCount - 1] >>> rightShiftCount;
+ result[i - 1] = source[i - intCount - 1] << count;
+ }
+ }
+
+ for (int i = 0; i < intCount; i++) {
+ result[i] = 0;
+ }
+ }
+
+ static BigInteger shiftLeftOneBit(BigInteger source) {
+ int srcLen = source.numberLength;
+ int resLen = srcLen + 1;
+ int resDigits[] = new int[resLen];
+ shiftLeftOneBit(resDigits, source.digits, srcLen);
+ BigInteger result = new BigInteger(source.sign, resLen, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Shifts the source digits left one bit, creating a value whose magnitude is
+ * doubled.
+ *
+ * @param result an array of digits that will hold the computed result when
+ * this method returns. The size of this array is {@code srcLen + 1},
+ * and the format is the same as {@link BigInteger#digits}.
+ * @param source the array of digits to shift left, in the same format as
+ * {@link BigInteger#digits}.
+ * @param srcLen the length of {@code source}; may be less than {@code
+ * source.length}
+ */
+ static void shiftLeftOneBit(int result[], int source[], int srcLen) {
+ int carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ int val = source[i];
+ result[i] = (val << 1) | carry;
+ carry = val >>> 31;
+ }
+ if (carry != 0) {
+ result[srcLen] = carry;
+ }
+ }
+
+ /**
+ * @see BigInteger#shiftRight(int)
+ * @param source
+ * @param count
+ * @return
+ */
+ static BigInteger shiftRight(BigInteger source, int count) {
+ int intCount = count >> 5; // count of integers
+ count &= 31; // count of remaining bits
+ if (intCount >= source.numberLength) {
+ return ((source.sign < 0) ? BigInteger.MINUS_ONE : BigInteger.ZERO);
+ }
+ int i;
+ int resLength = source.numberLength - intCount;
+ int resDigits[] = new int[resLength + 1];
+
+ shiftRight(resDigits, resLength, source.digits, intCount, count);
+ if (source.sign < 0) {
+ // Checking if the dropped bits are zeros (the remainder equals to
+ // 0)
+ for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) {
+ }
+ // If the remainder is not zero, add 1 to the result
+ if ((i < intCount)
+ || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) {
+ for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) {
+ resDigits[i] = 0;
+ }
+ if (i == resLength) {
+ resLength++;
+ }
+ resDigits[i]++;
+ }
+ }
+ BigInteger result = new BigInteger(source.sign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Shifts right an array of integers. Total shift distance in bits is intCount
+ * * 32 + count.
+ *
+ * @param result the destination array
+ * @param resultLen the destination array's length
+ * @param source the source array
+ * @param intCount the number of elements to be shifted
+ * @param count the number of bits to be shifted
+ * @return dropped bit's are all zero (i.e. remaider is zero)
+ */
+ static boolean shiftRight(int result[], int resultLen, int source[],
+ int intCount, int count) {
+ int i;
+ boolean allZero = true;
+ for (i = 0; i < intCount; i++) {
+ allZero &= source[i] == 0;
+ }
+ if (count == 0) {
+ System.arraycopy(source, intCount, result, 0, resultLen);
+ i = resultLen;
+ } else {
+ int leftShiftCount = 32 - count;
+
+ allZero &= (source[i] << leftShiftCount) == 0;
+ for (i = 0; i < resultLen - 1; i++) {
+ result[i] = (source[i + intCount] >>> count)
+ | (source[i + intCount + 1] << leftShiftCount);
+ }
+ result[i] = (source[i + intCount] >>> count);
+ i++;
+ }
+
+ return allZero;
+ }
+
+ /**
+ * Performs a fast bit testing for positive numbers. The bit to to be tested
+ * must be in the range {@code [0, val.bitLength()-1]}
+ */
+ static boolean testBit(BigInteger val, int n) {
+ // PRE: 0 <= n < val.bitLength()
+ return ((val.digits[n >> 5] & (1 << (n & 31))) != 0);
+ }
+
+ /**
+ * Just to denote that this class can't be instantiated.
+ */
+ private BitLevel() {
+ }
+}
diff --git a/gwt/jre/java/math/Conversion.java b/gwt/jre/java/math/Conversion.java
new file mode 100644
index 0000000..14cc0bb
--- /dev/null
+++ b/gwt/jre/java/math/Conversion.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+/**
+ * Static library that provides {@link BigInteger} base conversion from/to any
+ * integer represented in a {@link java.lang.String} Object.
+ */
+class Conversion {
+
+ /**
+ * bigRadices values are precomputed maximal powers of radices (integer
+ * numbers from 2 to 36) that fit into unsigned int (32 bits). bigRadices[0] =
+ * 2 ^ 31, bigRadices[8] = 10 ^ 9, etc.
+ */
+
+ static final int bigRadices[] = {
+ -2147483648, 1162261467, 1073741824, 1220703125, 362797056, 1977326743,
+ 1073741824, 387420489, 1000000000, 214358881, 429981696, 815730721,
+ 1475789056, 170859375, 268435456, 410338673, 612220032, 893871739,
+ 1280000000, 1801088541, 113379904, 148035889, 191102976, 244140625,
+ 308915776, 387420489, 481890304, 594823321, 729000000, 887503681,
+ 1073741824, 1291467969, 1544804416, 1838265625, 60466176};
+
+ /**
+ * Holds the maximal exponent for each radix, so that
+ * radixdigitFitInInt[radix] fit in an {@code int} (32 bits).
+ */
+ static final int[] digitFitInInt = {
+ -1, -1, 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
+ 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5};
+
+ /**
+ * @see BigInteger#toString(int)
+ * @param val
+ * @param radix
+ * @return
+ */
+ static String bigInteger2String(BigInteger val, int radix) {
+ int sign = val.sign;
+ int numberLength = val.numberLength;
+ int digits[] = val.digits;
+
+ if (sign == 0) {
+ return "0"; //$NON-NLS-1$
+ }
+ if (numberLength == 1) {
+ int highDigit = digits[numberLength - 1];
+ long v = highDigit & 0xFFFFFFFFL;
+ if (sign < 0) {
+ v = -v;
+ }
+ return Long.toString(v, radix);
+ }
+ if ((radix == 10) || (radix < Character.MIN_RADIX)
+ || (radix > Character.MAX_RADIX)) {
+ return val.toString();
+ }
+ double bitsForRadixDigit;
+ bitsForRadixDigit = Math.log(radix) / Math.log(2);
+ int resLengthInChars = (int) (val.abs().bitLength() / bitsForRadixDigit + ((sign < 0)
+ ? 1 : 0)) + 1;
+
+ char result[] = new char[resLengthInChars];
+ int currentChar = resLengthInChars;
+ int resDigit;
+ if (radix != 16) {
+ int temp[] = new int[numberLength];
+ System.arraycopy(digits, 0, temp, 0, numberLength);
+ int tempLen = numberLength;
+ int charsPerInt = digitFitInInt[radix];
+ int i;
+ // get the maximal power of radix that fits in int
+ int bigRadix = bigRadices[radix - 2];
+ while (true) {
+ // divide the array of digits by bigRadix and convert remainders
+ // to characters collecting them in the char array
+ resDigit = Division.divideArrayByInt(temp, temp, tempLen, bigRadix);
+ int previous = currentChar;
+ do {
+ result[--currentChar] = Character.forDigit(resDigit % radix, radix);
+ } while (((resDigit /= radix) != 0) && (currentChar != 0));
+ int delta = charsPerInt - previous + currentChar;
+ for (i = 0; i < delta && currentChar > 0; i++) {
+ result[--currentChar] = '0';
+ }
+ for (i = tempLen - 1; (i > 0) && (temp[i] == 0); i--) {
+ // empty
+ }
+ tempLen = i + 1;
+ if ((tempLen == 1) && (temp[0] == 0)) { // the quotient is 0
+ break;
+ }
+ }
+ } else {
+ // radix == 16
+ for (int i = 0; i < numberLength; i++) {
+ for (int j = 0; (j < 8) && (currentChar > 0); j++) {
+ resDigit = digits[i] >> (j << 2) & 0xf;
+ result[--currentChar] = Character.forDigit(resDigit, 16);
+ }
+ }
+ }
+ while (result[currentChar] == '0') {
+ currentChar++;
+ }
+ if (sign == -1) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar);
+ }
+
+ static long divideLongByBillion(long a) {
+ long quot;
+ long rem;
+
+ if (a >= 0) {
+ long bLong = 1000000000L;
+ quot = (a / bLong);
+ rem = (a % bLong);
+ } else {
+ /*
+ * Make the dividend positive shifting it right by 1 bit then get the
+ * quotient an remainder and correct them properly
+ */
+ long aPos = a >>> 1;
+ long bPos = 1000000000L >>> 1;
+ quot = aPos / bPos;
+ rem = aPos % bPos;
+ // double the remainder and add 1 if 'a' is odd
+ rem = (rem << 1) + (a & 1);
+ }
+ return ((rem << 32) | (quot & 0xFFFFFFFFL));
+ }
+
+ /**
+ * Builds the correspondent {@code String} representation of {@code val} being
+ * scaled by {@code scale}.
+ *
+ * @see BigInteger#toString()
+ * @see BigDecimal#toString()
+ */
+ static String toDecimalScaledString(BigInteger val, int scale) {
+ int sign = val.sign;
+ int numberLength = val.numberLength;
+ int digits[] = val.digits;
+ int resLengthInChars;
+ int currentChar;
+ char result[];
+
+ if (sign == 0) {
+ switch (scale) {
+ case 0:
+ return "0"; //$NON-NLS-1$
+ case 1:
+ return "0.0"; //$NON-NLS-1$
+ case 2:
+ return "0.00"; //$NON-NLS-1$
+ case 3:
+ return "0.000"; //$NON-NLS-1$
+ case 4:
+ return "0.0000"; //$NON-NLS-1$
+ case 5:
+ return "0.00000"; //$NON-NLS-1$
+ case 6:
+ return "0.000000"; //$NON-NLS-1$
+ default:
+ StringBuilder result1 = new StringBuilder();
+ if (scale < 0) {
+ result1.append("0E+"); //$NON-NLS-1$
+ } else {
+ result1.append("0E"); //$NON-NLS-1$
+ }
+ result1.append(-scale);
+ return result1.toString();
+ }
+ }
+ // one 32-bit unsigned value may contains 10 decimal digits
+ resLengthInChars = numberLength * 10 + 1 + 7;
+ // Explanation why +1+7:
+ // +1 - one char for sign if needed.
+ // +7 - For "special case 2" (see below) we have 7 free chars for
+ // inserting necessary scaled digits.
+ result = new char[resLengthInChars + 1];
+ // allocated [resLengthInChars+1] characters.
+ // a free latest character may be used for "special case 1" (see
+ // below)
+ currentChar = resLengthInChars;
+ if (numberLength == 1) {
+ int highDigit = digits[0];
+ if (highDigit < 0) {
+ long v = highDigit & 0xFFFFFFFFL;
+ do {
+ long prev = v;
+ v /= 10;
+ result[--currentChar] = (char) (0x0030 + ((int) (prev - v * 10)));
+ } while (v != 0);
+ } else {
+ int v = highDigit;
+ do {
+ int prev = v;
+ v /= 10;
+ result[--currentChar] = (char) (0x0030 + (prev - v * 10));
+ } while (v != 0);
+ }
+ } else {
+ int temp[] = new int[numberLength];
+ int tempLen = numberLength;
+ System.arraycopy(digits, 0, temp, 0, tempLen);
+ BIG_LOOP : while (true) {
+ // divide the array of digits by bigRadix and convert
+ // remainders
+ // to characters collecting them in the char array
+ long result11 = 0;
+ for (int i1 = tempLen - 1; i1 >= 0; i1--) {
+ long temp1 = (result11 << 32) + (temp[i1] & 0xFFFFFFFFL);
+ long res = divideLongByBillion(temp1);
+ temp[i1] = (int) res;
+ result11 = (int) (res >> 32);
+ }
+ int resDigit = (int) result11;
+ int previous = currentChar;
+ do {
+ result[--currentChar] = (char) (0x0030 + (resDigit % 10));
+ } while (((resDigit /= 10) != 0) && (currentChar != 0));
+ int delta = 9 - previous + currentChar;
+ for (int i = 0; (i < delta) && (currentChar > 0); i++) {
+ result[--currentChar] = '0';
+ }
+ int j = tempLen - 1;
+ for (; temp[j] == 0; j--) {
+ if (j == 0) { // means temp[0] == 0
+ break BIG_LOOP;
+ }
+ }
+ tempLen = j + 1;
+ }
+ while (result[currentChar] == '0') {
+ currentChar++;
+ }
+ }
+ boolean negNumber = (sign < 0);
+ int exponent = resLengthInChars - currentChar - scale - 1;
+ if (scale == 0) {
+ if (negNumber) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar);
+ }
+ if ((scale > 0) && (exponent >= -6)) {
+ if (exponent >= 0) {
+ // special case 1
+ int insertPoint = currentChar + exponent;
+ for (int j = resLengthInChars - 1; j >= insertPoint; j--) {
+ result[j + 1] = result[j];
+ }
+ result[++insertPoint] = '.';
+ if (negNumber) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar
+ + 1);
+ }
+ // special case 2
+ for (int j = 2; j < -exponent + 1; j++) {
+ result[--currentChar] = '0';
+ }
+ result[--currentChar] = '.';
+ result[--currentChar] = '0';
+ if (negNumber) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar);
+ }
+ int startPoint = currentChar + 1;
+ int endPoint = resLengthInChars;
+ StringBuilder result1 = new StringBuilder(16 + endPoint - startPoint);
+ if (negNumber) {
+ result1.append('-');
+ }
+ if (endPoint - startPoint >= 1) {
+ result1.append(result[currentChar]);
+ result1.append('.');
+ result1.append(result, currentChar + 1, resLengthInChars - currentChar
+ - 1);
+ } else {
+ result1.append(result, currentChar, resLengthInChars - currentChar);
+ }
+ result1.append('E');
+ if (exponent > 0) {
+ result1.append('+');
+ }
+ result1.append(Integer.toString(exponent));
+ return result1.toString();
+ }
+
+ /* can process only 32-bit numbers */
+ static String toDecimalScaledString(long value, int scale) {
+ int resLengthInChars;
+ int currentChar;
+ char result[];
+ boolean negNumber = value < 0;
+ if (negNumber) {
+ value = -value;
+ }
+ if (value == 0) {
+ switch (scale) {
+ case 0:
+ return "0"; //$NON-NLS-1$
+ case 1:
+ return "0.0"; //$NON-NLS-1$
+ case 2:
+ return "0.00"; //$NON-NLS-1$
+ case 3:
+ return "0.000"; //$NON-NLS-1$
+ case 4:
+ return "0.0000"; //$NON-NLS-1$
+ case 5:
+ return "0.00000"; //$NON-NLS-1$
+ case 6:
+ return "0.000000"; //$NON-NLS-1$
+ default:
+ StringBuilder result1 = new StringBuilder();
+ if (scale < 0) {
+ result1.append("0E+"); //$NON-NLS-1$
+ } else {
+ result1.append("0E"); //$NON-NLS-1$
+ }
+ result1.append((scale == Integer.MIN_VALUE)
+ ? "2147483648" : Integer.toString(-scale)); //$NON-NLS-1$
+ return result1.toString();
+ }
+ }
+ // one 32-bit unsigned value may contains 10 decimal digits
+ resLengthInChars = 18;
+ // Explanation why +1+7:
+ // +1 - one char for sign if needed.
+ // +7 - For "special case 2" (see below) we have 7 free chars for
+ // inserting necessary scaled digits.
+ result = new char[resLengthInChars + 1];
+ // Allocated [resLengthInChars+1] characters.
+ // a free latest character may be used for "special case 1" (see below)
+ currentChar = resLengthInChars;
+ long v = value;
+ do {
+ long prev = v;
+ v /= 10;
+ result[--currentChar] = (char) (0x0030 + (prev - v * 10));
+ } while (v != 0);
+
+ long exponent = (long) resLengthInChars - (long) currentChar - scale - 1L;
+ if (scale == 0) {
+ if (negNumber) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar);
+ }
+ if (scale > 0 && exponent >= -6) {
+ if (exponent >= 0) {
+ // special case 1
+ int insertPoint = currentChar + (int) exponent;
+ for (int j = resLengthInChars - 1; j >= insertPoint; j--) {
+ result[j + 1] = result[j];
+ }
+ result[++insertPoint] = '.';
+ if (negNumber) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar
+ + 1);
+ }
+ // special case 2
+ for (int j = 2; j < -exponent + 1; j++) {
+ result[--currentChar] = '0';
+ }
+ result[--currentChar] = '.';
+ result[--currentChar] = '0';
+ if (negNumber) {
+ result[--currentChar] = '-';
+ }
+ return new String(result, currentChar, resLengthInChars - currentChar);
+ }
+ int startPoint = currentChar + 1;
+ int endPoint = resLengthInChars;
+ StringBuilder result1 = new StringBuilder(16 + endPoint - startPoint);
+ if (negNumber) {
+ result1.append('-');
+ }
+ if (endPoint - startPoint >= 1) {
+ result1.append(result[currentChar]);
+ result1.append('.');
+ result1.append(result, currentChar + 1, resLengthInChars - currentChar
+ - 1);
+ } else {
+ result1.append(result, currentChar, resLengthInChars - currentChar);
+ }
+ result1.append('E');
+ if (exponent > 0) {
+ result1.append('+');
+ }
+ result1.append(Long.toString(exponent));
+ return result1.toString();
+ }
+
+ /**
+ * Just to denote that this class can't be instantiated.
+ */
+ private Conversion() {
+ }
+
+// /**
+// * @see BigInteger#doubleValue()
+// */
+ // static double bigInteger2Double(BigInteger val) {
+ // // val.bitLength() < 64
+ // if ((val.numberLength < 2)
+ // || ((val.numberLength == 2) && (val.digits[1] > 0))) {
+ // return val.longValue();
+ // }
+ // // val.bitLength() >= 33 * 32 > 1024
+ // if (val.numberLength > 32) {
+ // return ((val.sign > 0) ? Double.POSITIVE_INFINITY
+ // : Double.NEGATIVE_INFINITY);
+ // }
+ // int bitLen = val.abs().bitLength();
+ // long exponent = bitLen - 1;
+ // int delta = bitLen - 54;
+ // // We need 54 top bits from this, the 53th bit is always 1 in lVal.
+ // long lVal = val.abs().shiftRight(delta).longValue();
+ // /*
+ // * Take 53 bits from lVal to mantissa. The least significant bit is
+ // * needed for rounding.
+ // */
+ // long mantissa = lVal & 0x1FFFFFFFFFFFFFL;
+ // if (exponent == 1023) {
+ // if (mantissa == 0X1FFFFFFFFFFFFFL) {
+ // return ((val.sign > 0) ? Double.POSITIVE_INFINITY
+ // : Double.NEGATIVE_INFINITY);
+ // }
+ // if (mantissa == 0x1FFFFFFFFFFFFEL) {
+ // return ((val.sign > 0) ? Double.MAX_VALUE : -Double.MAX_VALUE);
+ // }
+ // }
+ // // Round the mantissa
+ // if (((mantissa & 1) == 1)
+ // && (((mantissa & 2) == 2) || BitLevel.nonZeroDroppedBits(delta,
+ // val.digits))) {
+ // mantissa += 2;
+ // }
+ // mantissa >>= 1; // drop the rounding bit
+ // long resSign = (val.sign < 0) ? 0x8000000000000000L : 0;
+ // exponent = ((1023 + exponent) << 52) & 0x7FF0000000000000L;
+ // long result = resSign | exponent | mantissa;
+ // return Double.longBitsToDouble(result);
+ // }
+}
diff --git a/gwt/jre/java/math/Division.java b/gwt/jre/java/math/Division.java
new file mode 100644
index 0000000..9b676e3
--- /dev/null
+++ b/gwt/jre/java/math/Division.java
@@ -0,0 +1,1013 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+/**
+ * Static library that provides all operations related with division and modular
+ * arithmetic to {@link BigInteger}. Some methods are provided in both mutable
+ * and immutable way. There are several variants provided listed below:
+ *
+ *
+ */
+class Division {
+
+ /**
+ * Divides the array 'a' by the array 'b' and gets the quotient and the
+ * remainder. Implements the Knuth's division algorithm. See D. Knuth, The Art
+ * of Computer Programming, vol. 2. Steps D1-D8 correspond the steps in the
+ * algorithm description.
+ *
+ * @param quot the quotient
+ * @param quotLength the quotient's length
+ * @param a the dividend
+ * @param aLength the dividend's length
+ * @param b the divisor
+ * @param bLength the divisor's length
+ * @return the remainder
+ */
+ static int[] divide(int quot[], int quotLength, int a[], int aLength,
+ int b[], int bLength) {
+
+ int normA[] = new int[aLength + 1]; // the normalized dividend
+ // an extra byte is needed for correct shift
+ int normB[] = new int[bLength + 1]; // the normalized divisor;
+ int normBLength = bLength;
+ /*
+ * Step D1: normalize a and b and put the results to a1 and b1 the
+ * normalized divisor's first digit must be >= 2^31
+ */
+ int divisorShift = Integer.numberOfLeadingZeros(b[bLength - 1]);
+ if (divisorShift != 0) {
+ BitLevel.shiftLeft(normB, b, 0, divisorShift);
+ BitLevel.shiftLeft(normA, a, 0, divisorShift);
+ } else {
+ System.arraycopy(a, 0, normA, 0, aLength);
+ System.arraycopy(b, 0, normB, 0, bLength);
+ }
+ int firstDivisorDigit = normB[normBLength - 1];
+ // Step D2: set the quotient index
+ int i = quotLength - 1;
+ int j = aLength;
+
+ while (i >= 0) {
+ // Step D3: calculate a guess digit guessDigit
+ int guessDigit = 0;
+ if (normA[j] == firstDivisorDigit) {
+ // set guessDigit to the largest unsigned int value
+ guessDigit = -1;
+ } else {
+ long product = (((normA[j] & 0xffffffffL) << 32) + (normA[j - 1] & 0xffffffffL));
+ long res = Division.divideLongByInt(product, firstDivisorDigit);
+ guessDigit = (int) res; // the quotient of divideLongByInt
+ int rem = (int) (res >> 32); // the remainder of
+ // divideLongByInt
+ // decrease guessDigit by 1 while leftHand > rightHand
+ if (guessDigit != 0) {
+ long leftHand = 0;
+ long rightHand = 0;
+ boolean rOverflowed = false;
+ guessDigit++; // to have the proper value in the loop
+ // below
+ do {
+ guessDigit--;
+ if (rOverflowed) {
+ break;
+ }
+ // leftHand always fits in an unsigned long
+ leftHand = (guessDigit & 0xffffffffL)
+ * (normB[normBLength - 2] & 0xffffffffL);
+ /*
+ * rightHand can overflow; in this case the loop condition will be
+ * true in the next step of the loop
+ */
+ rightHand = ((long) rem << 32) + (normA[j - 2] & 0xffffffffL);
+ long longR = (rem & 0xffffffffL)
+ + (firstDivisorDigit & 0xffffffffL);
+ /*
+ * checks that longR does not fit in an unsigned int; this ensures
+ * that rightHand will overflow unsigned long in the next step
+ */
+ if (Integer.numberOfLeadingZeros((int) (longR >>> 32)) < 32) {
+ rOverflowed = true;
+ } else {
+ rem = (int) longR;
+ }
+ } while (((leftHand ^ 0x8000000000000000L) > (rightHand ^ 0x8000000000000000L)));
+ }
+ }
+ // Step D4: multiply normB by guessDigit and subtract the production
+ // from normA.
+ if (guessDigit != 0) {
+ int borrow = Division.multiplyAndSubtract(normA, j - normBLength,
+ normB, normBLength, guessDigit);
+ // Step D5: check the borrow
+ if (borrow != 0) {
+ // Step D6: compensating addition
+ guessDigit--;
+ long carry = 0;
+ for (int k = 0; k < normBLength; k++) {
+ carry += (normA[j - normBLength + k] & 0xffffffffL)
+ + (normB[k] & 0xffffffffL);
+ normA[j - normBLength + k] = (int) carry;
+ carry >>>= 32;
+ }
+ }
+ }
+ if (quot != null) {
+ quot[i] = guessDigit;
+ }
+ // Step D7
+ j--;
+ i--;
+ }
+ /*
+ * Step D8: we got the remainder in normA. Denormalize it id needed
+ */
+ if (divisorShift != 0) {
+ // reuse normB
+ BitLevel.shiftRight(normB, normBLength, normA, 0, divisorShift);
+ return normB;
+ }
+ System.arraycopy(normA, 0, normB, 0, bLength);
+ return normA;
+ }
+
+ /**
+ * Computes the quotient and the remainder after a division by an {@code int}
+ * number.
+ *
+ * @return an array of the form {@code [quotient, remainder]}.
+ */
+ static BigInteger[] divideAndRemainderByInteger(BigInteger val, int divisor,
+ int divisorSign) {
+ // res[0] is a quotient and res[1] is a remainder:
+ int[] valDigits = val.digits;
+ int valLen = val.numberLength;
+ int valSign = val.sign;
+ if (valLen == 1) {
+ long a = (valDigits[0] & 0xffffffffL);
+ long b = (divisor & 0xffffffffL);
+ long quo = a / b;
+ long rem = a % b;
+ if (valSign != divisorSign) {
+ quo = -quo;
+ }
+ if (valSign < 0) {
+ rem = -rem;
+ }
+ return new BigInteger[] {BigInteger.valueOf(quo), BigInteger.valueOf(rem)};
+ }
+ int quotientLength = valLen;
+ int quotientSign = ((valSign == divisorSign) ? 1 : -1);
+ int quotientDigits[] = new int[quotientLength];
+ int remainderDigits[];
+ remainderDigits = new int[] {Division.divideArrayByInt(quotientDigits,
+ valDigits, valLen, divisor)};
+ BigInteger result0 = new BigInteger(quotientSign, quotientLength,
+ quotientDigits);
+ BigInteger result1 = new BigInteger(valSign, 1, remainderDigits);
+ result0.cutOffLeadingZeroes();
+ result1.cutOffLeadingZeroes();
+ return new BigInteger[] {result0, result1};
+ }
+
+ /**
+ * Divides an array by an integer value. Implements the Knuth's division
+ * algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
+ *
+ * @param dest the quotient
+ * @param src the dividend
+ * @param srcLength the length of the dividend
+ * @param divisor the divisor
+ * @return remainder
+ */
+ static int divideArrayByInt(int dest[], int src[], final int srcLength,
+ final int divisor) {
+
+ long rem = 0;
+ long bLong = divisor & 0xffffffffL;
+
+ for (int i = srcLength - 1; i >= 0; i--) {
+ long temp = (rem << 32) | (src[i] & 0xffffffffL);
+ long quot;
+ if (temp >= 0) {
+ quot = (temp / bLong);
+ rem = (temp % bLong);
+ } else {
+ /*
+ * make the dividend positive shifting it right by 1 bit then get the
+ * quotient an remainder and correct them properly
+ */
+ long aPos = temp >>> 1;
+ long bPos = divisor >>> 1;
+ quot = aPos / bPos;
+ rem = aPos % bPos;
+ // double the remainder and add 1 if a is odd
+ rem = (rem << 1) + (temp & 1);
+ if ((divisor & 1) != 0) {
+ // the divisor is odd
+ if (quot <= rem) {
+ rem -= quot;
+ } else {
+ if (quot - rem <= bLong) {
+ rem += bLong - quot;
+ quot -= 1;
+ } else {
+ rem += (bLong << 1) - quot;
+ quot -= 2;
+ }
+ }
+ }
+ }
+ dest[i] = (int) (quot & 0xffffffffL);
+ }
+ return (int) rem;
+ }
+
+ /**
+ * Divides an unsigned long a by an unsigned int b. It is supposed that the
+ * most significant bit of b is set to 1, i.e. b < 0
+ *
+ * @param a the dividend
+ * @param b the divisor
+ * @return the long value containing the unsigned integer remainder in the
+ * left half and the unsigned integer quotient in the right half
+ */
+ static long divideLongByInt(long a, int b) {
+ long quot;
+ long rem;
+ long bLong = b & 0xffffffffL;
+
+ if (a >= 0) {
+ quot = (a / bLong);
+ rem = (a % bLong);
+ } else {
+ /*
+ * Make the dividend positive shifting it right by 1 bit then get the
+ * quotient an remainder and correct them properly
+ */
+ long aPos = a >>> 1;
+ long bPos = b >>> 1;
+ quot = aPos / bPos;
+ rem = aPos % bPos;
+ // double the remainder and add 1 if a is odd
+ rem = (rem << 1) + (a & 1);
+ if ((b & 1) != 0) { // the divisor is odd
+ if (quot <= rem) {
+ rem -= quot;
+ } else {
+ if (quot - rem <= bLong) {
+ rem += bLong - quot;
+ quot -= 1;
+ } else {
+ rem += (bLong << 1) - quot;
+ quot -= 2;
+ }
+ }
+ }
+ }
+ return (rem << 32) | (quot & 0xffffffffL);
+ }
+
+ /**
+ * Performs modular exponentiation using the Montgomery Reduction. It requires
+ * that all parameters be positive and the modulus be even. Based The
+ * square and multiply algorithm and the Montgomery Reduction C. K. Koc -
+ * Montgomery Reduction with Even Modulus. The square and multiply
+ * algorithm and the Montgomery Reduction.
+ *
+ * @ar.org.fitc.ref "C. K. Koc - Montgomery Reduction with Even Modulus"
+ * @see BigInteger#modPow(BigInteger, BigInteger)
+ */
+ static BigInteger evenModPow(BigInteger base, BigInteger exponent,
+ BigInteger modulus) {
+ // PRE: (base > 0), (exponent > 0), (modulus > 0) and (modulus even)
+ // STEP 1: Obtain the factorization 'modulus'= q * 2^j.
+ int j = modulus.getLowestSetBit();
+ BigInteger q = modulus.shiftRight(j);
+
+ // STEP 2: Compute x1 := base^exponent (mod q).
+ BigInteger x1 = oddModPow(base, exponent, q);
+
+ // STEP 3: Compute x2 := base^exponent (mod 2^j).
+ BigInteger x2 = pow2ModPow(base, exponent, j);
+
+ // STEP 4: Compute q^(-1) (mod 2^j) and y := (x2-x1) * q^(-1) (mod 2^j)
+ BigInteger qInv = modPow2Inverse(q, j);
+ BigInteger y = (x2.subtract(x1)).multiply(qInv);
+ inplaceModPow2(y, j);
+ if (y.sign < 0) {
+ y = y.add(BigInteger.getPowerOfTwo(j));
+ }
+ // STEP 5: Compute and return: x1 + q * y
+ return x1.add(q.multiply(y));
+ }
+
+ /**
+ * Performs the final reduction of the Montgomery algorithm.
+ *
+ * @see #monPro(BigInteger, BigInteger, BigInteger, long)
+ * @see #monSquare(BigInteger, BigInteger, long)
+ */
+ static BigInteger finalSubtraction(int res[], BigInteger modulus) {
+
+ // skipping leading zeros
+ int modulusLen = modulus.numberLength;
+ boolean doSub = res[modulusLen] != 0;
+ if (!doSub) {
+ int modulusDigits[] = modulus.digits;
+ doSub = true;
+ for (int i = modulusLen - 1; i >= 0; i--) {
+ if (res[i] != modulusDigits[i]) {
+ doSub = (res[i] != 0)
+ && ((res[i] & 0xFFFFFFFFL) > (modulusDigits[i] & 0xFFFFFFFFL));
+ break;
+ }
+ }
+ }
+
+ BigInteger result = new BigInteger(1, modulusLen + 1, res);
+
+ // if (res >= modulusDigits) compute (res - modulusDigits)
+ if (doSub) {
+ Elementary.inplaceSubtract(result, modulus);
+ }
+
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * @param m a positive modulus Return the greatest common divisor of op1 and
+ * op2,
+ *
+ * @param op1 must be greater than zero
+ * @param op2 must be greater than zero
+ * @see BigInteger#gcd(BigInteger)
+ * @return {@code GCD(op1, op2)}
+ */
+ static BigInteger gcdBinary(BigInteger op1, BigInteger op2) {
+ // PRE: (op1 > 0) and (op2 > 0)
+
+ /*
+ * Divide both number the maximal possible times by 2 without rounding
+ * gcd(2*a, 2*b) = 2 * gcd(a,b)
+ */
+ int lsb1 = op1.getLowestSetBit();
+ int lsb2 = op2.getLowestSetBit();
+ int pow2Count = Math.min(lsb1, lsb2);
+
+ BitLevel.inplaceShiftRight(op1, lsb1);
+ BitLevel.inplaceShiftRight(op2, lsb2);
+
+ BigInteger swap;
+ // I want op2 > op1
+ if (op1.compareTo(op2) == BigInteger.GREATER) {
+ swap = op1;
+ op1 = op2;
+ op2 = swap;
+ }
+
+ do { // INV: op2 >= op1 && both are odd unless op1 = 0
+
+ // Optimization for small operands
+ // (op2.bitLength() < 64) implies by INV (op1.bitLength() < 64)
+ if ((op2.numberLength == 1)
+ || ((op2.numberLength == 2) && (op2.digits[1] > 0))) {
+ op2 = BigInteger.valueOf(Division.gcdBinary(op1.longValue(),
+ op2.longValue()));
+ break;
+ }
+
+ // Implements one step of the Euclidean algorithm
+ // To reduce one operand if it's much smaller than the other one
+ if (op2.numberLength > op1.numberLength * 1.2) {
+ op2 = op2.remainder(op1);
+ if (op2.signum() != 0) {
+ BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit());
+ }
+ } else {
+
+ // Use Knuth's algorithm of successive subtract and shifting
+ do {
+ Elementary.inplaceSubtract(op2, op1); // both are odd
+ BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); // op2 is even
+ } while (op2.compareTo(op1) >= BigInteger.EQUALS);
+ }
+ // now op1 >= op2
+ swap = op2;
+ op2 = op1;
+ op1 = swap;
+ } while (op1.sign != 0);
+ return op2.shiftLeft(pow2Count);
+ }
+
+ /**
+ * Performs the same as {@link #gcdBinary(BigInteger, BigInteger)}, but with
+ * numbers of 63 bits, represented in positives values of {@code long} type.
+ *
+ * @param op1 a positive number
+ * @param op2 a positive number
+ * @see #gcdBinary(BigInteger, BigInteger)
+ * @return
GCD(op1, op2)
+ */
+ static long gcdBinary(long op1, long op2) {
+ // PRE: (op1 > 0) and (op2 > 0)
+ int lsb1 = Long.numberOfTrailingZeros(op1);
+ int lsb2 = Long.numberOfTrailingZeros(op2);
+ int pow2Count = Math.min(lsb1, lsb2);
+
+ if (lsb1 != 0) {
+ op1 >>>= lsb1;
+ }
+ if (lsb2 != 0) {
+ op2 >>>= lsb2;
+ }
+ do {
+ if (op1 >= op2) {
+ op1 -= op2;
+ op1 >>>= Long.numberOfTrailingZeros(op1);
+ } else {
+ op2 -= op1;
+ op2 >>>= Long.numberOfTrailingZeros(op2);
+ }
+ } while (op1 != 0);
+ return (op2 << pow2Count);
+ }
+
+ /**
+ * Performs {@code x = x mod (2n)}.
+ *
+ * @param x a positive number, it will store the result.
+ * @param n a positive exponent of {@code 2}.
+ */
+ static void inplaceModPow2(BigInteger x, int n) {
+ // PRE: (x > 0) and (n >= 0)
+ int fd = n >> 5;
+ int leadingZeros;
+
+ if ((x.numberLength < fd) || (x.bitLength() <= n)) {
+ return;
+ }
+ leadingZeros = 32 - (n & 31);
+ x.numberLength = fd + 1;
+ x.digits[fd] &= (leadingZeros < 32) ? (-1 >>> leadingZeros) : 0;
+ x.cutOffLeadingZeroes();
+ }
+
+ /**
+ *
+ * Based on "New Algorithm for Classical Modular Inverse" Róbert Lórencz. LNCS
+ * 2523 (2002)
+ *
+ * @return a^(-1) mod m
+ */
+ static BigInteger modInverseLorencz(BigInteger a, BigInteger modulo) {
+ // PRE: a is coprime with modulo, a < modulo
+
+ int max = Math.max(a.numberLength, modulo.numberLength);
+ int uDigits[] = new int[max + 1]; // enough place to make all the inplace
+ // operation
+ int vDigits[] = new int[max + 1];
+ System.arraycopy(modulo.digits, 0, uDigits, 0, modulo.numberLength);
+ System.arraycopy(a.digits, 0, vDigits, 0, a.numberLength);
+ BigInteger u = new BigInteger(modulo.sign, modulo.numberLength, uDigits);
+ BigInteger v = new BigInteger(a.sign, a.numberLength, vDigits);
+
+ BigInteger r = new BigInteger(0, 1, new int[max + 1]); // BigInteger.ZERO;
+ BigInteger s = new BigInteger(1, 1, new int[max + 1]);
+ s.digits[0] = 1;
+ // r == 0 && s == 1, but with enough place
+
+ int coefU = 0, coefV = 0;
+ int n = modulo.bitLength();
+ int k;
+ while (!isPowerOfTwo(u, coefU) && !isPowerOfTwo(v, coefV)) {
+
+ // modification of original algorithm: I calculate how many times the
+ // algorithm will enter in the same branch of if
+ k = howManyIterations(u, n);
+
+ if (k != 0) {
+ BitLevel.inplaceShiftLeft(u, k);
+ if (coefU >= coefV) {
+ BitLevel.inplaceShiftLeft(r, k);
+ } else {
+ BitLevel.inplaceShiftRight(s, Math.min(coefV - coefU, k));
+ if (k - (coefV - coefU) > 0) {
+ BitLevel.inplaceShiftLeft(r, k - coefV + coefU);
+ }
+ }
+ coefU += k;
+ }
+
+ k = howManyIterations(v, n);
+ if (k != 0) {
+ BitLevel.inplaceShiftLeft(v, k);
+ if (coefV >= coefU) {
+ BitLevel.inplaceShiftLeft(s, k);
+ } else {
+ BitLevel.inplaceShiftRight(r, Math.min(coefU - coefV, k));
+ if (k - (coefU - coefV) > 0) {
+ BitLevel.inplaceShiftLeft(s, k - coefU + coefV);
+ }
+ }
+ coefV += k;
+ }
+
+ if (u.signum() == v.signum()) {
+ if (coefU <= coefV) {
+ Elementary.completeInPlaceSubtract(u, v);
+ Elementary.completeInPlaceSubtract(r, s);
+ } else {
+ Elementary.completeInPlaceSubtract(v, u);
+ Elementary.completeInPlaceSubtract(s, r);
+ }
+ } else {
+ if (coefU <= coefV) {
+ Elementary.completeInPlaceAdd(u, v);
+ Elementary.completeInPlaceAdd(r, s);
+ } else {
+ Elementary.completeInPlaceAdd(v, u);
+ Elementary.completeInPlaceAdd(s, r);
+ }
+ }
+ if (v.signum() == 0 || u.signum() == 0) {
+ // math.19: BigInteger not invertible
+ throw new ArithmeticException("BigInteger not invertible.");
+ }
+ }
+
+ if (isPowerOfTwo(v, coefV)) {
+ r = s;
+ if (v.signum() != u.signum()) {
+ u = u.negate();
+ }
+ }
+ if (u.testBit(n)) {
+ if (r.signum() < 0) {
+ r = r.negate();
+ } else {
+ r = modulo.subtract(r);
+ }
+ }
+ if (r.signum() < 0) {
+ r = r.add(modulo);
+ }
+
+ return r;
+ }
+
+ /**
+ * Calculates a.modInverse(p) Based on: Savas, E; Koc, C "The Montgomery
+ * Modular Inverse - Revised".
+ */
+ static BigInteger modInverseMontgomery(BigInteger a, BigInteger p) {
+ if (a.sign == 0) {
+ // ZERO hasn't inverse
+ // math.19: BigInteger not invertible
+ throw new ArithmeticException("BigInteger not invertible.");
+ }
+
+ if (!p.testBit(0)) {
+ // montgomery inverse require even modulo
+ return modInverseLorencz(a, p);
+ }
+
+ int m = p.numberLength * 32;
+ // PRE: a \in [1, p - 1]
+ BigInteger u, v, r, s;
+ u = p.copy(); // make copy to use inplace method
+ v = a.copy();
+ int max = Math.max(v.numberLength, u.numberLength);
+ r = new BigInteger(1, 1, new int[max + 1]);
+ s = new BigInteger(1, 1, new int[max + 1]);
+ s.digits[0] = 1;
+ // s == 1 && v == 0
+
+ int k = 0;
+
+ int lsbu = u.getLowestSetBit();
+ int lsbv = v.getLowestSetBit();
+ int toShift;
+
+ if (lsbu > lsbv) {
+ BitLevel.inplaceShiftRight(u, lsbu);
+ BitLevel.inplaceShiftRight(v, lsbv);
+ BitLevel.inplaceShiftLeft(r, lsbv);
+ k += lsbu - lsbv;
+ } else {
+ BitLevel.inplaceShiftRight(u, lsbu);
+ BitLevel.inplaceShiftRight(v, lsbv);
+ BitLevel.inplaceShiftLeft(s, lsbu);
+ k += lsbv - lsbu;
+ }
+
+ r.sign = 1;
+ while (v.signum() > 0) {
+ // INV v >= 0, u >= 0, v odd, u odd (except last iteration when v is even
+ // (0))
+
+ while (u.compareTo(v) > BigInteger.EQUALS) {
+ Elementary.inplaceSubtract(u, v);
+ toShift = u.getLowestSetBit();
+ BitLevel.inplaceShiftRight(u, toShift);
+ Elementary.inplaceAdd(r, s);
+ BitLevel.inplaceShiftLeft(s, toShift);
+ k += toShift;
+ }
+
+ while (u.compareTo(v) <= BigInteger.EQUALS) {
+ Elementary.inplaceSubtract(v, u);
+ if (v.signum() == 0) {
+ break;
+ }
+ toShift = v.getLowestSetBit();
+ BitLevel.inplaceShiftRight(v, toShift);
+ Elementary.inplaceAdd(s, r);
+ BitLevel.inplaceShiftLeft(r, toShift);
+ k += toShift;
+ }
+ }
+ if (!u.isOne()) {
+ // in u is stored the gcd
+ // math.19: BigInteger not invertible.
+ throw new ArithmeticException("BigInteger not invertible.");
+ }
+ if (r.compareTo(p) >= BigInteger.EQUALS) {
+ Elementary.inplaceSubtract(r, p);
+ }
+
+ r = p.subtract(r);
+
+ // Have pair: ((BigInteger)r, (Integer)k) where r == a^(-1) * 2^k mod
+ // (module)
+ int n1 = calcN(p);
+ if (k > m) {
+ r = monPro(r, BigInteger.ONE, p, n1);
+ k = k - m;
+ }
+
+ r = monPro(r, BigInteger.getPowerOfTwo(m - k), p, n1);
+ return r;
+ }
+
+ /**
+ * @param x an odd positive number.
+ * @param n the exponent by which 2 is raised.
+ * @return {@code x-1 (mod 2n)}.
+ */
+ static BigInteger modPow2Inverse(BigInteger x, int n) {
+ // PRE: (x > 0), (x is odd), and (n > 0)
+ BigInteger y = new BigInteger(1, new int[1 << n]);
+ y.numberLength = 1;
+ y.digits[0] = 1;
+ y.sign = 1;
+
+ for (int i = 1; i < n; i++) {
+ if (BitLevel.testBit(x.multiply(y), i)) {
+ // Adding 2^i to y (setting the i-th bit)
+ y.digits[i >> 5] |= (1 << (i & 31));
+ }
+ }
+ return y;
+ }
+
+ /**
+ * Implements the Montgomery Product of two integers represented by {@code
+ * int} arrays. The arrays are supposed in little endian notation.
+ *
+ * @param a The first factor of the product.
+ * @param b The second factor of the product.
+ * @param modulus The modulus of the operations. Zmodulus.
+ * @param n2 The digit modulus'[0].
+ * @ar.org.fitc.ref "C. K. Koc - Analyzing and Comparing Montgomery
+ * Multiplication Algorithms"
+ * @see #modPowOdd(BigInteger, BigInteger, BigInteger)
+ */
+ static BigInteger monPro(BigInteger a, BigInteger b, BigInteger modulus,
+ int n2) {
+ int modulusLen = modulus.numberLength;
+ int res[] = new int[(modulusLen << 1) + 1];
+ Multiplication.multArraysPAP(a.digits,
+ Math.min(modulusLen, a.numberLength), b.digits, Math.min(modulusLen,
+ b.numberLength), res);
+ monReduction(res, modulus, n2);
+ return finalSubtraction(res, modulus);
+ }
+
+ /**
+ * Multiplies an array by int and subtracts it from a subarray of another
+ * array.
+ *
+ * @param a the array to subtract from
+ * @param start the start element of the subarray of a
+ * @param b the array to be multiplied and subtracted
+ * @param bLen the length of b
+ * @param c the multiplier of b
+ * @return the carry element of subtraction
+ */
+ static int multiplyAndSubtract(int a[], int start, int b[], int bLen, int c) {
+ long carry0 = 0;
+ long carry1 = 0;
+
+ for (int i = 0; i < bLen; i++) {
+ carry0 = Multiplication.unsignedMultAddAdd(b[i], c, (int) carry0, 0);
+ carry1 = (a[start + i] & 0xffffffffL) - (carry0 & 0xffffffffL) + carry1;
+ a[start + i] = (int) carry1;
+ carry1 >>= 32; // -1 or 0
+ carry0 >>>= 32;
+ }
+
+ carry1 = (a[start + bLen] & 0xffffffffL) - carry0 + carry1;
+ a[start + bLen] = (int) carry1;
+ return (int) (carry1 >> 32); // -1 or 0
+ }
+
+ /**
+ * Performs modular exponentiation using the Montgomery Reduction. It requires
+ * that all parameters be positive and the modulus be odd. >
+ *
+ * @see BigInteger#modPow(BigInteger, BigInteger)
+ * @see #monPro(BigInteger, BigInteger, BigInteger, int)
+ * @see #slidingWindow(BigInteger, BigInteger, BigInteger, BigInteger, int)
+ * @see #squareAndMultiply(BigInteger, BigInteger, BigInteger, BigInteger,
+ * int)
+ */
+ static BigInteger oddModPow(BigInteger base, BigInteger exponent,
+ BigInteger modulus) {
+ // PRE: (base > 0), (exponent > 0), (modulus > 0) and (odd modulus)
+ int k = (modulus.numberLength << 5); // r = 2^k
+ // n-residue of base [base * r (mod modulus)]
+ BigInteger a2 = base.shiftLeft(k).mod(modulus);
+ // n-residue of base [1 * r (mod modulus)]
+ BigInteger x2 = BigInteger.getPowerOfTwo(k).mod(modulus);
+ BigInteger res;
+ // Compute (modulus[0]^(-1)) (mod 2^32) for odd modulus
+
+ int n2 = calcN(modulus);
+ if (modulus.numberLength == 1) {
+ res = squareAndMultiply(x2, a2, exponent, modulus, n2);
+ } else {
+ res = slidingWindow(x2, a2, exponent, modulus, n2);
+ }
+
+ return monPro(res, BigInteger.ONE, modulus, n2);
+ }
+
+ /**
+ * It requires that all parameters be positive.
+ *
+ * @return {@code baseexponent mod (2j)}.
+ * @see BigInteger#modPow(BigInteger, BigInteger)
+ */
+ static BigInteger pow2ModPow(BigInteger base, BigInteger exponent, int j) {
+ // PRE: (base > 0), (exponent > 0) and (j > 0)
+ BigInteger res = BigInteger.ONE;
+ BigInteger e = exponent.copy();
+ BigInteger baseMod2toN = base.copy();
+ BigInteger res2;
+ /*
+ * If 'base' is odd then it's coprime with 2^j and phi(2^j) = 2^(j-1); so we
+ * can reduce reduce the exponent (mod 2^(j-1)).
+ */
+ if (base.testBit(0)) {
+ inplaceModPow2(e, j - 1);
+ }
+ inplaceModPow2(baseMod2toN, j);
+
+ for (int i = e.bitLength() - 1; i >= 0; i--) {
+ res2 = res.copy();
+ inplaceModPow2(res2, j);
+ res = res.multiply(res2);
+ if (BitLevel.testBit(e, i)) {
+ res = res.multiply(baseMod2toN);
+ inplaceModPow2(res, j);
+ }
+ }
+ inplaceModPow2(res, j);
+ return res;
+ }
+
+ /**
+ * Divides a BigInteger
by a signed int
and returns
+ * the remainder.
+ *
+ * @param dividend the BigInteger to be divided. Must be non-negative.
+ * @param divisor a signed int
+ * @return divide % divisor
+ */
+ static int remainder(BigInteger dividend, int divisor) {
+ return remainderArrayByInt(dividend.digits, dividend.numberLength, divisor);
+ }
+
+ /**
+ * Divides an array by an integer value. Implements the Knuth's division
+ * algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
+ *
+ * @param src the dividend
+ * @param srcLength the length of the dividend
+ * @param divisor the divisor
+ * @return remainder
+ */
+ static int remainderArrayByInt(int src[], final int srcLength,
+ final int divisor) {
+
+ long result = 0;
+
+ for (int i = srcLength - 1; i >= 0; i--) {
+ long temp = (result << 32) + (src[i] & 0xffffffffL);
+ long res = divideLongByInt(temp, divisor);
+ result = (int) (res >> 32);
+ }
+ return (int) result;
+ }
+
+ /*
+ * Implements the Montgomery modular exponentiation based in The sliding
+ * windows algorithm and the MongomeryReduction.
+ *
+ * @ar.org.fitc.ref
+ * "A. Menezes,P. van Oorschot, S. Vanstone - Handbook of Applied Cryptography"
+ * ;
+ *
+ * @see #oddModPow(BigInteger, BigInteger, BigInteger)
+ */
+ static BigInteger slidingWindow(BigInteger x2, BigInteger a2,
+ BigInteger exponent, BigInteger modulus, int n2) {
+ // fill odd low pows of a2
+ BigInteger pows[] = new BigInteger[8];
+ BigInteger res = x2;
+ int lowexp;
+ BigInteger x3;
+ int acc3;
+ pows[0] = a2;
+
+ x3 = monPro(a2, a2, modulus, n2);
+ for (int i = 1; i <= 7; i++) {
+ pows[i] = monPro(pows[i - 1], x3, modulus, n2);
+ }
+
+ for (int i = exponent.bitLength() - 1; i >= 0; i--) {
+ if (BitLevel.testBit(exponent, i)) {
+ lowexp = 1;
+ acc3 = i;
+
+ for (int j = Math.max(i - 3, 0); j <= i - 1; j++) {
+ if (BitLevel.testBit(exponent, j)) {
+ if (j < acc3) {
+ acc3 = j;
+ lowexp = (lowexp << (i - j)) ^ 1;
+ } else {
+ lowexp = lowexp ^ (1 << (j - acc3));
+ }
+ }
+ }
+
+ for (int j = acc3; j <= i; j++) {
+ res = monPro(res, res, modulus, n2);
+ }
+ res = monPro(pows[(lowexp - 1) >> 1], res, modulus, n2);
+ i = acc3;
+ } else {
+ res = monPro(res, res, modulus, n2);
+ }
+ }
+ return res;
+ }
+
+ static BigInteger squareAndMultiply(BigInteger x2, BigInteger a2,
+ BigInteger exponent, BigInteger modulus, int n2) {
+ BigInteger res = x2;
+ for (int i = exponent.bitLength() - 1; i >= 0; i--) {
+ res = monPro(res, res, modulus, n2);
+ if (BitLevel.testBit(exponent, i)) {
+ res = monPro(res, a2, modulus, n2);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Calculate the first digit of the inverse.
+ */
+ private static int calcN(BigInteger a) {
+ long m0 = a.digits[0] & 0xFFFFFFFFL;
+ long n2 = 1L; // this is a'[0]
+ long powerOfTwo = 2L;
+ do {
+ if (((m0 * n2) & powerOfTwo) != 0) {
+ n2 |= powerOfTwo;
+ }
+ powerOfTwo <<= 1;
+ } while (powerOfTwo < 0x100000000L);
+ n2 = -n2;
+ return (int) (n2 & 0xFFFFFFFFL);
+ }
+
+ /**
+ * Calculate how many iteration of Lorencz's algorithm would perform the same
+ * operation.
+ *
+ * @param bi
+ * @param n
+ * @return
+ */
+ private static int howManyIterations(BigInteger bi, int n) {
+ int i = n - 1;
+ if (bi.sign > 0) {
+ while (!bi.testBit(i)) {
+ i--;
+ }
+ return n - 1 - i;
+ } else {
+ while (bi.testBit(i)) {
+ i--;
+ }
+ return n - 1 - Math.max(i, bi.getLowestSetBit());
+ }
+ }
+
+ /**
+ * Returns {@code bi == abs(2^exp)}.
+ */
+ private static boolean isPowerOfTwo(BigInteger bi, int exp) {
+ boolean result = false;
+ result = (exp >> 5 == bi.numberLength - 1)
+ && (bi.digits[bi.numberLength - 1] == 1 << (exp & 31));
+ if (result) {
+ for (int i = 0; result && i < bi.numberLength - 1; i++) {
+ result = bi.digits[i] == 0;
+ }
+ }
+ return result;
+ }
+
+ private static void monReduction(int[] res, BigInteger modulus, int n2) {
+
+ /* res + m*modulus_digits */
+ int[] modulusDigits = modulus.digits;
+ int modulusLen = modulus.numberLength;
+ long outerCarry = 0;
+
+ for (int i = 0; i < modulusLen; i++) {
+ long innnerCarry = 0;
+ int m = (int) Multiplication.unsignedMultAddAdd(res[i], n2, 0, 0);
+ for (int j = 0; j < modulusLen; j++) {
+ innnerCarry = Multiplication.unsignedMultAddAdd(m, modulusDigits[j],
+ res[i + j], (int) innnerCarry);
+ res[i + j] = (int) innnerCarry;
+ innnerCarry >>>= 32;
+ }
+
+ outerCarry += (res[i + modulusLen] & 0xFFFFFFFFL) + innnerCarry;
+ res[i + modulusLen] = (int) outerCarry;
+ outerCarry >>>= 32;
+ }
+
+ res[modulusLen << 1] = (int) outerCarry;
+
+ /* res / r */
+ for (int j = 0; j < modulusLen + 1; j++) {
+ res[j] = res[j + modulusLen];
+ }
+ }
+}
diff --git a/gwt/jre/java/math/Elementary.java b/gwt/jre/java/math/Elementary.java
new file mode 100644
index 0000000..58bec5b
--- /dev/null
+++ b/gwt/jre/java/math/Elementary.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+/**
+ * Static library that provides the basic arithmetic mutable operations for
+ * {@link BigInteger}. The operations provided are listed below.
In addition to this, some Inplace (mutable) methods are
+ * provided.
+ */
+class Elementary {
+
+ /**
+ * @see BigInteger#add(BigInteger) .
+ * @param op1
+ * @param op2
+ * @return
+ */
+ static BigInteger add(BigInteger op1, BigInteger op2) {
+ int resDigits[];
+ int resSign;
+ int op1Sign = op1.sign;
+ int op2Sign = op2.sign;
+
+ if (op1Sign == 0) {
+ return op2;
+ }
+ if (op2Sign == 0) {
+ return op1;
+ }
+ int op1Len = op1.numberLength;
+ int op2Len = op2.numberLength;
+
+ if (op1Len + op2Len == 2) {
+ long a = (op1.digits[0] & 0xFFFFFFFFL);
+ long b = (op2.digits[0] & 0xFFFFFFFFL);
+ long res;
+ int valueLo;
+ int valueHi;
+
+ if (op1Sign == op2Sign) {
+ res = a + b;
+ valueLo = (int) res;
+ valueHi = (int) (res >>> 32);
+ return ((valueHi == 0) ? new BigInteger(op1Sign, valueLo)
+ : new BigInteger(op1Sign, 2, new int[] {valueLo, valueHi}));
+ }
+ return BigInteger.valueOf((op1Sign < 0) ? (b - a) : (a - b));
+ } else if (op1Sign == op2Sign) {
+ resSign = op1Sign;
+ // an augend should not be shorter than addend
+ resDigits = (op1Len >= op2Len) ? add(op1.digits, op1Len, op2.digits,
+ op2Len) : add(op2.digits, op2Len, op1.digits, op1Len);
+ } else { // signs are different
+ int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1)
+ : compareArrays(op1.digits, op2.digits, op1Len));
+
+ if (cmp == BigInteger.EQUALS) {
+ return BigInteger.ZERO;
+ }
+ // a minuend should not be shorter than subtrahend
+ if (cmp == BigInteger.GREATER) {
+ resSign = op1Sign;
+ resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len);
+ } else {
+ resSign = op2Sign;
+ resDigits = subtract(op2.digits, op2Len, op1.digits, op1Len);
+ }
+ }
+ BigInteger res = new BigInteger(resSign, resDigits.length, resDigits);
+ res.cutOffLeadingZeroes();
+ return res;
+ }
+
+ /**
+ * Compares two arrays. All elements are treated as unsigned integers. The
+ * magnitude is the bit chain of elements in big-endian order.
+ *
+ * @param a the first array
+ * @param b the second array
+ * @param size the size of arrays
+ * @return 1 if a > b, -1 if a < b, 0 if a == b
+ */
+ static int compareArrays(final int[] a, final int[] b, final int size) {
+ int i;
+ for (i = size - 1; (i >= 0) && (a[i] == b[i]); i--) {
+ // empty
+ }
+ return ((i < 0) ? BigInteger.EQUALS
+ : (a[i] & 0xFFFFFFFFL) < (b[i] & 0xFFFFFFFFL) ? BigInteger.LESS
+ : BigInteger.GREATER);
+ }
+
+ /**
+ * Same as @link #inplaceAdd(BigInteger, BigInteger), but without the
+ * restriction of non-positive values.
+ *
+ * @param op1 any number
+ * @param op2 any number
+ */
+ static void completeInPlaceAdd(BigInteger op1, BigInteger op2) {
+ if (op1.sign == 0) {
+ System.arraycopy(op2.digits, 0, op1.digits, 0, op2.numberLength);
+ } else if (op2.sign == 0) {
+ return;
+ } else if (op1.sign == op2.sign) {
+ add(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength);
+ } else {
+ int sign = unsignedArraysCompare(op1.digits, op2.digits,
+ op1.numberLength, op2.numberLength);
+ if (sign > 0) {
+ subtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength);
+ } else {
+ inverseSubtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength);
+ op1.sign = -op1.sign;
+ }
+ }
+ op1.numberLength = Math.max(op1.numberLength, op2.numberLength) + 1;
+ op1.cutOffLeadingZeroes();
+ op1.unCache();
+ }
+
+ /**
+ * Same as @link #inplaceSubtract(BigInteger, BigInteger), but without the
+ * restriction of non-positive values.
+ *
+ * @param op1 should have enough space to save the result
+ * @param op2
+ */
+ static void completeInPlaceSubtract(BigInteger op1, BigInteger op2) {
+ int resultSign = op1.compareTo(op2);
+ if (op1.sign == 0) {
+ System.arraycopy(op2.digits, 0, op1.digits, 0, op2.numberLength);
+ op1.sign = -op2.sign;
+ } else if (op1.sign != op2.sign) {
+ add(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength);
+ op1.sign = resultSign;
+ } else {
+ int sign = unsignedArraysCompare(op1.digits, op2.digits,
+ op1.numberLength, op2.numberLength);
+ if (sign > 0) {
+ subtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength); // op1 = op1 - op2
+ // op1.sign remains equal
+ } else {
+ inverseSubtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength); // op1 = op2 - op1
+ op1.sign = -op1.sign;
+ }
+ }
+ op1.numberLength = Math.max(op1.numberLength, op2.numberLength) + 1;
+ op1.cutOffLeadingZeroes();
+ op1.unCache();
+ }
+
+ /**
+ * Performs {@code op1 += op2}. {@code op1} must have enough place to store
+ * the result (i.e. {@code op1.bitLength() >= op2.bitLength()}). Both should
+ * be positive (i.e. {@code op1 >= op2}).
+ *
+ * @param op1 the input minuend, and the output result.
+ * @param op2 the addend
+ */
+ static void inplaceAdd(BigInteger op1, BigInteger op2) {
+ // PRE: op1 >= op2 > 0
+ add(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength);
+ op1.numberLength = Math.min(
+ Math.max(op1.numberLength, op2.numberLength) + 1, op1.digits.length);
+ op1.cutOffLeadingZeroes();
+ op1.unCache();
+ }
+
+ /**
+ * Performs: {@code op1 += addend}. The number must to have place to hold a
+ * possible carry.
+ */
+ static void inplaceAdd(BigInteger op1, final int addend) {
+ int carry = inplaceAdd(op1.digits, op1.numberLength, addend);
+ if (carry == 1) {
+ op1.digits[op1.numberLength] = 1;
+ op1.numberLength++;
+ }
+ op1.unCache();
+ }
+
+ /**
+ * Adds an integer value to the array of integers remembering carry.
+ *
+ * @return a possible generated carry (0 or 1)
+ */
+ static int inplaceAdd(int a[], final int aSize, final int addend) {
+ long carry = addend & 0xFFFFFFFFL;
+
+ for (int i = 0; (carry != 0) && (i < aSize); i++) {
+ carry += a[i] & 0xFFFFFFFFL;
+ a[i] = (int) carry;
+ carry >>= 32;
+ }
+ return (int) carry;
+ }
+
+ /**
+ * Performs {@code op1 -= op2}. {@code op1} must have enough place to store
+ * the result (i.e. {@code op1.bitLength() >= op2.bitLength()}). Both should
+ * be positive (what implies that {@code op1 >= op2}).
+ *
+ * @param op1 the input minuend, and the output result.
+ * @param op2 the subtrahend
+ */
+ static void inplaceSubtract(BigInteger op1, BigInteger op2) {
+ // PRE: op1 >= op2 > 0
+ subtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
+ op2.numberLength);
+ op1.cutOffLeadingZeroes();
+ op1.unCache();
+ }
+
+ /**
+ * @see BigInteger#subtract(BigInteger) .
+ * @param op1
+ * @param op2
+ * @return
+ */
+ static BigInteger subtract(BigInteger op1, BigInteger op2) {
+ int resSign;
+ int resDigits[];
+ int op1Sign = op1.sign;
+ int op2Sign = op2.sign;
+
+ if (op2Sign == 0) {
+ return op1;
+ }
+ if (op1Sign == 0) {
+ return op2.negate();
+ }
+ int op1Len = op1.numberLength;
+ int op2Len = op2.numberLength;
+ if (op1Len + op2Len == 2) {
+ long a = (op1.digits[0] & 0xFFFFFFFFL);
+ long b = (op2.digits[0] & 0xFFFFFFFFL);
+ if (op1Sign < 0) {
+ a = -a;
+ }
+ if (op2Sign < 0) {
+ b = -b;
+ }
+ return BigInteger.valueOf(a - b);
+ }
+ int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1)
+ : Elementary.compareArrays(op1.digits, op2.digits, op1Len));
+
+ if (cmp == BigInteger.LESS) {
+ resSign = -op2Sign;
+ resDigits = (op1Sign == op2Sign) ? subtract(op2.digits, op2Len,
+ op1.digits, op1Len) : add(op2.digits, op2Len, op1.digits, op1Len);
+ } else {
+ resSign = op1Sign;
+ if (op1Sign == op2Sign) {
+ if (cmp == BigInteger.EQUALS) {
+ return BigInteger.ZERO;
+ }
+ resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len);
+ } else {
+ resDigits = add(op1.digits, op1Len, op2.digits, op2Len);
+ }
+ }
+ BigInteger res = new BigInteger(resSign, resDigits.length, resDigits);
+ res.cutOffLeadingZeroes();
+ return res;
+ }
+
+ /**
+ * Addss the value represented by {@code b} to the value represented by
+ * {@code a}. It is assumed the magnitude of a is not less than the magnitude
+ * of b.
+ *
+ * @return {@code a + b}
+ */
+ private static int[] add(int a[], int aSize, int b[], int bSize) {
+ // PRE: a[] >= b[]
+ int res[] = new int[aSize + 1];
+ add(res, a, aSize, b, bSize);
+ return res;
+ }
+
+ /**
+ * Performs {@code res = a + b}.
+ */
+ private static void add(int res[], int a[], int aSize, int b[], int bSize) {
+ // PRE: a.length < max(aSize, bSize)
+
+ int i;
+ long carry = (a[0] & 0xFFFFFFFFL) + (b[0] & 0xFFFFFFFFL);
+
+ res[0] = (int) carry;
+ carry >>= 32;
+
+ if (aSize >= bSize) {
+ for (i = 1; i < bSize; i++) {
+ carry += (a[i] & 0xFFFFFFFFL) + (b[i] & 0xFFFFFFFFL);
+ res[i] = (int) carry;
+ carry >>= 32;
+ }
+ for (; i < aSize; i++) {
+ carry += a[i] & 0xFFFFFFFFL;
+ res[i] = (int) carry;
+ carry >>= 32;
+ }
+ } else {
+ for (i = 1; i < aSize; i++) {
+ carry += (a[i] & 0xFFFFFFFFL) + (b[i] & 0xFFFFFFFFL);
+ res[i] = (int) carry;
+ carry >>= 32;
+ }
+ for (; i < bSize; i++) {
+ carry += b[i] & 0xFFFFFFFFL;
+ res[i] = (int) carry;
+ carry >>= 32;
+ }
+ }
+ if (carry != 0) {
+ res[i] = (int) carry;
+ }
+ }
+
+ /**
+ * Performs {@code res = b - a}.
+ */
+ private static void inverseSubtract(int res[], int a[], int aSize, int b[],
+ int bSize) {
+ int i;
+ long borrow = 0;
+ if (aSize < bSize) {
+ for (i = 0; i < aSize; i++) {
+ borrow += (b[i] & 0xFFFFFFFFL) - (a[i] & 0xFFFFFFFFL);
+ res[i] = (int) borrow;
+ borrow >>= 32; // -1 or 0
+ }
+ for (; i < bSize; i++) {
+ borrow += b[i] & 0xFFFFFFFFL;
+ res[i] = (int) borrow;
+ borrow >>= 32; // -1 or 0
+ }
+ } else {
+ for (i = 0; i < bSize; i++) {
+ borrow += (b[i] & 0xFFFFFFFFL) - (a[i] & 0xFFFFFFFFL);
+ res[i] = (int) borrow;
+ borrow >>= 32; // -1 or 0
+ }
+ for (; i < aSize; i++) {
+ borrow -= a[i] & 0xFFFFFFFFL;
+ res[i] = (int) borrow;
+ borrow >>= 32; // -1 or 0
+ }
+ }
+ }
+
+ /**
+ * Subtracts the value represented by {@code b} from the value represented by
+ * {@code a}. It is assumed the magnitude of a is not less than the magnitude
+ * of b.
+ *
+ * @return {@code a - b}
+ */
+ private static int[] subtract(int a[], int aSize, int b[], int bSize) {
+ // PRE: a[] >= b[]
+ int res[] = new int[aSize];
+ subtract(res, a, aSize, b, bSize);
+ return res;
+ }
+
+ /**
+ * Performs {@code res = a - b}. It is assumed the magnitude of a is not less
+ * than the magnitude of b.
+ */
+ private static void subtract(int res[], int a[], int aSize, int b[], int bSize) {
+ // PRE: a[] >= b[]
+ int i;
+ long borrow = 0;
+
+ for (i = 0; i < bSize; i++) {
+ borrow += (a[i] & 0xFFFFFFFFL) - (b[i] & 0xFFFFFFFFL);
+ res[i] = (int) borrow;
+ borrow >>= 32; // -1 or 0
+ }
+ for (; i < aSize; i++) {
+ borrow += a[i] & 0xFFFFFFFFL;
+ res[i] = (int) borrow;
+ borrow >>= 32; // -1 or 0
+ }
+ }
+
+ /**
+ * Compares two arrays, representing unsigned integer in little-endian order.
+ * Returns +1,0,-1 if a is - respective - greater, equal or lesser then b
+ */
+ private static int unsignedArraysCompare(int[] a, int[] b, int aSize,
+ int bSize) {
+ if (aSize > bSize) {
+ return 1;
+ } else if (aSize < bSize) {
+ return -1;
+ } else {
+ int i;
+ for (i = aSize - 1; i >= 0 && a[i] == b[i]; i--) {
+ // empty
+ }
+ return i < 0 ? BigInteger.EQUALS
+ : ((a[i] & 0xFFFFFFFFL) < (b[i] & 0xFFFFFFFFL) ? BigInteger.LESS
+ : BigInteger.GREATER);
+ }
+ }
+
+ /**
+ * Just to denote that this class can't be instantiated.
+ */
+ private Elementary() {
+ }
+
+}
diff --git a/gwt/jre/java/math/Logical.java b/gwt/jre/java/math/Logical.java
new file mode 100644
index 0000000..d3ab03e
--- /dev/null
+++ b/gwt/jre/java/math/Logical.java
@@ -0,0 +1,926 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+/**
+ * The library implements some logical operations over {@code BigInteger}. The
+ * operations provided are listed below.
+ */
+class Logical {
+
+ /**
+ * @see BigInteger#and(BigInteger)
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger and(BigInteger val, BigInteger that) {
+ if (that.sign == 0 || val.sign == 0) {
+ return BigInteger.ZERO;
+ }
+ if (that.equals(BigInteger.MINUS_ONE)) {
+ return val;
+ }
+ if (val.equals(BigInteger.MINUS_ONE)) {
+ return that;
+ }
+
+ if (val.sign > 0) {
+ if (that.sign > 0) {
+ return andPositive(val, that);
+ } else {
+ return andDiffSigns(val, that);
+ }
+ } else {
+ if (that.sign > 0) {
+ return andDiffSigns(that, val);
+ } else if (val.numberLength > that.numberLength) {
+ return andNegative(val, that);
+ } else {
+ return andNegative(that, val);
+ }
+ }
+ }
+
+ /**
+ * Return sign = positive.magnitude & magnitude = -negative.magnitude.
+ * @param positive
+ * @param negative
+ * @return
+ */
+ static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) {
+ // PRE: positive is positive and negative is negative
+ int iPos = positive.getFirstNonzeroDigit();
+ int iNeg = negative.getFirstNonzeroDigit();
+
+ // Look if the trailing zeros of the negative will "blank" all
+ // the positive digits
+ if (iNeg >= positive.numberLength) {
+ return BigInteger.ZERO;
+ }
+ int resLength = positive.numberLength;
+ int resDigits[] = new int[resLength];
+
+ // Must start from max(iPos, iNeg)
+ int i = Math.max(iPos, iNeg);
+ if (i == iNeg) {
+ resDigits[i] = -negative.digits[i] & positive.digits[i];
+ i++;
+ }
+ int limit = Math.min(negative.numberLength, positive.numberLength);
+ for (; i < limit; i++) {
+ resDigits[i] = ~negative.digits[i] & positive.digits[i];
+ }
+ // if the negative was shorter must copy the remaining digits
+ // from positive
+ if (i >= negative.numberLength) {
+ for (; i < positive.numberLength; i++) {
+ resDigits[i] = positive.digits[i];
+ }
+ } // else positive ended and must "copy" virtual 0's, do nothing then
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude).
+ * @param longer
+ * @param shorter
+ * @return
+ */
+ static BigInteger andNegative(BigInteger longer, BigInteger shorter) {
+ // PRE: longer and shorter are negative
+ // PRE: longer has at least as many digits as shorter
+ int iLonger = longer.getFirstNonzeroDigit();
+ int iShorter = shorter.getFirstNonzeroDigit();
+
+ // Does shorter matter?
+ if (iLonger >= shorter.numberLength) {
+ return longer;
+ }
+
+ int resLength;
+ int resDigits[];
+ int i = Math.max(iShorter, iLonger);
+ int digit;
+ if (iShorter > iLonger) {
+ digit = -shorter.digits[i] & ~longer.digits[i];
+ } else if (iShorter < iLonger) {
+ digit = ~shorter.digits[i] & -longer.digits[i];
+ } else {
+ digit = -shorter.digits[i] & -longer.digits[i];
+ }
+ if (digit == 0) {
+ for (i++; i < shorter.numberLength
+ && (digit = ~(longer.digits[i] | shorter.digits[i])) == 0; i++) {
+ // digit
+ }
+ // = ~longer.digits[i] & ~shorter.digits[i]
+ if (digit == 0) {
+ // shorter has only the remaining virtual sign bits
+ for (; i < longer.numberLength && (digit = ~longer.digits[i]) == 0; i++) {
+ // empty
+ }
+ if (digit == 0) {
+ resLength = longer.numberLength + 1;
+ resDigits = new int[resLength];
+ resDigits[resLength - 1] = 1;
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+ }
+ }
+ resLength = longer.numberLength;
+ resDigits = new int[resLength];
+ resDigits[i] = -digit;
+ for (i++; i < shorter.numberLength; i++) {
+ // resDigits[i] = ~(~longer.digits[i] & ~shorter.digits[i];)
+ resDigits[i] = longer.digits[i] | shorter.digits[i];
+ }
+ // shorter has only the remaining virtual sign bits
+ for (; i < longer.numberLength; i++) {
+ resDigits[i] = longer.digits[i];
+ }
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+
+ /**
+ * @see BigInteger#andNot(BigInteger)
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger andNot(BigInteger val, BigInteger that) {
+ if (that.sign == 0) {
+ return val;
+ }
+ if (val.sign == 0) {
+ return BigInteger.ZERO;
+ }
+ if (val.equals(BigInteger.MINUS_ONE)) {
+ return that.not();
+ }
+ if (that.equals(BigInteger.MINUS_ONE)) {
+ return BigInteger.ZERO;
+ }
+
+ // if val == that, return 0
+
+ if (val.sign > 0) {
+ if (that.sign > 0) {
+ return andNotPositive(val, that);
+ } else {
+ return andNotPositiveNegative(val, that);
+ }
+ } else {
+ if (that.sign > 0) {
+ return andNotNegativePositive(val, that);
+ } else {
+ return andNotNegative(val, that);
+ }
+ }
+ }
+
+ /**
+ * Return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude).
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger andNotNegative(BigInteger val, BigInteger that) {
+ // PRE: val < 0 && that < 0
+ int iVal = val.getFirstNonzeroDigit();
+ int iThat = that.getFirstNonzeroDigit();
+
+ if (iVal >= that.numberLength) {
+ return BigInteger.ZERO;
+ }
+
+ int resLength = that.numberLength;
+ int resDigits[] = new int[resLength];
+ int limit;
+ int i = iVal;
+ if (iVal < iThat) {
+ // resDigits[i] = -val.digits[i] & -1;
+ resDigits[i] = -val.digits[i];
+ limit = Math.min(val.numberLength, iThat);
+ for (i++; i < limit; i++) {
+ // resDigits[i] = ~val.digits[i] & -1;
+ resDigits[i] = ~val.digits[i];
+ }
+ if (i == val.numberLength) {
+ for (; i < iThat; i++) {
+ // resDigits[i] = -1 & -1;
+ resDigits[i] = -1;
+ }
+ // resDigits[i] = -1 & ~-that.digits[i];
+ resDigits[i] = that.digits[i] - 1;
+ } else {
+ // resDigits[i] = ~val.digits[i] & ~-that.digits[i];
+ resDigits[i] = ~val.digits[i] & (that.digits[i] - 1);
+ }
+ } else if (iThat < iVal) {
+ // resDigits[i] = -val.digits[i] & ~~that.digits[i];
+ resDigits[i] = -val.digits[i] & that.digits[i];
+ } else {
+ // resDigits[i] = -val.digits[i] & ~-that.digits[i];
+ resDigits[i] = -val.digits[i] & (that.digits[i] - 1);
+ }
+
+ limit = Math.min(val.numberLength, that.numberLength);
+ for (i++; i < limit; i++) {
+ // resDigits[i] = ~val.digits[i] & ~~that.digits[i];
+ resDigits[i] = ~val.digits[i] & that.digits[i];
+ }
+ for (; i < that.numberLength; i++) {
+ // resDigits[i] = -1 & ~~that.digits[i];
+ resDigits[i] = that.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = -1, magnitude = -(-negative.magnitude & ~positive.magnitude).
+ * @param negative
+ * @param positive
+ * @return
+ */
+ static BigInteger andNotNegativePositive(BigInteger negative,
+ BigInteger positive) {
+ // PRE: negative < 0 && positive > 0
+ int resLength;
+ int resDigits[];
+ int limit;
+ int digit;
+
+ int iNeg = negative.getFirstNonzeroDigit();
+ int iPos = positive.getFirstNonzeroDigit();
+
+ if (iNeg >= positive.numberLength) {
+ return negative;
+ }
+
+ resLength = Math.max(negative.numberLength, positive.numberLength);
+ int i = iNeg;
+ if (iPos > iNeg) {
+ resDigits = new int[resLength];
+ limit = Math.min(negative.numberLength, iPos);
+ for (; i < limit; i++) {
+ // 1st case: resDigits [i] = -(-negative.digits[i] & (~0))
+ // otherwise: resDigits[i] = ~(~negative.digits[i] & ~0) ;
+ resDigits[i] = negative.digits[i];
+ }
+ if (i == negative.numberLength) {
+ for (i = iPos; i < positive.numberLength; i++) {
+ // resDigits[i] = ~(~positive.digits[i] & -1);
+ resDigits[i] = positive.digits[i];
+ }
+ }
+ } else {
+ digit = -negative.digits[i] & ~positive.digits[i];
+ if (digit == 0) {
+ limit = Math.min(positive.numberLength, negative.numberLength);
+ for (i++; i < limit
+ && (digit = ~(negative.digits[i] | positive.digits[i])) == 0; i++) {
+ // digit
+ }
+ // = ~negative.digits[i] & ~positive.digits[i]
+ if (digit == 0) {
+ // the shorter has only the remaining virtual sign bits
+ for (; i < positive.numberLength
+ && (digit = ~positive.digits[i]) == 0; i++) {
+ // digit = -1 & ~positive.digits[i]
+ }
+ for (; i < negative.numberLength
+ && (digit = ~negative.digits[i]) == 0; i++) {
+ // empty
+ }
+ // digit = ~negative.digits[i] & ~0
+ if (digit == 0) {
+ resLength++;
+ resDigits = new int[resLength];
+ resDigits[resLength - 1] = 1;
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+ }
+ }
+ resDigits = new int[resLength];
+ resDigits[i] = -digit;
+ i++;
+ }
+
+ limit = Math.min(positive.numberLength, negative.numberLength);
+ for (; i < limit; i++) {
+ // resDigits[i] = ~(~negative.digits[i] & ~positive.digits[i]);
+ resDigits[i] = negative.digits[i] | positive.digits[i];
+ }
+ // Actually one of the next two cycles will be executed
+ for (; i < negative.numberLength; i++) {
+ resDigits[i] = negative.digits[i];
+ }
+ for (; i < positive.numberLength; i++) {
+ resDigits[i] = positive.digits[i];
+ }
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+
+ /**
+ * Return sign = 1, magnitude = val.magnitude & ~that.magnitude.
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger andNotPositive(BigInteger val, BigInteger that) {
+ // PRE: both arguments are positive
+ int resDigits[] = new int[val.numberLength];
+
+ int limit = Math.min(val.numberLength, that.numberLength);
+ int i;
+ for (i = val.getFirstNonzeroDigit(); i < limit; i++) {
+ resDigits[i] = val.digits[i] & ~that.digits[i];
+ }
+ for (; i < val.numberLength; i++) {
+ resDigits[i] = val.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, val.numberLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = 1, magnitude = positive.magnitude & ~(-negative.magnitude).
+ * @param positive
+ * @param negative
+ * @return
+ */
+ static BigInteger andNotPositiveNegative(BigInteger positive,
+ BigInteger negative) {
+ // PRE: positive > 0 && negative < 0
+ int iNeg = negative.getFirstNonzeroDigit();
+ int iPos = positive.getFirstNonzeroDigit();
+
+ if (iNeg >= positive.numberLength) {
+ return positive;
+ }
+
+ int resLength = Math.min(positive.numberLength, negative.numberLength);
+ int resDigits[] = new int[resLength];
+
+ // Always start from first non zero of positive
+ int i = iPos;
+ for (; i < iNeg; i++) {
+ // resDigits[i] = positive.digits[i] & -1 (~0)
+ resDigits[i] = positive.digits[i];
+ }
+ if (i == iNeg) {
+ resDigits[i] = positive.digits[i] & (negative.digits[i] - 1);
+ i++;
+ }
+ for (; i < resLength; i++) {
+ // resDigits[i] = positive.digits[i] & ~(~negative.digits[i]);
+ resDigits[i] = positive.digits[i] & negative.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = 1, magnitude = val.magnitude & that.magnitude.
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger andPositive(BigInteger val, BigInteger that) {
+ // PRE: both arguments are positive
+ int resLength = Math.min(val.numberLength, that.numberLength);
+ int i = Math.max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit());
+
+ if (i >= resLength) {
+ return BigInteger.ZERO;
+ }
+
+ int resDigits[] = new int[resLength];
+ for (; i < resLength; i++) {
+ resDigits[i] = val.digits[i] & that.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * @see BigInteger#not()
+ * @param val
+ * @return
+ */
+ static BigInteger not(BigInteger val) {
+ if (val.sign == 0) {
+ return BigInteger.MINUS_ONE;
+ }
+ if (val.equals(BigInteger.MINUS_ONE)) {
+ return BigInteger.ZERO;
+ }
+ int resDigits[] = new int[val.numberLength + 1];
+ int i;
+
+ if (val.sign > 0) {
+ // ~val = -val + 1
+ if (val.digits[val.numberLength - 1] != -1) {
+ for (i = 0; val.digits[i] == -1; i++) {
+ // empty
+ }
+ } else {
+ for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
+ // empty
+ }
+ if (i == val.numberLength) {
+ resDigits[i] = 1;
+ return new BigInteger(-val.sign, i + 1, resDigits);
+ }
+ }
+ // Here a carry 1 was generated
+ } else {
+ // (val.sign < 0)
+ // ~val = -val - 1
+ for (i = 0; val.digits[i] == 0; i++) {
+ resDigits[i] = -1;
+ }
+ // Here a borrow -1 was generated
+ }
+ // Now, the carry/borrow can be absorbed
+ resDigits[i] = val.digits[i] + val.sign;
+ // Copying the remaining unchanged digit
+ for (i++; i < val.numberLength; i++) {
+ resDigits[i] = val.digits[i];
+ }
+ return new BigInteger(-val.sign, i, resDigits);
+ }
+
+ /**
+ * @see BigInteger#or(BigInteger).
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger or(BigInteger val, BigInteger that) {
+ if (that.equals(BigInteger.MINUS_ONE) || val.equals(BigInteger.MINUS_ONE)) {
+ return BigInteger.MINUS_ONE;
+ }
+ if (that.sign == 0) {
+ return val;
+ }
+ if (val.sign == 0) {
+ return that;
+ }
+
+ if (val.sign > 0) {
+ if (that.sign > 0) {
+ if (val.numberLength > that.numberLength) {
+ return orPositive(val, that);
+ } else {
+ return orPositive(that, val);
+ }
+ } else {
+ return orDiffSigns(val, that);
+ }
+ } else {
+ if (that.sign > 0) {
+ return orDiffSigns(that, val);
+ } else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
+ return orNegative(that, val);
+ } else {
+ return orNegative(val, that);
+ }
+ }
+ }
+
+ /**
+ * Return sign = -1, magnitude = -(positive.magnitude | -negative.magnitude).
+ * @param positive
+ * @param negative
+ * @return
+ */
+ static BigInteger orDiffSigns(BigInteger positive, BigInteger negative) {
+ // Jumping over the least significant zero bits
+ int iNeg = negative.getFirstNonzeroDigit();
+ int iPos = positive.getFirstNonzeroDigit();
+ int i;
+ int limit;
+
+ // Look if the trailing zeros of the positive will "copy" all
+ // the negative digits
+ if (iPos >= negative.numberLength) {
+ return negative;
+ }
+ int resLength = negative.numberLength;
+ int resDigits[] = new int[resLength];
+
+ if (iNeg < iPos) {
+ // We know for sure that this will
+ // be the first non zero digit in the result
+ for (i = iNeg; i < iPos; i++) {
+ resDigits[i] = negative.digits[i];
+ }
+ } else if (iPos < iNeg) {
+ i = iPos;
+ resDigits[i] = -positive.digits[i];
+ limit = Math.min(positive.numberLength, iNeg);
+ for (i++; i < limit; i++) {
+ resDigits[i] = ~positive.digits[i];
+ }
+ if (i != positive.numberLength) {
+ resDigits[i] = ~(-negative.digits[i] | positive.digits[i]);
+ } else {
+ for (; i < iNeg; i++) {
+ resDigits[i] = -1;
+ }
+ // resDigits[i] = ~(-negative.digits[i] | 0);
+ resDigits[i] = negative.digits[i] - 1;
+ }
+ i++;
+ } else {
+ // iNeg == iPos
+ // Applying two complement to negative and to result
+ i = iPos;
+ resDigits[i] = -(-negative.digits[i] | positive.digits[i]);
+ i++;
+ }
+ limit = Math.min(negative.numberLength, positive.numberLength);
+ for (; i < limit; i++) {
+ // Applying two complement to negative and to result
+ // resDigits[i] = ~(~negative.digits[i] | positive.digits[i] );
+ resDigits[i] = negative.digits[i] & ~positive.digits[i];
+ }
+ for (; i < negative.numberLength; i++) {
+ resDigits[i] = negative.digits[i];
+ }
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = -1, magnitude = -(-val.magnitude | -that.magnitude).
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger orNegative(BigInteger val, BigInteger that) {
+ // PRE: val and that are negative;
+ // PRE: val has at least as many trailing zeros digits as that
+ int iThat = that.getFirstNonzeroDigit();
+ int iVal = val.getFirstNonzeroDigit();
+ int i;
+
+ if (iVal >= that.numberLength) {
+ return that;
+ } else if (iThat >= val.numberLength) {
+ return val;
+ }
+
+ int resLength = Math.min(val.numberLength, that.numberLength);
+ int resDigits[] = new int[resLength];
+
+ // Looking for the first non-zero digit of the result
+ if (iThat == iVal) {
+ resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]);
+ i = iVal;
+ } else {
+ for (i = iThat; i < iVal; i++) {
+ resDigits[i] = that.digits[i];
+ }
+ resDigits[i] = that.digits[i] & (val.digits[i] - 1);
+ }
+
+ for (i++; i < resLength; i++) {
+ resDigits[i] = val.digits[i] & that.digits[i];
+ }
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = 1, magnitude = longer.magnitude | shorter.magnitude.
+ * @param longer
+ * @param shorter
+ * @return
+ */
+ static BigInteger orPositive(BigInteger longer, BigInteger shorter) {
+ // PRE: longer and shorter are positive;
+ // PRE: longer has at least as many digits as shorter
+ int resLength = longer.numberLength;
+ int resDigits[] = new int[resLength];
+
+ int i = Math.min(longer.getFirstNonzeroDigit(),
+ shorter.getFirstNonzeroDigit());
+ for (i = 0; i < shorter.numberLength; i++) {
+ resDigits[i] = longer.digits[i] | shorter.digits[i];
+ }
+ for (; i < resLength; i++) {
+ resDigits[i] = longer.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ return result;
+ }
+
+ /**
+ * @see BigInteger#xor(BigInteger)
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger xor(BigInteger val, BigInteger that) {
+ if (that.sign == 0) {
+ return val;
+ }
+ if (val.sign == 0) {
+ return that;
+ }
+ if (that.equals(BigInteger.MINUS_ONE)) {
+ return val.not();
+ }
+ if (val.equals(BigInteger.MINUS_ONE)) {
+ return that.not();
+ }
+
+ if (val.sign > 0) {
+ if (that.sign > 0) {
+ if (val.numberLength > that.numberLength) {
+ return xorPositive(val, that);
+ } else {
+ return xorPositive(that, val);
+ }
+ } else {
+ return xorDiffSigns(val, that);
+ }
+ } else {
+ if (that.sign > 0) {
+ return xorDiffSigns(that, val);
+ } else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
+ return xorNegative(that, val);
+ } else {
+ return xorNegative(val, that);
+ }
+ }
+ }
+
+ /**
+ * Return sign = 1, magnitude = -(positive.magnitude ^ -negative.magnitude).
+ * @param positive
+ * @param negative
+ * @return
+ */
+ static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative) {
+ int resLength = Math.max(negative.numberLength, positive.numberLength);
+ int resDigits[];
+ int iNeg = negative.getFirstNonzeroDigit();
+ int iPos = positive.getFirstNonzeroDigit();
+ int i;
+ int limit;
+
+ // The first
+ if (iNeg < iPos) {
+ resDigits = new int[resLength];
+ i = iNeg;
+ // resDigits[i] = -(-negative.digits[i]);
+ resDigits[i] = negative.digits[i];
+ limit = Math.min(negative.numberLength, iPos);
+ // Skip the positive digits while they are zeros
+ for (i++; i < limit; i++) {
+ // resDigits[i] = ~(~negative.digits[i]);
+ resDigits[i] = negative.digits[i];
+ }
+ // if the negative has no more elements, must fill the
+ // result with the remaining digits of the positive
+ if (i == negative.numberLength) {
+ for (; i < positive.numberLength; i++) {
+ // resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i])
+ resDigits[i] = positive.digits[i];
+ }
+ }
+ } else if (iPos < iNeg) {
+ resDigits = new int[resLength];
+ i = iPos;
+ // Applying two complement to the first non-zero digit of the result
+ resDigits[i] = -positive.digits[i];
+ limit = Math.min(positive.numberLength, iNeg);
+ for (i++; i < limit; i++) {
+ // Continue applying two complement the result
+ resDigits[i] = ~positive.digits[i];
+ }
+ // When the first non-zero digit of the negative is reached, must apply
+ // two complement (arithmetic negation) to it, and then operate
+ if (i == iNeg) {
+ resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]);
+ i++;
+ } else {
+ // if the positive has no more elements must fill the remaining digits
+ // with
+ // the negative ones
+ for (; i < iNeg; i++) {
+ // resDigits[i] = ~(0 ^ 0)
+ resDigits[i] = -1;
+ }
+ for (; i < negative.numberLength; i++) {
+ // resDigits[i] = ~(~negative.digits[i] ^ 0)
+ resDigits[i] = negative.digits[i];
+ }
+ }
+ } else {
+ int digit;
+ // The first non-zero digit of the positive and negative are the same
+ i = iNeg;
+ digit = positive.digits[i] ^ -negative.digits[i];
+ if (digit == 0) {
+ limit = Math.min(positive.numberLength, negative.numberLength);
+ for (i++; i < limit
+ && (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++) {
+ // empty
+ }
+ if (digit == 0) {
+ // shorter has only the remaining virtual sign bits
+ for (; i < positive.numberLength
+ && (digit = ~positive.digits[i]) == 0; i++) {
+ // empty
+ }
+ for (; i < negative.numberLength
+ && (digit = ~negative.digits[i]) == 0; i++) {
+ // empty
+ }
+ if (digit == 0) {
+ resLength = resLength + 1;
+ resDigits = new int[resLength];
+ resDigits[resLength - 1] = 1;
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+ }
+ }
+ resDigits = new int[resLength];
+ resDigits[i] = -digit;
+ i++;
+ }
+
+ limit = Math.min(negative.numberLength, positive.numberLength);
+ for (; i < limit; i++) {
+ resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]);
+ }
+ for (; i < positive.numberLength; i++) {
+ // resDigits[i] = ~(positive.digits[i] ^ -1)
+ resDigits[i] = positive.digits[i];
+ }
+ for (; i < negative.numberLength; i++) {
+ // resDigits[i] = ~(0 ^ ~negative.digits[i])
+ resDigits[i] = negative.digits[i];
+ }
+
+ BigInteger result = new BigInteger(-1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = 0, magnitude = -val.magnitude ^ -that.magnitude.
+ * @param val
+ * @param that
+ * @return
+ */
+ static BigInteger xorNegative(BigInteger val, BigInteger that) {
+ // PRE: val and that are negative
+ // PRE: val has at least as many trailing zero digits as that
+ int resLength = Math.max(val.numberLength, that.numberLength);
+ int resDigits[] = new int[resLength];
+ int iVal = val.getFirstNonzeroDigit();
+ int iThat = that.getFirstNonzeroDigit();
+ int i = iThat;
+ int limit;
+
+ if (iVal == iThat) {
+ resDigits[i] = -val.digits[i] ^ -that.digits[i];
+ } else {
+ resDigits[i] = -that.digits[i];
+ limit = Math.min(that.numberLength, iVal);
+ for (i++; i < limit; i++) {
+ resDigits[i] = ~that.digits[i];
+ }
+ // Remains digits in that?
+ if (i == that.numberLength) {
+ // Jumping over the remaining zero to the first non one
+ for (; i < iVal; i++) {
+ // resDigits[i] = 0 ^ -1;
+ resDigits[i] = -1;
+ }
+ // resDigits[i] = -val.digits[i] ^ -1;
+ resDigits[i] = val.digits[i] - 1;
+ } else {
+ resDigits[i] = -val.digits[i] ^ ~that.digits[i];
+ }
+ }
+
+ limit = Math.min(val.numberLength, that.numberLength);
+ // Perform ^ between that al val until that ends
+ for (i++; i < limit; i++) {
+ // resDigits[i] = ~val.digits[i] ^ ~that.digits[i];
+ resDigits[i] = val.digits[i] ^ that.digits[i];
+ }
+ // Perform ^ between val digits and -1 until val ends
+ for (; i < val.numberLength; i++) {
+ // resDigits[i] = ~val.digits[i] ^ -1 ;
+ resDigits[i] = val.digits[i];
+ }
+ for (; i < that.numberLength; i++) {
+ // resDigits[i] = -1 ^ ~that.digits[i] ;
+ resDigits[i] = that.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Return sign = 0, magnitude = longer.magnitude | shorter.magnitude.
+ *
+ * @param longer
+ * @param shorter
+ * @return
+ */
+ static BigInteger xorPositive(BigInteger longer, BigInteger shorter) {
+ // PRE: longer and shorter are positive;
+ // PRE: longer has at least as many digits as shorter
+ int resLength = longer.numberLength;
+ int resDigits[] = new int[resLength];
+ int i = Math.min(longer.getFirstNonzeroDigit(),
+ shorter.getFirstNonzeroDigit());
+ for (; i < shorter.numberLength; i++) {
+ resDigits[i] = longer.digits[i] ^ shorter.digits[i];
+ }
+ for (; i < longer.numberLength; i++) {
+ resDigits[i] = longer.digits[i];
+ }
+
+ BigInteger result = new BigInteger(1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Just to denote that this class can't be instantiated.
+ */
+ private Logical() {
+ }
+}
diff --git a/gwt/jre/java/math/MathContext.java b/gwt/jre/java/math/MathContext.java
new file mode 100644
index 0000000..c1cbf8c
--- /dev/null
+++ b/gwt/jre/java/math/MathContext.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+import java.io.Serializable;
+
+/**
+ * Immutable objects describing settings such as rounding mode and digit
+ * precision for the numerical operations provided by class {@link BigDecimal}.
+ */
+public final class MathContext implements Serializable {
+
+ /**
+ * A {@code MathContext} which corresponds to the IEEE 754r quadruple decimal
+ * precision format: 34 digit precision and {@link RoundingMode#HALF_EVEN}
+ * rounding.
+ */
+ public static final MathContext DECIMAL128 = new MathContext(34,
+ RoundingMode.HALF_EVEN);
+
+ /**
+ * A {@code MathContext} which corresponds to the IEEE 754r single decimal
+ * precision format: 7 digit precision and {@link RoundingMode#HALF_EVEN}
+ * rounding.
+ */
+ public static final MathContext DECIMAL32 = new MathContext(7,
+ RoundingMode.HALF_EVEN);
+
+ /**
+ * A {@code MathContext} which corresponds to the IEEE 754r double decimal
+ * precision format: 16 digit precision and {@link RoundingMode#HALF_EVEN}
+ * rounding.
+ */
+ public static final MathContext DECIMAL64 = new MathContext(16,
+ RoundingMode.HALF_EVEN);
+
+ /**
+ * A {@code MathContext} for unlimited precision with
+ * {@link RoundingMode#HALF_UP} rounding.
+ */
+ public static final MathContext UNLIMITED = new MathContext(0,
+ RoundingMode.HALF_UP);
+
+ /**
+ * An array of {@code char} containing: {@code
+ * 'p','r','e','c','i','s','i','o','n','='}. It's used to improve the methods
+ * related to {@code String} conversion.
+ *
+ * @see #MathContext(String)
+ * @see #toString()
+ */
+ private static final char[] chPrecision = {
+ 'p', 'r', 'e', 'c', 'i', 's', 'i', 'o', 'n', '='};
+
+ /**
+ * An array of {@code char} containing: {@code
+ * 'r','o','u','n','d','i','n','g','M','o','d','e','='}. It's used to improve
+ * the methods related to {@code String} conversion.
+ *
+ * @see #MathContext(String)
+ * @see #toString()
+ */
+ private static final char[] chRoundingMode = {
+ 'r', 'o', 'u', 'n', 'd', 'i', 'n', 'g', 'M', 'o', 'd', 'e', '='};
+
+ /**
+ * This is the serialVersionUID used by the sun implementation.
+ */
+ private static final long serialVersionUID = 5579720004786848255L;
+
+ /**
+ * The number of digits to be used for an operation; results are rounded to
+ * this precision.
+ */
+ private int precision;
+
+ /**
+ * A {@code RoundingMode} object which specifies the algorithm to be used for
+ * rounding.
+ */
+ private RoundingMode roundingMode;
+
+ /**
+ * Constructs a new {@code MathContext} with the specified precision and with
+ * the rounding mode {@link RoundingMode#HALF_UP HALF_UP}. If the precision
+ * passed is zero, then this implies that the computations have to be
+ * performed exact, the rounding mode in this case is irrelevant.
+ *
+ * @param precision the precision for the new {@code MathContext}.
+ * @throws IllegalArgumentException if {@code precision < 0}.
+ */
+ public MathContext(int precision) {
+ this(precision, RoundingMode.HALF_UP);
+ }
+
+ /**
+ * Constructs a new {@code MathContext} with the specified precision and with
+ * the specified rounding mode. If the precision passed is zero, then this
+ * implies that the computations have to be performed exact, the rounding mode
+ * in this case is irrelevant.
+ *
+ * @param precision the precision for the new {@code MathContext}.
+ * @param roundingMode the rounding mode for the new {@code MathContext}.
+ * @throws IllegalArgumentException if {@code precision < 0}.
+ * @throws NullPointerException if {@code roundingMode} is {@code null}.
+ */
+ public MathContext(int precision, RoundingMode roundingMode) {
+ if (precision < 0) {
+ // math.0C=Digits < 0
+ throw new IllegalArgumentException("Digits < 0"); //$NON-NLS-1$
+ }
+ if (roundingMode == null) {
+ // math.0D=null RoundingMode
+ throw new NullPointerException("null RoundingMode"); //$NON-NLS-1$
+ }
+ this.precision = precision;
+ this.roundingMode = roundingMode;
+ }
+
+ /**
+ * Constructs a new {@code MathContext} from a string. The string has to
+ * specify the precision and the rounding mode to be used and has to follow
+ * the following syntax:
+ * "precision=<precision> roundingMode=<roundingMode>" This is the
+ * same form as the one returned by the {@link #toString} method.
+ *
+ * @param val a string describing the precision and rounding mode for the new
+ * {@code MathContext}.
+ * @throws IllegalArgumentException if the string is not in the correct format
+ * or if the precision specified is < 0.
+ */
+ public MathContext(String val) {
+ if (val == null) {
+ throw new NullPointerException("null string");
+ }
+ char[] charVal = val.toCharArray();
+ int i; // Index of charVal
+ int j; // Index of chRoundingMode
+ int digit; // It will contain the digit parsed
+
+ if ((charVal.length < 27) || (charVal.length > 45)) {
+ // math.0E=bad string format
+ throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
+ }
+ // Parsing "precision=" String
+ for (i = 0; (i < chPrecision.length) && (charVal[i] == chPrecision[i]); i++) {
+ // empty
+ }
+
+ if (i < chPrecision.length) {
+ // math.0E=bad string format
+ throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
+ }
+ // Parsing the value for "precision="...
+ digit = Character.digit(charVal[i], 10);
+ if (digit == -1) {
+ // math.0E=bad string format
+ throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
+ }
+ this.precision = this.precision * 10 + digit;
+ i++;
+
+ do {
+ digit = Character.digit(charVal[i], 10);
+ if (digit == -1) {
+ if (charVal[i] == ' ') {
+ // It parsed all the digits
+ i++;
+ break;
+ }
+ // It isn't a valid digit, and isn't a white space
+ // math.0E=bad string format
+ throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
+ }
+ // Accumulating the value parsed
+ this.precision = this.precision * 10 + digit;
+ if (this.precision < 0) {
+ // math.0E=bad string format
+ throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
+ }
+ i++;
+ } while (true);
+ // Parsing "roundingMode="
+ for (j = 0; (j < chRoundingMode.length)
+ && (charVal[i] == chRoundingMode[j]); i++, j++) {
+ // empty
+ }
+
+ if (j < chRoundingMode.length) {
+ // math.0E=bad string format
+ throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
+ }
+
+ // Parsing the value for "roundingMode"...
+ /*
+ * don't use implicit calls to RoundingMode.valueOf here, since it will break
+ * if enum name obfuscation is enabled.
+ */
+ this.roundingMode = RoundingMode.valueOfExplicit(String.valueOf(charVal, i,
+ charVal.length - i));
+ }
+
+ /* Public Methods */
+
+ /**
+ * Returns true if x is a {@code MathContext} with the same precision setting
+ * and the same rounding mode as this {@code MathContext} instance.
+ *
+ * @param x object to be compared.
+ * @return {@code true} if this {@code MathContext} instance is equal to the
+ * {@code x} argument; {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object x) {
+ return ((x instanceof MathContext)
+ && (((MathContext) x).getPrecision() == precision)
+ && (((MathContext) x).getRoundingMode() == roundingMode));
+ }
+
+ /**
+ * Returns the precision. The precision is the number of digits used for an
+ * operation. Results are rounded to this precision. The precision is
+ * guaranteed to be non negative. If the precision is zero, then the
+ * computations have to be performed exact, results are not rounded in this
+ * case.
+ *
+ * @return the precision.
+ */
+ public int getPrecision() {
+ return precision;
+ }
+
+ /**
+ * Returns the rounding mode. The rounding mode is the strategy to be used to
+ * round results.
+ *
+ * v = v1 * B + v0
+ *
+ *
+ * u*v = (u1 * v1) * B2 + ((u1 - u0) * (v0 - v1) + u1 * v1 +
+ * u0 * v0 ) * B + u0 * v0
+ *
+ *
+ * @param op1 first factor of the product
+ * @param op2 second factor of the product
+ * @return {@code op1 * op2}
+ * @see #multiply(BigInteger, BigInteger)
+ */
+ static BigInteger karatsuba(BigInteger op1, BigInteger op2) {
+ BigInteger temp;
+ if (op2.numberLength > op1.numberLength) {
+ temp = op1;
+ op1 = op2;
+ op2 = temp;
+ }
+ if (op2.numberLength < whenUseKaratsuba) {
+ return multiplyPAP(op1, op2);
+ }
+ /*
+ * Karatsuba: u = u1*B + u0 v = v1*B + v0 u*v = (u1*v1)*B^2 +
+ * ((u1-u0)*(v0-v1) + u1*v1 + u0*v0)*B + u0*v0
+ */
+ // ndiv2 = (op1.numberLength / 2) * 32
+ int ndiv2 = (op1.numberLength & 0xFFFFFFFE) << 4;
+ BigInteger upperOp1 = op1.shiftRight(ndiv2);
+ BigInteger upperOp2 = op2.shiftRight(ndiv2);
+ BigInteger lowerOp1 = op1.subtract(upperOp1.shiftLeft(ndiv2));
+ BigInteger lowerOp2 = op2.subtract(upperOp2.shiftLeft(ndiv2));
+
+ BigInteger upper = karatsuba(upperOp1, upperOp2);
+ BigInteger lower = karatsuba(lowerOp1, lowerOp2);
+ BigInteger middle = karatsuba(upperOp1.subtract(lowerOp1),
+ lowerOp2.subtract(upperOp2));
+ middle = middle.add(upper).add(lower);
+ middle = middle.shiftLeft(ndiv2);
+ upper = upper.shiftLeft(ndiv2 << 1);
+
+ return upper.add(middle).add(lower);
+ }
+
+ static void multArraysPAP(int[] aDigits, int aLen, int[] bDigits, int bLen,
+ int[] resDigits) {
+ if (aLen == 0 || bLen == 0) {
+ return;
+ }
+
+ if (aLen == 1) {
+ resDigits[bLen] = multiplyByInt(resDigits, bDigits, bLen, aDigits[0]);
+ } else if (bLen == 1) {
+ resDigits[aLen] = multiplyByInt(resDigits, aDigits, aLen, bDigits[0]);
+ } else {
+ multPAP(aDigits, bDigits, resDigits, aLen, bLen);
+ }
+ }
+
+ /**
+ * Performs a multiplication of two BigInteger and hides the algorithm used.
+ *
+ * @see BigInteger#multiply(BigInteger)
+ */
+ static BigInteger multiply(BigInteger x, BigInteger y) {
+ return karatsuba(x, y);
+ }
+
+ /**
+ * Multiplies a number by a power of five. This method is used in {@code
+ * BigDecimal} class.
+ *
+ * @param val the number to be multiplied
+ * @param exp a positive {@code int} exponent
+ * @return {@code val * 5exp}
+ */
+ static BigInteger multiplyByFivePow(BigInteger val, int exp) {
+ // PRE: exp >= 0
+ if (exp < fivePows.length) {
+ return multiplyByPositiveInt(val, fivePows[exp]);
+ } else if (exp < bigFivePows.length) {
+ return val.multiply(bigFivePows[exp]);
+ } else {
+ // Large powers of five
+ return val.multiply(bigFivePows[1].pow(exp));
+ }
+ }
+
+ /**
+ * Multiplies an array of integers by an integer value.
+ *
+ * @param a the array of integers
+ * @param aSize the number of elements of intArray to be multiplied
+ * @param factor the multiplier
+ * @return the top digit of production
+ */
+ static int multiplyByInt(int a[], final int aSize, final int factor) {
+ return multiplyByInt(a, a, aSize, factor);
+ }
+
+ /**
+ * Multiplies a number by a positive integer.
+ *
+ * @param val an arbitrary {@code BigInteger}
+ * @param factor a positive {@code int} number
+ * @return {@code val * factor}
+ */
+ static BigInteger multiplyByPositiveInt(BigInteger val, int factor) {
+ int resSign = val.sign;
+ if (resSign == 0) {
+ return BigInteger.ZERO;
+ }
+ int aNumberLength = val.numberLength;
+ int[] aDigits = val.digits;
+
+ if (aNumberLength == 1) {
+ long res = unsignedMultAddAdd(aDigits[0], factor, 0, 0);
+ int resLo = (int) res;
+ int resHi = (int) (res >>> 32);
+ return ((resHi == 0) ? new BigInteger(resSign, resLo) : new BigInteger(
+ resSign, 2, new int[] {resLo, resHi}));
+ }
+ // Common case
+ int resLength = aNumberLength + 1;
+ int resDigits[] = new int[resLength];
+
+ resDigits[aNumberLength] = multiplyByInt(resDigits, aDigits, aNumberLength,
+ factor);
+ BigInteger result = new BigInteger(resSign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ /**
+ * Multiplies a number by a power of ten. This method is used in {@code
+ * BigDecimal} class.
+ *
+ * @param val the number to be multiplied
+ * @param exp a positive {@code long} exponent
+ * @return {@code val * 10exp}
+ */
+ static BigInteger multiplyByTenPow(BigInteger val, int exp) {
+ // PRE: exp >= 0
+ return ((exp < tenPows.length) ? multiplyByPositiveInt(val,
+ tenPows[(int) exp]) : val.multiply(powerOf10(exp)));
+ }
+
+ /**
+ * Multiplies two BigIntegers. Implements traditional scholar algorithm
+ * described by Knuth.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @param op1 first factor of the multiplication {@code op1 >= 0}
+ * @param op2 second factor of the multiplication {@code op2 >= 0}
+ * @return a {@code BigInteger} of value {@code op1 * op2}
+ */
+ static BigInteger multiplyPAP(BigInteger a, BigInteger b) {
+ // PRE: a >= b
+ int aLen = a.numberLength;
+ int bLen = b.numberLength;
+ int resLength = aLen + bLen;
+ int resSign = (a.sign != b.sign) ? -1 : 1;
+ // A special case when both numbers don't exceed int
+ if (resLength == 2) {
+ long val = unsignedMultAddAdd(a.digits[0], b.digits[0], 0, 0);
+ int valueLo = (int) val;
+ int valueHi = (int) (val >>> 32);
+ return ((valueHi == 0) ? new BigInteger(resSign, valueLo)
+ : new BigInteger(resSign, 2, new int[] {valueLo, valueHi}));
+ }
+ int[] aDigits = a.digits;
+ int[] bDigits = b.digits;
+ int resDigits[] = new int[resLength];
+ // Common case
+ multArraysPAP(aDigits, aLen, bDigits, bLen, resDigits);
+ BigInteger result = new BigInteger(resSign, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+
+ static void multPAP(int a[], int b[], int t[], int aLen, int bLen) {
+ if (a == b && aLen == bLen) {
+ square(a, aLen, t);
+ return;
+ }
+
+ for (int i = 0; i < aLen; i++) {
+ long carry = 0;
+ int aI = a[i];
+ for (int j = 0; j < bLen; j++) {
+ carry = unsignedMultAddAdd(aI, b[j], t[i + j], (int) carry);
+ t[i + j] = (int) carry;
+ carry >>>= 32;
+ }
+ t[i + bLen] = (int) carry;
+ }
+ }
+
+ static BigInteger pow(BigInteger base, int exponent) {
+ // PRE: exp > 0
+ BigInteger res = BigInteger.ONE;
+ BigInteger acc = base;
+
+ for (; exponent > 1; exponent >>= 1) {
+ if ((exponent & 1) != 0) {
+ // if odd, multiply one more time by acc
+ res = res.multiply(acc);
+ }
+ // acc = base^(2^i)
+ // a limit where karatsuba performs a faster square than the square
+ // algorithm
+ if (acc.numberLength == 1) {
+ acc = acc.multiply(acc); // square
+ } else {
+ acc = new BigInteger(1, square(acc.digits, acc.numberLength,
+ new int[acc.numberLength << 1]));
+ }
+ }
+ // exponent == 1, multiply one more time
+ res = res.multiply(acc);
+ return res;
+ }
+
+ /**
+ * It calculates a power of ten, which exponent could be out of 32-bit range.
+ * Note that internally this method will be used in the worst case with an
+ * exponent equals to: {@code Integer.MAX_VALUE - Integer.MIN_VALUE}.
+ *
+ * @param exp the exponent of power of ten, it must be positive.
+ * @return a {@code BigInteger} with value {@code 10exp}.
+ */
+ static BigInteger powerOf10(double exp) {
+ // PRE: exp >= 0
+ int intExp = (int) exp;
+ // "SMALL POWERS"
+ if (exp < bigTenPows.length) {
+ // The largest power that fit in 'long' type
+ return bigTenPows[intExp];
+ } else if (exp <= 50) {
+ // To calculate: 10^exp
+ return BigInteger.TEN.pow(intExp);
+ } else if (exp <= 1000) {
+ // To calculate: 5^exp * 2^exp
+ return bigFivePows[1].pow(intExp).shiftLeft(intExp);
+ }
+ // "LARGE POWERS"
+ /*
+ * To check if there is free memory to allocate a BigInteger of the
+ * estimated size, measured in bytes: 1 + [exp / log10(2)]
+ */
+ if (exp > 1000000) {
+ throw new ArithmeticException("power of ten too big"); //$NON-NLS-1$
+ }
+
+ if (exp <= Integer.MAX_VALUE) {
+ // To calculate: 5^exp * 2^exp
+ return bigFivePows[1].pow(intExp).shiftLeft(intExp);
+ }
+ /*
+ * "HUGE POWERS"
+ *
+ * This branch probably won't be executed since the power of ten is too big.
+ */
+ // To calculate: 5^exp
+ BigInteger powerOfFive = bigFivePows[1].pow(Integer.MAX_VALUE);
+ BigInteger res = powerOfFive;
+ long longExp = (long) (exp - Integer.MAX_VALUE);
+
+ intExp = (int) (exp % Integer.MAX_VALUE);
+ while (longExp > Integer.MAX_VALUE) {
+ res = res.multiply(powerOfFive);
+ longExp -= Integer.MAX_VALUE;
+ }
+ res = res.multiply(bigFivePows[1].pow(intExp));
+ // To calculate: 5^exp << exp
+ res = res.shiftLeft(Integer.MAX_VALUE);
+ longExp = (long) (exp - Integer.MAX_VALUE);
+ while (longExp > Integer.MAX_VALUE) {
+ res = res.shiftLeft(Integer.MAX_VALUE);
+ longExp -= Integer.MAX_VALUE;
+ }
+ res = res.shiftLeft(intExp);
+ return res;
+ }
+
+ /**
+ * Performs a2.
+ *
+ * @param a The number to square.
+ * @param aLen The length of the number to square.
+ */
+ static int[] square(int[] a, int aLen, int[] res) {
+ long carry;
+
+ for (int i = 0; i < aLen; i++) {
+ carry = 0;
+ for (int j = i + 1; j < aLen; j++) {
+ carry = unsignedMultAddAdd(a[i], a[j], res[i + j], (int) carry);
+ res[i + j] = (int) carry;
+ carry >>>= 32;
+ }
+ res[i + aLen] = (int) carry;
+ }
+
+ BitLevel.shiftLeftOneBit(res, res, aLen << 1);
+
+ carry = 0;
+ for (int i = 0, index = 0; i < aLen; i++, index++) {
+ carry = unsignedMultAddAdd(a[i], a[i], res[index], (int) carry);
+ res[index] = (int) carry;
+ carry >>>= 32;
+ index++;
+ carry += res[index] & 0xFFFFFFFFL;
+ res[index] = (int) carry;
+ carry >>>= 32;
+ }
+ return res;
+ }
+
+ /**
+ * Computes the value unsigned ((uint)a*(uint)b + (uint)c + (uint)d). This
+ * method could improve the readability and performance of the code.
+ *
+ * @param a parameter 1
+ * @param b parameter 2
+ * @param c parameter 3
+ * @param d parameter 4
+ * @return value of expression
+ */
+ static long unsignedMultAddAdd(int a, int b, int c, int d) {
+ return (a & 0xFFFFFFFFL) * (b & 0xFFFFFFFFL) + (c & 0xFFFFFFFFL)
+ + (d & 0xFFFFFFFFL);
+ }
+
+ /**
+ * Multiplies an array of integers by an integer value and saves the result in
+ * {@code res}.
+ *
+ * @param a the array of integers
+ * @param aSize the number of elements of intArray to be multiplied
+ * @param factor the multiplier
+ * @return the top digit of production
+ */
+ private static int multiplyByInt(int res[], int a[], final int aSize,
+ final int factor) {
+ long carry = 0;
+ for (int i = 0; i < aSize; i++) {
+ carry = unsignedMultAddAdd(a[i], factor, (int) carry, 0);
+ res[i] = (int) carry;
+ carry >>>= 32;
+ }
+ return (int) carry;
+ }
+
+ /**
+ * Just to denote that this class can't be instantiated.
+ */
+ private Multiplication() {
+ }
+
+}
diff --git a/gwt/jre/java/math/Primality.java b/gwt/jre/java/math/Primality.java
new file mode 100644
index 0000000..016d99c
--- /dev/null
+++ b/gwt/jre/java/math/Primality.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Provides primality probabilistic methods.
+ */
+class Primality {
+
+ /**
+ * It encodes how many iterations of Miller-Rabin test are need to get an
+ * error bound not greater than {@code 2(-100)}. For example: for a
+ * {@code 1000}-bit number we need {@code 4} iterations, since {@code BITS[3]
+ * < 1000 <= BITS[4]}.
+ */
+ private static final int[] BITS = {
+ 0, 0, 1854, 1233, 927, 747, 627, 543, 480, 431, 393, 361, 335, 314, 295,
+ 279, 265, 253, 242, 232, 223, 216, 181, 169, 158, 150, 145, 140, 136,
+ 132, 127, 123, 119, 114, 110, 105, 101, 96, 92, 87, 83, 78, 73, 69, 64,
+ 59, 54, 49, 44, 38, 32, 26, 1};
+
+ /**
+ * It encodes how many i-bit primes there are in the table for {@code
+ * i=2,...,10}. For example {@code offsetPrimes[6]} says that from index
+ * {@code 11} exists {@code 7} consecutive {@code 6}-bit prime numbers in the
+ * array.
+ */
+ private static final int[][] offsetPrimes = {
+ null, null, {0, 2}, {2, 2}, {4, 2}, {6, 5}, {11, 7}, {18, 13}, {31, 23},
+ {54, 43}, {97, 75}};
+
+ /**
+ * All prime numbers with bit length lesser than 10 bits.
+ */
+ private static final int primes[] = {
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
+ 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
+ 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
+ 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
+ 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467,
+ 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571,
+ 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653,
+ 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
+ 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
+ 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021};
+
+ /**
+ * All {@code BigInteger} prime numbers with bit length lesser than 8 bits.
+ */
+ private static final BigInteger BIprimes[] = new BigInteger[primes.length];
+
+ static {
+ // To initialize the dual table of BigInteger primes
+ for (int i = 0; i < primes.length; i++) {
+ BIprimes[i] = BigInteger.valueOf(primes[i]);
+ }
+ }
+
+ /**
+ * A random number is generated until a probable prime number is found.
+ *
+ * @see BigInteger#BigInteger(int,int,Random)
+ * @see BigInteger#probablePrime(int,Random)
+ * @see #isProbablePrime(BigInteger, int)
+ */
+ static BigInteger consBigInteger(int bitLength, int certainty, Random rnd) {
+ // PRE: bitLength >= 2;
+ // For small numbers get a random prime from the prime table
+ if (bitLength <= 10) {
+ int rp[] = offsetPrimes[bitLength];
+ return BIprimes[rp[0] + rnd.nextInt(rp[1])];
+ }
+ int shiftCount = (-bitLength) & 31;
+ int last = (bitLength + 31) >> 5;
+ BigInteger n = new BigInteger(1, last, new int[last]);
+
+ last--;
+ do {
+ // To fill the array with random integers
+ for (int i = 0; i < n.numberLength; i++) {
+ n.digits[i] = rnd.nextInt();
+ }
+ // To fix to the correct bitLength
+ n.digits[last] |= 0x80000000;
+ n.digits[last] >>>= shiftCount;
+ // To create an odd number
+ n.digits[0] |= 1;
+ } while (!isProbablePrime(n, certainty));
+ return n;
+ }
+
+ /**
+ * @see BigInteger#isProbablePrime(int)
+ * @see #millerRabin(BigInteger, int)
+ * @ar.org.fitc.ref Optimizations: "A. Menezes - Handbook of applied
+ * Cryptography, Chapter 4".
+ */
+ static boolean isProbablePrime(BigInteger n, int certainty) {
+ // PRE: n >= 0;
+ if ((certainty <= 0) || ((n.numberLength == 1) && (n.digits[0] == 2))) {
+ return true;
+ }
+ // To discard all even numbers
+ if (!n.testBit(0)) {
+ return false;
+ }
+ // To check if 'n' exists in the table (it fit in 10 bits)
+ if ((n.numberLength == 1) && ((n.digits[0] & 0XFFFFFC00) == 0)) {
+ return (Arrays.binarySearch(primes, n.digits[0]) >= 0);
+ }
+ // To check if 'n' is divisible by some prime of the table
+ for (int i = 1; i < primes.length; i++) {
+ if (Division.remainderArrayByInt(n.digits, n.numberLength, primes[i]) == 0) {
+ return false;
+ }
+ }
+ // To set the number of iterations necessary for Miller-Rabin test
+ int i;
+ int bitLength = n.bitLength();
+
+ for (i = 2; bitLength < BITS[i]; i++) {
+ // empty
+ }
+ certainty = Math.min(i, 1 + ((certainty - 1) >> 1));
+
+ return millerRabin(n, certainty);
+ }
+
+ /**
+ * It uses the sieve of Eratosthenes to discard several composite numbers in
+ * some appropriate range (at the moment {@code [this, this + 1024]}). After
+ * this process it applies the Miller-Rabin test to the numbers that were not
+ * discarded in the sieve.
+ *
+ * @see BigInteger#nextProbablePrime()
+ * @see #millerRabin(BigInteger, int)
+ */
+ static BigInteger nextProbablePrime(BigInteger n) {
+ // PRE: n >= 0
+ int i, j;
+ int certainty;
+ int gapSize = 1024; // for searching of the next probable prime number
+ int modules[] = new int[primes.length];
+ boolean isDivisible[] = new boolean[gapSize];
+ BigInteger startPoint;
+ BigInteger probPrime;
+ // If n < "last prime of table" searches next prime in the table
+ if ((n.numberLength == 1) && (n.digits[0] >= 0)
+ && (n.digits[0] < primes[primes.length - 1])) {
+ for (i = 0; n.digits[0] >= primes[i]; i++) {
+ // empty
+ }
+ return BIprimes[i];
+ }
+ /*
+ * Creates a "N" enough big to hold the next probable prime Note that: N <
+ * "next prime" < 2*N
+ */
+ startPoint = new BigInteger(1, n.numberLength, new int[n.numberLength + 1]);
+ System.arraycopy(n.digits, 0, startPoint.digits, 0, n.numberLength);
+ // To fix N to the "next odd number"
+ if (n.testBit(0)) {
+ Elementary.inplaceAdd(startPoint, 2);
+ } else {
+ startPoint.digits[0] |= 1;
+ }
+ // To set the improved certainly of Miller-Rabin
+ j = startPoint.bitLength();
+ for (certainty = 2; j < BITS[certainty]; certainty++) {
+ // empty
+ }
+ // To calculate modules: N mod p1, N mod p2, ... for first primes.
+ for (i = 0; i < primes.length; i++) {
+ modules[i] = Division.remainder(startPoint, primes[i]) - gapSize;
+ }
+ while (true) {
+ // At this point, all numbers in the gap are initialized as
+ // probably primes
+ Arrays.fill(isDivisible, false);
+ // To discard multiples of first primes
+ for (i = 0; i < primes.length; i++) {
+ modules[i] = (modules[i] + gapSize) % primes[i];
+ j = (modules[i] == 0) ? 0 : (primes[i] - modules[i]);
+ for (; j < gapSize; j += primes[i]) {
+ isDivisible[j] = true;
+ }
+ }
+ // To execute Miller-Rabin for non-divisible numbers by all first
+ // primes
+ for (j = 0; j < gapSize; j++) {
+ if (!isDivisible[j]) {
+ probPrime = startPoint.copy();
+ Elementary.inplaceAdd(probPrime, j);
+
+ if (millerRabin(probPrime, certainty)) {
+ return probPrime;
+ }
+ }
+ }
+ Elementary.inplaceAdd(startPoint, gapSize);
+ }
+ }
+
+ /**
+ * The Miller-Rabin primality test.
+ *
+ * @param n the input number to be tested.
+ * @param t the number of trials.
+ * @return {@code false} if the number is definitely compose, otherwise
+ * {@code true} with probability {@code 1 - 4(-t)}.
+ * @ar.org.fitc.ref "D. Knuth, The Art of Computer Programming Vo.2, Section
+ * 4.5.4., Algorithm P"
+ */
+ private static boolean millerRabin(BigInteger n, int t) {
+ // PRE: n >= 0, t >= 0
+ BigInteger x; // x := UNIFORM{2...n-1}
+ BigInteger y; // y := x^(q * 2^j) mod n
+ BigInteger nMinus1 = n.subtract(BigInteger.ONE); // n-1
+ int bitLength = nMinus1.bitLength(); // ~ log2(n-1)
+ // (q,k) such that: n-1 = q * 2^k and q is odd
+ int k = nMinus1.getLowestSetBit();
+ BigInteger q = nMinus1.shiftRight(k);
+ Random rnd = new Random();
+
+ for (int i = 0; i < t; i++) {
+ // To generate a witness 'x', first it use the primes of table
+ if (i < primes.length) {
+ x = BIprimes[i];
+ } else {
+ /*
+ * It generates random witness only if it's necesssary. Note that all
+ * methods would call Miller-Rabin with t <= 50 so this part is only to
+ * do more robust the algorithm
+ */
+ do {
+ x = new BigInteger(bitLength, rnd);
+ } while ((x.compareTo(n) >= BigInteger.EQUALS) || (x.sign == 0)
+ || x.isOne());
+ }
+ y = x.modPow(q, n);
+ if (y.isOne() || y.equals(nMinus1)) {
+ continue;
+ }
+ for (int j = 1; j < k; j++) {
+ if (y.equals(nMinus1)) {
+ continue;
+ }
+ y = y.multiply(y).mod(n);
+ if (y.isOne()) {
+ return false;
+ }
+ }
+ if (!y.equals(nMinus1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Just to denote that this class can't be instantiated.
+ */
+ private Primality() {
+ }
+
+}
diff --git a/gwt/jre/java/math/RoundingMode.java b/gwt/jre/java/math/RoundingMode.java
new file mode 100644
index 0000000..ef7bdbc
--- /dev/null
+++ b/gwt/jre/java/math/RoundingMode.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
+ */
+package java.math;
+
+/**
+ * Specifies the rounding behavior for operations whose results cannot be
+ * represented exactly.
+ */
+public enum RoundingMode {
+
+ /**
+ * Rounding mode where positive values are rounded towards positive infinity
+ * and negative values towards negative infinity.
+ *
+ *
+ * A=
+ * a3
+ * a2
+ * a1
+ * a0
+ *
+ *
+ *
+ *
+ *
+ * B=
+ *
+ * b2
+ * b1
+ * b1
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * b0*a3
+ * b0*a2
+ * b0*a1
+ * b0*a0
+ *
+ *
+ *
+ *
+ *
+ * b1*a3
+ * b1*a2
+ * b1*a1
+ * b1*a0
+ *
+ *
+ *
+ * +
+ * b2*a3
+ * b2*a2
+ * b2*a1
+ * b2*a0
+ *
+ *
+ *
+ *
+ * ______
+ * ______
+ * ______
+ * ______
+ * ______
+ * ______
+ *
+ *
+ *
+ *
+ *
+ * A*B=R=
+ * r5
+ * r4
+ * r3
+ * r2
+ * r1
+ * r0
+ *
+ *
+ * Rule: {@code x.round().abs() >= x.abs()}
+ */
+ UP(BigDecimal.ROUND_UP),
+
+ /**
+ * Rounding mode where the values are rounded towards zero.
+ * Rule: {@code x.round().abs() <= x.abs()}
+ */
+ DOWN(BigDecimal.ROUND_DOWN),
+
+ /**
+ * Rounding mode to round towards positive infinity. For positive values this
+ * rounding mode behaves as {@link #UP}, for negative values as {@link #DOWN}.
+ * Rule: {@code x.round() >= x}
+ */
+ CEILING(BigDecimal.ROUND_CEILING),
+
+ /**
+ * Rounding mode to round towards negative infinity. For positive values this
+ * rounding mode behaves as {@link #DOWN}, for negative values as {@link #UP}.
+ * Rule: {@code x.round() <= x}
+ */
+ FLOOR(BigDecimal.ROUND_FLOOR),
+
+ /**
+ * Rounding mode where values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding up.
+ */
+ HALF_UP(BigDecimal.ROUND_HALF_UP),
+
+ /**
+ * Rounding mode where values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding down.
+ */
+ HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
+
+ /**
+ * Rounding mode where values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding to the even neighbor.
+ */
+ HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
+
+ /**
+ * Rounding mode where the rounding operations throws an ArithmeticException
+ * for the case that rounding is necessary, i.e. for the case that the value
+ * cannot be represented exactly.
+ */
+ UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
+
+ /**
+ * Some constant char arrays for optimized comparisons
+ */
+ private static final char[] chCEILING = {'C','E','I','L','I','N','G'};
+ private static final char[] chDOWN = {'D','O','W','N'};
+ private static final char[] chFLOOR = {'F','L','O','O','R'};
+ private static final char[] chHALF_DOWN = {'H','A','L','F','_','D','O','W','N'};
+ private static final char[] chHALF_EVEN = {'H','A','L','F','_','E','V','E','N'};
+ private static final char[] chHALF_UP = {'H','A','L','F','_','U','P'};
+ private static final char[] chUNNECESSARY = {'U','N','N','E','C','E','S','S','A','R','Y'};
+ private static final char[] chUP = {'U','P'};
+
+ /**
+ * Converts rounding mode constants from class {@code BigDecimal} into {@code
+ * RoundingMode} values.
+ *
+ * @param mode rounding mode constant as defined in class {@code BigDecimal}
+ * @return corresponding rounding mode object
+ */
+ public static RoundingMode valueOf(int mode) {
+ switch (mode) {
+ case BigDecimal.ROUND_CEILING:
+ return CEILING;
+ case BigDecimal.ROUND_DOWN:
+ return DOWN;
+ case BigDecimal.ROUND_FLOOR:
+ return FLOOR;
+ case BigDecimal.ROUND_HALF_DOWN:
+ return HALF_DOWN;
+ case BigDecimal.ROUND_HALF_EVEN:
+ return HALF_EVEN;
+ case BigDecimal.ROUND_HALF_UP:
+ return HALF_UP;
+ case BigDecimal.ROUND_UNNECESSARY:
+ return UNNECESSARY;
+ case BigDecimal.ROUND_UP:
+ return UP;
+ default:
+ // math.00=Invalid rounding mode
+ throw new IllegalArgumentException("Invalid rounding mode"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Bypasses calls to the implicit valueOf(String) method, which will break
+ * if enum name obfuscation is enabled. This should be package visible only.
+ *
+ * @param mode rounding mode string as defined in class {@code BigDecimal}
+ * @return corresponding rounding mode object
+ */
+ static RoundingMode valueOfExplicit(String mode) {
+ /*
+ * Note this is optimized to avoid multiple String compares,
+ * using specific knowledge of the set of allowed enum constants.
+ */
+
+ if (mode == null) {
+ throw new NullPointerException();
+ }
+
+ char[] modeChars = mode.toCharArray();
+ int len = modeChars.length;
+ if (len < chUP.length || len > chUNNECESSARY.length) {
+ throw new IllegalArgumentException();
+ }
+
+ char[] targetChars = null;
+ RoundingMode target = null;
+ if (modeChars[0] == 'C') {
+ target = RoundingMode.CEILING;
+ targetChars = chCEILING;
+ } else if (modeChars[0] == 'D') {
+ target = RoundingMode.DOWN;
+ targetChars = chDOWN;
+ } else if (modeChars[0] == 'F') {
+ target = RoundingMode.FLOOR;
+ targetChars = chFLOOR;
+ } else if (modeChars[0] == 'H') {
+ if (len > 6) {
+ if (modeChars[5] == 'D') {
+ target = RoundingMode.HALF_DOWN;
+ targetChars = chHALF_DOWN;
+ } else if (modeChars[5] == 'E') {
+ target = RoundingMode.HALF_EVEN;
+ targetChars = chHALF_EVEN;
+ } else if (modeChars[5] == 'U') {
+ target = RoundingMode.HALF_UP;
+ targetChars = chHALF_UP;
+ }
+ }
+ } else if (modeChars[0] == 'U') {
+ if (modeChars[1] == 'P') {
+ target = RoundingMode.UP;
+ targetChars = chUP;
+ } else if (modeChars[1] == 'N') {
+ target = RoundingMode.UNNECESSARY;
+ targetChars = chUNNECESSARY;
+ }
+ }
+
+ if (target != null && len == targetChars.length) {
+ int i;
+ for (i = 1; i < len && modeChars[i] == targetChars[i]; i++) {
+ }
+ if (i == len) {
+ return target;
+ }
+ }
+
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Set the old constant.
+ * @param rm unused
+ */
+ RoundingMode(int rm) {
+ // Note that we do not need the old-style rounding mode, so we ignore it.
+ }
+}
diff --git a/gwt/jre/java/net/UnknownServiceException.java b/gwt/jre/java/net/UnknownServiceException.java
new file mode 100644
index 0000000..d5d5b9a
--- /dev/null
+++ b/gwt/jre/java/net/UnknownServiceException.java
@@ -0,0 +1,21 @@
+package java.net;
+
+import java.io.IOException;
+
+public class UnknownServiceException extends IOException {
+
+ public UnknownServiceException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public UnknownServiceException(String s) {
+ super(s);
+ // TODO Auto-generated constructor stub
+ }
+
+ public UnknownServiceException(Exception e) {
+ super(e);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/gwt/jre/java/security/SecureRandom.java b/gwt/jre/java/security/SecureRandom.java
new file mode 100644
index 0000000..f380e2a
--- /dev/null
+++ b/gwt/jre/java/security/SecureRandom.java
@@ -0,0 +1,121 @@
+package java.security;
+
+import com.google.gwt.core.client.JsArrayInteger;
+
+public class SecureRandom extends java.util.Random
+{
+ private static final double twoToThe24 = 16777216.0;
+ private static final double twoToThe31 = 2147483648.0;
+ private static final double twoToThe32 = 4294967296.0;
+ private static final double twoToTheMinus24 =
+ 5.9604644775390625e-8;
+ private static final double twoToTheMinus26 =
+ 1.490116119384765625e-8;
+ private static final double twoToTheMinus31 =
+ 4.656612873077392578125e-10;
+ private static final double twoToTheMinus53 =
+ 1.1102230246251565404236316680908203125e-16;
+
+ protected native JsArrayInteger jsNextChunk() /*-{
+ var words = $wnd.sjcl.random.randomWords(4);
+ return words;
+ }-*/;
+
+ public int next(int numBits)
+ {
+ int numBytes = (numBits+7)/8;
+ byte[] bytes = new byte[numBytes];
+ nextBytes(bytes);
+
+ int result=0;
+ for (int i=0; ionModuleLoad()
.
+ */
+public class Mailiverse_GWT implements EntryPoint {
+
+ /**
+ * This is the entry point method.
+ */
+ public native void propagateLoad (JavaScriptObject main) /*-{
+ $wnd.onMailiverseBootstrapGWT(main);
+ }-*/;
+
+
+ public void onModuleLoad()
+ {
+ ExporterUtil.exportAll();
+ propagateLoad(ExporterUtil.wrap(new Main()));
+ }
+}
diff --git a/gwt/src/core/GWT.gwt.xml b/gwt/src/core/GWT.gwt.xml
new file mode 100644
index 0000000..afb96ab
--- /dev/null
+++ b/gwt/src/core/GWT.gwt.xml
@@ -0,0 +1,12 @@
+
+
+
+