Add BigDecimal/etc support.
This is what was previously rolled back in r7359 with a couple of
fixes.
Public review: http://gwt-code-reviews.appspot.com/126811
Patch by: jat
Review by: rice
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7618 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/i18n/client/NumberFormat.java b/user/src/com/google/gwt/i18n/client/NumberFormat.java
index 7b2ba5c..6d3a60d 100644
--- a/user/src/com/google/gwt/i18n/client/NumberFormat.java
+++ b/user/src/com/google/gwt/i18n/client/NumberFormat.java
@@ -15,9 +15,11 @@
*/
package com.google.gwt.i18n.client;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.constants.NumberConstants;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
/**
* Formats and parses numbers using locale-sensitive patterns.
*
@@ -349,7 +351,7 @@
public static boolean forcedLatinDigits() {
return defaultNumberConstants != localizedNumberConstants;
}
-
+
/**
* Provides the standard currency format for the default locale.
*
@@ -363,7 +365,7 @@
}
return cachedCurrencyFormat;
}
-
+
/**
* Provides the standard currency format for the default locale using a
* specified currency.
@@ -376,7 +378,7 @@
return new NumberFormat(defaultNumberConstants.currencyPattern(),
currencyData, false);
}
-
+
/**
* Provides the standard currency format for the default locale using a
* specified currency.
@@ -609,6 +611,47 @@
}
/**
+ * Appends a scaled string representation to a buffer, returning the scale
+ * (which is the number of places to the right of the end of the string the
+ * decimal point should be moved -- i.e., 3.5 would be added to the buffer
+ * as "35" and a returned scale of -1).
+ *
+ * @param buf
+ * @param val
+ * @return scale to apply to the result
+ */
+ // @VisibleForTesting
+ static int toScaledString(StringBuilder buf, double val) {
+ int startLen = buf.length();
+ buf.append(toPrecision(val, 20));
+ int scale = 0;
+
+ // remove exponent if present, adjusting scale
+ int expIdx = buf.indexOf("e", startLen);
+ if (expIdx < 0) {
+ expIdx = buf.indexOf("E", startLen);
+ }
+ if (expIdx >= 0) {
+ int expDigits = expIdx + 1;
+ if (expDigits < buf.length() && buf.charAt(expDigits) == '+') {
+ ++expDigits;
+ }
+ if (expDigits < buf.length()) {
+ scale = Integer.parseInt(buf.substring(expDigits));
+ }
+ buf.delete(expIdx, buf.length());
+ }
+
+ // remove decimal point if present, adjusting scale
+ int dot = buf.indexOf(".", startLen);
+ if (dot >= 0) {
+ buf.deleteCharAt(dot);
+ scale -= buf.length() - dot;
+ }
+ return scale;
+ }
+
+ /**
* Lookup a currency code.
*
* @param currencyCode ISO4217 currency code
@@ -625,26 +668,43 @@
return currencyData;
}
- private static native String toFixed(double d, int digits) /*-{
- return d.toFixed(digits);
+ /**
+ * 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);
}-*/;
- // The currency code.
+ /**
+ * The currency code.
+ */
private final String currencyCode;
- // Currency setting.
+ /**
+ * Currency symbol to use.
+ */
private final String currencySymbol;
- // Forces the decimal separator to always appear in a formatted number.
+ /**
+ * Forces the decimal separator to always appear in a formatted number.
+ */
private boolean decimalSeparatorAlwaysShown = false;
- // The number of digits between grouping separators in the integer
- // portion of a number.
+ /**
+ * The number of digits between grouping separators in the integer portion of
+ * a number.
+ */
private int groupingSize = 3;
-
+
private boolean isCurrencyFormat = false;
-
+
private int maximumFractionDigits = 3; // invariant, >= minFractionDigits.
+
private int maximumIntegerDigits = 40;
private int minExponentDigits;
private int minimumFractionDigits = 0;
@@ -671,6 +731,24 @@
private boolean useExponentialNotation = false;
/**
+ * Holds the current exponent during one call to
+ * {@link #format(boolean, StringBuilder, int)}.
+ */
+ private transient int exponent;
+
+ /**
+ * Holds the current decimal position during one call to
+ * {@link #format(boolean, StringBuilder, int)}.
+ */
+ private transient int decimalPosition;
+
+ /**
+ * Holds the current digits length during one call to
+ * {@link #format(boolean, StringBuilder, int)}.
+ */
+ private transient int digitsLength;
+
+ /**
* Constructs a format object based on the specified settings.
*
* @param numberConstants the locale-specific number constants to use for this
@@ -719,33 +797,75 @@
* @return the formatted number string
*/
public String format(double number) {
- StringBuffer result = new StringBuffer();
-
if (Double.isNaN(number)) {
- result.append(numberConstants.notANumber());
- return result.toString();
+ return numberConstants.notANumber();
}
-
- boolean isNegative = ((number < 0.0) || (number == 0.0 && 1 / number < 0.0));
-
- result.append(isNegative ? negativePrefix : positivePrefix);
+ boolean isNegative = ((number < 0.0)
+ || (number == 0.0 && 1 / number < 0.0));
+ if (isNegative) {
+ number = -number;
+ }
+ StringBuilder buf = new StringBuilder();
if (Double.isInfinite(number)) {
- result.append(numberConstants.infinity());
- } else {
- if (isNegative) {
- number = -number;
- }
- number *= multiplier;
- if (useExponentialNotation) {
- subformatExponential(number, result);
- } else {
- subformatFixed(number, result, minimumIntegerDigits);
- }
+ buf.append(isNegative ? negativePrefix : positivePrefix);
+ buf.append(numberConstants.infinity());
+ buf.append(isNegative ? negativeSuffix : positiveSuffix);
+ return buf.toString();
+ }
+ number *= multiplier;
+ int scale = toScaledString(buf, number);
+
+ // pre-round value to deal with .15 being represented as .149999... etc
+ // check at 3 more digits than will be required in the output
+ int preRound = buf.length() + scale + maximumFractionDigits + 3;
+ if (preRound > 0 && preRound < buf.length()
+ && buf.charAt(preRound) == '9') {
+ propagateCarry(buf, preRound - 1);
+ scale += buf.length() - preRound;
+ buf.delete(preRound, buf.length());
}
- result.append(isNegative ? negativeSuffix : positiveSuffix);
+ format(isNegative, buf, scale);
+ return buf.toString();
+ }
- return result.toString();
+ /**
+ * This method formats a Number to produce a string.
+ * <p>
+ * Any {@link Number} which is not a {@link BigDecimal}, {@link BigInteger},
+ * or {@link Long} instance is formatted as a {@code double} value.
+ *
+ * @param number The Number instance to format
+ * @return the formatted number string
+ */
+ public String format(Number number) {
+ if (number instanceof BigDecimal) {
+ BigDecimal bigDec = (BigDecimal) number;
+ boolean isNegative = bigDec.signum() < 0;
+ if (isNegative) {
+ bigDec = bigDec.negate();
+ }
+ bigDec = bigDec.multiply(BigDecimal.valueOf(multiplier));
+ StringBuilder buf = new StringBuilder();
+ buf.append(bigDec.unscaledValue().toString());
+ format(isNegative, buf, -bigDec.scale());
+ return buf.toString();
+ } else if (number instanceof BigInteger) {
+ BigInteger bigInt = (BigInteger) number;
+ boolean isNegative = bigInt.signum() < 0;
+ if (isNegative) {
+ bigInt = bigInt.negate();
+ }
+ bigInt = bigInt.multiply(BigInteger.valueOf(multiplier));
+ StringBuilder buf = new StringBuilder();
+ buf.append(bigInt.toString());
+ format(isNegative, buf, 0);
+ return buf.toString();
+ } else if (number instanceof Long) {
+ return format(number.longValue(), 0);
+ } else {
+ return format(number.doubleValue());
+ }
}
/**
@@ -761,9 +881,9 @@
* characters of the text.
*
* @param text the string being parsed
- * @return a parsed number value
+ * @return a double value representing the parsed number
* @throws NumberFormatException if the entire text could not be converted
- * into a number
+ * into a double
*/
public double parse(String text) throws NumberFormatException {
int[] pos = {0};
@@ -789,9 +909,9 @@
*
* @param text the string to be parsed
* @param inOutPos position to pass in and get back
- * @return a double value representing the parsed number, or <code>0.0</code>
- * if the parse fails
- * @throws NumberFormatException if the text segment could not be converted into a number
+ * @return a double value representing the parsed number
+ * @throws NumberFormatException if the text segment could not be converted
+ * into a double
*/
public double parse(String text, int[] inOutPos) throws NumberFormatException {
double ret = 0.0;
@@ -863,56 +983,294 @@
return ret;
}
+ /**
+ * Format a number with its significant digits already represented in string
+ * form. This is done so both double and BigInteger/Decimal formatting can
+ * share code without requiring all users to pay the code size penalty for
+ * BigDecimal/etc.
+ * <p>
+ * Example values passed in:
+ * <ul>
+ * <li>-13e2
+ * <br>{@code isNegative=true, digits="13", scale=2}
+ * <li>3.14158
+ * <br>{@code isNegative=false, digits="314158", scale=-5}
+ * <li>.0001
+ * <br>{@code isNegative=false, digits="1" ("0001" would be ok), scale=-4}
+ * </ul>
+ *
+ * @param isNegative true if the value to be formatted is negative
+ * @param digits a StringBuilder containing just the significant digits in
+ * the value to be formatted, the formatted result will be left here
+ * @param scale the number of places to the right the decimal point should
+ * be moved in the digit string -- negative means the value contains
+ * fractional digits
+ */
+ protected void format(boolean isNegative, StringBuilder digits, int scale) {
+ char decimalSeparator;
+ char groupingSeparator;
+ if (isCurrencyFormat) {
+ decimalSeparator = numberConstants.monetarySeparator().charAt(0);
+ groupingSeparator = numberConstants.monetaryGroupingSeparator().charAt(0);
+ } else {
+ decimalSeparator = numberConstants.decimalSeparator().charAt(0);
+ groupingSeparator = numberConstants.groupingSeparator().charAt(0);
+ }
+
+ // Set these transient fields, which will be adjusted/used by the routines
+ // called in this method.
+ exponent = 0;
+ digitsLength = digits.length();
+ decimalPosition = digitsLength + scale;
+
+ boolean useExponent = this.useExponentialNotation;
+ int currentGroupingSize = this.groupingSize;
+ if (decimalPosition > 1024) {
+ // force really large numbers to be in exponential form
+ useExponent = true;
+ }
+
+ if (useExponent) {
+ computeExponent(digits);
+ }
+ processLeadingZeros(digits);
+ roundValue(digits);
+ insertGroupingSeparators(digits, groupingSeparator, currentGroupingSize);
+ adjustFractionDigits(digits);
+ addZeroAndDecimal(digits, decimalSeparator);
+ if (useExponent) {
+ addExponent(digits);
+ // the above call has invalidated digitsLength == digits.length()
+ }
+ char zeroChar = numberConstants.zeroDigit().charAt(0);
+ if (zeroChar != '0') {
+ localizeDigits(digits, zeroChar);
+ }
+
+ // add prefix/suffix
+ digits.insert(0, isNegative ? negativePrefix : positivePrefix);
+ digits.append(isNegative ? negativeSuffix : positiveSuffix);
+ }
+
+ /**
+ * Parses text to produce a numeric value. A {@link NumberFormatException} is
+ * thrown if either the text is empty or if the parse does not consume all
+ * characters of the text.
+ *
+ * param text the string to be parsed
+ * return a parsed number value, which may be a Double, BigInteger, or
+ * BigDecimal
+ * throws NumberFormatException if the text segment could not be converted
+ * into a number
+ */
+// public Number parseBig(String text) throws NumberFormatException {
+// // TODO(jat): implement
+// return Double.valueOf(parse(text));
+// }
+
+ /**
+ * Parses text to produce a numeric value.
+ *
+ * <p>
+ * The method attempts to parse text starting at the index given by pos. If
+ * parsing succeeds, then the index of <code>pos</code> is updated to the
+ * index after the last character used (parsing does not necessarily use all
+ * characters up to the end of the string), and the parsed number is returned.
+ * The updated <code>pos</code> can be used to indicate the starting point
+ * for the next call to this method. If an error occurs, then the index of
+ * <code>pos</code> is not changed.
+ * </p>
+ *
+ * param text the string to be parsed
+ * pparam inOutPos position to pass in and get back
+ * return a parsed number value, which may be a Double, BigInteger, or
+ * BigDecimal
+ * throws NumberFormatException if the text segment could not be converted
+ * into a number
+ */
+// public Number parseBig(String text, int[] inOutPos)
+// throws NumberFormatException {
+// // TODO(jat): implement
+// return Double.valueOf(parse(text, inOutPos));
+// }
+
+ /**
+ * Format a possibly scaled long value.
+ *
+ * @param value value to format
+ * @param scale the number of places to the right the decimal point should
+ * be moved in the digit string -- negative means the value contains
+ * fractional digits
+ * @return formatted value
+ */
+ protected String format(long value, int scale) {
+ boolean isNegative = value < 0;
+ if (isNegative) {
+ value = -value;
+ }
+ value *= multiplier;
+ StringBuilder buf = new StringBuilder();
+ buf.append(String.valueOf(value));
+ format(isNegative, buf, scale);
+ return buf.toString();
+ }
+
+ /**
+ * @return the number of digits between grouping separators in the integer
+ * portion of a number.
+ */
protected int getGroupingSize() {
return groupingSize;
}
+ /**
+ * @return the prefix to use for negative values.
+ */
protected String getNegativePrefix() {
return negativePrefix;
}
+ /**
+ * @return the suffix to use for negative values.
+ */
protected String getNegativeSuffix() {
return negativeSuffix;
}
+ /**
+ * @return the NumberConstants instance for this formatter.
+ */
protected NumberConstants getNumberConstants() {
return numberConstants;
}
+ /**
+ * @return the prefix to use for positive values.
+ */
protected String getPositivePrefix() {
return positivePrefix;
}
+ /**
+ * @return the suffix to use for positive values.
+ */
protected String getPositiveSuffix() {
return positiveSuffix;
}
+ /**
+ * @return true if the decimal separator should always be shown.
+ */
protected boolean isDecimalSeparatorAlwaysShown() {
return decimalSeparatorAlwaysShown;
}
/**
- * This method formats the exponent part of a double.
+ * Add exponent suffix.
*
- * @param exponent exponential value
- * @param result formatted exponential part will be append to it
+ * @param digits
*/
- private void addExponentPart(int exponent, StringBuffer result) {
- result.append(numberConstants.exponentialSymbol());
-
+ private void addExponent(StringBuilder digits) {
+ digits.append(numberConstants.exponentialSymbol());
if (exponent < 0) {
exponent = -exponent;
- result.append(numberConstants.minusSign());
+ digits.append(numberConstants.minusSign());
+ }
+ String exponentDigits = String.valueOf(exponent);
+ for (int i = exponentDigits.length(); i < minExponentDigits; ++i) {
+ digits.append('0');
+ }
+ digits.append(exponentDigits);
+ }
+
+ /**
+ * @param digits
+ * @param decimalSeparator
+ */
+ private void addZeroAndDecimal(StringBuilder digits, char decimalSeparator) {
+ // add zero and decimal point if required
+ if (digitsLength == 0) {
+ digits.insert(0, '0');
+ ++decimalPosition;
+ ++digitsLength;
+ }
+ if (decimalPosition < digitsLength || decimalSeparatorAlwaysShown) {
+ digits.insert(decimalPosition, decimalSeparator);
+ ++digitsLength;
+ }
+ }
+
+ /**
+ * Adjust the fraction digits, adding trailing zeroes if necessary or removing
+ * excess trailing zeroes.
+ *
+ * @param digits
+ */
+ private void adjustFractionDigits(StringBuilder digits) {
+ // adjust fraction digits as required
+ int requiredDigits = decimalPosition + minimumFractionDigits;
+ if (digitsLength < requiredDigits) {
+ // add trailing zeros
+ while (digitsLength < requiredDigits) {
+ digits.append('0');
+ ++digitsLength;
+ }
+ } else {
+ // remove excess trailing zeros
+ int toRemove = decimalPosition + maximumFractionDigits;
+ if (toRemove > digitsLength) {
+ toRemove = digitsLength;
+ }
+ while (toRemove > requiredDigits
+ && digits.charAt(toRemove - 1) == '0') {
+ --toRemove;
+ }
+ if (toRemove < digitsLength) {
+ digits.delete(toRemove, digitsLength);
+ digitsLength = toRemove;
+ }
+ }
+ }
+
+ /**
+ * Compute the exponent to use and adjust decimal position if we are using
+ * exponential notation.
+ *
+ * @param digits
+ */
+ private void computeExponent(StringBuilder digits) {
+ // always trim leading zeros
+ int strip = 0;
+ while (strip < digitsLength - 1 && digits.charAt(strip) == '0') {
+ ++strip;
+ }
+ if (strip > 0) {
+ digits.delete(0, strip);
+ digitsLength -= strip;
+ exponent -= strip;
}
- String exponentDigits = String.valueOf(exponent);
- int len = exponentDigits.length();
- for (int i = len; i < minExponentDigits; ++i) {
- result.append(numberConstants.zeroDigit());
+ // decimal should wind up between minimum & maximumIntegerDigits
+ if (maximumIntegerDigits > minimumIntegerDigits
+ && maximumIntegerDigits > 0) {
+ // in this case, the exponent should be a multiple of
+ // maximumIntegerDigits and 1 <= decimal <= maximumIntegerDigits
+ exponent += decimalPosition - 1;
+ int remainder = exponent % maximumIntegerDigits;
+ if (remainder < 0) {
+ remainder += maximumIntegerDigits;
+ }
+ decimalPosition = remainder + 1;
+ exponent -= remainder;
+ } else {
+ exponent += decimalPosition - minimumIntegerDigits;
+ decimalPosition = minimumIntegerDigits;
}
- int zeroDelta = numberConstants.zeroDigit().charAt(0) - '0';
- for (int i = 0; i < len; ++i) {
- result.append((char) (exponentDigits.charAt(i) + zeroDelta));
+
+ // special-case 0 to have an exponent of 0
+ if (digitsLength == 1 && digits.charAt(0) == '0') {
+ exponent = 0;
+ decimalPosition = minimumIntegerDigits;
}
}
@@ -933,47 +1291,41 @@
}
/**
- * This does the work of String.valueOf(long), but given a double as input
- * and avoiding our emulated longs. Contrasted with String.valueOf(double),
- * it ensures (a) there will be no trailing .0, and (b) unwinds E-notation.
- *
- * @param number the integral value to convert
- * @return the string representing that integer
+ * Insert grouping separators if needed.
+ *
+ * @param digits
+ * @param groupingSeparator
+ * @param g
*/
- private String makeIntString(double number) {
- String intPart = String.valueOf(number);
- if (GWT.isScript()) {
- return intPart; // JavaScript does the right thing for integral doubles
+ private void insertGroupingSeparators(StringBuilder digits,
+ char groupingSeparator, int g) {
+ if (g > 0) {
+ for (int i = g; i < decimalPosition; i += g + 1) {
+ digits.insert(decimalPosition - i, groupingSeparator);
+ ++decimalPosition;
+ ++digitsLength;
+ }
}
- // ...but bytecode (hosted mode) does not... String.valueOf(double) will
- // either end in .0 (non internationalized) which we don't want but is
- // easy, or, for large numbers, it will be E-notation, which is annoying.
- int digitLen = intPart.length();
-
- if (intPart.charAt(digitLen - 2) == '.') {
- return intPart.substring(0, digitLen - 2);
- }
-
- // if we have E notation, (1) the exponent will be positive (else
- // intValue is 0, which doesn't need E notation), and (2) there will
- // be a radix dot (String.valueOf() isn't interationalized)
- int radix = intPart.indexOf('.');
- int exp = intPart.indexOf('E');
- int digits = 0;
- for (int i = exp + 1; i < intPart.length(); i++) {
- digits = digits * 10 + (intPart.charAt(i) - '0');
- }
- digits++; // exp of zero is one int digit...
- StringBuffer newIntPart = new StringBuffer();
- newIntPart.append(intPart.substring(0, radix));
- newIntPart.append(intPart.substring(radix + 1, exp));
- while (newIntPart.length() < digits) {
- newIntPart.append('0');
- }
- newIntPart.setLength(digits);
- return newIntPart.toString();
}
-
+
+ /**
+ * Replace locale-independent digits with locale-specific ones.
+ *
+ * @param digits StringBuilder containing formatted number
+ * @param zero locale-specific zero character -- the rest of the digits must
+ * be consecutive
+ */
+ private void localizeDigits(StringBuilder digits, char zero) {
+ // don't use digitsLength since we may have added an exponent
+ int n = digits.length();
+ for (int i = 0; i < n; ++i) {
+ char ch = digits.charAt(i);
+ if (ch >= '0' && ch <= '9') {
+ digits.setCharAt(i, (char) (ch - '0' + zero));
+ }
+ }
+ }
+
/**
* This method parses affix part of pattern.
*
@@ -1301,141 +1653,87 @@
return pos - start;
}
-
+
/**
- * This method formats a <code>double</code> in exponential format.
+ * Remove excess leading zeros or add some if we don't have enough.
*
- * @param number value need to be formated
- * @param result where the formatted string goes
+ * @param digits
*/
- private void subformatExponential(double number, StringBuffer result) {
- if (number == 0.0) {
- subformatFixed(number, result, minimumIntegerDigits);
- addExponentPart(0, result);
- return;
+ private void processLeadingZeros(StringBuilder digits) {
+ // make sure we have enough trailing zeros
+ if (decimalPosition > digitsLength) {
+ while (digitsLength < decimalPosition) {
+ digits.append('0');
+ ++digitsLength;
+ }
}
- int exponent = (int) Math.floor(Math.log(number) / Math.log(10));
- number /= Math.pow(10, exponent);
-
- int minIntDigits = minimumIntegerDigits;
- if (maximumIntegerDigits > 1 && maximumIntegerDigits > minimumIntegerDigits) {
- // A repeating range is defined; adjust to it as follows.
- // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
- // -3,-4,-5=>-6, etc. This takes into account that the
- // exponent we have here is off by one from what we expect;
- // it is for the format 0.MMMMMx10^n.
- while ((exponent % maximumIntegerDigits) != 0) {
- number *= 10;
- exponent--;
- }
- minIntDigits = 1;
- } else {
- // No repeating range is defined; use minimum integer digits.
- if (minimumIntegerDigits < 1) {
- exponent++;
- number /= 10;
- } else {
- for (int i = 1; i < minimumIntegerDigits; i++) {
- exponent--;
- number *= 10;
+ if (!useExponentialNotation) {
+ // make sure we have the right number of leading zeros
+ if (decimalPosition < minimumIntegerDigits) {
+ // add leading zeros
+ StringBuilder prefix = new StringBuilder();
+ while (decimalPosition < minimumIntegerDigits) {
+ prefix.append('0');
+ ++decimalPosition;
+ ++digitsLength;
+ }
+ digits.insert(0, prefix);
+ } else if (decimalPosition > minimumIntegerDigits) {
+ // trim excess leading zeros
+ int strip = decimalPosition - minimumIntegerDigits;
+ for (int i = 0; i < strip; ++i) {
+ if (digits.charAt(i) != '0') {
+ strip = i;
+ break;
+ }
+ }
+ if (strip > 0) {
+ digits.delete(0, strip);
+ digitsLength -= strip;
+ decimalPosition -= strip;
}
}
}
-
- subformatFixed(number, result, minIntDigits);
- addExponentPart(exponent, result);
}
/**
- * This method formats a <code>double</code> into a fractional
- * representation.
+ * Propagate a carry from incrementing the {@code i+1}'th digit.
*
- * @param number value need to be formated
- * @param result result will be written here
- * @param minIntDigits minimum integer digits
+ * @param digits
+ * @param i digit to start incrementing
*/
- private void subformatFixed(double number, StringBuffer result,
- int minIntDigits) {
- double power = Math.pow(10, maximumFractionDigits);
- // Use 3 extra digits to allow us to do our own rounding since
- // Java rounds up on .5 whereas some browsers might use 'round to even'
- // or other rules.
-
- // There are cases where more digits would be required to get
- // guaranteed results, but this at least makes such cases rarer.
- String fixedString = toFixed(number, maximumFractionDigits + 3);
-
- double intValue = 0, fracValue = 0;
- int exponentIndex = fixedString.indexOf('e');
- if (exponentIndex != -1) {
- // Large numbers may be returned in exponential notation: such numbers
- // are integers anyway
- intValue = Math.floor(number);
- } else {
- int decimalIndex = fixedString.indexOf('.');
- int len = fixedString.length();
- if (decimalIndex == -1) {
- decimalIndex = len;
- }
- if (decimalIndex > 0) {
- intValue = Double.parseDouble(fixedString.substring(0, decimalIndex));
- }
- if (decimalIndex < len - 1) {
- fracValue = Double.parseDouble(fixedString.substring(decimalIndex + 1));
- fracValue = (((int) fracValue) + 500) / 1000;
- if (fracValue >= power) {
- fracValue -= power;
- intValue++;
- }
+ private void propagateCarry(StringBuilder digits, int i) {
+ boolean carry = true;
+ while (carry && i >= 0) {
+ char digit = digits.charAt(i);
+ if (digit == '9') {
+ // set this to zero and keep going
+ digits.setCharAt(i--, '0');
+ } else {
+ digits.setCharAt(i, (char) (digit + 1));
+ carry = false;
}
}
-
- boolean fractionPresent = (minimumFractionDigits > 0) || (fracValue > 0);
-
- String intPart = makeIntString(intValue);
- String grouping = isCurrencyFormat
- ? numberConstants.monetaryGroupingSeparator()
- : numberConstants.groupingSeparator();
- String decimal = isCurrencyFormat ? numberConstants.monetarySeparator()
- : numberConstants.decimalSeparator();
-
- int zeroDelta = numberConstants.zeroDigit().charAt(0) - '0';
- int digitLen = intPart.length();
-
- if (intValue > 0 || minIntDigits > 0) {
- for (int i = digitLen; i < minIntDigits; i++) {
- result.append(numberConstants.zeroDigit());
- }
-
- for (int i = 0; i < digitLen; i++) {
- result.append((char) (intPart.charAt(i) + zeroDelta));
-
- if (digitLen - i > 1 && groupingSize > 0
- && ((digitLen - i) % groupingSize == 1)) {
- result.append(grouping);
- }
- }
- } else if (!fractionPresent) {
- // If there is no fraction present, and we haven't printed any
- // integer digits, then print a zero.
- result.append(numberConstants.zeroDigit());
+ if (carry) {
+ // ran off the front, prepend a 1
+ digits.insert(0, '1');
+ ++decimalPosition;
+ ++digitsLength;
}
+ }
- // Output the decimal separator if we always do so.
- if (decimalSeparatorAlwaysShown || fractionPresent) {
- result.append(decimal);
- }
-
- // To make sure it lead zero will be kept.
- String fracPart = makeIntString(Math.floor(fracValue + power + 0.5d));
- int fracLen = fracPart.length();
- while (fracPart.charAt(fracLen - 1) == '0' && fracLen > minimumFractionDigits + 1) {
- fracLen--;
- }
-
- for (int i = 1; i < fracLen; i++) {
- result.append((char) (fracPart.charAt(i) + zeroDelta));
+ /**
+ * Round the value at the requested place, propagating any carry backward.
+ *
+ * @param digits
+ */
+ private void roundValue(StringBuilder digits) {
+ // TODO(jat): other rounding modes?
+ if (digitsLength > decimalPosition + maximumFractionDigits
+ && digits.charAt(decimalPosition + maximumFractionDigits) >= '5') {
+ int i = decimalPosition + maximumFractionDigits - 1;
+ propagateCarry(digits, i);
}
}
}
diff --git a/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java b/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
index a360356..4513ab0 100644
--- a/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
@@ -83,9 +83,21 @@
public String format(StringGenerator out, String subformat, String argName,
JType argType) {
JPrimitiveType argPrimType = argType.isPrimitive();
- if (argPrimType == null || argPrimType == JPrimitiveType.BOOLEAN
- || argPrimType == JPrimitiveType.VOID) {
- return "Illegal argument type for number format";
+ if (argPrimType != null) {
+ if (argPrimType == JPrimitiveType.BOOLEAN
+ || argPrimType == JPrimitiveType.VOID) {
+ return "Illegal argument type for number format";
+ }
+ } else {
+ JClassType classType = argType.isClass();
+ if (classType == null) {
+ return "Unexpected argument type for number format";
+ }
+ TypeOracle oracle = classType.getOracle();
+ JClassType numberType = oracle.findType("java.lang.Number");
+ if (!classType.isAssignableTo(numberType)) {
+ return "Only Number subclasses may be formatted as a number";
+ }
}
if (subformat == null) {
out.appendExpression(numFormatClassName + ".getDecimalFormat().format("
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/math/BigDecimal_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/math/BigDecimal_CustomFieldSerializer.java
new file mode 100644
index 0000000..8bd01ee
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/math/BigDecimal_CustomFieldSerializer.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+/*
+ * author Richard Zschech
+ */
+package com.google.gwt.user.client.rpc.core.java.math;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+import java.math.BigDecimal;
+
+/**
+ * Custom field serializer for BigDecimal.
+ */
+public class BigDecimal_CustomFieldSerializer {
+
+ public static void deserialize(SerializationStreamReader streamReader,
+ BigDecimal instance) {
+ }
+
+ public static BigDecimal instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return new BigDecimal(streamReader.readString());
+ }
+
+ public static void serialize(SerializationStreamWriter streamWriter,
+ BigDecimal instance) throws SerializationException {
+ streamWriter.writeString(instance.toString());
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/math/BigInteger_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/math/BigInteger_CustomFieldSerializer.java
new file mode 100644
index 0000000..57ed4ba
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/math/BigInteger_CustomFieldSerializer.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+/*
+ * author Richard Zschech
+ */
+package com.google.gwt.user.client.rpc.core.java.math;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+import java.math.BigInteger;
+
+/**
+ * Custom field serializer for BigInteger.
+ */
+public class BigInteger_CustomFieldSerializer {
+
+ public static void deserialize(SerializationStreamReader streamReader,
+ BigInteger instance) {
+ }
+
+ public static BigInteger instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return new BigInteger(streamReader.readString());
+ }
+
+ public static void serialize(SerializationStreamWriter streamWriter,
+ BigInteger instance) throws SerializationException {
+ streamWriter.writeString(instance.toString());
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/math/MathContext_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/math/MathContext_CustomFieldSerializer.java
new file mode 100644
index 0000000..a9b3277
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/math/MathContext_CustomFieldSerializer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+/*
+ * author Richard Zschech
+ */
+package com.google.gwt.user.client.rpc.core.java.math;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+/**
+ * Custom field serializer for MathContext.
+ */
+public class MathContext_CustomFieldSerializer {
+
+ public static void deserialize(SerializationStreamReader streamReader,
+ MathContext instance) {
+ }
+
+ public static MathContext instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return new MathContext(streamReader.readInt(),
+ RoundingMode.values()[streamReader.readInt()]);
+ }
+
+ public static void serialize(SerializationStreamWriter streamWriter,
+ MathContext instance) throws SerializationException {
+ streamWriter.writeInt(instance.getPrecision());
+ streamWriter.writeInt(instance.getRoundingMode().ordinal());
+ }
+}
diff --git a/user/super/com/google/gwt/emul/java/lang/ArithmeticException.java b/user/super/com/google/gwt/emul/java/lang/ArithmeticException.java
index faf821e..235bc2c 100644
--- a/user/super/com/google/gwt/emul/java/lang/ArithmeticException.java
+++ b/user/super/com/google/gwt/emul/java/lang/ArithmeticException.java
@@ -16,10 +16,11 @@
package java.lang;
/**
- * NOTE: in GWT this is only thrown for division by zero on longs.
- *
+ * NOTE: in GWT this is only thrown for division by zero on longs and
+ * BigInteger/BigDecimal.
+ * <p>
* See <a
- * href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ArrayIndexOutOfBoundsException.html">the
+ * href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ArithmeticException.html">the
* official Java API doc</a> for details.
*/
public class ArithmeticException extends RuntimeException {
diff --git a/user/super/com/google/gwt/emul/java/lang/Float.java b/user/super/com/google/gwt/emul/java/lang/Float.java
index 8d9e849..b3c9576 100644
--- a/user/super/com/google/gwt/emul/java/lang/Float.java
+++ b/user/super/com/google/gwt/emul/java/lang/Float.java
@@ -16,7 +16,7 @@
package java.lang;
/**
- * Wraps a primitve <code>float</code> as an object.
+ * Wraps a primitive <code>float</code> as an object.
*/
public final class Float extends Number implements Comparable<Float> {
public static final float MAX_VALUE = 3.4028235e+38f;
@@ -40,7 +40,9 @@
}
/**
- * @skip Here for shared implementation with Arrays.hashCode
+ * @skip Here for shared implementation with Arrays.hashCode.
+ * @param f
+ * @return hash value of float (currently just truncated to int)
*/
public static int hashCode(float f) {
return (int) f;
@@ -55,7 +57,13 @@
}-*/;
public static float parseFloat(String s) throws NumberFormatException {
- return (float) __parseAndValidateDouble(s);
+ double doubleValue = __parseAndValidateDouble(s);
+ if (doubleValue > Float.MAX_VALUE) {
+ return Float.POSITIVE_INFINITY;
+ } else if (doubleValue < -Float.MAX_VALUE) {
+ return Float.NEGATIVE_INFINITY;
+ }
+ return (float) doubleValue;
}
public static String toString(float b) {
diff --git a/user/super/com/google/gwt/emul/java/math/BigDecimal.java b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
new file mode 100644
index 0000000..569918e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
@@ -0,0 +1,2979 @@
+/*
+ * 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 Comparable<BigDecimal>,
+ Serializable {
+
+ /**
+ * The constant one as a {@code BigDecimal}.
+ */
+ public static final BigDecimal ONE = new BigDecimal(1, 0);
+
+ /**
+ * Rounding mode to round towards positive infinity. For positive values this
+ * rounding mode behaves as {@link #ROUND_UP}, for negative values as
+ * {@link #ROUND_DOWN}.
+ *
+ * @see RoundingMode#CEILING
+ */
+ public static final int ROUND_CEILING = 2;
+
+ /**
+ * Rounding mode where the values are rounded towards zero.
+ *
+ * @see RoundingMode#DOWN
+ */
+ public static final int ROUND_DOWN = 1;
+
+ /**
+ * Rounding mode to round towards negative infinity. For positive values this
+ * rounding mode behaves as {@link #ROUND_DOWN}, for negative values as
+ * {@link #ROUND_UP}.
+ *
+ * @see RoundingMode#FLOOR
+ */
+ public static final int ROUND_FLOOR = 3;
+
+ /**
+ * Rounding mode where values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding down.
+ *
+ * @see RoundingMode#HALF_DOWN
+ */
+ public static final int ROUND_HALF_DOWN = 5;
+
+ /**
+ * Rounding mode where values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding to the even neighbor.
+ *
+ * @see RoundingMode#HALF_EVEN
+ */
+ public static final int ROUND_HALF_EVEN = 6;
+
+ /**
+ * Rounding mode where values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding up.
+ *
+ * @see RoundingMode#HALF_UP
+ */
+ public static final int ROUND_HALF_UP = 4;
+
+ /**
+ * Rounding mode where the rounding operations throws an {@code
+ * ArithmeticException} for the case that rounding is necessary, i.e. for the
+ * case that the value cannot be represented exactly.
+ *
+ * @see RoundingMode#UNNECESSARY
+ */
+ public static final int ROUND_UNNECESSARY = 7;
+
+ /**
+ * Rounding mode where positive values are rounded towards positive infinity
+ * and negative values towards negative infinity.
+ *
+ * @see RoundingMode#UP
+ */
+ public static final int ROUND_UP = 0;
+
+ /**
+ * The constant ten as a {@code BigDecimal}.
+ */
+ public static final BigDecimal TEN = new BigDecimal(10, 0);
+
+ /**
+ * The constant zero as a {@code BigDecimal}.
+ */
+ public static final BigDecimal ZERO = new BigDecimal(0, 0);
+
+ protected static JavaScriptObject unscaledRegex;
+
+ private static final int BI_SCALED_BY_ZERO_LENGTH = 11;
+
+ /**
+ * An array with the first <code>BigInteger</code> scaled by zero. (
+ * <code>[0,0],[1,0],...,[10,0]</code>).
+ */
+ private static final BigDecimal BI_SCALED_BY_ZERO[] = new BigDecimal[BI_SCALED_BY_ZERO_LENGTH];
+
+ /**
+ * An array filled with characters <code>'0'</code>.
+ */
+ 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 <code>double</code> (
+ * <code>10^0,10^1,...,10^18</code>).
+ */
+ private static final double[] DOUBLE_TEN_POW = new double[] {
+ 1D, 10D, 100D, 1000D, 10000D, 100000D, 1000000D, 10000000D, 100000000D,
+ 1000000000D, 10000000000D, 100000000000D, 1000000000000D,
+ 10000000000000D, 100000000000000D,};
+
+ 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 <code>double</code> (
+ * <code>5^0,5^1,...,5^27</code>).
+ */
+ private static final BigInteger FIVE_POW[];
+ /**
+ * The double closer to <code>Log10(2)</code>.
+ */
+ private static final double LOG10_2 = 0.3010299956639812;
+
+ /**
+ * 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 <code>double</code> (
+ * <code>10^0,10^1,...,10^18</code>).
+ */
+ private static final BigInteger TEN_POW[];
+
+ /**
+ * An array with the zero number scaled by the first positive scales. (
+ * <code>0*10^0, 0*10^1, ..., 0*10^10</code>).
+ */
+ 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 < 54) {
+ 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 sv) {
+ long smallValue = (long) sv;
+ if (smallValue < 0) {
+ smallValue = ~smallValue;
+ }
+ return 64 - Long.numberOfLeadingZeros(smallValue);
+ }
+
+ private static int bitLength(long smallValue) {
+ if (smallValue < 0) {
+ smallValue = ~smallValue;
+ }
+ return 64 - Long.numberOfLeadingZeros(smallValue);
+ }
+
+ 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() < 54) {
+ 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() < 54) {
+ 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);
+ }
+
+ // TODO convert to double math dont use longs
+ private static BigDecimal dividePrimitiveLongs(long scaledDividend,
+ long scaledDivisor, int scale, RoundingMode roundingMode) {
+ long quotient = scaledDividend / scaledDivisor;
+ long remainder = scaledDividend % scaledDivisor;
+ int sign = Long.signum(scaledDividend) * Long.signum(scaledDivisor);
+ if (remainder != 0) {
+ // Checking if: remainder * 2 >= scaledDivisor
+ int compRem; // 'compare to remainder'
+ compRem = longCompareTo(Math.abs(remainder) << 1, 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 int longCompareTo(long value1, long value2) {
+ return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0);
+ }
+
+ 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;
+
+ /**
+ * Constructs a new {@code BigDecimal} instance from the 64bit double {@code
+ * val}. The constructed big decimal is equivalent to the given double. For
+ * example, {@code new BigDecimal(0.1)} is equal to {@code
+ * 0.1000000000000000055511151231257827021181583404541015625}. This happens as
+ * {@code 0.1} cannot be represented exactly in binary.
+ * <p>
+ * To generate a big decimal instance which is equivalent to {@code 0.1} use
+ * the {@code BigDecimal(String)} constructor.
+ *
+ * @param val double value to be converted to a {@code BigDecimal} instance.
+ * @throws NumberFormatException if {@code val} is infinity or not a number.
+ */
+ // 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$
+ // }
+ // long bits = Double.doubleToLongBits(val); // IEEE-754
+ // long mantisa;
+ // int trailingZeros;
+ // // Extracting the exponent, note that the bias is 1023
+ // scale = 1075 - (int)((bits >> 52) & 0x7FFL);
+ // // Extracting the 52 bits of the mantisa.
+ // mantisa = (scale == 1075) ? (bits & 0xFFFFFFFFFFFFFL) << 1
+ // : (bits & 0xFFFFFFFFFFFFFL) | 0x10000000000000L;
+ // if (mantisa == 0) {
+ // scale = 0;
+ // precision = 1;
+ // }
+ // // To simplify all factors '2' in the mantisa
+ // if (scale > 0) {
+ // trailingZeros = Math.min(scale, Long.numberOfTrailingZeros(mantisa));
+ // mantisa >>>= trailingZeros;
+ // scale -= trailingZeros;
+ // }
+ // // Calculating the new unscaled value and the new scale
+ // if((bits >> 63) != 0) {
+ // mantisa = -mantisa;
+ // }
+ // int mantisaBits = bitLength(mantisa);
+ // if (scale < 0) {
+ // bitLength = mantisaBits == 0 ? 0 : mantisaBits - scale;
+ // if(bitLength < 64) {
+ // smallValue = mantisa << (-scale);
+ // } else {
+ // intVal = BigInteger.valueOf(mantisa).shiftLeft(-scale);
+ // }
+ // scale = 0;
+ // } else if (scale > 0) {
+ // // m * 2^e = (m * 5^(-e)) * 10^e
+ // if(scale < LONG_FIVE_POW.length
+ // && mantisaBits+LONG_FIVE_POW_BIT_LENGTH[scale] < 64) {
+ // smallValue = mantisa * LONG_FIVE_POW[scale];
+ // bitLength = bitLength(smallValue);
+ // } else {
+ // setUnscaledValue(Multiplication.multiplyByFivePow(BigInteger.valueOf(mantisa),
+ // scale));
+ // }
+ // } else { // scale == 0
+ // smallValue = mantisa;
+ // bitLength = mantisaBits;
+ // }
+ // }
+ /**
+ * Constructs a new {@code BigDecimal} instance from the 64bit double {@code
+ * val}. The constructed big decimal is equivalent to the given double. For
+ * example, {@code new BigDecimal(0.1)} is equal to {@code
+ * 0.1000000000000000055511151231257827021181583404541015625}. This happens as
+ * {@code 0.1} cannot be represented exactly in binary.
+ * <p>
+ * To generate a big decimal instance which is equivalent to {@code 0.1} use
+ * the {@code BigDecimal(String)} constructor.
+ *
+ * @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 infinity or not a number.
+ * @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) {
+ // this(val);
+ // inplaceRound(mc);
+ // }
+ /**
+ * 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 <code>precision()</code>. Note that some call to the private method
+ * <code>inplaceRound()</code> could update this field.
+ *
+ * @see #precision()
+ * @see #inplaceRound(MathContext)
+ */
+ private transient int precision;
+
+ private double scale;
+
+ private transient double smallValue;
+
+ /**
+ * The <code>String</code> 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 < 54) {
+ 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 < 54) {
+ 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 < 54 && val.bitLength < 54) {
+ 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 < 54 && divisor.bitLength < 54) {
+ if (diffScale == 0) {
+ return dividePrimitiveLongs((long) this.smallValue,
+ (long) divisor.smallValue, scale, roundingMode);
+ } else if (diffScale > 0) {
+ if (diffScale < DOUBLE_TEN_POW.length
+ && divisor.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale] < 54) {
+ return dividePrimitiveLongs((long) this.smallValue,
+ (long) (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] < 54) {
+ return dividePrimitiveLongs(
+ (long) (this.smallValue * DOUBLE_TEN_POW[(int) -diffScale]),
+ (long) 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is
+ * converted to a double, the result is {@code 9.007199254740992E15}.
+ * <p>
+ *
+ * @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 < 54 ? (x1.smallValue == smallValue)
+ : intVal.equals(x1.intVal));
+ }
+ return false;
+ }
+
+ // @Override
+ // public double doubleValue() {
+ // int sign = signum();
+ // int exponent = 1076; // bias + 53
+ // int lowestSetBit;
+ // int discardedSize;
+ // long powerOfTwo = this.bitLength - (long)(scale / LOG10_2);
+ // long bits; // IEEE-754 Standard
+ // long tempBits; // for temporal calculations
+ // BigInteger mantisa;
+ //
+ // if ((powerOfTwo < -1074) || (sign == 0)) {
+ // // Cases which 'this' is very small
+ // return (sign * 0.0d);
+ // } else if (powerOfTwo > 1025) {
+ // // Cases which 'this' is very large
+ // return (sign * Double.POSITIVE_INFINITY);
+ // }
+ // mantisa = getUnscaledValue().abs();
+ // // Let be: this = [u,s], with s > 0
+ // if (scale <= 0) {
+ // // mantisa = abs(u) * 10^s
+ // mantisa = mantisa.multiply(Multiplication.powerOf10(-scale));
+ // } else {// (scale > 0)
+ // BigInteger quotAndRem[];
+ // BigInteger powerOfTen = Multiplication.powerOf10(scale);
+ // int k = 100 - (int)powerOfTwo;
+ // int compRem;
+ //
+ // if (k > 0) {
+ // /* Computing (mantisa * 2^k) , where 'k' is a enough big
+ // * power of '2' to can divide by 10^s */
+ // mantisa = mantisa.shiftLeft(k);
+ // exponent -= k;
+ // }
+ // // Computing (mantisa * 2^k) / 10^s
+ // quotAndRem = mantisa.divideAndRemainder(powerOfTen);
+ // // To check if the fractional part >= 0.5
+ // compRem = quotAndRem[1].shiftLeftOneBit().compareTo(powerOfTen);
+ // // To add two rounded bits at end of mantisa
+ // mantisa = quotAndRem[0].shiftLeft(2).add(
+ // BigInteger.valueOf((compRem * (compRem + 3)) / 2 + 1));
+ // exponent -= 2;
+ // }
+ // lowestSetBit = mantisa.getLowestSetBit();
+ // discardedSize = mantisa.bitLength() - 54;
+ // if (discardedSize > 0) {// (n > 54)
+ // // mantisa = (abs(u) * 10^s) >> (n - 54)
+ // bits = mantisa.shiftRight(discardedSize).longValue();
+ // tempBits = bits;
+ // // #bits = 54, to check if the discarded fraction produces a carry
+ // if ((((bits & 1) == 1) && (lowestSetBit < discardedSize))
+ // || ((bits & 3) == 3)) {
+ // bits += 2;
+ // }
+ // } else {// (n <= 54)
+ // // mantisa = (abs(u) * 10^s) << (54 - n)
+ // bits = mantisa.longValue() << -discardedSize;
+ // tempBits = bits;
+ // // #bits = 54, to check if the discarded fraction produces a carry:
+ // if ((bits & 3) == 3) {
+ // bits += 2;
+ // }
+ // }
+ // // Testing bit 54 to check if the carry creates a new binary digit
+ // if ((bits & 0x40000000000000L) == 0) {
+ // // To drop the last bit of mantisa (first discarded)
+ // bits >>= 1;
+ // // exponent = 2^(s-n+53+bias)
+ // exponent += discardedSize;
+ // } else {// #bits = 54
+ // bits >>= 2;
+ // exponent += discardedSize + 1;
+ // }
+ // // To test if the 53-bits number fits in 'double'
+ // if (exponent > 2046) {// (exponent - bias > 1023)
+ // return (sign * Double.POSITIVE_INFINITY);
+ // } else if (exponent <= 0) {// (exponent - bias <= -1023)
+ // // Denormalized numbers (having exponent == 0)
+ // if (exponent < -53) {// exponent - bias < -1076
+ // return (sign * 0.0d);
+ // }
+ // // -1076 <= exponent - bias <= -1023
+ // // To discard '- exponent + 1' bits
+ // bits = tempBits >> 1;
+ // tempBits = bits & (-1L >>> (63 + exponent));
+ // bits >>= (-exponent );
+ // // To test if after discard bits, a new carry is generated
+ // if (((bits & 3) == 3) || (((bits & 1) == 1) && (tempBits != 0)
+ // && (lowestSetBit < discardedSize))) {
+ // bits += 1;
+ // }
+ // exponent = 0;
+ // bits >>= 1;
+ // }
+ // // Construct the 64 double bits: [sign(1), exponent(11), mantisa(52)]
+ // bits = (sign & 0x8000000000000000L) | ((long)exponent << 52)
+ // | (bits & 0xFFFFFFFFFFFFFL);
+ // return Double.longBitsToDouble(bits);
+ // }
+
+ /**
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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 < 54) {
+ 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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 < 54) {
+ 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 < 54) {
+ 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}.
+ * <p>
+ * {@code x.pow(0)} returns {@code 1}, even if {@code x == 0}.
+ * <p>
+ * 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}.
+ * <p>
+ * 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;
+ }
+ int decimalDigits = 1; // the precision to be calculated
+ double doubleUnsc = 1; // intVal in 'double'
+
+ if (bitLength < 1024) {
+ // To calculate the precision for small numbers
+ if (bitLength >= 54) {
+ doubleUnsc = getUnscaledValue().doubleValue();
+ } else if (bitLength >= 1) {
+ doubleUnsc = smallValue;
+ }
+ decimalDigits += (int) 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 = decimalDigits;
+ return precision;
+ }
+
+ /**
+ * Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
+ * <p>
+ * 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}.
+ * <p>
+ * The remainder is defined as {@code this -
+ * this.divideToIntegralValue(divisor) * divisor}.
+ * <p>
+ * 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}.
+ * <p>
+ * If {@code mc.precision = 0}, then no rounding is performed.
+ * <p>
+ * 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}.
+ * <p>
+ * 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 < 54) {
+ // 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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]) < 54) {
+ 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 < 54 && -diffScale < DOUBLE_TEN_POW.length) {
+ return dividePrimitiveLongs((long) this.smallValue,
+ (long) 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 < 54) {
+ 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 < 54) {
+ 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 < 54) {
+ 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 < 54) {
+ 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.
+ * <p>
+ * 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();
+ }
+
+ /* Private Methods */
+
+ /**
+ * Returns a string representation of this {@code BigDecimal}. No scientific
+ * notation is used. This methods adds zeros where necessary.
+ * <p>
+ * If this string representation is used to create a new instance, this
+ * instance is generally not identical to {@code this} as the precision
+ * changes.
+ * <p>
+ * {@code x.equals(new BigDecimal(x.toPlainString())} usually returns {@code
+ * false}.
+ * <p>
+ * {@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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * For class {@code BigDecimal}, the ULP of a number is simply 10^(-scale).
+ * <p>
+ * 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((long) smallValue);
+ }
+ return intVal;
+ }
+
+ private void initFrom(String val) {
+ int begin = 0; // first index to be copied
+ int offset = 0;
+ int last = val.length() - 1; // last index to be copied
+ String scaleString = null; // buffer for scale
+ StringBuilder unscaledBuffer; // buffer for unscaled value
+
+ if (val == null) {
+ throw new NullPointerException();
+ }
+ unscaledBuffer = new StringBuilder(val.length());
+ // To skip a possible '+' symbol
+ if ((offset <= last) && (val.charAt(offset) == '+')) {
+ offset++;
+ begin++;
+ }
+ 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 + 1);
+ // 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;
+ if (unscaledBuffer.charAt(0) == '-') {
+ 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 < 54) {
+ 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 < 54) {
+ 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] < 54) {
+ 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 < 54) {
+ 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/user/super/com/google/gwt/emul/java/math/BigInteger.java b/user/super/com/google/gwt/emul/java/math/BigInteger.java
new file mode 100644
index 0000000..e36c778
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/math/BigInteger.java
@@ -0,0 +1,1497 @@
+/*
+ * 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.
+ * <p>
+ * 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<BigInteger>,
+ Serializable {
+
+ /**
+ * The {@code BigInteger} constant 1.
+ */
+ public static final BigInteger ONE = new BigInteger(1, 1);
+
+ /* Fields used for the internal representation. */
+
+ /**
+ * The {@code BigInteger} constant 10.
+ */
+ public static final BigInteger TEN = new BigInteger(1, 10);
+
+ /**
+ * The {@code BigInteger} constant 0.
+ */
+ public static final BigInteger ZERO = new BigInteger(0, 0);
+
+ /**
+ * The {@code BigInteger} constant 0 used for comparison.
+ */
+ static final int EQUALS = 0;
+
+ /**
+ * The {@code BigInteger} constant 1 used for comparison.
+ */
+ static final int GREATER = 1;
+
+ /**
+ * The {@code BigInteger} constant -1 used for comparison.
+ */
+ static final int LESS = -1;
+
+ /**
+ * The {@code BigInteger} constant -1.
+ */
+ static final BigInteger MINUS_ONE = new BigInteger(-1, 1);
+
+ /**
+ * All the {@code BigInteger} numbers in the range [0,10] are cached.
+ */
+ static final BigInteger[] SMALL_VALUES = {
+ ZERO, ONE, new BigInteger(1, 2), new BigInteger(1, 3),
+ new BigInteger(1, 4), new BigInteger(1, 5), new BigInteger(1, 6),
+ new BigInteger(1, 7), new BigInteger(1, 8), new BigInteger(1, 9), TEN};
+
+ static final BigInteger[] TWO_POWS;
+
+ /**
+ * This is the serialVersionUID used by the sun implementation.
+ */
+ private static final long serialVersionUID = -8287574255936472291L;
+
+ static {
+ TWO_POWS = new BigInteger[32];
+ for (int i = 0; i < TWO_POWS.length; i++) {
+ TWO_POWS[i] = BigInteger.valueOf(1L << i);
+ }
+ }
+
+ /**
+ * Returns a random positive {@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^80).
+ * <p>
+ * <b>Implementation Note:</b> 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);
+ }
+
+ /**
+ * @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();
+ }
+
+ /**
+ * The magnitude of this big integer. This array holds unsigned little endian
+ * digits. 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.
+ */
+ 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)};
+ }
+ }
+
+ /**
+ * 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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())}.
+ * <p>
+ * <b>Implementation Note:</b> 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.
+ * <p>
+ * 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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.
+ * <p>
+ * The two's complement representation of {@code this} will be at least
+ * {@code bitLength() + 1} bits long.
+ * <p>
+ * 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)}.
+ * <p>
+ * <b>Implementation Note:</b> 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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.
+ * <p>
+ * <b>Implementation Note:</b> 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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))}.
+ * <p>
+ * <b>Implementation Note:</b> 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.
+ * <p>
+ * <b>Implementation Note:</b> 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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}.
+ * <p>
+ * <b>Implementation Note:</b> 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/user/super/com/google/gwt/emul/java/math/BitLevel.java b/user/super/com/google/gwt/emul/java/math/BitLevel.java
new file mode 100644
index 0000000..b539637
--- /dev/null
+++ b/user/super/com/google/gwt/emul/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 <b>bit level</b> operations for
+ * {@link BigInteger}. The operations are: <ul type="circle"> <li>Left Shifting</li>
+ * <li>Right Shifting</li> <li>Bit clearing</li> <li>Bit setting</li> <li>Bit
+ * counting</li> <li>Bit testing</li> <li>Getting of the lowest bit set</li>
+ * </ul> 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/user/super/com/google/gwt/emul/java/math/Conversion.java b/user/super/com/google/gwt/emul/java/math/Conversion.java
new file mode 100644
index 0000000..28b8a95
--- /dev/null
+++ b/user/super/com/google/gwt/emul/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 an {@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
+ * radix<sup>digitFitInInt[radix]</sup> 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/user/super/com/google/gwt/emul/java/math/Division.java b/user/super/com/google/gwt/emul/java/math/Division.java
new file mode 100644
index 0000000..4179a82
--- /dev/null
+++ b/user/super/com/google/gwt/emul/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:
+ *
+ * <ul type="circle"> <li><b>Division</b> <ul type="circle"> <li>
+ * {@link BigInteger} division and remainder by {@link BigInteger}.</li> <li>
+ * {@link BigInteger} division and remainder by {@code int}.</li> <li><i>gcd</i>
+ * between {@link BigInteger} numbers.</li> </ul> </li> <li><b>Modular
+ * arithmetic </b> <ul type="circle"> <li>Modular exponentiation between
+ * {@link BigInteger} numbers.</li> <li>Modular inverse of a {@link BigInteger}
+ * numbers.</li> </ul> </li> </ul>
+ */
+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 <i>The
+ * square and multiply algorithm and the Montgomery Reduction C. K. Koc -
+ * Montgomery Reduction with Even Modulus</i>. 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 <code>GCD(op1, op2)</code>
+ */
+ 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 (2<sup>n</sup>)}.
+ *
+ * @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<sup>-1</sup> (mod 2<sup>n</sup>)}.
+ */
+ 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 <i>little endian</i> notation.
+ *
+ * @param a The first factor of the product.
+ * @param b The second factor of the product.
+ * @param modulus The modulus of the operations. Z<sub>modulus</sub>.
+ * @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 base<sup>exponent</sup> mod (2<sup>j</sup>)}.
+ * @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 <code>BigInteger</code> by a signed <code>int</code> 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 <i>The sliding
+ * windows algorithm and the MongomeryReduction</i>.
+ *
+ * @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());
+ }
+ }
+
+ /**
+ * @return 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/user/super/com/google/gwt/emul/java/math/Elementary.java b/user/super/com/google/gwt/emul/java/math/Elementary.java
new file mode 100644
index 0000000..58bec5b
--- /dev/null
+++ b/user/super/com/google/gwt/emul/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. <ul
+ * type="circle"> <li>Addition.</li> <li>Subtraction.</li> <li>Comparison.</li>
+ * </ul> In addition to this, some <i><b>Inplace</b></i> (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/user/super/com/google/gwt/emul/java/math/Logical.java b/user/super/com/google/gwt/emul/java/math/Logical.java
new file mode 100644
index 0000000..d3ab03e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/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. <ul type="circle"> <li>not</li> <li>and
+ * </li> <li>andNot</li> <li>or</li> <li>xor</li> </ul>
+ */
+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/user/super/com/google/gwt/emul/java/math/MathContext.java b/user/super/com/google/gwt/emul/java/math/MathContext.java
new file mode 100644
index 0000000..ecde7c2
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/math/MathContext.java
@@ -0,0 +1,304 @@
+/*
+ * 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) {
+ 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"...
+ this.roundingMode = RoundingMode.valueOf(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.
+ * <p>
+ * 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=<precision> roundingMode=<roundingMode>" * } where
+ * {@code <precision>} is an integer describing the number of digits
+ * used for operations and {@code <roundingMode>} is the string
+ * representation of the rounding mode.
+ *
+ * @return a string representation for this {@code MathContext} instance
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(45);
+
+ sb.append(chPrecision);
+ sb.append(precision);
+ sb.append(' ');
+ sb.append(chRoundingMode);
+ sb.append(roundingMode);
+ return sb.toString();
+ }
+}
diff --git a/user/super/com/google/gwt/emul/java/math/Multiplication.java b/user/super/com/google/gwt/emul/java/math/Multiplication.java
new file mode 100644
index 0000000..22fdf49
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/math/Multiplication.java
@@ -0,0 +1,534 @@
+/*
+ * 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 multiplication of {@link BigInteger}
+ * methods.
+ */
+class Multiplication {
+
+ /**
+ * An array with the first powers of five in {@code BigInteger} version. (
+ * {@code 5^0,5^1,...,5^31})
+ */
+ static final BigInteger bigFivePows[] = new BigInteger[32];
+
+ /**
+ * An array with the first powers of ten in {@code BigInteger} version. (
+ * {@code 10^0,10^1,...,10^31})
+ */
+ static final BigInteger[] bigTenPows = new BigInteger[32];
+
+ /**
+ * An array with powers of five that fit in the type {@code int}. ({@code
+ * 5^0,5^1,...,5^13})
+ */
+ static final int fivePows[] = {
+ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
+ 48828125, 244140625, 1220703125};
+
+ /**
+ * An array with powers of ten that fit in the type {@code int}. ({@code
+ * 10^0,10^1,...,10^9})
+ */
+ static final int tenPows[] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
+
+ /**
+ * Break point in digits (number of {@code int} elements) between Karatsuba
+ * and Pencil and Paper multiply.
+ */
+ static final int whenUseKaratsuba = 63; // an heuristic value
+
+ static {
+ int i;
+ long fivePow = 1L;
+
+ for (i = 0; i <= 18; i++) {
+ bigFivePows[i] = BigInteger.valueOf(fivePow);
+ bigTenPows[i] = BigInteger.valueOf(fivePow << i);
+ fivePow *= 5;
+ }
+ for (; i < bigTenPows.length; i++) {
+ bigFivePows[i] = bigFivePows[i - 1].multiply(bigFivePows[1]);
+ bigTenPows[i] = bigTenPows[i - 1].multiply(BigInteger.TEN);
+ }
+ }
+
+ /**
+ * Performs the multiplication with the Karatsuba's algorithm. <b>Karatsuba's
+ * algorithm:</b> <tt>
+ * u = u<sub>1</sub> * B + u<sub>0</sub><br>
+ * v = v<sub>1</sub> * B + v<sub>0</sub><br>
+ *
+ *
+ * u*v = (u<sub>1</sub> * v<sub>1</sub>) * B<sub>2</sub> + ((u<sub>1</sub> - u<sub>0</sub>) * (v<sub>0</sub> - v<sub>1</sub>) + u<sub>1</sub> * v<sub>1</sub> +
+ * u<sub>0</sub> * v<sub>0</sub> ) * B + u<sub>0</sub> * v<sub>0</sub><br>
+ *</tt>
+ *
+ * @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 * 5<sup>exp</sup>}
+ */
+ 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 * 10<sup>exp</sup>}
+ */
+ 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.
+ *
+ * <br>
+ * <tt>
+ * <table border="0">
+ * <tbody>
+ *
+ *
+ * <tr>
+ * <td align="center">A=</td>
+ * <td>a<sub>3</sub></td>
+ * <td>a<sub>2</sub></td>
+ * <td>a<sub>1</sub></td>
+ * <td>a<sub>0</sub></td>
+ * <td></td>
+ * <td></td>
+ * </tr>
+ *
+ * <tr>
+ * <td align="center">B=</td>
+ * <td></td>
+ * <td>b<sub>2</sub></td>
+ * <td>b<sub>1</sub></td>
+ * <td>b<sub>1</sub></td>
+ * <td></td>
+ * <td></td>
+ * </tr>
+ *
+ * <tr>
+ * <td></td>
+ * <td></td>
+ * <td></td>
+ * <td>b<sub>0</sub>*a<sub>3</sub></td>
+ * <td>b<sub>0</sub>*a<sub>2</sub></td>
+ * <td>b<sub>0</sub>*a<sub>1</sub></td>
+ * <td>b<sub>0</sub>*a<sub>0</sub></td>
+ * </tr>
+ *
+ * <tr>
+ * <td></td>
+ * <td></td>
+ * <td>b<sub>1</sub>*a<sub>3</sub></td>
+ * <td>b<sub>1</sub>*a<sub>2</sub></td>
+ * <td>b<sub>1</sub>*a1</td>
+ * <td>b<sub>1</sub>*a0</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>+</td>
+ * <td>b<sub>2</sub>*a<sub>3</sub></td>
+ * <td>b<sub>2</sub>*a<sub>2</sub></td>
+ * <td>b<sub>2</sub>*a<sub>1</sub></td>
+ * <td>b<sub>2</sub>*a<sub>0</sub></td>
+ * </tr>
+ *
+ * <tr>
+ * <td></td>
+ * <td>______</td>
+ * <td>______</td>
+ * <td>______</td>
+ * <td>______</td>
+ * <td>______</td>
+ * <td>______</td>
+ * </tr>
+ *
+ * <tr>
+ *
+ * <td align="center">A*B=R=</td>
+ * <td align="center">r<sub>5</sub></td>
+ * <td align="center">r<sub>4</sub></td>
+ * <td align="center">r<sub>3</sub></td>
+ * <td align="center">r<sub>2</sub></td>
+ * <td align="center">r<sub>1</sub></td>
+ * <td align="center">r<sub>0</sub></td>
+ * <td></td>
+ * </tr>
+ *
+ * </tbody>
+ * </table>
+ *
+ *</tt>
+ *
+ * @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 10<sup>exp</sup>}.
+ */
+ 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 a<sup>2</sup>.
+ *
+ * @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/user/super/com/google/gwt/emul/java/math/Primality.java b/user/super/com/google/gwt/emul/java/math/Primality.java
new file mode 100644
index 0000000..016d99c
--- /dev/null
+++ b/user/super/com/google/gwt/emul/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<sup>(-100)</sup>}. 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<sup>(-t)</sup>}.
+ * @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/user/super/com/google/gwt/emul/java/math/RoundingMode.java b/user/super/com/google/gwt/emul/java/math/RoundingMode.java
new file mode 100644
index 0000000..f432d05
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/math/RoundingMode.java
@@ -0,0 +1,133 @@
+/*
+ * 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 to round towards positive infinity. For positive values this
+ * rounding mode behaves as {@link #UP}, for negative values as {@link #DOWN}. <br>
+ * Rule: {@code x.round() >= x}
+ */
+ CEILING(BigDecimal.ROUND_CEILING),
+
+ /**
+ * Rounding mode where the values are rounded towards zero. <br>
+ * Rule: {@code x.round().abs() <= x.abs()}
+ */
+ DOWN(BigDecimal.ROUND_DOWN),
+
+ /**
+ * Rounding mode to round towards negative infinity. For positive values this
+ * rounding mode behaves as {@link #DOWN}, for negative values as {@link #UP}. <br>
+ * Rule: {@code x.round() <= x}
+ */
+ FLOOR(BigDecimal.ROUND_FLOOR),
+
+ /**
+ * 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 values are rounded towards the nearest neighbor. Ties
+ * are broken by rounding up.
+ */
+ HALF_UP(BigDecimal.ROUND_HALF_UP),
+
+ /**
+ * 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),
+
+ /**
+ * Rounding mode where positive values are rounded towards positive infinity
+ * and negative values towards negative infinity. <br>
+ * Rule: {@code x.round().abs() >= x.abs()}
+ */
+ UP(BigDecimal.ROUND_UP);
+
+ /**
+ * 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$
+ }
+ }
+
+ /**
+ * 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/user/test/com/google/gwt/emultest/EmulSuite.java b/user/test/com/google/gwt/emultest/EmulSuite.java
index d036516..fec78f2 100644
--- a/user/test/com/google/gwt/emultest/EmulSuite.java
+++ b/user/test/com/google/gwt/emultest/EmulSuite.java
@@ -30,6 +30,26 @@
import com.google.gwt.emultest.java.lang.StringBufferTest;
import com.google.gwt.emultest.java.lang.StringTest;
import com.google.gwt.emultest.java.lang.SystemTest;
+import com.google.gwt.emultest.java.math.BigDecimalArithmeticTest;
+import com.google.gwt.emultest.java.math.BigDecimalCompareTest;
+import com.google.gwt.emultest.java.math.BigDecimalConstructorsTest;
+import com.google.gwt.emultest.java.math.BigDecimalConvertTest;
+import com.google.gwt.emultest.java.math.BigDecimalScaleOperationsTest;
+import com.google.gwt.emultest.java.math.BigIntegerAddTest;
+import com.google.gwt.emultest.java.math.BigIntegerAndTest;
+import com.google.gwt.emultest.java.math.BigIntegerCompareTest;
+import com.google.gwt.emultest.java.math.BigIntegerConstructorsTest;
+import com.google.gwt.emultest.java.math.BigIntegerConvertTest;
+import com.google.gwt.emultest.java.math.BigIntegerDivideTest;
+import com.google.gwt.emultest.java.math.BigIntegerHashCodeTest;
+import com.google.gwt.emultest.java.math.BigIntegerModPowTest;
+import com.google.gwt.emultest.java.math.BigIntegerMultiplyTest;
+import com.google.gwt.emultest.java.math.BigIntegerNotTest;
+import com.google.gwt.emultest.java.math.BigIntegerOperateBitsTest;
+import com.google.gwt.emultest.java.math.BigIntegerOrTest;
+import com.google.gwt.emultest.java.math.BigIntegerSubtractTest;
+import com.google.gwt.emultest.java.math.BigIntegerToStringTest;
+import com.google.gwt.emultest.java.math.BigIntegerXorTest;
import com.google.gwt.emultest.java.sql.SqlDateTest;
import com.google.gwt.emultest.java.sql.SqlTimeTest;
import com.google.gwt.emultest.java.sql.SqlTimestampTest;
@@ -80,6 +100,28 @@
suite.addTestSuite(StringTest.class);
suite.addTestSuite(SystemTest.class);
+ // java.math
+ suite.addTestSuite(BigDecimalArithmeticTest.class);
+ suite.addTestSuite(BigDecimalCompareTest.class);
+ suite.addTestSuite(BigDecimalConstructorsTest.class);
+ suite.addTestSuite(BigDecimalConvertTest.class);
+ suite.addTestSuite(BigDecimalScaleOperationsTest.class);
+ suite.addTestSuite(BigIntegerAddTest.class);
+ suite.addTestSuite(BigIntegerAndTest.class);
+ suite.addTestSuite(BigIntegerCompareTest.class);
+ suite.addTestSuite(BigIntegerConstructorsTest.class);
+ suite.addTestSuite(BigIntegerConvertTest.class);
+ suite.addTestSuite(BigIntegerDivideTest.class);
+ suite.addTestSuite(BigIntegerHashCodeTest.class);
+ suite.addTestSuite(BigIntegerModPowTest.class);
+ suite.addTestSuite(BigIntegerMultiplyTest.class);
+ suite.addTestSuite(BigIntegerNotTest.class);
+ suite.addTestSuite(BigIntegerOperateBitsTest.class);
+ suite.addTestSuite(BigIntegerOrTest.class);
+ suite.addTestSuite(BigIntegerSubtractTest.class);
+ suite.addTestSuite(BigIntegerToStringTest.class);
+ suite.addTestSuite(BigIntegerXorTest.class);
+
// java.util
suite.addTestSuite(ApacheMapTest.class);
suite.addTestSuite(ArrayListTest.class);
diff --git a/user/test/com/google/gwt/emultest/java/lang/FloatTest.java b/user/test/com/google/gwt/emultest/java/lang/FloatTest.java
index c8cea58..3254e20 100644
--- a/user/test/com/google/gwt/emultest/java/lang/FloatTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/FloatTest.java
@@ -24,6 +24,7 @@
*/
public class FloatTest extends GWTTestCase {
+ @Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuite";
}
@@ -77,9 +78,13 @@
assertEquals(-1.5f, Float.parseFloat("-1.5"), 0.0);
assertEquals(3.0f, Float.parseFloat("3."), 0.0);
assertEquals(0.5f, Float.parseFloat(".5"), 0.0);
- assertEquals("Can't parse MAX_VALUE", Float.MAX_VALUE,
- Float.parseFloat(String.valueOf(Float.MAX_VALUE)), 1e31);
- assertEquals("Can't parse MIN_VALUE", Float.MIN_VALUE,
- Float.parseFloat(String.valueOf(Float.MIN_VALUE)), Float.MIN_VALUE);
+ // TODO(jat): it isn't safe to parse MAX/MIN_VALUE because we also want to
+ // be able to get POSITIVE/NEGATIVE_INFINITY for out-of-range values, and
+ // since all math in JS is done in double we can't rely on getting the
+ // exact value back.
+// assertEquals("Can't parse MAX_VALUE", Float.MAX_VALUE,
+// Float.parseFloat(String.valueOf(Float.MAX_VALUE)), 1e31);
+// assertEquals("Can't parse MIN_VALUE", Float.MIN_VALUE,
+// Float.parseFloat(String.valueOf(Float.MIN_VALUE)), Float.MIN_VALUE);
}
}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalArithmeticTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalArithmeticTest.java
new file mode 100644
index 0000000..99ae798
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalArithmeticTest.java
@@ -0,0 +1,1741 @@
+/*
+ * 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 GOOGLE.
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+/**
+ * Class: java.math.BigDecimal Methods: add, subtract, multiply, divide
+ */
+public class BigDecimalArithmeticTest extends EmulTestBase {
+ /**
+ * Add two numbers of different scales; the first is negative
+ */
+ public void testAddDiffScaleNegPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1231212478987482988429808779810457634781459480137916301878791834798.7234564568";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of different scales; the first is positive
+ */
+ public void testAddDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "7472334294161400358170962860775454459810457634.781384756794987";
+ int cScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of different scales; the first is positive
+ */
+ public void testAddDiffScalePosPos() {
+ String a = "100";
+ int aScale = 15;
+ String b = "200";
+ int bScale = 14;
+ String c = "2.100E-12";
+ int cScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two zeroes of different scales; the first is negative
+ */
+ public void testAddDiffScaleZeroZero() {
+ String a = "0";
+ int aScale = -15;
+ String b = "0";
+ int bScale = 10;
+ String c = "0E-10";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal negative scales
+ */
+ public void testAddEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "1.231212478987483735663238072829245553129371991359555E+61";
+ int cScale = -10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal positive scales
+ */
+ public void testAddEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "123121247898748373566323807282924555312937.1991359555";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of different scales using MathContext; the first is
+ * positive
+ */
+ public void testAddMathContextDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "7.47233429416141E+45";
+ int cScale = -31;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(15, RoundingMode.CEILING);
+ BigDecimal result = aNumber.add(bNumber, mc);
+ assertEquals("incorrect value", c, c.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal negative scales using MathContext
+ */
+ public void testAddMathContextEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "1.2312E+61";
+ int cScale = -57;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(5, RoundingMode.FLOOR);
+ BigDecimal result = aNumber.add(bNumber, mc);
+ assertEquals("incorrect value ", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal positive scales using MathContext
+ */
+ public void testAddMathContextEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.2313E+41";
+ int cScale = -37;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(5, RoundingMode.UP);
+ BigDecimal result = aNumber.add(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ public void testAddZero() {
+ BigDecimal val = new BigDecimal("123456789");
+ BigDecimal sum = val.add(BigDecimal.ZERO);
+ assertEquals(val, sum);
+ sum = BigDecimal.ZERO.add(val);
+ assertEquals(val, sum);
+ val = BigDecimal.valueOf(0L, 1);
+ sum = val.add(BigDecimal.ZERO);
+ assertEquals(val, sum);
+ }
+
+
+ /**
+ * Test the the approximate scale is computed correctly.
+ * <p>
+ * See https://issues.apache.org/jira/browse/HARMONY-6406
+ */
+ public void testApproxScale() {
+ BigDecimal decVal = BigDecimal.TEN.multiply(new BigDecimal("0.1"));
+ int compare = decVal.compareTo(new BigDecimal("1.00"));
+ assertEquals(0, compare);
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal).
+ */
+ public void testDivideAndRemainder1() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ String res = "277923185514690367474770683";
+ int resScale = 0;
+ String rem = "1.3032693871288309587558885943391070087960319452465789990E-15";
+ int remScale = 70;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal).
+ */
+ public void testDivideAndRemainder2() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ String res = "2779231855146903674747706830969461168692256919247547952"
+ + "2608549363170374005512836303475980101168105698072946555" + "6862849";
+ int resScale = 0;
+ String rem = "3.4935796954060524114470681810486417234751682675102093970E-15";
+ int remScale = 70;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal, MathContext).
+ */
+ public void testDivideAndRemainderMathContextDOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 20;
+ int precision = 15;
+ RoundingMode rm = RoundingMode.DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "0E-25";
+ int resScale = 25;
+ String rem = "3736186567876.876578956958765675671119238118911893939591735";
+ int remScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal, MathContext).
+ */
+ public void testDivideAndRemainderMathContextUP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "277923185514690367474770683";
+ int resScale = 0;
+ String rem = "1.3032693871288309587558885943391070087960319452465789990E-15";
+ int remScale = 70;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * Divide to BigDecimal.
+ */
+ public void testDivideBigDecimal1() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "-5E+4";
+ int resScale = -4;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide to BigDecimal.
+ */
+ public void testDivideBigDecimal2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = -15;
+ String c = "-5E-26";
+ int resScale = 26;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextCEILING() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "4.98978611802562512996E+70";
+ int resScale = -50;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextDOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "4.98978611802562512995E+70";
+ int resScale = -50;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextFLOOR() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.FLOOR;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "4.98978611802562512995E+70";
+ int resScale = -50;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.77923185514690367475E+26";
+ int resScale = -6;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextHALF_EVEN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.HALF_EVEN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.77923185514690367475E+26";
+ int resScale = -6;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.77923185514690367475E+26";
+ int resScale = -6;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext).
+ */
+ public void testDivideBigDecimalScaleMathContextUP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 10;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.UP;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "49897861180.2562512996";
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeCEILING() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 100;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 45;
+ RoundingMode rm = RoundingMode.CEILING;
+ String c = "1E-45";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeDOWN() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 31;
+ RoundingMode rm = RoundingMode.DOWN;
+ String c = "-50000.0000000000000000000000000000000";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeFLOOR() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 100;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 45;
+ RoundingMode rm = RoundingMode.FLOOR;
+ String c = "0E-45";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 5;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 7;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ String c = "500002603731642864013619132621009722.1803810";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeHALF_EVEN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 5;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 7;
+ RoundingMode rm = RoundingMode.HALF_EVEN;
+ String c = "500002603731642864013619132621009722.1803810";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -51;
+ String b = "74723342238476237823787879183470";
+ int bScale = 45;
+ int newScale = 3;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ String c = "50000260373164286401361913262100972218038099522752460421"
+ + "05959924024355721031761947728703598332749334086415670525"
+ + "3761096961.670";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode).
+ */
+ public void testDivideBigDecimalScaleRoundingModeUP() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = -15;
+ int newScale = 31;
+ RoundingMode rm = RoundingMode.UP;
+ String c = "-5.00000E-26";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * Divide by zero.
+ */
+ public void testDivideByZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = BigDecimal.valueOf(0L);
+ try {
+ aNumber.divide(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Division by zero",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Divide with invalid rounding mode.
+ */
+ public void testDivideExceptionInvalidRM() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ try {
+ aNumber.divide(bNumber, 100);
+ fail("IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Improper exception message", "Invalid rounding mode",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Divide with ROUND_UNNECESSARY.
+ */
+ public void testDivideExceptionRM() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ try {
+ aNumber.divide(bNumber, BigDecimal.ROUND_UNNECESSARY);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Rounding necessary",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Divide: local variable exponent is equal to zero.
+ */
+ public void testDivideExpEqualsZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.64769459009933764189139568605273529E+40";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: local variable exponent is greater than zero.
+ */
+ public void testDivideExpGreaterZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 20;
+ String c = "1.647694590099337641891395686052735285121058381E+50";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: local variable exponent is less than zero.
+ */
+ public void testDivideExpLessZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.64770E+10";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * BigDecimal.divide with a scale that's too large.
+ *
+ * Regression test for HARMONY-6271
+ */
+ public void testDivideLargeScale() {
+ BigDecimal arg1 = new BigDecimal("320.0E+2147483647");
+ BigDecimal arg2 = new BigDecimal("6E-2147483647");
+ try {
+ arg1.divide(arg2, Integer.MAX_VALUE, RoundingMode.CEILING);
+ fail("Expected ArithmeticException when dividing with a scale that's too large");
+ } catch (ArithmeticException e) {
+ // expected behaviour
+ }
+ }
+
+ /**
+ * Divide: remainder is zero.
+ */
+ public void testDivideRemainderIsZero() {
+ String a = "8311389578904553209874735431110";
+ int aScale = -15;
+ String b = "237468273682987234567849583746";
+ int bScale = 20;
+ String c = "3.5000000000000000000000000000000E+36";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_CEILING, result is negative.
+ */
+ public void testDivideRoundCeilingNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_CEILING, result is positive.
+ */
+ public void testDivideRoundCeilingPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_DOWN, result is negative.
+ */
+ public void testDivideRoundDownNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_DOWN, result is positive.
+ */
+ public void testDivideRoundDownPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_FLOOR, result is negative.
+ */
+ public void testDivideRoundFloorNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_FLOOR);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_FLOOR, result is positive.
+ */
+ public void testDivideRoundFloorPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_FLOOR);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is negative;
+ * distance = -1.
+ */
+ public void testDivideRoundHalfDownNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is negative; distance = 1.
+ */
+ public void testDivideRoundHalfDownNeg1() {
+ String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; equidistant.
+ */
+ public void testDivideRoundHalfDownNeg2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "0E+5";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is positive;
+ * distance = -1.
+ */
+ public void testDivideRoundHalfDownPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is positive; distance = 1.
+ */
+ public void testDivideRoundHalfDownPos1() {
+ String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is negative;
+ * distance = -1.
+ */
+ public void testDivideRoundHalfEvenNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; distance = 1
+ */
+ public void testDivideRoundHalfEvenNeg1() {
+ String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; equidistant
+ */
+ public void testDivideRoundHalfEvenNeg2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "0E+5";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is positive; distance = -1
+ */
+ public void testDivideRoundHalfEvenPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is positive; distance = 1
+ */
+ public void testDivideRoundHalfEvenPos1() {
+ String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; distance = -1
+ */
+ public void testDivideRoundHalfUpNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; distance = 1
+ */
+ public void testDivideRoundHalfUpNeg1() {
+ String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; equidistant
+ */
+ public void testDivideRoundHalfUpNeg2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "-1E+5";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is positive; distance = -1
+ */
+ public void testDivideRoundHalfUpPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is positive; distance = 1
+ */
+ public void testDivideRoundHalfUpPos1() {
+ String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale,
+ BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_UP, result is negative
+ */
+ public void testDivideRoundUpNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_UP, result is positive
+ */
+ public void testDivideRoundUpPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ public void testDivideSmall() {
+ BigDecimal a = BigDecimal.valueOf(6);
+ BigDecimal b = BigDecimal.valueOf(2);
+ BigDecimal quotient = a.divide(b);
+ assertEquals("3", quotient.toString());
+ quotient = a.divideToIntegralValue(b);
+ assertEquals("3", quotient.toString());
+ quotient = a.divide(BigDecimal.ONE);
+ assertEquals("6", quotient.toString());
+ quotient = a.divide(BigDecimal.ONE.negate());
+ assertEquals("-6", quotient.toString());
+ }
+
+ /**
+ * divideToIntegralValue(BigDecimal)
+ */
+ public void testDivideToIntegralValue() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ String c = "277923185514690367474770683";
+ int resScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divideToIntegralValue(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divideToIntegralValue(BigDecimal, MathContext)
+ */
+ public void testDivideToIntegralValueMathContextDOWN() {
+ String a = "3736186567876876578956958769675785435673453453653543654354365435675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.7792318551469036747477068339450205874992634417590178670822889E+62";
+ int resScale = -1;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divideToIntegralValue(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divideToIntegralValue(BigDecimal, MathContext)
+ */
+ public void testDivideToIntegralValueMathContextUP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 32;
+ RoundingMode rm = RoundingMode.UP;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "277923185514690367474770683";
+ int resScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divideToIntegralValue(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ public void testDivideZero() {
+ BigDecimal quotient = BigDecimal.ZERO.divide(BigDecimal.ONE);
+ assertEquals(BigDecimal.ZERO, quotient);
+ quotient = BigDecimal.ZERO.negate().divide(BigDecimal.ONE);
+ assertEquals(BigDecimal.ZERO, quotient);
+ try {
+ quotient = BigDecimal.ZERO.divide(BigDecimal.ZERO);
+ fail("Expected ArithmeticException, divide by zero");
+ } catch (ArithmeticException expected) {
+ }
+ assertEquals(BigDecimal.ZERO, quotient);
+ try {
+ quotient = BigDecimal.ONE.divide(BigDecimal.ZERO);
+ fail("Expected ArithmeticException, divide by zero");
+ } catch (ArithmeticException expected) {
+ }
+ try {
+ quotient = BigDecimal.ONE.divideToIntegralValue(BigDecimal.ZERO);
+ fail("Expected ArithmeticException, divide by zero");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * Multiply two numbers of different scales
+ */
+ public void testMultiplyDiffScaleNegPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "9.20003122862175749786430095741145455670101391569026662845893091880727173060570190220616E+91";
+ int cScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales
+ */
+ public void testMultiplyDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "920003122862175749786430095741145455670101391569026662845893091880727173060570190220616";
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of negative scales
+ */
+ public void testMultiplyEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "9.20003122862175749786430095741145455670101391569026662845893091880727173060570190220616E+111";
+ int cScale = -25;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales using MathContext
+ */
+ public void testMultiplyMathContextDiffScaleNegPos() {
+ String a = "488757458676796558668876576576579097029810457634781384756794987";
+ int aScale = -63;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 63;
+ String c = "3.6521591193960361339707130098174381429788164316E+98";
+ int cScale = -52;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(47, RoundingMode.HALF_UP);
+ BigDecimal result = aNumber.multiply(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales using MathContext
+ */
+ public void testMultiplyMathContextDiffScalePosNeg() {
+ String a = "987667796597975765768768767866756808779810457634781384756794987";
+ int aScale = 100;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -70;
+ String c = "7.3801839465418518653942222612429081498248509257207477E+68";
+ int cScale = -16;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(53, RoundingMode.HALF_UP);
+ BigDecimal result = aNumber.multiply(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of positive scales using MathContext
+ */
+ public void testMultiplyMathContextScalePosPos() {
+ String a = "97665696756578755423325476545428779810457634781384756794987";
+ int aScale = -25;
+ String b = "87656965586786097685674786576598865";
+ int bScale = 10;
+ String c = "8.561078619600910561431314228543672720908E+108";
+ int cScale = -69;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(40, RoundingMode.HALF_DOWN);
+ BigDecimal result = aNumber.multiply(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of positive scales
+ */
+ public void testMultiplyScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "92000312286217574978643009574114545567010139156902666284589309.1880727173060570190220616";
+ int cScale = 25;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * pow(int)
+ */
+ public void testPow() {
+ String a = "123121247898748298842980";
+ int aScale = 10;
+ int exp = 10;
+ String c = "8004424019039195734129783677098845174704975003788210729597"
+ + "4875206425711159855030832837132149513512555214958035390490"
+ + "798520842025826.594316163502809818340013610490541783276343"
+ + "6514490899700151256484355936102754469438371850240000000000";
+ int cScale = 100;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.pow(exp);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * pow(0)
+ */
+ public void testPow0() {
+ String a = "123121247898748298842980";
+ int aScale = 10;
+ int exp = 0;
+ String c = "1";
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.pow(exp);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * pow(int, MathContext)
+ */
+ public void testPowMathContext() {
+ String a = "123121247898748298842980";
+ int aScale = 10;
+ int exp = 10;
+ String c = "8.0044E+130";
+ int cScale = -126;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
+ BigDecimal result = aNumber.pow(exp, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal)
+ */
+ public void testRemainder1() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ String res = "3736186567876.876578956958765675671119238118911893939591735";
+ int resScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal)
+ */
+ public void testRemainder2() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ String res = "1149310942946292909508821656680979993738625937.2065885780";
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal, MathContext)
+ */
+ public void testRemainderMathContextHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "1149310942946292909508821656680979993738625937.2065885780";
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal, MathContext)
+ */
+ public void testRemainderMathContextHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ int precision = 15;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3736186567876.876578956958765675671119238118911893939591735";
+ int resScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * round(BigDecimal, MathContext)
+ */
+ public void testRoundMathContextHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3.736186567876876578956958765675671119238118911893939591735E+102";
+ int resScale = -45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.round(mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * round(BigDecimal, MathContext)
+ */
+ public void testRoundMathContextHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ int precision = 15;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3736186567876.88";
+ int resScale = 2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.round(mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * round(BigDecimal, MathContext) when precision = 0
+ */
+ public void testRoundMathContextPrecision0() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ int precision = 0;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3736186567876.876578956958765675671119238118911893939591735";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.round(mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", aScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales; the first is negative
+ */
+ public void testSubtractDiffScaleNegPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1231212478987482988429808779810457634781310033452057698121208165201.2765435432";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales; the first is positive
+ */
+ public void testSubtractDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "-7472334291698975400195996883915836900189542365.218615243205013";
+ int cScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of equal negative scales
+ */
+ public void testSubtractEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "1.231212478987482241196379486791669716433397522230419E+61";
+ int cScale = -10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of equal positive scales
+ */
+ public void testSubtractEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "123121247898748224119637948679166971643339.7522230419";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales using MathContext; the first is
+ * negative
+ */
+ public void testSubtractMathContextDiffScaleNegPos() {
+ String a = "986798656676789766678767876078779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 40;
+ String c = "9.867986566767897666787678760787798104576347813847567949870000000000000E+71";
+ int cScale = -2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(70, RoundingMode.HALF_DOWN);
+ BigDecimal result = aNumber.subtract(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales using MathContext; the first is
+ * positive
+ */
+ public void testSubtractMathContextDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "-7.4723342916989754E+45";
+ int cScale = -29;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(17, RoundingMode.DOWN);
+ BigDecimal result = aNumber.subtract(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of equal positive scales using MathContext
+ */
+ public void testSubtractMathContextEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.23121247898749E+41";
+ int cScale = -27;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(15, RoundingMode.CEILING);
+ BigDecimal result = aNumber.subtract(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * ulp() of a negative BigDecimal
+ */
+ public void testUlpNeg() {
+ String a = "-3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.ulp();
+ String res = "1E-45";
+ int resScale = 45;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * ulp() of a positive BigDecimal
+ */
+ public void testUlpPos() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.ulp();
+ String res = "1E+45";
+ int resScale = -45;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * ulp() of a negative BigDecimal
+ */
+ public void testUlpZero() {
+ String a = "0";
+ int aScale = 2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.ulp();
+ String res = "0.01";
+ int resScale = 2;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * ZERO.pow(0)
+ */
+ public void testZeroPow0() {
+ String c = "1";
+ int cScale = 0;
+ BigDecimal result = BigDecimal.ZERO.pow(0);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java
new file mode 100644
index 0000000..d91f5b1
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java
@@ -0,0 +1,529 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+/**
+ * Class: java.math.BigDecimal Methods: abs, compareTo, equals, hashCode, max,
+ * min, negate, signum.
+ */
+public class BigDecimalCompareTest extends EmulTestBase {
+
+ /**
+ * Abs(MathContext) of a negative BigDecimal.
+ */
+ public void testAbsMathContextNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int precision = 15;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String result = "1.23809648392385E+53";
+ int resScale = -39;
+ BigDecimal res = aNumber.abs(mc);
+ assertEquals("incorrect value", result, res.toString());
+ assertEquals("incorrect scale", resScale, res.scale());
+ }
+
+ /**
+ * Abs(MathContext) of a positive BigDecimal.
+ */
+ public void testAbsMathContextPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int precision = 41;
+ RoundingMode rm = RoundingMode.HALF_EVEN;
+ MathContext mc = new MathContext(precision, rm);
+ String result = "1.2380964839238475457356735674573563567890E+53";
+ int resScale = -13;
+ BigDecimal res = aNumber.abs(mc);
+ assertEquals("incorrect value", result, res.toString());
+ assertEquals("incorrect scale", resScale, res.scale());
+ }
+
+ /**
+ * Abs() of a negative BigDecimal.
+ */
+ public void testAbsNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "123809648392384754573567356745735635678902957849027687.87678287";
+ assertEquals("incorrect value", result, aNumber.abs().toString());
+ }
+
+ /**
+ * Abs() of a positive BigDecimal.
+ */
+ public void testAbsPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "123809648392384754573567356745735635678902957849027687.87678287";
+ assertEquals("incorrect value", result, aNumber.abs().toString());
+ }
+
+ /**
+ * Compare to a number of an equal scale.
+ */
+ public void testCompareEqualScale1() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 18;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = 1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an equal scale.
+ */
+ public void testCompareEqualScale2() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 18;
+ String b = "4573563923487289357829759278282992758247567890295784902768787678287";
+ int bScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = -1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an greater scale.
+ */
+ public void testCompareGreaterScale1() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 28;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = 1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an greater scale.
+ */
+ public void testCompareGreaterScale2() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 48;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = -1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an less scale.
+ */
+ public void testCompareLessScale1() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 18;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 28;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = 1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an less scale.
+ */
+ public void testCompareLessScale2() {
+ String a = "12380964839238475457356735674573";
+ int aScale = 36;
+ String b = "45735635948573894578349572001798379183767890295784902768787678287";
+ int bScale = 48;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = -1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * equals() for equal BigDecimals.
+ */
+ public void testEqualsEqual() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertEquals(aNumber, bNumber);
+ }
+
+ /**
+ * equals() for equal BigDecimals.
+ */
+ public void testEqualsNull() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertFalse(aNumber.equals(null));
+ }
+
+ /**
+ * Equals() for unequal BigDecimals.
+ */
+ public void testEqualsUnequal1() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertFalse(aNumber.equals(bNumber));
+ }
+
+ /**
+ * Equals() for unequal BigDecimals.
+ */
+ public void testEqualsUnequal2() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = 13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertFalse(aNumber.equals(bNumber));
+ }
+
+ /**
+ * Equals() for unequal BigDecimals.
+ */
+ public void testEqualsUnequal3() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertFalse(aNumber.equals(b));
+ }
+
+ /**
+ * hashCode() for equal BigDecimals.
+ */
+ public void testHashCodeEqual() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertEquals("incorrect value", aNumber.hashCode(), bNumber.hashCode());
+ }
+
+ /**
+ * hashCode() for unequal BigDecimals.
+ */
+ public void testHashCodeUnequal() {
+ String a = "8478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertTrue("incorrect value", aNumber.hashCode() != bNumber.hashCode());
+ }
+
+ /**
+ * max() for equal BigDecimals.
+ */
+ public void testMaxEqual() {
+ String a = "8478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "8478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "8478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+ }
+
+ /**
+ * max() for unequal BigDecimals.
+ */
+ public void testMaxUnequal1() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+ }
+
+ /**
+ * max() for unequal BigDecimals.
+ */
+ public void testMaxUnequal2() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "94488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+ }
+
+ /**
+ * min() for equal BigDecimals.
+ */
+ public void testMinEqual() {
+ String a = "8478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "8478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "8478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+ }
+
+ /**
+ * min() for unequal BigDecimals.
+ */
+ public void testMinUnequal1() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+ }
+
+ /**
+ * min() for unequal BigDecimals.
+ */
+ public void testMinUnequal2() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "94488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "94488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+ }
+
+ /**
+ * negate(MathContext) for a negative BigDecimal.
+ */
+ public void testNegateMathContextNegative() {
+ if (!GWT.isScript()) {
+ // OpenJDK fails this test, so for now we only run it in web mode
+ return;
+ }
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 49;
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "9294878209448847823.121247898748298842980877981";
+ int cScale = 27;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.negate(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * negate(MathContext) for a positive BigDecimal.
+ */
+ public void testNegateMathContextPositive() {
+ if (!GWT.isScript()) {
+ // OpenJDK fails this test, so for now we only run it in web mode
+ return;
+ }
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ int precision = 37;
+ RoundingMode rm = RoundingMode.FLOOR;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "-929487820944884782312124789.8748298842";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.negate(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * negate() for a negative BigDecimal.
+ */
+ public void testNegateNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.negate());
+ }
+
+ /**
+ * negate() for a positive BigDecimal.
+ */
+ public void testNegatePositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.negate());
+ }
+
+ /**
+ * plus(MathContext) for a negative BigDecimal.
+ */
+ public void testPlusMathContextNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 49;
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "-9294878209448847823.121247898748298842980877981";
+ int cScale = 27;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.plus(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * plus(MathContext) for a positive BigDecimal.
+ */
+ public void testPlusMathContextPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ int precision = 37;
+ RoundingMode rm = RoundingMode.FLOOR;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "929487820944884782312124789.8748298842";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.plus(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * plus() for a negative BigDecimal.
+ */
+ public void testPlusNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.plus());
+ }
+
+ /**
+ * plus() for a positive BigDecimal.
+ */
+ public void testPlusPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.plus());
+ }
+
+ /**
+ * signum() for a negative BigDecimal.
+ */
+ public void testSignumNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertEquals("incorrect value", -1, aNumber.signum());
+ }
+
+ /**
+ * signum() for a positive BigDecimal.
+ */
+ public void testSignumPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertEquals("incorrect value", 1, aNumber.signum());
+ }
+
+ /**
+ * signum() for zero.
+ */
+ public void testSignumZero() {
+ String a = "0";
+ int aScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertEquals("incorrect value", 0, aNumber.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java
new file mode 100644
index 0000000..66fe6ba
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java
@@ -0,0 +1,763 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+/**
+ * Class: java.math.BigDecimal Methods: constructors and fields.
+ */
+public class BigDecimalConstructorsTest extends EmulTestBase {
+
+ /**
+ * new BigDecimal(BigInteger value).
+ */
+ public void testConstrBI() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ BigDecimal aNumber = new BigDecimal(bA);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", 0, aNumber.scale());
+
+ try {
+ new BigDecimal((BigInteger) null);
+ fail("No NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * new BigDecimal(BigInteger value, MathContext).
+ */
+ public void testConstrBigIntegerMathContext() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "1231212478987482988429808779810457634781384757";
+ int resScale = -6;
+ BigDecimal result = new BigDecimal(bA, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(BigInteger value, int scale, MathContext).
+ */
+ public void testConstrBigIntegerScaleMathContext() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ int aScale = 10;
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "1231212478987482988429808779810457634781384757";
+ int resScale = 4;
+ BigDecimal result = new BigDecimal(bA, aScale, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(BigInteger value, int scale).
+ */
+ public void testConstrBIScale() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ int aScale = 10;
+ BigDecimal aNumber = new BigDecimal(bA, aScale);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(char[] value).
+ */
+ public void testConstrChar() {
+ char value[] = {
+ '-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4',
+ '2', '3'};
+ BigDecimal result = new BigDecimal(value);
+ String res = "-1.23804738E-419";
+ int resScale = 427;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {});
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len).
+ */
+ public void testConstrCharIntInt() {
+ char value[] = {
+ '-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4',
+ '2', '3'};
+ int offset = 3;
+ int len = 12;
+ BigDecimal result = new BigDecimal(value, offset, len);
+ String res = "3.804738E-40";
+ int resScale = 46;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {}, 0, 0);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len, MathContext mc).
+ */
+ public void testConstrCharIntIntMathContext() {
+ char value[] = {
+ '-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4',
+ '2', '3'};
+ int offset = 3;
+ int len = 12;
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ BigDecimal result = new BigDecimal(value, offset, len, mc);
+ String res = "3.805E-40";
+ int resScale = 43;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {}, 0, 0, MathContext.DECIMAL32);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len, MathContext mc).
+ */
+ public void testConstrCharIntIntMathContextException1() {
+ char value[] = {
+ '-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4',
+ '2', '3'};
+ int offset = 3;
+ int len = 120;
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ try {
+ new BigDecimal(value, offset, len, mc);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len, MathContext mc).
+ */
+ public void testConstrCharIntIntMathContextException2() {
+ char value[] = {
+ '-', '1', '2', '3', '8', '0', ',', '4', '7', '3', '8', 'E', '-', '4',
+ '2', '3'};
+ int offset = 3;
+ int len = 120;
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ try {
+ new BigDecimal(value, offset, len, mc);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, MathContext mc).
+ */
+ public void testConstrCharMathContext() {
+ char value[] = {
+ '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2'
+ };
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ BigDecimal result = new BigDecimal(value, mc);
+ String res = "3.805E-40";
+ int resScale = 43;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ // Regression for HARMONY-783
+ try {
+ new BigDecimal(new char[] {}, MathContext.DECIMAL32);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(double value).
+ */
+ public void testConstrDouble() {
+ double a = 732546982374982347892379283571094797.287346782359284756;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal expected = new BigDecimal(
+ "732546982374982347892379283571094797.287346782359284756");
+ assertEquals(expected, aNumber, 1e21);
+ }
+
+ /**
+ * new BigDecimal(0.1).
+ */
+ public void testConstrDouble01() {
+ double a = 1.E-1;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal expected = new BigDecimal(
+ ".1000000000000000055511151231257827021181583404541015625");
+ assertEquals(expected, aNumber, 1e-9);
+ }
+
+ /**
+ * new BigDecimal(0.555).
+ */
+ public void testConstrDouble02() {
+ double a = 0.555;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal expected = new BigDecimal(
+ ".55500000000000004884981308350688777863979339599609375");
+ assertEquals(expected, aNumber, 1e-8);
+ }
+
+ /**
+ * new BigDecimal(double value) when value is denormalized.
+ */
+ @DoNotRunWith(Platform.HtmlUnit)
+ public void testConstrDoubleDenormalized() {
+ // HtmlUnit incorrectly converts the following double to a string
+ // Safari can't handle e-309 here
+ double a = 2.274341322658976E-304;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal expected = new BigDecimal(
+ "2.274341322658976E-304");
+ assertEquals(expected, aNumber, 1e-305);
+ }
+
+ /**
+ * new BigDecimal(double, MathContext).
+ */
+ public void testConstrDoubleMathContext() {
+ double a = 732546982374982347892379283571094797.287346782359284756;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ BigDecimal result = new BigDecimal(a, mc);
+ BigDecimal expected = new BigDecimal("732546982374982e21");
+ assertEquals(expected, result, 1e21);
+ try {
+ new BigDecimal(Double.NaN);
+ fail("Expected NumberFormatException on NaN");
+ } catch (NumberFormatException expectedException) {
+ }
+ try {
+ new BigDecimal(Double.POSITIVE_INFINITY);
+ fail("Expected NumberFormatException on +Infinity");
+ } catch (NumberFormatException expectedException) {
+ }
+ try {
+ new BigDecimal(Double.NEGATIVE_INFINITY);
+ fail("Expected NumberFormatException on -Infinity");
+ } catch (NumberFormatException expectedException) {
+ }
+ }
+
+ /**
+ * new BigDecimal(-0.1).
+ */
+ public void testConstrDoubleMinus01() {
+ double a = -1.E-1;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal expected = new BigDecimal(
+ "-.1000000000000000055511151231257827021181583404541015625");
+ assertEquals(expected, aNumber, 1e-9);
+ }
+
+ /**
+ * new BigDecimal(double value) when value is NaN.
+ */
+ public void testConstrDoubleNaN() {
+ double a = Double.NaN;
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Infinite or NaN",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * new BigDecimal(double value) when value is positive infinity.
+ */
+ public void testConstrDoubleNegInfinity() {
+ double a = Double.NEGATIVE_INFINITY;
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Infinite or NaN",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * new BigDecimal(double value) when value is positive infinity.
+ */
+ public void testConstrDoublePosInfinity() {
+ double a = Double.POSITIVE_INFINITY;
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Infinite or NaN",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * new BigDecimal(int value).
+ */
+ public void testConstrInt() {
+ int a = 732546982;
+ String res = "732546982";
+ int resScale = 0;
+ BigDecimal result = new BigDecimal(a);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(int, MathContext).
+ */
+ public void testConstrIntMathContext() {
+ int a = 732546982;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "732546982";
+ int resScale = 0;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(long value).
+ */
+ public void testConstrLong() {
+ long a = 4576578677732546982L;
+ String res = "4576578677732546982";
+ int resScale = 0;
+ BigDecimal result = new BigDecimal(a);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(long, MathContext).
+ */
+ public void testConstrLongMathContext() {
+ long a = 4576578677732546982L;
+ int precision = 5;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "45766";
+ int resScale = -14;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(String value) when value is not a valid representation of
+ * BigDecimal.
+ */
+ public void testConstrStringException() {
+ String a = "-238768.787678287a+10";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is empty.
+ */
+ public void testConstrStringExceptionEmptyExponent1() {
+ String a = "-238768.787678287e";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is empty.
+ */
+ public void testConstrStringExceptionEmptyExponent2() {
+ String a = "-238768.787678287e-";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is greater than
+ * Integer.MAX_VALUE.
+ */
+ public void testConstrStringExceptionExponentGreaterIntegerMax() {
+ String a = "-238768.787678287e214748364767876";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is less than Integer.MIN_VALUE.
+ */
+ public void testConstrStringExceptionExponentLessIntegerMin() {
+ String a = "-238768.787678287e-214748364767876";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is Integer.MAX_VALUE.
+ */
+ public void testConstrStringExponentIntegerMax() {
+ String a = "-238768.787678287e2147483647";
+ int aScale = -2147483638;
+ BigInteger bA = new BigInteger("-238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is Integer.MIN_VALUE.
+ */
+ public void testConstrStringExponentIntegerMin() {
+ String a = ".238768e-2147483648";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Scale out of range.",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * new BigDecimal(String value, MathContext).
+ */
+ public void testConstrStringMathContext() {
+ String a = "-238768787678287e214";
+ int precision = 5;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "-23876";
+ int resScale = -224;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent and does not contain
+ * decimal point.
+ */
+ public void testConstrStringWithExponentWithoutPoint1() {
+ String a = "-238768787678287e214";
+ int aScale = -214;
+ BigInteger bA = new BigInteger("-238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent and does not contain
+ * decimal point.
+ */
+ public void testConstrStringWithExponentWithoutPoint2() {
+ String a = "-238768787678287e-214";
+ int aScale = 214;
+ BigInteger bA = new BigInteger("-238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent and does not contain
+ * decimal point.
+ */
+ public void testConstrStringWithExponentWithoutPoint3() {
+ String a = "238768787678287e-214";
+ int aScale = 214;
+ BigInteger bA = new BigInteger("238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent and does not contain
+ * decimal point.
+ */
+ public void testConstrStringWithExponentWithoutPoint4() {
+ String a = "238768787678287e+214";
+ int aScale = -214;
+ BigInteger bA = new BigInteger("238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent and does not contain
+ * decimal point.
+ */
+ public void testConstrStringWithExponentWithoutPoint5() {
+ String a = "238768787678287E214";
+ int aScale = -214;
+ BigInteger bA = new BigInteger("238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains both exponent and decimal
+ * point.
+ */
+ public void testConstrStringWithExponentWithPoint1() {
+ String a = "23985439837984782435652424523876878.7678287e+214";
+ int aScale = -207;
+ BigInteger bA = new BigInteger("239854398379847824356524245238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains both exponent and decimal
+ * point.
+ */
+ public void testConstrStringWithExponentWithPoint2() {
+ String a = "238096483923847545735673567457356356789029578490276878.7678287e-214";
+ int aScale = 221;
+ BigInteger bA = new BigInteger(
+ "2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains both exponent and decimal
+ * point.
+ */
+ public void testConstrStringWithExponentWithPoint3() {
+ String a = "2380964839238475457356735674573563567890.295784902768787678287E+21";
+ int aScale = 0;
+ BigInteger bA = new BigInteger(
+ "2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains both exponent and decimal
+ * point.
+ */
+ public void testConstrStringWithExponentWithPoint4() {
+ String a = "23809648392384754573567356745735635678.90295784902768787678287E+21";
+ int aScale = 2;
+ BigInteger bA = new BigInteger(
+ "2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains both exponent and decimal
+ * point.
+ */
+ public void testConstrStringWithExponentWithPoint5() {
+ String a = "238096483923847545735673567457356356789029.5784902768787678287E+21";
+ int aScale = -2;
+ BigInteger bA = new BigInteger(
+ "2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent.
+ */
+ public void testConstrStringWithoutExpNeg() {
+ String a = "-732546982374982347892379283571094797.287346782359284756";
+ int aScale = 18;
+ BigInteger bA = new BigInteger(
+ "-732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent.
+ */
+ public void testConstrStringWithoutExpPos1() {
+ String a = "732546982374982347892379283571094797.287346782359284756";
+ int aScale = 18;
+ BigInteger bA = new BigInteger(
+ "732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent.
+ */
+ public void testConstrStringWithoutExpPos2() {
+ String a = "+732546982374982347892379283571094797.287346782359284756";
+ int aScale = 18;
+ BigInteger bA = new BigInteger(
+ "732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent and decimal
+ * point.
+ */
+ public void testConstrStringWithoutExpWithoutPoint() {
+ String a = "-732546982374982347892379283571094797287346782359284756";
+ int aScale = 0;
+ BigInteger bA = new BigInteger(
+ "-732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * check ONE.
+ */
+ public void testFieldONE() {
+ String oneS = "1";
+ double oneD = 1.0;
+ assertEquals("incorrect string value", oneS, BigDecimal.ONE.toString());
+ assertEquals("incorrect double value", oneD, BigDecimal.ONE.doubleValue(),
+ 0);
+ }
+
+ /**
+ * check TEN.
+ */
+ public void testFieldTEN() {
+ String oneS = "10";
+ double oneD = 10.0;
+ assertEquals("incorrect string value", oneS, BigDecimal.TEN.toString());
+ assertEquals("incorrect double value", oneD, BigDecimal.TEN.doubleValue(),
+ 0);
+ }
+
+ /**
+ * check ZERO.
+ */
+ public void testFieldZERO() {
+ String oneS = "0";
+ double oneD = 0.0;
+ assertEquals("incorrect string value", oneS, BigDecimal.ZERO.toString());
+ assertEquals("incorrect double value", oneD, BigDecimal.ZERO.doubleValue(),
+ 0);
+ }
+
+ private void assertEquals(BigDecimal expected, BigDecimal actual,
+ double delta) {
+ BigDecimal actualDeltaDecimal = actual.subtract(expected);
+ double actualDelta = actualDeltaDecimal.abs().doubleValue();
+ if (actualDelta >= delta) {
+ fail("expected=" + expected + " actual=" + actual + " delta="
+ + actualDelta);
+ }
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalConvertTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalConvertTest.java
new file mode 100644
index 0000000..0547078
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalConvertTest.java
@@ -0,0 +1,656 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigDecimal. Methods: doubleValue, floatValue, intValue,
+ * longValue, valueOf, toString, toBigInteger
+ */
+public class BigDecimalConvertTest extends EmulTestBase {
+
+ public void testByteValue() {
+ assertEquals((byte) 1, BigDecimal.ONE.byteValue());
+ assertEquals((byte) -1, BigDecimal.valueOf(255).byteValue());
+ assertEquals((byte) 1, BigDecimal.ONE.byteValueExact());
+ try {
+ BigDecimal.valueOf(255).byteValueExact();
+ fail("Expected ArithmeticException on byteValueExact(255)");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * Double value of a small negative BigDecimal.
+ */
+ // TODO(jat): add back after Double.doubleToLongBits is implemented
+// public void testDoubleValueMinusZero() {
+// String a = "-123809648392384754573567356745735.63567890295784902768787678287E-400";
+// BigDecimal aNumber = new BigDecimal(a);
+// long minusZero = -9223372036854775808L;
+// double result = aNumber.doubleValue();
+// assertTrue("incorrect value", Double.doubleToLongBits(result) == minusZero);
+// }
+
+ /**
+ * Double value of a negative BigDecimal.
+ */
+ public void testDoubleValueNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = -1.2380964839238476E53;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a large negative BigDecimal.
+ */
+ public void testDoubleValueNegInfinity() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+400";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = Double.NEGATIVE_INFINITY;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a small positive BigDecimal.
+ */
+ // TODO(jat): add back after Double.doubleToLongBits is implemented
+// public void testDoubleValuePlusZero() {
+// String a = "123809648392384754573567356745735.63567890295784902768787678287E-400";
+// BigDecimal aNumber = new BigDecimal(a);
+// long zero = 0;
+// double result = aNumber.doubleValue();
+// assertTrue("incorrect value", Double.doubleToLongBits(result) == zero);
+// }
+
+ /**
+ * Double value of a positive BigDecimal.
+ */
+ public void testDoubleValuePos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = 1.2380964839238476E53;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a large positive BigDecimal.
+ */
+ public void testDoubleValuePosInfinity() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+400";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = Double.POSITIVE_INFINITY;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Float value of a small negative BigDecimal.
+ */
+ // TODO(jat): add back after Float.floatToIntBits is implemented
+// public void testFloatValueMinusZero() {
+// String a = "-123809648392384754573567356745735.63567890295784902768787678287E-400";
+// BigDecimal aNumber = new BigDecimal(a);
+// int minusZero = -2147483648;
+// float result = aNumber.floatValue();
+// assertTrue("incorrect value", Float.floatToIntBits(result) == minusZero);
+// }
+
+ /**
+ * Float value of a negative BigDecimal.
+ */
+ public void testFloatValueNeg() {
+ String a = "-1238096483923847.6356789029578E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = -1.2380965E36F;
+ // Use range rather than exact value check, since GWT uses doubles anyway
+ assertEquals("incorrect value", aNumber.floatValue(), result, 1E29);
+ }
+
+ /**
+ * Float value of a large negative BigDecimal.
+ */
+ public void testFloatValueNegInfinity() {
+ String a = "-123809648392384755735.63567887678287E+200";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = Float.NEGATIVE_INFINITY;
+ assertTrue("incorrect value", aNumber.floatValue() == result);
+ }
+
+ /**
+ * Float value of a small positive BigDecimal.
+ */
+ // TODO(jat): add back after Float.floatToIntBits is implemented
+// public void testFloatValuePlusZero() {
+// String a = "123809648392384754573567356745735.63567890295784902768787678287E-400";
+// BigDecimal aNumber = new BigDecimal(a);
+// int zero = 0;
+// float result = aNumber.floatValue();
+// assertTrue("incorrect value", Float.floatToIntBits(result) == zero);
+// }
+
+ /**
+ * Float value of a positive BigDecimal.
+ */
+ public void testFloatValuePos() {
+ String a = "1238096483923847.6356789029578E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = 1.2380965E36F;
+ // Use range rather than exact value check, since GWT uses doubles anyway
+ assertEquals("incorrect value", aNumber.floatValue(), result, 1E29);
+ }
+
+ /**
+ * Float value of a large positive BigDecimal.
+ */
+ public void testFloatValuePosInfinity() {
+ String a = "123809648373567356745735.6356789787678287E+200";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = Float.POSITIVE_INFINITY;
+ assertTrue("incorrect value", aNumber.floatValue() == result);
+ }
+
+ /**
+ * Integer value of a negative BigDecimal.
+ */
+ public void testIntValueNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int result = 218520473;
+ assertEquals("incorrect value", result, aNumber.intValue());
+ try {
+ aNumber.intValueExact();
+ fail("Expected ArithmeticException on intValueExact");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * Integer value of a positive BigDecimal.
+ */
+ public void testIntValuePos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int result = -218520473;
+ assertEquals("incorrect value", result, aNumber.intValue());
+ try {
+ aNumber.intValueExact();
+ fail("Expected ArithmeticException on intValueExact");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * Long value of a negative BigDecimal.
+ */
+ public void testLongValueNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ long result = -1246043477766677607L;
+ assertTrue("incorrect value", aNumber.longValue() == result);
+ try {
+ aNumber.longValueExact();
+ fail("Expected ArithmeticException on longValueExact");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * Long value of a positive BigDecimal.
+ */
+ public void testLongValuePos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ long result = 1246043477766677607L;
+ assertTrue("incorrect value", aNumber.longValue() == result);
+ try {
+ aNumber.longValueExact();
+ fail("Expected ArithmeticException on longValueExact");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * scaleByPowerOfTen(int n).
+ */
+ public void testScaleByPowerOfTen1() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.scaleByPowerOfTen(10);
+ String res = "1231212478987482988429808779810457634781384756794.987";
+ int resScale = 3;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * scaleByPowerOfTen(int n).
+ */
+ public void testScaleByPowerOfTen2() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.scaleByPowerOfTen(10);
+ String res = "1.231212478987482988429808779810457634781384756794987E+74";
+ int resScale = -23;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ public void testShortValue() {
+ BigDecimal value = BigDecimal.valueOf(0x13fff);
+ assertEquals(0x3fff, value.shortValue());
+ try {
+ value.shortValueExact();
+ fail("Expected ArithmeticException");
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ /**
+ * toBigIntegerExact().
+ */
+ public void testToBigIntegerExact1() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+45";
+ BigDecimal aNumber = new BigDecimal(a);
+ String res = "-123809648392384754573567356745735635678902957849027687876782870000000000000000";
+ BigInteger result = aNumber.toBigIntegerExact();
+ assertEquals("incorrect value", res, result.toString());
+ }
+
+ /**
+ * toBigIntegerExact().
+ */
+ public void testToBigIntegerExactException() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-10";
+ BigDecimal aNumber = new BigDecimal(a);
+ try {
+ aNumber.toBigIntegerExact();
+ fail("java.lang.ArithmeticException has not been thrown");
+ } catch (java.lang.ArithmeticException e) {
+ return;
+ }
+ }
+
+ /**
+ * Convert a negative BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerNeg1() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigInteger bNumber = new BigInteger(
+ "-123809648392384754573567356745735635678902957849027687");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a negative BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerNeg2() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+15";
+ BigInteger bNumber = new BigInteger(
+ "-123809648392384754573567356745735635678902957849");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a negative BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerNeg3() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+45";
+ BigInteger bNumber = new BigInteger(
+ "-123809648392384754573567356745735635678902957849027687876782870000000000000000");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a positive BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerPos1() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigInteger bNumber = new BigInteger(
+ "123809648392384754573567356745735635678902957849027687");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a positive BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerPos2() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+15";
+ BigInteger bNumber = new BigInteger(
+ "123809648392384754573567356745735635678902957849");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a positive BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerPos3() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+45";
+ BigInteger bNumber = new BigInteger(
+ "123809648392384754573567356745735635678902957849027687876782870000000000000000");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a small BigDecimal to BigInteger.
+ */
+ public void testToBigIntegerZero() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-500";
+ BigInteger bNumber = new BigInteger("0");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a negative BigDecimal to an engineering string representation.
+ */
+ public void testToEngineeringStringNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-501";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-123.80964839238475457356735674573563567890295784902768787678287E-471";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a positive BigDecimal to an engineering string representation.
+ */
+ public void testToEngineeringStringPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-501";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "123.80964839238475457356735674573563567890295784902768787678287E-471";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal to an engineering string representation.
+ */
+ public void testToEngineeringStringZeroNegExponent() {
+ String a = "0.0E-16";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "0.00E-15";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal to an engineering string representation.
+ */
+ public void testToEngineeringStringZeroPosExponent() {
+ String a = "0.0E+16";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "0E+15";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal with a negative exponent to a plain string
+ * representation; scale == 0.
+ */
+ public void testToPlainStringNegNegExp() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-0.000000000000000000000000000000000000000000000000000000000000000000012380964839238475457356735674573563567890295784902768787678287";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a negative BigDecimal with a positive exponent to a plain string
+ * representation; scale == 0.
+ */
+ public void testToPlainStringNegPosExp() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-1238096483923847545735673567457356356789029578490276878767828700000000000000000000000000000000000000000000000000000000000000000000000";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a positive BigDecimal with a negative exponent to a plain string
+ * representation; scale == 0.
+ */
+ public void testToPlainStringPosNegExp() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "0.000000000000000000000000000000000000000000000000000000000000000000012380964839238475457356735674573563567890295784902768787678287";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a negative BigDecimal with a negative exponent to a plain string
+ * representation; scale == 0.
+ */
+ public void testToPlainStringPosPosExp() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "1238096483923847545735673567457356356789029578490276878767828700000000000000000000000000000000000000000000000000000000000000000000000";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a negative BigDecimal to a string representation.
+ */
+ public void testToStringNeg() {
+ String a = "-123.4564563673567380964839238475457356735674573563567890295784902768787678287E-5";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-0.001234564563673567380964839238475457356735674573563567890295784902768787678287";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Convert a positive BigDecimal to a string representation.
+ */
+ public void testToStringPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-500";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "1.2380964839238475457356735674573563567890295784902768787678287E-468";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Convert a BigDecimal to a string representation; scale == 0.
+ */
+ public void testToStringZeroScale() {
+ String a = "-123809648392384754573567356745735635678902957849027687876782870";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a));
+ String result = "-123809648392384754573567356745735635678902957849027687876782870";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * valueOf(Double.NaN).
+ */
+ public void testValueOfDoubleNaN() {
+ double a = Double.NaN;
+ try {
+ BigDecimal.valueOf(a);
+ fail("NumberFormatException has not been thrown for Double.NaN");
+ } catch (NumberFormatException e) {
+ return;
+ }
+ }
+
+ /**
+ * Create a BigDecimal from a negative double value.
+ */
+ public void testValueOfDoubleNeg() {
+ double a = -65678765876567576.98788767;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "-65678765876567576";
+ int resScale = 0;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a positive double value.
+ */
+ public void testValueOfDoublePos1() {
+ double a = 65678765876567576.98788767;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "65678765876567576";
+ int resScale = 0;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a positive double value.
+ */
+ public void testValueOfDoublePos2() {
+ double a = 12321237576.98788767;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "12321237576.987888";
+ int resScale = 6;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a positive double value.
+ */
+ public void testValueOfDoublePos3() {
+ double a = 12321237576.9878838;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "12321237576.98788";
+ int resScale = 6;
+ assertTrue("incorrect value", result.toString().startsWith(res));
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is negative.
+ */
+ public void testValueOfNegScaleNeg() {
+ long a = -98374823947823578L;
+ int scale = -12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "-9.8374823947823578E+28";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is positive.
+ */
+ public void testValueOfNegScalePos() {
+ long a = -98374823947823578L;
+ int scale = 12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "-98374.823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is 0.
+ */
+ public void testValueOfNegZeroScale() {
+ long a = -98374823947823578L;
+ BigDecimal aNumber = BigDecimal.valueOf(a);
+ String result = "-98374823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is negative.
+ */
+ public void testValueOfPosScaleNeg() {
+ long a = 98374823947823578L;
+ int scale = -12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "9.8374823947823578E+28";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is positive.
+ */
+ public void testValueOfPosScalePos() {
+ long a = 98374823947823578L;
+ int scale = 12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "98374.823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a positive long value; scale == 0.
+ */
+ public void testValueOfPosZeroScale() {
+ long a = 98374823947823578L;
+ BigDecimal aNumber = BigDecimal.valueOf(a);
+ String result = "98374823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a zero value; with a small negative scale.
+ */
+ public void testValueOfZeroScaleNeg() {
+ int scale = -2;
+ BigDecimal number = BigDecimal.valueOf(0L, scale);
+ assertEquals("incorrect value", "0E+2", number.toString());
+ assertEquals("bad scale", scale, number.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a zero value; with a small positive scale.
+ */
+ public void testValueOfZeroScalePos() {
+ int scale = 1;
+ BigDecimal number = BigDecimal.valueOf(0L, scale);
+ assertEquals("incorrect value", "0.0", number.toString());
+ assertEquals("bad scale", scale, number.scale());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalScaleOperationsTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalScaleOperationsTest.java
new file mode 100644
index 0000000..ab9a5c7
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalScaleOperationsTest.java
@@ -0,0 +1,377 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+
+/**
+ * Class: java.math.BigDecimal Methods: movePointLeft, movePointRight, scale,
+ * setScale, unscaledValue *
+ */
+public class BigDecimalScaleOperationsTest extends EmulTestBase {
+
+ public void testScaleByPowerOfTen() {
+ BigDecimal val = BigDecimal.ONE.scaleByPowerOfTen(1);
+ assertEquals(10, val.intValue());
+ }
+
+ /**
+ * Check the default scale
+ */
+ public void testScaleDefault() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a));
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check a negative scale
+ */
+ public void testScaleNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ int cScale = -10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check a positive scale
+ */
+ public void testScalePos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check the zero scale
+ */
+ public void testScaleZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 0;
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check the unscaled value
+ */
+ public void testUnscaledValue() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 100;
+ BigInteger bNumber = new BigInteger(a);
+ BigDecimal aNumber = new BigDecimal(bNumber, aScale);
+ assertTrue("incorrect unscaled value", aNumber.unscaledValue().equals(
+ bNumber));
+ }
+
+ /**
+ * Set a greater new scale
+ */
+ public void testSetScaleGreater() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 18;
+ int newScale = 28;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertEquals("incorrect value", 0, bNumber.compareTo(aNumber));
+ }
+
+ /**
+ * Set a less new scale; this.scale == 8; newScale == 5.
+ */
+ public void testSetScaleLess() {
+ String a = "2.345726458768760000E+10";
+ int newScale = 5;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal bNumber = aNumber.setScale(newScale);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertEquals("incorrect value", 0, bNumber.compareTo(aNumber));
+ }
+
+ /**
+ * Verify an exception when setting a new scale
+ */
+ public void testSetScaleException() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ try {
+ aNumber.setScale(newScale);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Rounding necessary",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Set the same new scale
+ */
+ public void testSetScaleSame() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 18;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.equals(aNumber));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundUp() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478139";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_UP);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundDown() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_DOWN);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundCeiling() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478139";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_CEILING);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundFloor() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_FLOOR);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundHalfUp() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_UP);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundHalfDown() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_DOWN);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundHalfEven() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_EVEN);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * SetScale(int, RoundingMode)
+ */
+ public void testSetScaleIntRoundingMode() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.setScale(newScale, RoundingMode.HALF_EVEN);
+ String res = "123121247898748298842980.877981045763478138";
+ int resScale = 18;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Move the decimal point to the left; the shift value is positive
+ */
+ public void testMovePointLeftPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = 18;
+ int resScale = 46;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointLeft(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the left; the shift value is positive
+ */
+ public void testMovePointLeftNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = -18;
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointLeft(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the right; the shift value is positive
+ */
+ public void testMovePointRightPosGreater() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = 18;
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointRight(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the right; the shift value is positive
+ */
+ public void testMovePointRightPosLess() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138475679498700";
+ int aScale = 28;
+ int shift = 30;
+ int resScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointRight(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Move the decimal point to the right; the shift value is positive
+ */
+ public void testMovePointRightNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = -18;
+ int resScale = 46;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointRight(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the right when the scale overflows
+ */
+ public void testMovePointRightException() {
+ String a = "12312124789874829887348723648726347429808779810457634781384756794987";
+ int aScale = Integer.MAX_VALUE; // 2147483647
+ int shift = -18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ try {
+ aNumber.movePointRight(shift);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Underflow", e.getMessage());
+ }
+ }
+
+ /**
+ * precision()
+ */
+ public void testPrecision() {
+ String a = "12312124789874829887348723648726347429808779810457634781384756794987";
+ int aScale = 14;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ int prec = aNumber.precision();
+ assertEquals(68, prec);
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerAddTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerAddTest.java
new file mode 100644
index 0000000..aa125d1
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerAddTest.java
@@ -0,0 +1,503 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: add
+ */
+public class BigIntegerAddTest extends EmulTestBase {
+
+ /**
+ * Add two positive numbers of the same length
+ */
+ public void testCase1() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two negative numbers of the same length
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length. The first one is positive and the
+ * second is negative. The first one is greater in absolute value.
+ */
+ public void testCase3() {
+ byte aBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {2, 2, 2, 2, 2, 2, 2};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length. The first one is negative and the
+ * second is positive. The first one is greater in absolute value.
+ */
+ public void testCase4() {
+ byte aBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {-3, -3, -3, -3, -3, -3, -2};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length. The first is positive and the second is
+ * negative. The first is less in absolute value.
+ */
+ public void testCase5() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte rBytes[] = {-3, -3, -3, -3, -3, -3, -2};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length. The first one is negative and the
+ * second is positive. The first one is less in absolute value.
+ */
+ public void testCase6() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte rBytes[] = {2, 2, 2, 2, 2, 2, 2};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two positive numbers of different length. The first is longer.
+ */
+ public void testCase7() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two positive numbers of different length. The second is longer.
+ */
+ public void testCase8() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aBytes);
+ BigInteger bNumber = new BigInteger(bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two negative numbers of different length. The first is longer.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two negative numbers of different length. The second is longer.
+ */
+ public void testCase10() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign. The first is positive. The
+ * first is longer.
+ */
+ public void testCase11() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign. The first is positive. The
+ * second is longer.
+ */
+ public void testCase12() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign. The first is negative. The
+ * first is longer.
+ */
+ public void testCase13() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign. The first is negative. The
+ * second is longer.
+ */
+ public void testCase14() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two equal numbers of different signs
+ */
+ public void testCase15() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {0};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Add zero to a number
+ */
+ public void testCase16() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {0};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add a number to zero
+ */
+ public void testCase17() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add zero to zero
+ */
+ public void testCase18() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ byte rBytes[] = {0};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Add ZERO to a number
+ */
+ public void testCase19() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add a number to zero
+ */
+ public void testCase20() {
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int bSign = 1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add ZERO to ZERO
+ */
+ public void testCase21() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Add ONE to ONE
+ */
+ public void testCase22() {
+ byte rBytes[] = {2};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two numbers so that carry is 1
+ */
+ public void testCase23() {
+ byte aBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ byte bBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerAndTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerAndTest.java
new file mode 100644
index 0000000..d1db148
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerAndTest.java
@@ -0,0 +1,475 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: and
+ */
+public class BigIntegerAndTest extends EmulTestBase {
+
+ /**
+ * And for two negative numbers; the first is longer
+ */
+ public void testNegNegFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88,
+ -88, 16, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * And for two negative numbers; the first is shorter
+ */
+ public void testNegNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88,
+ -88, 16, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * And for two negative numbers of the same length
+ */
+ public void testNegNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 1, 2, 3, 3, 0, 65, -96, -48, -124, -60, 12, -40, -31, 97};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * And for a negative number and zero
+ */
+ public void testNegPos() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = -1;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a negative and a positive numbers; the first is shorter
+ */
+ public void testNegPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31,
+ -95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two numbers of different signs and the same length
+ */
+ public void testNegPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, 125, -60, -104, 1, 10, 6, 2, 32, 56, 2, 4, 4, 21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for one and one
+ */
+ public void testOneOne() {
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.and(bNumber);
+ assertTrue(result.equals(BigInteger.ONE));
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a positive and a negative numbers; the first is longer
+ */
+ public void testPosNegFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {
+ 0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31,
+ -95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a positive and a negative numbers; the first is shorter
+ */
+ public void testPosNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two numbers of different signs and the same length
+ */
+ public void testPosNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {0, -6, -80, 72, 8, 75, 2, -79, 34, 16, -119};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two positive numbers; the first is longer
+ */
+ public void testPosPosFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -76, 88, 44, 1, 2, 17, 35, 16, 9, 2, 5, 6, 21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two positive numbers; the first is shorter
+ */
+ public void testPosPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -76, 88, 44, 1, 2, 17, 35, 16, 9, 2, 5, 6, 21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two positive numbers of the same length
+ */
+ public void testPosPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -128, 56, 100, 4, 4, 17, 37, 16, 1, 64, 1, 10, 3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a positive number and zero
+ */
+ public void testPosZero() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Test for a special case
+ */
+ public void testSpecialCase1() {
+ byte aBytes[] = {-1, -1, -1, -1};
+ byte bBytes[] = {5, -4, -3, -2};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Test for a special case
+ */
+ public void testSpecialCase2() {
+ byte aBytes[] = {-51};
+ byte bBytes[] = {-52, -51, -50, -49, -48};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0, -52, -51, -50, -49, 16};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for zero and a negative number
+ */
+ public void testZeroNeg() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for zero and one
+ */
+ public void testZeroOne() {
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.and(bNumber);
+ assertTrue(result.equals(BigInteger.ZERO));
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for zero and a positive number
+ */
+ public void testZeroPos() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for zero and zero
+ */
+ public void testZeroZero() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ int aSign = 0;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerCompareTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerCompareTest.java
new file mode 100644
index 0000000..8b56def
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerCompareTest.java
@@ -0,0 +1,530 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Methods: abs, compareTo, equals, max, min,
+ * negate, signum
+ */
+public class BigIntegerCompareTest extends EmulTestBase {
+ /**
+ * abs() for a negative number
+ */
+ public void testAbsNegative() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.abs();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * abs() for a positive number
+ */
+ public void testAbsPositive() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.abs();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two negative numbers. The first is less in
+ * absolute value.
+ */
+ public void testCompareNegNeg2() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two numbers of different signs. The first
+ * is positive.
+ */
+ public void testCompareToDiffSigns1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two numbers of different signs. The first
+ * is negative.
+ */
+ public void testCompareToDiffSigns2() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two equal negative numbers.
+ */
+ public void testCompareToEqualNeg() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(0, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two equal positive numbers.
+ */
+ public void testCompareToEqualPos() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(0, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two negative numbers. The first is greater
+ * in absolute value.
+ */
+ public void testCompareToNegNeg1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare a negative number to ZERO.
+ */
+ public void testCompareToNegZero() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two positive numbers. The first is
+ * greater.
+ */
+ public void testCompareToPosPos1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare two positive numbers. The first is less.
+ */
+ public void testCompareToPosPos2() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare a positive number to ZERO.
+ */
+ public void testCompareToPosZero() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare ZERO to a negative number.
+ */
+ public void testCompareToZeroNeg() {
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int bSign = -1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare ZERO to a positive number.
+ */
+ public void testCompareToZeroPos() {
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int bSign = 1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a). Compare ZERO to ZERO.
+ */
+ public void testCompareToZeroZero() {
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ZERO;
+ assertEquals(0, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * equals(Object obj). obj is a BigInteger. numbers are not equal.
+ */
+ public void testEqualsBigIntegerFalse() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ Object bNumber = new BigInteger(bSign, bBytes);
+ assertFalse(aNumber.equals(bNumber));
+ }
+
+ /**
+ * equals(Object obj). obj is a BigInteger. numbers are equal.
+ */
+ public void testEqualsBigIntegerTrue() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ Object bNumber = new BigInteger(bSign, bBytes);
+ assertTrue(aNumber.equals(bNumber));
+ }
+
+ /**
+ * equals(null).
+ */
+ public void testEqualsNull() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertFalse(aNumber.equals(null));
+ }
+
+ /**
+ * equals(Object obj). obj is not a BigInteger
+ */
+ public void testEqualsObject() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ Object obj = new Object();
+ assertFalse(aNumber.equals(obj));
+ }
+
+ /**
+ * max(BigInteger val). numbers are equal.
+ */
+ public void testMaxEqual() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * max(BigInteger val). the first is greater.
+ */
+ public void testMaxGreater() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ result = bNumber.max(aNumber);
+ assertEquals(aNumber, result);
+ }
+
+ /**
+ * max(BigInteger val). the first is less.
+ */
+ public void testMaxLess() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * max(BigInteger val). max of negative and ZERO.
+ */
+ public void testMaxNegZero() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 0);
+ }
+
+ /**
+ * min(BigInteger val). numbers are equal.
+ */
+ public void testMinEqual() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * min(BigInteger val). the first is greater.
+ */
+ public void testMinGreater() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * min(BigInteger val). the first is less.
+ */
+ public void testMinLess() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * max(BigInteger val). min of positive and ZERO.
+ */
+ public void testMinPosZero() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 0);
+ }
+
+ /**
+ * negate() a negative number.
+ */
+ public void testNegateNegative() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.negate();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ } for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * negate() a positive number.
+ */
+ public void testNegatePositive() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ byte rBytes[] = {
+ -13, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -27, -4, -91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.negate();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == -1);
+ }
+
+ /**
+ * negate() ZERO.
+ */
+ public void testNegateZero() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.negate();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * signum() of a negative number.
+ */
+ public void testSignumNegative() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * signum() of a positive number.
+ */
+ public void testSignumPositive() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * signum() of ZERO.
+ */
+ public void testSignumZero() {
+ BigInteger aNumber = BigInteger.ZERO;
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java
new file mode 100644
index 0000000..6024e6f
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java
@@ -0,0 +1,779 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+/**
+ * Class: java.math.BigInteger Constructors: BigInteger(byte[] a),
+ * BigInteger(int sign, byte[] a), BigInteger(String val, int radix)
+ */
+public class BigIntegerConstructorsTest extends EmulTestBase {
+ /**
+ * Create a number from an array of bytes. Verify an exception thrown if an
+ * array is zero bytes long
+ */
+ public void testConstructorBytesException() {
+ byte aBytes[] = {};
+ try {
+ new BigInteger(aBytes);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Zero length BigInteger",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Create a negative number from an array of bytes. The number fits in an
+ * array of integers.
+ */
+ public void testConstructorBytesNegative1() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte rBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes. The number fits in an
+ * integer.
+ */
+ public void testConstructorBytesNegative2() {
+ byte aBytes[] = {-12, 56, 100};
+ byte rBytes[] = {-12, 56, 100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes. The number of bytes is 4.
+ */
+ public void testConstructorBytesNegative3() {
+ byte aBytes[] = {-128, -12, 56, 100};
+ byte rBytes[] = {-128, -12, 56, 100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes. The number of bytes is
+ * multiple of 4.
+ */
+ public void testConstructorBytesNegative4() {
+ byte aBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
+ byte rBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes. The number of bytes is
+ * multiple of 4.
+ */
+ public void testConstructorBytesPositive() {
+ byte aBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
+ byte rBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes. The number fits in an
+ * array of integers.
+ */
+ public void testConstructorBytesPositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes. The number fits in an
+ * integer.
+ */
+ public void testConstructorBytesPositive2() {
+ byte aBytes[] = {12, 56, 100};
+ byte rBytes[] = {12, 56, 100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes. The number of bytes is 4.
+ */
+ public void testConstructorBytesPositive3() {
+ byte aBytes[] = {127, 56, 100, -1};
+ byte rBytes[] = {127, 56, 100, -1};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from an array of zero bytes.
+ */
+ public void testConstructorBytesZero() {
+ byte aBytes[] = {0, 0, 0, -0, +0, 0, -0};
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a prime number of 25 bits length.
+ */
+ public void testConstructorPrime() {
+ int bitLen = 25;
+ Random rnd = new Random();
+ BigInteger aNumber = new BigInteger(bitLen, 80, rnd);
+ assertTrue("incorrect bitLength", aNumber.bitLength() == bitLen);
+ }
+
+ /**
+ * Create a prime number of 2 bits length.
+ */
+ public void testConstructorPrime2() {
+ int bitLen = 2;
+ Random rnd = new Random();
+ BigInteger aNumber = new BigInteger(bitLen, 80, rnd);
+ assertTrue("incorrect bitLength", aNumber.bitLength() == bitLen);
+ int num = aNumber.intValue();
+ assertTrue("incorrect value", num == 2 || num == 3);
+ }
+
+ /**
+ * Create a random number of 75 bits length.
+ */
+ public void testConstructorRandom() {
+ int bitLen = 75;
+ Random rnd = new Random();
+ BigInteger aNumber = new BigInteger(bitLen, rnd);
+ assertTrue("incorrect bitLength", aNumber.bitLength() <= bitLen);
+ }
+
+ /**
+ * Create a number from a sign and an array of bytes. Verify an exception
+ * thrown if a sign has improper value.
+ */
+ public void testConstructorSignBytesException1() {
+ byte aBytes[] = {123, 45, -3, -76};
+ int aSign = 3;
+ try {
+ new BigInteger(aSign, aBytes);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Invalid signum value",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Create a number from a sign and an array of bytes. Verify an exception
+ * thrown if the array contains non-zero bytes while the sign is 0.
+ */
+ public void testConstructorSignBytesException2() {
+ byte aBytes[] = {123, 45, -3, -76};
+ int aSign = 0;
+ try {
+ new BigInteger(aSign, aBytes);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "signum-magnitude mismatch",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number fits
+ * in an array of integers. The most significant byte is positive.
+ */
+ public void testConstructorSignBytesNegative1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = -1;
+ byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number fits
+ * in an array of integers. The most significant byte is negative.
+ */
+ public void testConstructorSignBytesNegative2() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = -1;
+ byte rBytes[] = {-1, 11, -57, -101, 1, 75, -90, -46, -92, -4, 15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number fits
+ * in an integer.
+ */
+ public void testConstructorSignBytesNegative3() {
+ byte aBytes[] = {-12, 56, 100};
+ int aSign = -1;
+ byte rBytes[] = {-1, 11, -57, -100};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number of
+ * bytes is 4. The most significant byte is positive.
+ */
+ public void testConstructorSignBytesNegative4() {
+ byte aBytes[] = {127, 56, 100, -2};
+ int aSign = -1;
+ byte rBytes[] = {-128, -57, -101, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number of
+ * bytes is 4. The most significant byte is negative.
+ */
+ public void testConstructorSignBytesNegative5() {
+ byte aBytes[] = {-127, 56, 100, -2};
+ int aSign = -1;
+ byte rBytes[] = {-1, 126, -57, -101, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number of
+ * bytes is multiple of 4. The most significant byte is positive.
+ */
+ public void testConstructorSignBytesNegative6() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = -1;
+ byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 14, -24, 101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes. The number of
+ * bytes is multiple of 4. The most significant byte is negative.
+ */
+ public void testConstructorSignBytesNegative7() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = -1;
+ byte rBytes[] = {-1, 11, -57, -101, 1, 75, -90, -46, -92, -4, 14, -24, 101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number fits
+ * in an array of integers. The most significant byte is positive.
+ */
+ public void testConstructorSignBytesPositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number fits
+ * in an array of integers. The most significant byte is negative.
+ */
+ public void testConstructorSignBytesPositive2() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = 1;
+ byte rBytes[] = {0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number fits
+ * in an integer.
+ */
+ public void testConstructorSignBytesPositive3() {
+ byte aBytes[] = {-12, 56, 100};
+ int aSign = 1;
+ byte rBytes[] = {0, -12, 56, 100};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number of
+ * bytes is 4. The most significant byte is positive.
+ */
+ public void testConstructorSignBytesPositive4() {
+ byte aBytes[] = {127, 56, 100, -2};
+ int aSign = 1;
+ byte rBytes[] = {127, 56, 100, -2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number of
+ * bytes is 4. The most significant byte is negative.
+ */
+ public void testConstructorSignBytesPositive5() {
+ byte aBytes[] = {-127, 56, 100, -2};
+ int aSign = 1;
+ byte rBytes[] = {0, -127, 56, 100, -2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number of
+ * bytes is multiple of 4. The most significant byte is positive.
+ */
+ public void testConstructorSignBytesPositive6() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes. The number of
+ * bytes is multiple of 4. The most significant byte is negative.
+ */
+ public void testConstructorSignBytesPositive7() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = 1;
+ byte rBytes[] = {0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero bytes. The sign is
+ * -1.
+ */
+ public void testConstructorSignBytesZero1() {
+ byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+ int aSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero bytes. The sign is 0.
+ */
+ public void testConstructorSignBytesZero2() {
+ byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+ int aSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero bytes. The sign is 1.
+ */
+ public void testConstructorSignBytesZero3() {
+ byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero length. The sign is
+ * -1.
+ */
+ public void testConstructorSignBytesZeroNull1() {
+ byte aBytes[] = {};
+ int aSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero length. The sign is
+ * 0.
+ */
+ public void testConstructorSignBytesZeroNull2() {
+ byte aBytes[] = {};
+ int aSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero length. The sign is
+ * 1.
+ */
+ public void testConstructorSignBytesZeroNull3() {
+ byte aBytes[] = {};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a number from a string value and radix. Verify an exception thrown
+ * if a radix is out of range
+ */
+ public void testConstructorStringException1() {
+ String value = "9234853876401";
+ int radix = 45;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "Radix out of range",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Create a number from a string value and radix. Verify an exception thrown
+ * if the string starts with a space.
+ */
+ public void testConstructorStringException2() {
+ String value = " 9234853876401";
+ int radix = 10;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a number from a string value and radix. Verify an exception thrown
+ * if the string contains improper characters.
+ */
+ public void testConstructorStringException3() {
+ String value = "92348$*#78987";
+ int radix = 34;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a number from a string value and radix. Verify an exception thrown
+ * if some digits are greater than radix.
+ */
+ public void testConstructorStringException4() {
+ String value = "98zv765hdsaiy";
+ int radix = 20;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a positive number from a string value and radix 10.
+ */
+ public void testConstructorStringRadix10() {
+ String value = "987328901348934898";
+ int radix = 10;
+ byte rBytes[] = {13, -77, -78, 103, -103, 97, 68, -14};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a string value and radix 10.
+ */
+ public void testConstructorStringRadix10Negative() {
+ String value = "-234871376037";
+ int radix = 36;
+ byte rBytes[] = {-4, 48, 71, 62, -76, 93, -105, 13};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a string value and radix 36.
+ */
+ public void testConstructorStringRadix10Zero() {
+ String value = "-00000000000000";
+ int radix = 10;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 16.
+ */
+ public void testConstructorStringRadix16() {
+ String value = "fe2340a8b5ce790";
+ int radix = 16;
+ byte rBytes[] = {15, -30, 52, 10, -117, 92, -25, -112};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 2.
+ */
+ public void testConstructorStringRadix2() {
+ String value = "10101010101010101";
+ int radix = 2;
+ byte rBytes[] = {1, 85, 85};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 36.
+ */
+ public void testConstructorStringRadix36() {
+ String value = "skdjgocvhdjfkl20jndjkf347ejg457";
+ int radix = 36;
+ byte rBytes[] = {
+ 0, -12, -116, 112, -105, 12, -36, 66, 108, 66, -20, -37, -15, 108, -7,
+ 52, -99, -109, -8, -45, -5};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 8.
+ */
+ public void testConstructorStringRadix8() {
+ String value = "76356237071623450";
+ int radix = 8;
+ byte rBytes[] = {7, -50, -28, -8, -25, 39, 40};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerConvertTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerConvertTest.java
new file mode 100644
index 0000000..df634f5
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerConvertTest.java
@@ -0,0 +1,811 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Methods: intValue, longValue, toByteArray(),
+ * valueOf(long val), floatValue(), doubleValue()
+ */
+public class BigIntegerConvertTest extends EmulTestBase {
+ /**
+ * Convert a negative number to a double value. The number's bit length is
+ * less than 64 bits.
+ */
+ public void testDoubleValueNegative1() {
+ String a = "-27467238945";
+ double result = -2.7467238945E10;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a double value. The number's bit length is
+ * inside [63, 1024].
+ */
+ public void testDoubleValueNegative2() {
+ String a = "-2746723894572364578265426346273456972";
+ double result = -2.7467238945723645E36;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a double value. The number's bit length is
+ * greater than 1024.
+ */
+ public void testDoubleValueNegativeInfinity1() {
+ String a = "-2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == Double.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a negative number to a double value. The exponent is 1023 and the
+ * mantissa is all 0s. The rounding bit is 0. The result is
+ * Double.NEGATIVE_INFINITY.
+ */
+ public void testDoubleValueNegativeInfinity2() {
+ byte[] a = {
+ -1, -1, -1, -1, -1, -1, -1, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == Double.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a double value. The exponent is 1023 and the
+ * mantissa is all 0s but the 54th bit (implicit) is 1.
+ */
+ public void testDoubleValueNegMantissaIsZero() {
+ byte[] a = {
+ -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == -8.98846567431158E307);
+ }
+
+ /**
+ * Convert a negative number to a double value. The exponent is 1023 and the
+ * mantissa is all 1s. The result is -Double.MAX_VALUE.
+ */
+ public void testDoubleValueNegMaxValue() {
+ byte[] a = {
+ 0, -1, -1, -1, -1, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1};
+ int aSign = -1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == -Double.MAX_VALUE);
+ }
+
+ /**
+ * Convert a positive number to a double value. Rounding is NOT needed.
+ */
+ public void testDoubleValueNegNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, -128, 23, 1, -3, -5};
+ int aSign = -1;
+ double result = -1.5474726438794828E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. Rounding is needed.
+ */
+ public void testDoubleValueNegRounded1() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ double result = -1.54747264387948E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. Rounding is needed. The
+ * rounding bit is 1 and the next bit to the left is 0 but some of dropped
+ * bits are 1s.
+ */
+ public void testDoubleValueNegRounded2() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 36, 23, 1, -3, -5};
+ int aSign = -1;
+ double result = -1.547472643879479E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. The number's length is less
+ * than 64 bits.
+ */
+ public void testDoubleValuePositive1() {
+ String a = "27467238945";
+ double result = 2.7467238945E10;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. The number's bit length is
+ * inside [63, 1024].
+ */
+ public void testDoubleValuePositive2() {
+ String a = "2746723894572364578265426346273456972";
+ double result = 2.7467238945723645E36;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. The exponent is 1023 and the
+ * mantissa is all 1s. The rounding bit is 1. The result is
+ * Double.POSITIVE_INFINITY.
+ */
+ public void testDoubleValuePositiveInfinity1() {
+ byte[] a = {
+ -1, -1, -1, -1, -1, -1, -1, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == Double.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a double value. The number's bit length is
+ * greater than 1024.
+ */
+ public void testDoubleValuePositiveInfinity2() {
+ String a = "2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == Double.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a double value. The exponent is 1023 and the
+ * mantissa is all 0s but the 54th bit (implicit) is 1.
+ */
+ public void testDoubleValuePosMantissaIsZero() {
+ byte[] a = {
+ -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ double result = 8.98846567431158E307;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. The exponent is 1023 and the
+ * mantissa is all 1s. The rounding bit is 0. The result is Double.MAX_VALUE.
+ */
+ public void testDoubleValuePosMaxValue() {
+ byte[] a = {
+ 0, -1, -1, -1, -1, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1};
+ int aSign = 1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == Double.MAX_VALUE);
+ }
+
+ /**
+ * Convert a positive number to a double value. Rounding is NOT needed.
+ */
+ public void testDoubleValuePosNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, -128, 23, 1, -3, -5};
+ int aSign = 1;
+ double result = 1.5474726438794828E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. Rounding is needed. The
+ * rounding bit is 1 and the next bit to the left is 1.
+ */
+ public void testDoubleValuePosRounded1() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ double result = 1.54747264387948E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value. Rounding is needed. The
+ * rounding bit is 1 and the next bit to the left is 0 but some of dropped
+ * bits are 1s.
+ */
+ public void testDoubleValuePosRounded2() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 36, 23, 1, -3, -5};
+ int aSign = 1;
+ double result = 1.547472643879479E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Return the double value of ZERO.
+ */
+ public void testDoubleValueZero() {
+ String a = "0";
+ double result = 0.0;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a float value. The number's bit length is less
+ * than 32 bits.
+ */
+ public void testFloatValueBug2482() {
+ String a = "2147483649";
+ float result = 2.14748365E9f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals("incorrect value", aNumber, result, 1);
+ }
+
+ /**
+ * Convert a negative number to a float value. The value is near
+ * Float.MAX_VALUE, but since all calculation in JS is done in double
+ * precision, it can't be completely accurate about passing that value
+ * through.
+ */
+ public void testFloatValueNearNegMaxValue() {
+ byte[] a = {
+ 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(-3.4028235e38, aNumber, 1e31);
+ }
+
+ /**
+ * Convert a positive number to a float value. The value is near
+ * Float.MAX_VALUE, but since all calculation in JS is done in double
+ * precision, it can't be completely accurate about passing that value
+ * through.
+ */
+ public void testFloatValueNearPosMaxValue() {
+ byte[] a = {
+ 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(3.4028235e38, aNumber, 1e31);
+ }
+
+ /**
+ * Convert a negative number to a float value. The number's bit length is less
+ * than 32 bits.
+ */
+ public void testFloatValueNegative1() {
+ String a = "-27467238";
+ float result = -2.7467238E7f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals("incorrect value", result, aNumber, 1);
+ }
+
+ /**
+ * Convert a negative number to a double value. The number's bit length
+ * is inside [63, 1024].
+ */
+ public void testFloatValueNegative2() {
+ String a = "-27467238945723645782";
+ float result = -2.7467239E19f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals("incorrect value", result, aNumber, 1e12);
+ }
+
+ /**
+ * Convert a negative number to a float value. The number's bit length is
+ * greater than 127.
+ */
+ public void testFloatValueNegativeInfinity1() {
+ String a = "-2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals("incorrect value", Float.NEGATIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a negative number to a float value. The exponent is 1023 and the
+ * mantissa is all 0s. The rounding bit is 0. The result is
+ * Float.NEGATIVE_INFINITY.
+ */
+ public void testFloatValueNegativeInfinity2() {
+ byte[] a = {
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(Float.NEGATIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a positive number to a double value. The exponent is 1023 and the
+ * mantissa is all 0s but the 54th bit (implicit) is 1.
+ */
+ public void testFloatValueNegMantissaIsZero() {
+ byte[] a = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(Float.NEGATIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a positive number to a float value. Rounding is NOT needed.
+ */
+ public void testFloatValueNegNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ float result = -1.5474726E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e19);
+ }
+
+ /**
+ * Convert a positive number to a float value. Rounding is needed.
+ */
+ public void testFloatValueNegRounded1() {
+ byte[] a = {-128, 1, -1, -4, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ float result = -1.5475195E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e19);
+ }
+
+ /**
+ * Convert a positive number to a float value. Rounding is needed. The
+ * rounding bit is 1 and the next bit to the left is 0 but some of dropped
+ * bits are 1s.
+ */
+ public void testFloatValueNegRounded2() {
+ byte[] a = {-128, 1, 2, -128, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ float result = -1.5474728E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e19);
+ }
+
+ /**
+ * Convert a negative number beyond Float.MAX_VALUE, ensuring that it is
+ * converted to Float.NEGATIVE_INFINITY.
+ */
+ public void testFloatValuePastNegMaxValue() {
+ byte[] a = {
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(Float.NEGATIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a positive number beyond Float.MAX_VALUE, ensuring that it is
+ * converted to Float.POSITIVE_INFINITY.
+ */
+ public void testFloatValuePastPosMaxValue() {
+ byte[] a = {
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = 1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(Float.POSITIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a positive number to a float value. The number's length is less
+ * than 32 bits.
+ */
+ public void testFloatValuePositive1() {
+ String a = "27467238";
+ float result = 2.7467238E7f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * Convert a positive number to a float value. The number's bit length is
+ * inside [32, 127].
+ */
+ public void testFloatValuePositive2() {
+ String a = "27467238945723645782";
+ float result = 2.7467239E19f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals(result, aNumber, 1e12);
+ }
+
+ /**
+ * Convert a positive number to a float value. The exponent is 1023 and the
+ * mantissa is all 1s. The rounding bit is 1. The result is
+ * Float.POSITIVE_INFINITY.
+ */
+ public void testFloatValuePositiveInfinity1() {
+ byte[] a = {
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = 1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(Float.POSITIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a positive number to a float value. The number's bit length is
+ * greater than 127.
+ */
+ public void testFloatValuePositiveInfinity2() {
+ String a = "274672389457236457826542634627345697228374687236476867674746234"
+ + "23423423423423423423234234234234234234267674563457452937623847562384"
+ + "75634563456845634568934568347586346578648576478568456457634875673845"
+ + "67845678658734587364576745683475674576345786348576847567846578345670"
+ + "2897830296720476846578634576384567845678346573465786457863";
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals(Float.POSITIVE_INFINITY, aNumber);
+ }
+
+ /**
+ * Convert a positive number to a float value. The exponent is 1023 and the
+ * mantissa is all 0s but the 54th bit (implicit) is 1.
+ */
+ public void testFloatValuePosMantissaIsZero() {
+ byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ float result = 1.7014118E38f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e31);
+ }
+
+ /**
+ * Convert a positive number to a float value. Rounding is NOT needed.
+ */
+ public void testFloatValuePosNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ float result = 1.5474726E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e19);
+ }
+
+ /**
+ * Convert a positive number to a float value. Rounding is needed. The
+ * rounding bit is 1 and the next bit to the left is 1.
+ */
+ public void testFloatValuePosRounded1() {
+ byte[] a = {-128, 1, -1, -4, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ float result = 1.5475195E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e19);
+ }
+
+ /**
+ * Convert a positive number to a float value. Rounding is needed. The
+ * rounding bit is 1 and the next bit to the left is 0 but some of dropped
+ * bits are 1s.
+ */
+ public void testFloatValuePosRounded2() {
+ byte[] a = {-128, 1, 2, -128, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ float result = 1.5474728E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertEquals(result, aNumber, 1e19);
+ }
+
+ /**
+ * Return the float value of ZERO.
+ */
+ public void testFloatValueZero() {
+ String a = "0";
+ float result = 0.0f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * Convert a negative BigInteger to an integer value. The low digit is
+ * negative.
+ */
+ public void testIntValueNegative1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, -128, 45, 91, 3};
+ int sign = -1;
+ int resInt = 2144511229;
+ int aNumber = new BigInteger(sign, aBytes).intValue();
+ assertEquals(resInt, aNumber);
+ }
+
+ /**
+ * Convert a negative BigInteger to an integer value. The low digit is
+ * negative.
+ */
+ public void testIntValueNegative2() {
+ byte aBytes[] = {-12, 56, 100};
+ int result = -771996;
+ int aNumber = new BigInteger(aBytes).intValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * Convert a negative BigInteger to an integer value. The low digit is
+ * positive.
+ */
+ public void testIntValueNegative3() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 127, 45, 91, 3};
+ int sign = -1;
+ int resInt = -2133678851;
+ int aNumber = new BigInteger(sign, aBytes).intValue();
+ assertEquals(resInt, aNumber);
+ }
+
+ /**
+ * Convert a positive BigInteger to an integer value. The low digit is
+ * positive
+ */
+ public void testIntValuePositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3};
+ int resInt = 1496144643;
+ int aNumber = new BigInteger(aBytes).intValue();
+ assertEquals(resInt, aNumber);
+ }
+
+ /**
+ * Convert a positive BigInteger to an integer value. The low digit is
+ * positive
+ */
+ public void testIntValuePositive2() {
+ byte aBytes[] = {12, 56, 100};
+ int resInt = 800868;
+ int aNumber = new BigInteger(aBytes).intValue();
+ assertEquals(resInt, aNumber);
+ }
+
+ /**
+ * Convert a positive BigInteger to an integer value. The low digit is
+ * negative.
+ */
+ public void testIntValuePositive3() {
+ byte aBytes[] = {56, 13, 78, -12, -5, 56, 100};
+ int sign = 1;
+ int resInt = -184862620;
+ int aNumber = new BigInteger(sign, aBytes).intValue();
+ assertEquals(resInt, aNumber);
+ }
+
+ /**
+ * Convert a number to a negative long value The BigInteger is longer than
+ * int.
+ */
+ public void testLongValueNegative1() {
+ byte aBytes[] = {12, -1, 100, -2, -76, -128, 45, 91, 3};
+ long result = -43630045168837885L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * Convert a number to a negative long value The number fits in a long.
+ */
+ public void testLongValueNegative2() {
+ byte aBytes[] = {-12, 56, 100, 45, -101, 45, 98};
+ long result = -3315696807498398L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * Convert a BigInteger to a positive long value The BigInteger is longer than
+ * int.
+ */
+ public void testLongValuePositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, 120, -34, -12, 45, 98};
+ long result = 3268209772258930018L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * Convert a number to a positive long value The number fits in a long.
+ */
+ public void testLongValuePositive2() {
+ byte aBytes[] = {12, 56, 100, 18, -105, 34, -18, 45};
+ long result = 880563758158769709L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertEquals(result, aNumber);
+ }
+
+ /**
+ * valueOf (long val): convert Integer.MAX_VALUE to a BigInteger.
+ */
+ public void testValueOfIntegerMax() {
+ long longVal = Integer.MAX_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {127, -1, -1, -1};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert Integer.MIN_VALUE to a BigInteger.
+ */
+ public void testValueOfIntegerMin() {
+ long longVal = Integer.MIN_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-128, 0, 0, 0};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert Long.MAX_VALUE to a BigInteger.
+ */
+ public void testValueOfLongMax() {
+ long longVal = Long.MAX_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {127, -1, -1, -1, -1, -1, -1, -1};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert Long.MIN_VALUE to a BigInteger.
+ */
+ public void testValueOfLongMin() {
+ long longVal = Long.MIN_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-128, 0, 0, 0, 0, 0, 0, 0};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a negative long value to a BigInteger.
+ */
+ public void testValueOfLongNegative1() {
+ long longVal = -268209772258930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-4, 71, 32, -94, 23, 55, -46, -98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a negative long value to a BigInteger. The long
+ * value fits in integer.
+ */
+ public void testValueOfLongNegative2() {
+ long longVal = -58930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-4, 124, -52, -98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a positive long value to a BigInteger.
+ */
+ public void testValueOfLongPositive1() {
+ long longVal = 268209772258930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {3, -72, -33, 93, -24, -56, 45, 98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a positive long value to a BigInteger. The long
+ * value fits in integer.
+ */
+ public void testValueOfLongPositive2() {
+ long longVal = 58930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {3, -125, 51, 98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a zero long value to a BigInteger.
+ */
+ public void testValueOfLongZero() {
+ long longVal = 0L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {0};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerDivideTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerDivideTest.java
new file mode 100644
index 0000000..5975a2b
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerDivideTest.java
@@ -0,0 +1,687 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Methods: divide, remainder, mod, and
+ * divideAndRemainder
+ */
+public class BigIntegerDivideTest extends EmulTestBase {
+ /**
+ * Divide by zero
+ */
+ public void testCase1() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ try {
+ aNumber.divide(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "BigInteger divide by zero",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Divide two negative numbers.
+ */
+ public void testCase10() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {23, 115, 11, 78, 35, -11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide zero by a negative number.
+ */
+ public void testCase11() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 0;
+ int bSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide ZERO by a negative number.
+ */
+ public void testCase12() {
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int bSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide a positive number by ONE.
+ */
+ public void testCase13() {
+ byte aBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 1;
+ byte rBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide ONE by ONE.
+ */
+ public void testCase14() {
+ byte rBytes[] = {1};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Remainder of division by zero
+ */
+ public void testCase15() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ try {
+ aNumber.remainder(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "BigInteger divide by zero",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Remainder of division of equal numbers
+ */
+ public void testCase16() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Remainder of division of two positive numbers
+ */
+ public void testCase17() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, -21, 73, 56, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Remainder of division of two negative numbers
+ */
+ public void testCase18() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-13, 20, -74, -57, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Remainder of division of two numbers of different signs. The first is
+ * positive.
+ */
+ public void testCase19() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {12, -21, 73, 56, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide by ZERO
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ try {
+ aNumber.divide(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "BigInteger divide by zero",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Remainder of division of two numbers of different signs. The first is
+ * negative.
+ */
+ public void testCase20() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-13, 20, -74, -57, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * divideAndRemainder of two numbers of different signs. The first is
+ * negative.
+ */
+ public void testCase21() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[][] = { {-5, 94, -115, -74, -85, 84}, {-13, 20, -74, -57, -27}};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result[] = aNumber.divideAndRemainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result[0].toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ if (resBytes[i] != rBytes[0][i]) {
+ fail("Incorrect quotation");
+ }
+ }
+ assertEquals(-1, result[0].signum());
+ resBytes = result[1].toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ if (resBytes[i] != rBytes[1][i]) {
+ fail("Incorrect remainder");
+ }
+ assertEquals(-1, result[1].signum());
+ }
+ }
+
+ /**
+ * mod when modulus is negative
+ */
+ public void testCase22() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {1, 30, 40, 56, -1, 45};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ try {
+ aNumber.mod(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message",
+ "BigInteger: modulus not positive", e.getMessage());
+ }
+ }
+
+ /**
+ * mod when a divisor is positive
+ */
+ public void testCase23() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, -21, 73, 56, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.mod(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * mod when a divisor is negative
+ */
+ public void testCase24() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {15, 5, -9, -17, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.mod(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide two equal positive numbers
+ */
+ public void testCase3() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide two equal in absolute value numbers of different signs.
+ */
+ public void testCase4() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide two numbers of different length and different signs. The second is
+ * longer.
+ */
+ public void testCase5() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 1, 2, 3, 4, 5};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide two positive numbers of the same length. The second is greater.
+ */
+ public void testCase6() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {15, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide two positive numbers.
+ */
+ public void testCase7() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {23, 115, 11, 78, 35, -11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide a positive number by a negative one.
+ */
+ public void testCase8() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-24, -116, -12, -79, -36, 11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide a negative number by a positive one.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-24, -116, -12, -79, -36, 11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Verifies the case when borrow != 0 in the private divide method.
+ */
+ public void testDivisionKnuth1() {
+ byte aBytes[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {-3, -3, -3, -3};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -5, -12, -33, -96, -36, -105, -56, 92, 15, 48, -109};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Verifies the case when the first digits of the dividend and divisor equal.
+ */
+ public void testDivisionKnuthFirstDigitsEqual() {
+ byte aBytes[] = {2, -3, -4, -5, -1, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+ byte bBytes[] = {2, -3, -4, -5, -1, -1, -1, -1};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {0, -1, -1, -1, -1, -2, -88, -60, 41};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Verifies the case when the divisor is already normalized.
+ */
+ public void testDivisionKnuthIsNormalized() {
+ byte aBytes[] = {-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+ byte bBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {0, -9, -8, -7, -6, -5, -4, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide the number of multi digits by the number of one digit
+ */
+ public void testDivisionKnuthMultiDigitsByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5, 18, -34, 67, 39, -29};
+ byte bBytes[] = {2, -3, -4, -5};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-38, 2, 7, 30, 109, -43};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide the number of one digit by the number of one digit
+ */
+ public void testDivisionKnuthOneDigitByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5};
+ byte bBytes[] = {2, -3, -4, -5};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Tests the step D6 from the Knuth algorithm
+ */
+ public void testRemainderKnuth1() {
+ byte aBytes[] = {-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1};
+ byte bBytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7, 7, 18, -89};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide the number of multi digits by the number of one digit
+ */
+ public void testRemainderKnuthMultiDigitsByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5, 18, -34, 67, 39, -29};
+ byte bBytes[] = {2, -3, -4, -50};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {2, -37, -60, 59};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide the number of one digit by the number of one digit
+ */
+ public void testRemainderKnuthOneDigitByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5};
+ byte bBytes[] = {2, -3, -4, -50};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {2, -9, -14, 53};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerHashCodeTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerHashCodeTest.java
new file mode 100644
index 0000000..1e311c0
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerHashCodeTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: hashCode()
+ */
+public class BigIntegerHashCodeTest extends EmulTestBase {
+ /**
+ * Test hash codes for equal objects.
+ */
+ public void testEqualObjects() {
+ String value1 = "12378246728727834290276457386374882976782849";
+ String value2 = "12378246728727834290276457386374882976782849";
+ BigInteger aNumber1 = new BigInteger(value1);
+ BigInteger aNumber2 = new BigInteger(value2);
+ int code1 = aNumber1.hashCode();
+ int code2 = aNumber2.hashCode();
+ if (aNumber1.equals(aNumber2)) {
+ assertTrue("hash codes for equal objects are unequal", code1 == code2);
+ }
+ }
+
+ /**
+ * Test hash codes for the same object
+ */
+ public void testSameObject() {
+ String value1 = "12378246728727834290276457386374882976782849";
+ String value2 = "-5634562095872038262928728727834290276457386374882976782849";
+ BigInteger aNumber1 = new BigInteger(value1);
+ BigInteger aNumber2 = new BigInteger(value2);
+ int code1 = aNumber1.hashCode();
+ aNumber1.add(aNumber2).shiftLeft(125);
+ aNumber1.subtract(aNumber2).shiftRight(125);
+ aNumber1.multiply(aNumber2).toByteArray();
+ aNumber1.divide(aNumber2).bitLength();
+ aNumber1.gcd(aNumber2).pow(7);
+ int code2 = aNumber1.hashCode();
+ assertTrue("hash codes for the same object differ", code1 == code2);
+ }
+
+ /**
+ * Test hash codes for unequal objects. The codes are unequal.
+ */
+ public void testUnequalObjectsUnequal() {
+ String value1 = "12378246728727834290276457386374882976782849";
+ String value2 = "-5634562095872038262928728727834290276457386374882976782849";
+ BigInteger aNumber1 = new BigInteger(value1);
+ BigInteger aNumber2 = new BigInteger(value2);
+ int code1 = aNumber1.hashCode();
+ int code2 = aNumber2.hashCode();
+ if (!aNumber1.equals(aNumber2)) {
+ assertTrue("hash codes for unequal objects are equal", code1 != code2);
+ }
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerModPowTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerModPowTest.java
new file mode 100644
index 0000000..c3bb24f
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerModPowTest.java
@@ -0,0 +1,355 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Methods: modPow, modInverse, and gcd
+ */
+public class BigIntegerModPowTest extends EmulTestBase {
+ /**
+ * gcd: both numbers are zeros
+ */
+ public void testGcdBothZeros() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger("0");
+ BigInteger bNumber = BigInteger.valueOf(0L);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * gcd: the first number is longer
+ */
+ public void testGcdFirstLonger() {
+ byte aBytes[] = {
+ -15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28,
+ -127};
+ byte bBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the first number is zero
+ */
+ public void testGcdFirstZero() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the first number is ZERO
+ */
+ public void testGcdFirstZERO() {
+ byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ int bSign = 1;
+ byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the second number is longer
+ */
+ public void testGcdSecondLonger() {
+ byte aBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+ byte bBytes[] = {
+ -15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28,
+ -127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the second number is zero
+ */
+ public void testGcdSecondZero() {
+ byte aBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: non-positive modulus
+ */
+ public void testmodInverseException() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte mBytes[] = {1, 2, 3};
+ int aSign = 1;
+ int mSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ try {
+ aNumber.modInverse(modulus);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message",
+ "BigInteger: modulus not positive", e.getMessage());
+ }
+ }
+
+ /**
+ * modInverse: negative number
+ */
+ public void testmodInverseNeg1() {
+ byte aBytes[] = {
+ 15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28,
+ -127};
+ byte mBytes[] = {2, 122, 45, 36, 100};
+ int aSign = -1;
+ int mSign = 1;
+ byte rBytes[] = {0, -41, 4, -91, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: negative number (another case: x < 0)
+ */
+ public void testmodInverseNeg2() {
+ byte aBytes[] = {-15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ byte mBytes[] = {122, 2, 4, 122, 2, 4};
+ byte rBytes[] = {85, 47, 127, 4, -128, 45};
+ BigInteger aNumber = new BigInteger(aBytes);
+ BigInteger modulus = new BigInteger(mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: non-invertible number
+ */
+ public void testmodInverseNonInvertible() {
+ byte aBytes[] = {
+ -15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28,
+ -127};
+ byte mBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+ int aSign = 1;
+ int mSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ try {
+ aNumber.modInverse(modulus);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "BigInteger not invertible.",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * modInverse: positive number
+ */
+ public void testmodInversePos1() {
+ byte aBytes[] = {
+ 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ byte mBytes[] = {122, 45, 36, 100, 122, 45};
+ int aSign = 1;
+ int mSign = 1;
+ byte rBytes[] = {47, 3, 96, 62, 87, 19};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: positive number (another case: a < 0)
+ */
+ public void testmodInversePos2() {
+ byte aBytes[] = {
+ 15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28,
+ -127};
+ byte mBytes[] = {2, 122, 45, 36, 100};
+ int aSign = 1;
+ int mSign = 1;
+ byte rBytes[] = {1, -93, 40, 127, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modPow: non-positive modulus
+ */
+ public void testModPowException() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte eBytes[] = {1, 2, 3, 4, 5};
+ byte mBytes[] = {1, 2, 3};
+ int aSign = 1;
+ int eSign = 1;
+ int mSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger exp = new BigInteger(eSign, eBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ try {
+ aNumber.modPow(exp, modulus);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message",
+ "BigInteger: modulus not positive", e.getMessage());
+ }
+ }
+
+ /**
+ * modPow: negative exponent
+ */
+ public void testModPowNegExp() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
+ byte eBytes[] = {27, -15, 65, 39};
+ byte mBytes[] = {-128, 2, 3, 4, 5};
+ int aSign = 1;
+ int eSign = -1;
+ int mSign = 1;
+ byte rBytes[] = {12, 118, 46, 86, 92};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger exp = new BigInteger(eSign, eBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modPow(exp, modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modPow: positive exponent.
+ */
+ public void testModPowPosExp() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
+ byte eBytes[] = {27, -15, 65, 39};
+ byte mBytes[] = {-128, 2, 3, 4, 5};
+ int aSign = 1;
+ int eSign = 1;
+ int mSign = 1;
+ byte rBytes[] = {113, 100, -84, -28, -85};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger exp = new BigInteger(eSign, eBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modPow(exp, modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertEquals("Byte " + i, rBytes[i], resBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerMultiplyTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerMultiplyTest.java
new file mode 100644
index 0000000..5b24a50
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerMultiplyTest.java
@@ -0,0 +1,414 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: multiply
+ */
+public class BigIntegerMultiplyTest extends EmulTestBase {
+ /**
+ * Multiply two negative numbers of the same length
+ */
+ public void testCase1() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ 10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 105, 4, 28, -86, -117, -52,
+ 100, 120, 90};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply a negative number by ONE.
+ */
+ public void testCase10() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = -1;
+ byte rBytes[] = {-2, -3, -4, -5, -6, -7, -8, -2, -3, -4, -2, -3, -4, -5, -5};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of the same length and different signs. The first is
+ * negative.
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {
+ -11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -106, -5, -29, 85,
+ 116, 51, -101, -121, -90};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two positive numbers of different length. The first is longer.
+ */
+ public void testCase3() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 115, 44, -127, 115, -21,
+ -62, -15, 85, 64, -87, -2, -36, -36, -106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply two positive numbers of different length. The second is longer.
+ */
+ public void testCase4() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 115, 44, -127, 115, -21,
+ -62, -15, 85, 64, -87, -2, -36, -36, -106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of different length and different signs. The first is
+ * positive. The first is longer.
+ */
+ public void testCase5() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -116, -45, 126, -116,
+ 20, 61, 14, -86, -65, 86, 1, 35, 35, 106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of different length and different signs. The first is
+ * positive. The second is longer.
+ */
+ public void testCase6() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -116, -45, 126, -116,
+ 20, 61, 14, -86, -65, 86, 1, 35, 35, 106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply a number by zero.
+ */
+ public void testCase7() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Multiply a number by ZERO.
+ */
+ public void testCase8() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Multiply a positive number by ONE.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of 4 bytes length.
+ */
+ public void testIntbyInt1() {
+ byte aBytes[] = {10, 20, 30, 40};
+ byte bBytes[] = {1, 2, 3, 4};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-11, -41, -101, 55, 5, 15, 96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of 4 bytes length.
+ */
+ public void testIntbyInt2() {
+ byte aBytes[] = {-1, -1, -1, -1};
+ byte bBytes[] = {-1, -1, -1, -1};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -1, -1, -1, -2, 0, 0, 0, 1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Negative exponent.
+ */
+ public void testPowException() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int exp = -5;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.pow(exp);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Negative exponent",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Exponentiation of a negative number to an even exponent.
+ */
+ public void testPowNegativeNumToEvenExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = -1;
+ int exp = 4;
+ byte rBytes[] = {
+ 102, 107, -122, -43, -52, -20, -27, 25, -9, 88, -13, 75, 78, 81, -33,
+ -77, 39, 27, -37, 106, 121, -73, 108, -47, -101, 80, -25, 71, 13, 94,
+ -7, -33, 1, -17, -65, -70, -61, -3, -47};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a negative number to an odd exponent.
+ */
+ public void testPowNegativeNumToOddExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = -1;
+ int exp = 5;
+ byte rBytes[] = {
+ -21, -94, -42, -15, -127, 113, -50, -88, 115, -35, 3, 59, -92, 111,
+ -75, 103, -42, 41, 34, -114, 99, -32, 105, -59, 127, 45, 108, 74, -93,
+ 105, 33, 12, -5, -20, 17, -21, -119, -127, -115, 27, -122, 26, -67,
+ 109, -125, 16, 91, -70, 109};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a negative number to zero exponent.
+ */
+ public void testPowNegativeNumToZeroExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = -1;
+ int exp = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a positive number.
+ */
+ public void testPowPositiveNum() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = 1;
+ int exp = 5;
+ byte rBytes[] = {
+ 20, 93, 41, 14, 126, -114, 49, 87, -116, 34, -4, -60, 91, -112, 74,
+ -104, 41, -42, -35, 113, -100, 31, -106, 58, -128, -46, -109, -75, 92,
+ -106, -34, -13, 4, 19, -18, 20, 118, 126, 114, -28, 121, -27, 66, -110,
+ 124, -17, -92, 69, -109};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a negative number to zero exponent.
+ */
+ public void testPowPositiveNumToZeroExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = 1;
+ int exp = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerNotTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerNotTest.java
new file mode 100644
index 0000000..9a1b4f7
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerNotTest.java
@@ -0,0 +1,223 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Methods: and, andNot
+ */
+public class BigIntegerNotTest extends EmulTestBase {
+ /**
+ * andNot for two negative numbers; the first is longer
+ */
+ public void testAndNotNegNegFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * andNot for two positive numbers; the first is longer
+ */
+ public void testAndNotPosPosFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31,
+ -96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * andNot for two positive numbers; the first is shorter
+ */
+ public void testAndNotPosPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * andNot for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {
+ -1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88,
+ -88, 16, 72};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for a negative number
+ */
+ public void testNotNeg() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ int aSign = -1;
+ byte rBytes[] = {
+ 0, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -118};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Not for ONE
+ */
+ public void testNotOne() {
+ byte rBytes[] = {-2};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for a positive number
+ */
+ public void testNotPos() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ int aSign = 1;
+ byte rBytes[] = {
+ -1, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -27, 116};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for a negative number
+ */
+
+ public void testNotSpecialCase() {
+ byte aBytes[] = {-1, -1, -1, -1};
+ int aSign = 1;
+ byte rBytes[] = {-1, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for ZERO
+ */
+ public void testNotZero() {
+ byte rBytes[] = {-1};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerOperateBitsTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerOperateBitsTest.java
new file mode 100644
index 0000000..3e62f59
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerOperateBitsTest.java
@@ -0,0 +1,1418 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Methods: bitLength, shiftLeft, shiftRight,
+ * clearBit, flipBit, setBit, testBit
+ */
+public class BigIntegerOperateBitsTest extends EmulTestBase {
+ /**
+ * bitCount() of a negative number.
+ */
+ public void testBitCountNeg() {
+ BigInteger aNumber = new BigInteger(
+ "-12378634756382937873487638746283767238657872368748726875");
+ assertEquals(87, aNumber.bitCount());
+ }
+
+ /**
+ * bitCount() of a negative number.
+ */
+ public void testBitCountPos() {
+ BigInteger aNumber = new BigInteger(
+ "12378634756343564757582937873487638746283767238657872368748726875");
+ assertEquals(107, aNumber.bitCount());
+ }
+
+ /**
+ * bitCount() of zero.
+ */
+ public void testBitCountZero() {
+ BigInteger aNumber = new BigInteger("0");
+ assertEquals(0, aNumber.bitCount());
+ }
+
+ /**
+ * bitLength() of a negative number.
+ */
+ public void testBitLengthNegative1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(108, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a negative number with the leftmost bit set
+ */
+ public void testBitLengthNegative2() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(96, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a negative number which is a power of 2
+ */
+ public void testBitLengthNegative3() {
+ byte aBytes[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(80, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a positive number.
+ */
+ public void testBitLengthPositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(108, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a positive number with the leftmost bit set
+ */
+ public void testBitLengthPositive2() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(96, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a positive number which is a power of 2
+ */
+ public void testBitLengthPositive3() {
+ byte aBytes[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(81, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of zero.
+ */
+ public void testBitLengthZero() {
+ BigInteger aNumber = new BigInteger("0");
+ assertEquals(0, aNumber.bitLength());
+ }
+
+ /**
+ * clearBit(int n) of a negative n
+ */
+ public void testClearBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.clearBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Negative bit address",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * clearBit(int n) inside a negative number
+ */
+ public void testClearBitNegativeInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 15;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, 92, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a negative number
+ */
+ public void testClearBitNegativeInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 44;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -62, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(2) in the negative number with all ones in bit representation
+ */
+ public void testClearBitNegativeInside3() {
+ String as = "-18446744073709551615";
+ int number = 2;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.clearBit(number);
+ assertEquals(as, result.toString());
+ }
+
+ /**
+ * clearBit(0) in the negative number of length 1 with all ones in bit
+ * representation. the resulting number's length is 2.
+ */
+ public void testClearBitNegativeInside4() {
+ String as = "-4294967295";
+ String res = "-4294967296";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.clearBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * clearBit(0) in the negative number of length 2 with all ones in bit
+ * representation. the resulting number's length is 3.
+ */
+ public void testClearBitNegativeInside5() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551616";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.clearBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * clearBit(int n) outside a negative number
+ */
+ public void testClearBitNegativeOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 150;
+ byte rBytes[] = {
+ -65, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4,
+ 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside a negative number
+ */
+ public void testClearBitNegativeOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 165;
+ byte rBytes[] = {
+ -33, -1, -1, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46,
+ -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 20;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -31, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 17;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 13, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside4() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 50;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside5() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 63;
+ byte rBytes[] = {1, -128, 56, 100, -2, 52, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside a positive number
+ */
+ public void testClearBitPositiveOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 150;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside a positive number
+ */
+ public void testClearBitPositiveOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 191;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) the leftmost bit in a negative number
+ */
+ public void testClearBitTopNegative() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = -1;
+ int number = 63;
+ byte rBytes[] = {-1, 127, -2, 127, -57, -101, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside zero
+ */
+ public void testClearBitZero() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside zero
+ */
+ public void testClearBitZeroOutside1() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 95;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * flipBit(int n) of a negative n
+ */
+ public void testFlipBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.flipBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Negative bit address",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * flipBit(int n) the leftmost bit in a negative number
+ */
+ public void testFlipBitLeftmostNegative() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = -1;
+ int number = 48;
+ byte rBytes[] = {-1, 127, -57, -101, 14, -36, -26, 49};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) the leftmost bit in a positive number
+ */
+ public void testFlipBitLeftmostPositive() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = 1;
+ int number = 48;
+ byte rBytes[] = {0, -128, 56, 100, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a negative number
+ */
+ public void testFlipBitNegativeInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 15;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, 92, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a negative number
+ */
+ public void testFlipBitNegativeInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 45;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -14, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a negative number with all ones in bit representation
+ */
+ public void testFlipBitNegativeInside3() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551611";
+ int number = 2;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.flipBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * flipBit(0) in the negative number of length 1 with all ones in bit
+ * representation. the resulting number's length is 2.
+ */
+ public void testFlipBitNegativeInside4() {
+ String as = "-4294967295";
+ String res = "-4294967296";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.flipBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * flipBit(0) in the negative number of length 2 with all ones in bit
+ * representation. the resulting number's length is 3.
+ */
+ public void testFlipBitNegativeInside5() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551616";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.flipBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * flipBit(int n) outside a negative number
+ */
+ public void testFlipBitNegativeOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 150;
+ byte rBytes[] = {
+ -65, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4,
+ 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside a negative number
+ */
+ public void testFlipBitNegativeOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 191;
+ byte rBytes[] = {
+ -1, 127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1,
+ 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a positive number
+ */
+ public void testFlipBitPositiveInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 15;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, -93, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a positive number
+ */
+ public void testFlipBitPositiveInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 13, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside a positive number
+ */
+ public void testFlipBitPositiveOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 150;
+ byte rBytes[] = {
+ 64, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35,
+ 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside a positive number
+ */
+ public void testFlipBitPositiveOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 191;
+ byte rBytes[] = {
+ 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89,
+ 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) zero
+ */
+ public void testFlipBitZero() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside zero
+ */
+ public void testFlipBitZeroOutside1() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 62;
+ byte rBytes[] = {64, 0, 0, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue("incorrect value", resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside zero
+ */
+ public void testFlipBitZeroOutside2() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 63;
+ byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue("incorrect value", resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit: check the case when the number of bit to be set can be represented
+ * as n * 32 + 31, where n is an arbitrary integer. Here 191 = 5 * 32 + 31
+ */
+ public void testSetBitBug1331() {
+ BigInteger result = BigInteger.valueOf(0L).setBit(191);
+ assertEquals("incorrect value",
+ "3138550867693340381917894711603833208051177722232017256448",
+ result.toString());
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) of a negative n
+ */
+ public void testSetBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.setBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Negative bit address",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * setBit(int n) the leftmost bit in a negative number
+ */
+ public void testSetBitLeftmostNegative() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = -1;
+ int number = 48;
+ byte rBytes[] = {-1, 127, -57, -101, 14, -36, -26, 49};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a negative number
+ */
+ public void testSetBitNegativeInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 15;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a negative number
+ */
+ public void testSetBitNegativeInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 44;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a negative number with all ones in bit representation
+ */
+ public void testSetBitNegativeInside3() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551611";
+ int number = 2;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.setBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * setBit(0) in the negative number of length 1 with all ones in bit
+ * representation. the resulting number's length is 2.
+ */
+ public void testSetBitNegativeInside4() {
+ String as = "-4294967295";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.setBit(number);
+ assertEquals(as, result.toString());
+ }
+
+ /**
+ * setBit(0) in the negative number of length 2 with all ones in bit
+ * representation. the resulting number's length is 3.
+ */
+ public void testSetBitNegativeInside5() {
+ String as = "-18446744073709551615";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.setBit(number);
+ assertEquals(as, result.toString());
+ }
+
+ /**
+ * setBit(int n) outside a negative number
+ */
+ public void testSetBitNegativeOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 150;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside a negative number
+ */
+ public void testSetBitNegativeOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 191;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 20;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 17;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -13, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside4() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 50;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 93, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside a positive number
+ */
+ public void testSetBitPositiveOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 150;
+ byte rBytes[] = {
+ 64, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35,
+ 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside a positive number
+ */
+ public void testSetBitPositiveOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 223;
+ byte rBytes[] = {
+ 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -128, 56, 100,
+ -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) the leftmost bit in a positive number
+ */
+ public void testSetBitTopPositive() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = 1;
+ int number = 63;
+ byte rBytes[] = {0, -128, 1, -128, 56, 100, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside zero
+ */
+ public void testSetBitZero() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside zero
+ */
+ public void testSetBitZeroOutside1() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 95;
+ byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n), n = 0
+ */
+ public void testShiftLeft1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 0;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n), n < 0
+ */
+ public void testShiftLeft2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -27;
+ byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n) a positive number, n > 0
+ */
+ public void testShiftLeft3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 27;
+ byte rBytes[] = {
+ 12, 1, -61, 39, -11, -94, -55, 106, -40, 31, -119, 24, -48, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n) a positive number, n > 0
+ */
+ public void testShiftLeft4() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {
+ 48, 7, 12, -97, -42, -117, 37, -85, 96, 126, 36, 99, 64, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n) a negative number, n > 0
+ */
+ public void testShiftLeft5() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 45;
+ byte rBytes[] = {
+ -49, -8, -13, 96, 41, 116, -38, 84, -97, -127, -37, -100, -64, 0, 0, 0,
+ 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n = 0
+ */
+ public void testShiftRight1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 0;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n < 0
+ */
+ public void testShiftRight2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -27;
+ byte rBytes[] = {
+ 12, 1, -61, 39, -11, -94, -55, 106, -40, 31, -119, 24, -48, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), 0 < n < 32
+ */
+ public void testShiftRight3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 27;
+ byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n > 32
+ */
+ public void testShiftRight4() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {12, 1, -61, 39, -11, -94, -55};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n is greater than bitLength()
+ */
+ public void testShiftRight5() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 300;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number; shift distance is NOT multiple of 32; shifted
+ * bits are NOT zeroes.
+ */
+ public void testShiftRightNegNonZeroes() {
+ byte aBytes[] = {
+ 1, -128, 56, 100, -2, -76, 89, 45, 91, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 68;
+ byte rBytes[] = {-25, -4, 121, -80, 20, -70, 109, 42};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number; shift distance is multiple of 32; shifted
+ * bits are NOT zeroes.
+ */
+ public void testShiftRightNegNonZeroesMul32() {
+ byte aBytes[] = {
+ 1, -128, 56, 100, -2, -76, 89, 45, 91, 1, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 64;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number; shift distance is NOT multiple of 32; shifted
+ * bits are zeroes.
+ */
+ public void testShiftRightNegZeroes() {
+ byte aBytes[] = {
+ 1, -128, 56, 100, -2, -76, 89, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 68;
+ byte rBytes[] = {-25, -4, 121, -80, 20, -70, 109, 48};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number; shift distance is multiple of 32; shifted
+ * bits are zeroes.
+ */
+ public void testShiftRightNegZeroesMul32() {
+ byte aBytes[] = {
+ 1, -128, 56, 100, -2, -76, 89, 45, 91, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 64;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * testBit(int n) of a negative n
+ */
+ public void testTestBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.testBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Negative bit address",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * testBit(int n) of a negative number
+ */
+ public void testTestBitNegative1() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive n
+ */
+ public void testTestBitNegative2() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 45;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(!aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive n, n > bitLength()
+ */
+ public void testTestBitNegative3() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 300;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive number
+ */
+ public void testTestBitPositive1() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(!aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive number
+ */
+ public void testTestBitPositive2() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive number, n > bitLength()
+ */
+ public void testTestBitPositive3() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 300;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(!aNumber.testBit(number));
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerOrTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerOrTest.java
new file mode 100644
index 0000000..e67cb2e
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerOrTest.java
@@ -0,0 +1,467 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: or
+ */
+public class BigIntegerOrTest extends EmulTestBase {
+ /**
+ * Or for two negative numbers; the first is longer
+ */
+ public void testNegNegFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 1, 75, -89, -45, -2, -3, -18, -36, -17, -10, -3, -6, -7, -21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers; the first is shorter
+ */
+ public void testNegNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 1, 75, -89, -45, -2, -3, -18, -36, -17, -10, -3, -6, -7, -21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers of the same length
+ */
+ public void testNegNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 127, -57, -101, -5, -5, -18, -38, -17, -2, -65, -2, -11, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a negative number and zero
+ */
+ public void testNegPos() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = -1;
+ int bSign = 0;
+ byte rBytes[] = {
+ -1, 1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {
+ -1, 127, -10, -57, -101, -1, -1, -2, -2, -91, -2, 31, -1, -11, 125,
+ -22, -83, 30, 95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers; the first is shorter
+ */
+ public void testNegPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-74, 91, 47, -5, -13, -7, -5, -33, -49, -65, -1, -9, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two numbers of different signs and the same length
+ */
+ public void testNegPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-1, 5, 79, -73, -9, -76, -3, 78, -35, -17, 119};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for one and one
+ */
+ public void testOneOne() {
+ byte aBytes[] = {1};
+ byte bBytes[] = {1};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for a positive and a negative numbers; the first is longer
+ */
+ public void testPosNegFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-74, 91, 47, -5, -13, -7, -5, -33, -49, -65, -1, -9, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a positive and a negative number; the first is shorter
+ */
+ public void testPosNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 127, -10, -57, -101, -1, -1, -2, -2, -91, -2, 31, -1, -11, 125,
+ -22, -83, 30, 95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two numbers of different signs and the same length
+ */
+ public void testPosNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 1, -126, 59, 103, -2, -11, -7, -3, -33, -57, -3, -5, -5, -21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two positive numbers; the first is longer
+ */
+ public void testPosPosFirstLonger() {
+ byte aBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 0, -128, 9, 56, 100, -2, -3, -3, -3, 95, 15, -9, 39, 58, -69, 87, 87,
+ -17, -73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for two positive numbers; the first is shorter
+ */
+ public void testPosPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {
+ -128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87,
+ -25, -75};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 0, -128, 9, 56, 100, -2, -3, -3, -3, 95, 15, -9, 39, 58, -69, 87, 87,
+ -17, -73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for two positive numbers of the same length
+ */
+ public void testPosPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {
+ 0, -2, -3, -4, -4, -1, -66, 95, 47, 123, 59, -13, 39, 30, -97};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for a positive number and zero
+ */
+ public void testPosZero() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ byte rBytes[] = {0, -2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ public void testRegression() {
+ // Regression test for HARMONY-1996
+ BigInteger x = new BigInteger("-1023");
+ BigInteger r1 = x.and((BigInteger.ZERO.not()).shiftLeft(32));
+ BigInteger r3 = x.and((BigInteger.ZERO.not().shiftLeft(32)).not());
+ BigInteger result = r1.or(r3);
+ assertEquals(x, result);
+ }
+
+ /**
+ * Or for zero and a negative number
+ */
+ public void testZeroNeg() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = -1;
+ byte rBytes[] = {
+ -1, 1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for zero and one
+ */
+ public void testZeroOne() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {1};
+ int aSign = 0;
+ int bSign = 1;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for zero and a positive number
+ */
+ public void testZeroPos() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for zero and zero
+ */
+ public void testZeroZero() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ int aSign = 0;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerSubtractTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerSubtractTest.java
new file mode 100644
index 0000000..8e6290a
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerSubtractTest.java
@@ -0,0 +1,547 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: subtract
+ */
+public class BigIntegerSubtractTest extends EmulTestBase {
+ /**
+ * Subtract two positive numbers of the same length. The first is greater.
+ */
+ public void testCase1() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {9, 18, 27, 36, 45, 54, 63, 9, 18, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two positive numbers of different length. The second is longer.
+ */
+ public void testCase10() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of different length and different signs. The first is
+ * positive. The first is greater in absolute value.
+ */
+ public void testCase11() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs. The first is
+ * positive. The second is greater in absolute value.
+ */
+ public void testCase12() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of different length and different signs. The first is
+ * negative. The first is longer.
+ */
+ public void testCase13() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {
+ -2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs. The first is
+ * negative. The second is longer.
+ */
+ public void testCase14() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {
+ -2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of different length. The first is longer.
+ */
+ public void testCase15() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of different length. The second is longer.
+ */
+ public void testCase16() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two positive equal in absolute value numbers.
+ */
+ public void testCase17() {
+ byte aBytes[] = {-120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte bBytes[] = {-120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {0};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract zero from a number. The number is positive.
+ */
+ public void testCase18() {
+ byte aBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte bBytes[] = {0};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int aSign = 1;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract a number from zero. The number is negative.
+ */
+ public void testCase19() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int aSign = 0;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two positive numbers of the same length. The second is greater.
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {-10, -19, -28, -37, -46, -55, -64, -10, -19, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract zero from zero.
+ */
+ public void testCase20() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ byte rBytes[] = {0};
+ int aSign = 0;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract ZERO from a number. The number is positive.
+ */
+ public void testCase21() {
+ byte aBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract a number from ZERO. The number is negative.
+ */
+ public void testCase22() {
+ byte bBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int bSign = -1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract ZERO from ZERO.
+ */
+ public void testCase23() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract ONE from ONE.
+ */
+ public void testCase24() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract two numbers so that borrow is 1.
+ */
+ public void testCase25() {
+ byte aBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ byte bBytes[] = {-128, -128, -128, -128, -128, -128, -128, -128, -128};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {-128, 127, 127, 127, 127, 127, 127, 127, 127};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs. The first is
+ * positive. The first is greater in absolute value.
+ */
+ public void testCase3() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs. The first is
+ * positive. The second is greater in absolute value.
+ */
+ public void testCase4() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of the same length. The first is greater in
+ * absolute value.
+ */
+ public void testCase5() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-10, -19, -28, -37, -46, -55, -64, -10, -19, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of the same length. The second is greater in
+ * absolute value.
+ */
+ public void testCase6() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {9, 18, 27, 36, 45, 54, 63, 9, 18, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs. The first is
+ * negative. The first is greater in absolute value.
+ */
+ public void testCase7() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs. The first is
+ * negative. The second is greater in absolute value.
+ */
+ public void testCase8() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two positive numbers of different length. The first is longer.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for (int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerToStringTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerToStringTest.java
new file mode 100644
index 0000000..958025c
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerToStringTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: toString(int radix)
+ */
+public class BigIntegerToStringTest extends EmulTestBase {
+ /**
+ * test negative number of radix 10
+ */
+ public void testRadix10Neg() {
+ String value = "-2489756308572364789878394872984";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 10
+ */
+ public void testRadix10Pos() {
+ String value = "2387627892347567398736473476";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 16
+ */
+ public void testRadix16Neg() {
+ String value = "-287628a883451b800865c67e8d7ff20";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 16
+ */
+ public void testRadix16Pos() {
+ String value = "287628a883451b800865c67e8d7ff20";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 24
+ */
+ public void testRadix24Neg() {
+ String value = "-287628a88gmn3451b8ijk00865c67e8d7ff20";
+ int radix = 24;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 24
+ */
+ public void testRadix24Pos() {
+ String value = "287628a883451bg80ijhk0865c67e8d7ff20";
+ int radix = 24;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 2
+ */
+ public void testRadix2Neg() {
+ String value = "-101001100010010001001010101110000101010110001010010101010101010101010101010101010101010101010010101";
+ int radix = 2;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 2
+ */
+ public void testRadix2Pos() {
+ String value = "101000011111000000110101010101010101010001001010101010101010010101010101010000100010010";
+ int radix = 2;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 24
+ */
+ public void testRadix36Neg() {
+ String value = "-uhguweut98iu4h3478tq3985pq98yeiuth33485yq4aiuhalai485yiaehasdkr8tywi5uhslei8";
+ int radix = 36;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 24
+ */
+ public void testRadix36Pos() {
+ String value = "23895lt45y6vhgliuwhgi45y845htsuerhsi4586ysuerhtsio5y68peruhgsil4568ypeorihtse48y6";
+ int radix = 36;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * If 36 < radix < 2 it should be set to 10
+ */
+ public void testRadixOutOfRange() {
+ String value = "442429234853876401";
+ int radix = 10;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(45);
+ assertTrue(result.equals(value));
+ }
+}
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerXorTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerXorTest.java
new file mode 100644
index 0000000..028fdfa
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerXorTest.java
@@ -0,0 +1,294 @@
+/*
+ * 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 GOOGLE.
+ */
+/**
+ * author Elena Semukhina
+ */
+package com.google.gwt.emultest.java.math;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger Method: xor
+ */
+public class BigIntegerXorTest extends EmulTestBase {
+ /**
+ * Xor for two negative numbers; the first is longer
+ */
+ public void testNegNegFirstLonger() {
+ String numA = "-2837462783428374767845648748973847593874837948575684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers; the first is shorter
+ */
+ public void testNegNegFirstShorter() {
+ String numA = "293478573489347658763745839457637";
+ String numB = "2837462783428374767845648748973847593874837948575684767";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers of the same length
+ */
+ public void testNegNegSameLength() {
+ String numA = "-283746278342837476784564875684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "71412358434940908477702819237626";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a negative number and zero
+ */
+ public void testNegPos() {
+ String numA = "-27384627835298756289327365";
+ String numB = "0";
+ String res = "-27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ String numA = "-2837462783428374767845648748973847593874837948575684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers; the first is shorter
+ */
+ public void testNegPosFirstShorter() {
+ String numA = "-293478573489347658763745839457637";
+ String numB = "2837462783428374767845648748973847593874837948575684767";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two numbers of different signs and the same length
+ */
+ public void testNegPosSameLength() {
+ String numA = "-283746278342837476784564875684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "-71412358434940908477702819237628";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for one and one
+ */
+ public void testOneOne() {
+ String numA = "1";
+ String numB = "1";
+ String res = "0";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a positive and a negative numbers; the first is longer
+ */
+ public void testPosNegFirstLonger() {
+ String numA = "2837462783428374767845648748973847593874837948575684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a positive and a negative number; the first is shorter
+ */
+ public void testPosNegFirstShorter() {
+ String numA = "293478573489347658763745839457637";
+ String numB = "-2837462783428374767845648748973847593874837948575684767";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two numbers of different signs and the same length
+ */
+ public void testPosNegSameLength() {
+ String numA = "283746278342837476784564875684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "-71412358434940908477702819237628";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two positive numbers; the first is longer
+ */
+ public void testPosPosFirstLonger() {
+ String numA = "2837462783428374767845648748973847593874837948575684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two positive numbers; the first is shorter
+ */
+ public void testPosPosFirstShorter() {
+ String numA = "293478573489347658763745839457637";
+ String numB = "2837462783428374767845648748973847593874837948575684767";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two positive numbers of the same length
+ */
+ public void testPosPosSameLength() {
+ String numA = "283746278342837476784564875684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "71412358434940908477702819237626";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a positive number and zero
+ */
+ public void testPosZero() {
+ String numA = "27384627835298756289327365";
+ String numB = "0";
+ String res = "27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and a negative number
+ */
+ public void testZeroNeg() {
+ String numA = "0";
+ String numB = "-27384627835298756289327365";
+ String res = "-27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and one
+ */
+ public void testZeroOne() {
+ String numA = "0";
+ String numB = "1";
+ String res = "1";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and a positive number
+ */
+ public void testZeroPos() {
+ String numA = "0";
+ String numB = "27384627835298756289327365";
+ String res = "27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and zero
+ */
+ public void testZeroZero() {
+ String numA = "0";
+ String numB = "0";
+ String res = "0";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+}
diff --git a/user/test/com/google/gwt/i18n/client/I18NTest.java b/user/test/com/google/gwt/i18n/client/I18NTest.java
index 48d6f3a..51a10ec 100644
--- a/user/test/com/google/gwt/i18n/client/I18NTest.java
+++ b/user/test/com/google/gwt/i18n/client/I18NTest.java
@@ -33,6 +33,8 @@
import com.google.gwt.i18n.client.resolutiontest.Inners.InnerClass.LocalizableInnerInner;
import com.google.gwt.junit.client.GWTTestCase;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -559,6 +561,21 @@
assertEquals("estednay underscoray", m.nestedUnderscore());
}
+ /**
+ * Test that messages works with Number subclasses.
+ */
+ public void testNumber() {
+ TestAnnotatedMessages m = GWT.create(TestAnnotatedMessages.class);
+ BigInteger intVal = new BigInteger("1000000000000000000");
+ assertEquals("Total is US$1,000,000,000,000,000,000.00",
+ m.withNumberCurrency(intVal));
+ BigDecimal decVal = new BigDecimal("1000000000000000000.01");
+ assertEquals("Total is US$1,000,000,000,000,000,000.01",
+ m.withNumberCurrency(decVal));
+ assertEquals("Distance is 1.0E18", m.withNumberExponent(intVal));
+ assertEquals("Distance is 100.0E6", m.withNumberExponent(1e8f));
+ }
+
public void testShapesFamily() {
Shapes shapes = GWT.create(Shapes.class);
// test overload
diff --git a/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java b/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
index b729c16..d3b7f30 100644
--- a/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
+++ b/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
@@ -13,13 +13,15 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-
package com.google.gwt.i18n.client;
import com.google.gwt.junit.client.GWTTestCase;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
/**
- * GWT JUnit tests must extend GWTTestCase.
+ * Test {@link NumberFormat} in the {@code en} locale.
*/
public class NumberFormat_en_Test extends GWTTestCase {
@@ -52,16 +54,39 @@
assertEquals("R$123,456.79", str);
}
- /**
- * Add as many tests as you like.
- */
public void testBasicFormat() {
String str = NumberFormat.getFormat("0.0000").format(123.45789179565757f);
assertEquals("123.4579", str);
-
+
// tests for overflow of mantissa bits during formatting
- str = NumberFormat.getFormat("#,##0.000").format(112589990684262.5);
- assertEquals("112,589,990,684,262.500", str);
+ // Low bits are not dependable across browsers, so use .41 instead of
+ // .5 and only one decimal digits.
+ str = NumberFormat.getFormat("#,##0.0").format(112589990684262.41);
+ assertEquals("112,589,990,684,262.4", str);
+ }
+
+ public void testBigDecimal() {
+ BigDecimal decVal = new BigDecimal("1000000000000000000000000");
+ String str = NumberFormat.getFormat("0.000").format(decVal);
+ assertEquals("1000000000000000000000000.000", str);
+
+ decVal = decVal.add(new BigDecimal(".1"));
+ str = NumberFormat.getFormat("#,##0.000").format(decVal);
+ assertEquals("1,000,000,000,000,000,000,000,000.100", str);
+
+ decVal = new BigDecimal(".1499999999999999999999");
+ str = NumberFormat.getFormat(".0").format(decVal);
+ assertEquals(".1", str);
+}
+
+ public void testBigInteger() {
+ BigInteger intVal = new BigInteger("1000000000000000000000000");
+ String str = NumberFormat.getFormat("#,##0").format(intVal);
+ assertEquals("1,000,000,000,000,000,000,000,000", str);
+
+ intVal = intVal.add(BigInteger.ONE);
+ str = NumberFormat.getFormat("#,##0").format(intVal);
+ assertEquals("1,000,000,000,000,000,000,000,001", str);
}
public void testCurrency() {
@@ -94,7 +119,7 @@
assertEquals("BRL 1,234.56", str);
str = formatter.format(-1234.56);
assertEquals("(BRL 1,234.56)", str);
-
+
// Test using a deprecated currency.
formatter = NumberFormat.getCurrencyFormat("ITL");
str = formatter.format(1234.556);
@@ -238,18 +263,6 @@
assertTrue(value == 12345.0);
}
- public void testGrouping() {
- String str;
-
- str = NumberFormat.getFormat("#,###").format(1234567890);
- assertEquals("1,234,567,890", str);
- str = NumberFormat.getFormat("#,####").format(1234567890);
- assertEquals("12,3456,7890", str);
-
- str = NumberFormat.getFormat("#").format(1234567890);
- assertEquals("1234567890", str);
- }
-
public void testForceLatin() {
assertFalse(NumberFormat.forcedLatinDigits());
NumberFormat.setForcedLatinDigits(true);
@@ -263,10 +276,51 @@
NumberFormat unforced = NumberFormat.getDecimalFormat();
assertEquals("3.14", unforced.format(3.14));
}
-
+
+ public void testGrouping() {
+ String str;
+
+ str = NumberFormat.getFormat("#,###").format(1234567890);
+ assertEquals("1,234,567,890", str);
+ str = NumberFormat.getFormat("#,####").format(1234567890);
+ assertEquals("12,3456,7890", str);
+
+ str = NumberFormat.getFormat("#").format(1234567890);
+ assertEquals("1234567890", str);
+ }
+
+ // See external issue 3140
+ public void testLeadingZeros() {
+ String str;
+
+ str = NumberFormat.getFormat("0,000,000,000.#").format(123456789.489123);
+ assertEquals("0,123,456,789.5", str);
+
+ str = NumberFormat.getFormat("#,###.####").format(0.414014);
+ assertEquals("0.414", str); // why leading 0?
+
+ str = NumberFormat.getFormat("#.####").format(0.414014);
+ assertEquals("0.414", str); // why leading 0?
+
+ str = NumberFormat.getFormat("#.0###").format(0.414014);
+ assertEquals(".414", str);
+
+ str = NumberFormat.getFormat("0.0###").format(0.414014);
+ assertEquals("0.414", str);
+
+ str = NumberFormat.getFormat("0.####").format(0.414014);
+ assertEquals("0.414", str);
+
+ str = NumberFormat.getFormat("0.0000").format(0.414014);
+ assertEquals("0.4140", str);
+
+ str = NumberFormat.getFormat("#.0000").format(0.414014);
+ assertEquals(".4140", str);
+ }
+
public void testNegative() {
String str;
-
+
// verify default negative pattern
str = NumberFormat.getFormat("#,##0.0").format(-0.15);
assertEquals("-0.2", str);
@@ -274,7 +328,7 @@
assertEquals("-15.3%", str);
str = NumberFormat.getFormat("X #,##0.0%").format(-0.1534);
assertEquals("-X 15.3%", str);
-
+
// verify we can specify percent/permille suffixes in both parts
str = NumberFormat.getFormat("#,##0.0%;#,##0.0%-").format(-0.152);
assertEquals("15.2%-", str);
@@ -288,7 +342,7 @@
public void testParseNotANumber() {
try {
- double d = NumberFormat.getDecimalFormat().parse("blue");
+ NumberFormat.getDecimalFormat().parse("blue");
fail("Expected a NumberFormatException");
} catch (NumberFormatException e) {
assertEquals("blue", e.getMessage());
@@ -323,6 +377,67 @@
assertEquals("a'b123", str);
}
+ public void testRounding() {
+ String str;
+
+ str = NumberFormat.getFormat("#0.##").format(0.555);
+ assertEquals("0.56", str);
+
+ str = NumberFormat.getFormat("#.##").format(30.555);
+ assertEquals("30.56", str);
+
+ str = NumberFormat.getFormat("#.00").format(0.997);
+ assertEquals("1.00", str);
+
+ str = NumberFormat.getFormat("#.00").format(-0.997);
+ assertEquals("-1.00", str);
+
+ str = NumberFormat.getFormat("#.00").format(27.997);
+ assertEquals("28.00", str);
+
+ str = NumberFormat.getFormat("#.00").format(-27.997);
+ assertEquals("-28.00", str);
+
+ str = NumberFormat.getFormat("#0.00000").format(1.23456789E-03);
+ assertEquals("0.00123", str);
+
+ str = NumberFormat.getFormat("#0.0000000").format(1.23456789E-03);
+ assertEquals("0.0012346", str);
+
+ str = NumberFormat.getFormat("#0.0000").format(1.2E-03);
+ assertEquals("0.0012", str);
+
+ str = NumberFormat.getFormat("#0.000").format(1.2E-03);
+ assertEquals("0.001", str);
+
+ str = NumberFormat.getFormat("#0.00").format(1.2E-03);
+ assertEquals("0.00", str);
+
+ str = NumberFormat.getFormat("#0.0").format(1.2E-03);
+ assertEquals("0.0", str);
+
+ str = NumberFormat.getFormat("#0.00").format(11.2E-03);
+ assertEquals("0.01", str);
+
+ str = NumberFormat.getFormat("#0.00").format(111.2E-03);
+ assertEquals("0.11", str);
+
+ str = NumberFormat.getFormat("#0.00").format(1111.2E-03);
+ assertEquals("1.11", str);
+
+ str = NumberFormat.getFormat("#0.00000").format(1.23456789E-05);
+ assertEquals("0.00001", str);
+
+ str = NumberFormat.getFormat("#0.0000000").format(1.23456789E-05);
+ assertEquals("0.0000123", str);
+
+ str = NumberFormat.getFormat("#0.0000000").format(1.23756789E-05);
+ assertEquals("0.0000124", str);
+
+ str = NumberFormat.getFormat("#,##,###,##0.00000000000").format(111.18);
+ assertEquals("111.18000000000", str);
+ }
+
public void testStandardFormat() {
String str;
@@ -336,6 +451,19 @@
assertEquals("1E3", str);
}
+ public void testToScaledString() {
+ StringBuilder buf = new StringBuilder();
+ int scale = NumberFormat.toScaledString(buf, .1);
+ String str = buf.toString();
+ assertStartsWith("100", str.substring(str.length() + scale));
+ assertAllZeros(str, str.length() + scale);
+ buf = new StringBuilder();
+ scale = NumberFormat.toScaledString(buf, 12345e38);
+ str = buf.toString();
+ assertStartsWith("12345", str);
+ assertEquals(43, scale + str.length());
+ }
+
public void testZeros() {
String str;
@@ -357,62 +485,17 @@
str = NumberFormat.getFormat("#").format(0);
assertEquals("0", str);
}
-
- public void testRounding() {
- String str;
-
- str = NumberFormat.getFormat("#0.##").format(0.555);
- assertEquals("0.56", str);
-
- str = NumberFormat.getFormat("#.##").format(30.555);
- assertEquals("30.56", str);
-
- str = NumberFormat.getFormat("#.00").format(0.997);
- assertEquals("1.00", str);
-
- str = NumberFormat.getFormat("#.00").format(-0.997);
- assertEquals("-1.00", str);
-
- str = NumberFormat.getFormat("#.00").format(27.997);
- assertEquals("28.00", str);
-
- str = NumberFormat.getFormat("#.00").format(-27.997);
- assertEquals("-28.00", str);
-
- str = NumberFormat.getFormat("#0.00000").format(1.23456789E-03);
- assertEquals("0.00123", str);
-
- str = NumberFormat.getFormat("#0.0000000").format(1.23456789E-03);
- assertEquals("0.0012346", str);
-
- str = NumberFormat.getFormat("#0.0000").format(1.2E-03);
- assertEquals("0.0012", str);
-
- str = NumberFormat.getFormat("#0.000").format(1.2E-03);
- assertEquals("0.001", str);
-
- str = NumberFormat.getFormat("#0.00").format(1.2E-03);
- assertEquals("0.00", str);
-
- str = NumberFormat.getFormat("#0.0").format(1.2E-03);
- assertEquals("0.0", str);
-
- str = NumberFormat.getFormat("#0.00").format(11.2E-03);
- assertEquals("0.01", str);
-
- str = NumberFormat.getFormat("#0.00").format(111.2E-03);
- assertEquals("0.11", str);
-
- str = NumberFormat.getFormat("#0.00").format(1111.2E-03);
- assertEquals("1.11", str);
-
- str = NumberFormat.getFormat("#0.00000").format(1.23456789E-05);
- assertEquals("0.00001", str);
-
- str = NumberFormat.getFormat("#0.0000000").format(1.23456789E-05);
- assertEquals("0.0000123", str);
-
- str = NumberFormat.getFormat("#0.0000000").format(1.23756789E-05);
- assertEquals("0.0000124", str);
+
+ private void assertAllZeros(String str, int prefixLen) {
+ if (prefixLen > str.length()) {
+ prefixLen = str.length();
+ }
+ for (int i = 0; i < prefixLen; ++i) {
+ assertEquals('0', str.charAt(i));
+ }
+ }
+
+ private void assertStartsWith(String prefix, String str) {
+ assertTrue(str + " does not start with " + prefix, str.startsWith(prefix));
}
}
diff --git a/user/test/com/google/gwt/i18n/client/TestAnnotatedMessages.java b/user/test/com/google/gwt/i18n/client/TestAnnotatedMessages.java
index 55210ce..0892190 100644
--- a/user/test/com/google/gwt/i18n/client/TestAnnotatedMessages.java
+++ b/user/test/com/google/gwt/i18n/client/TestAnnotatedMessages.java
@@ -88,4 +88,10 @@
@PluralText({"one", "A {0}"})
String twoParamPlural(String name, @PluralCount
int count);
+
+ @DefaultMessage("Total is {0,number,currency}")
+ String withNumberCurrency(Number value);
+
+ @DefaultMessage("Distance is {0,number,##0.0##E0}")
+ String withNumberExponent(Number value);
}
diff --git a/user/test/com/google/gwt/user/client/rpc/ValueTypesTest.java b/user/test/com/google/gwt/user/client/rpc/ValueTypesTest.java
index aad328b..d650250 100644
--- a/user/test/com/google/gwt/user/client/rpc/ValueTypesTest.java
+++ b/user/test/com/google/gwt/user/client/rpc/ValueTypesTest.java
@@ -17,25 +17,60 @@
import com.google.gwt.core.client.GWT;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
/**
- * TODO: document me.
+ * Test transfer of value types over RPC.
*/
public class ValueTypesTest extends RpcTestBase {
private ValueTypesTestServiceAsync primitiveTypeTestService;
+ public void testBigDecimal_base() {
+ assertEcho(new BigDecimal("42"));
+ }
+
+ public void testBigDecimal_exponential() {
+ assertEcho(new BigDecimal("0.00000000000000000001"));
+ }
+
+ public void testBigDecimal_negative() {
+ assertEcho(new BigDecimal("-42"));
+ }
+
+ public void testBigDecimal_zero() {
+ assertEcho(new BigDecimal("0.0"));
+ }
+
+ public void testBigInteger_base() {
+ assertEcho(new BigInteger("42"));
+ }
+
+ public void testBigInteger_exponential() {
+ assertEcho(new BigInteger("100000000000000000000"));
+ }
+
+ public void testBigInteger_negative() {
+ assertEcho(new BigInteger("-42"));
+ }
+
+ public void testBigInteger_zero() {
+ assertEcho(new BigInteger("0"));
+ }
+
public void testBoolean_FALSE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_FALSE(false, new AsyncCallback() {
+ service.echo_FALSE(false, new AsyncCallback<Boolean>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Boolean result) {
assertNotNull("Was null", result);
- assertFalse("Should have been false", ((Boolean) result).booleanValue());
+ assertFalse("Should have been false", result.booleanValue());
finishTest();
}
});
@@ -44,15 +79,15 @@
public void testBoolean_TRUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_TRUE(true, new AsyncCallback() {
+ service.echo_TRUE(true, new AsyncCallback<Boolean>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Boolean result) {
assertNotNull(result);
- assertTrue(((Boolean) result).booleanValue());
+ assertTrue(result.booleanValue());
finishTest();
}
});
@@ -61,15 +96,15 @@
public void testByte() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo((byte) (Byte.MAX_VALUE / (byte) 2), new AsyncCallback() {
+ service.echo((byte) (Byte.MAX_VALUE / (byte) 2), new AsyncCallback<Byte>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Byte result) {
assertNotNull(result);
- assertEquals(Byte.MAX_VALUE / 2, ((Byte) result).byteValue());
+ assertEquals(Byte.MAX_VALUE / 2, result.byteValue());
finishTest();
}
});
@@ -78,15 +113,15 @@
public void testByte_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Byte.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Byte.MAX_VALUE, new AsyncCallback<Byte>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Byte result) {
assertNotNull(result);
- assertEquals(Byte.MAX_VALUE, ((Byte) result).byteValue());
+ assertEquals(Byte.MAX_VALUE, result.byteValue());
finishTest();
}
});
@@ -95,15 +130,15 @@
public void testByte_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Byte.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Byte.MIN_VALUE, new AsyncCallback<Byte>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Byte result) {
assertNotNull(result);
- assertEquals(Byte.MIN_VALUE, ((Byte) result).byteValue());
+ assertEquals(Byte.MIN_VALUE, result.byteValue());
finishTest();
}
});
@@ -112,16 +147,16 @@
public void testChar() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo((char) (Character.MAX_VALUE / (char) 2), new AsyncCallback() {
+ final char value = (char) (Character.MAX_VALUE / (char) 2);
+ service.echo(value, new AsyncCallback<Character>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Character result) {
assertNotNull(result);
- assertEquals((char) (Character.MAX_VALUE / (char) 2),
- ((Character) result).charValue());
+ assertEquals(value, result.charValue());
finishTest();
}
});
@@ -130,15 +165,15 @@
public void testChar_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Character.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Character.MAX_VALUE, new AsyncCallback<Character>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Character result) {
assertNotNull(result);
- assertEquals(Character.MAX_VALUE, ((Character) result).charValue());
+ assertEquals(Character.MAX_VALUE, result.charValue());
finishTest();
}
});
@@ -147,15 +182,15 @@
public void testChar_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Character.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Character.MIN_VALUE, new AsyncCallback<Character>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Character result) {
assertNotNull(result);
- assertEquals(Character.MIN_VALUE, ((Character) result).charValue());
+ assertEquals(Character.MIN_VALUE, result.charValue());
finishTest();
}
});
@@ -164,15 +199,15 @@
public void testDouble() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Double.MAX_VALUE / 2, new AsyncCallback() {
+ service.echo(Double.MAX_VALUE / 2, new AsyncCallback<Double>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Double result) {
assertNotNull(result);
- assertEquals(Double.MAX_VALUE / 2, ((Double) result).doubleValue(), 0.0);
+ assertEquals(Double.MAX_VALUE / 2, result.doubleValue(), 0.0);
finishTest();
}
});
@@ -181,15 +216,15 @@
public void testDouble_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Double.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Double.MAX_VALUE, new AsyncCallback<Double>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Double result) {
assertNotNull(result);
- assertEquals(Double.MAX_VALUE, ((Double) result).doubleValue(), 0.0);
+ assertEquals(Double.MAX_VALUE, result.doubleValue(), 0.0);
finishTest();
}
});
@@ -198,15 +233,15 @@
public void testDouble_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Double.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Double.MIN_VALUE, new AsyncCallback<Double>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Double result) {
assertNotNull(result);
- assertEquals(Double.MIN_VALUE, ((Double) result).doubleValue(), 0.0);
+ assertEquals(Double.MIN_VALUE, result.doubleValue(), 0.0);
finishTest();
}
});
@@ -218,15 +253,15 @@
public void testDouble_NaN() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Double.NaN, new AsyncCallback() {
+ service.echo(Double.NaN, new AsyncCallback<Double>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Double result) {
assertNotNull(result);
- assertTrue(Double.isNaN(((Double) result).doubleValue()));
+ assertTrue(Double.isNaN(result.doubleValue()));
finishTest();
}
});
@@ -238,15 +273,15 @@
public void testDouble_NegInfinity() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Double.NEGATIVE_INFINITY, new AsyncCallback() {
+ service.echo(Double.NEGATIVE_INFINITY, new AsyncCallback<Double>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Double result) {
assertNotNull(result);
- double doubleValue = ((Double) result).doubleValue();
+ double doubleValue = result.doubleValue();
assertTrue(Double.isInfinite(doubleValue) && doubleValue < 0);
finishTest();
}
@@ -259,15 +294,15 @@
public void testDouble_PosInfinity() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Double.POSITIVE_INFINITY, new AsyncCallback() {
+ service.echo(Double.POSITIVE_INFINITY, new AsyncCallback<Double>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Double result) {
assertNotNull(result);
- double doubleValue = ((Double) result).doubleValue();
+ double doubleValue = result.doubleValue();
assertTrue(Double.isInfinite(doubleValue) && doubleValue > 0);
finishTest();
}
@@ -277,15 +312,15 @@
public void testFloat() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Float.MAX_VALUE / 2, new AsyncCallback() {
+ service.echo(Float.MAX_VALUE / 2, new AsyncCallback<Float>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Float result) {
assertNotNull(result);
- assertEquals(Float.MAX_VALUE / 2, ((Float) result).floatValue(), 0.0);
+ assertEquals(Float.MAX_VALUE / 2, result.floatValue(), 0.0);
finishTest();
}
});
@@ -294,15 +329,15 @@
public void testFloat_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Float.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Float.MAX_VALUE, new AsyncCallback<Float>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Float result) {
assertNotNull(result);
- assertEquals(Float.MAX_VALUE, ((Float) result).floatValue(), 0.0);
+ assertEquals(Float.MAX_VALUE, result.floatValue(), 0.0);
finishTest();
}
});
@@ -311,15 +346,15 @@
public void testFloat_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Float.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Float.MIN_VALUE, new AsyncCallback<Float>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Float result) {
assertNotNull(result);
- assertEquals(Float.MIN_VALUE, ((Float) result).floatValue(), 0.0);
+ assertEquals(Float.MIN_VALUE, result.floatValue(), 0.0);
finishTest();
}
});
@@ -331,15 +366,15 @@
public void testFloat_NaN() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Float.NaN, new AsyncCallback() {
+ service.echo(Float.NaN, new AsyncCallback<Float>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Float result) {
assertNotNull(result);
- assertTrue(Float.isNaN(((Float) result).floatValue()));
+ assertTrue(Float.isNaN(result.floatValue()));
finishTest();
}
});
@@ -351,15 +386,15 @@
public void testFloat_NegInfinity() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Float.NEGATIVE_INFINITY, new AsyncCallback() {
+ service.echo(Float.NEGATIVE_INFINITY, new AsyncCallback<Float>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Float result) {
assertNotNull(result);
- float floatValue = ((Float) result).floatValue();
+ float floatValue = result.floatValue();
assertTrue(Float.isInfinite(floatValue) && floatValue < 0);
finishTest();
}
@@ -372,15 +407,15 @@
public void testFloat_PosInfinity() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Float.POSITIVE_INFINITY, new AsyncCallback() {
+ service.echo(Float.POSITIVE_INFINITY, new AsyncCallback<Float>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Float result) {
assertNotNull(result);
- float floatValue = ((Float) result).floatValue();
+ float floatValue = result.floatValue();
assertTrue(Float.isInfinite(floatValue) && floatValue > 0);
finishTest();
}
@@ -390,15 +425,15 @@
public void testInteger() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Integer.MAX_VALUE / 2, new AsyncCallback() {
+ service.echo(Integer.MAX_VALUE / 2, new AsyncCallback<Integer>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Integer result) {
assertNotNull(result);
- assertEquals(Integer.MAX_VALUE / 2, ((Integer) result).intValue());
+ assertEquals(Integer.MAX_VALUE / 2, result.intValue());
finishTest();
}
});
@@ -407,15 +442,15 @@
public void testInteger_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Integer.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Integer.MAX_VALUE, new AsyncCallback<Integer>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Integer result) {
assertNotNull(result);
- assertEquals(Integer.MAX_VALUE, ((Integer) result).intValue());
+ assertEquals(Integer.MAX_VALUE, result.intValue());
finishTest();
}
});
@@ -424,15 +459,15 @@
public void testInteger_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Integer.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Integer.MIN_VALUE, new AsyncCallback<Integer>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Integer result) {
assertNotNull(result);
- assertEquals(Integer.MIN_VALUE, ((Integer) result).intValue());
+ assertEquals(Integer.MIN_VALUE, result.intValue());
finishTest();
}
});
@@ -441,16 +476,16 @@
public void testLong() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo(Long.MAX_VALUE / 2, new AsyncCallback() {
+ service.echo(Long.MAX_VALUE / 2, new AsyncCallback<Long>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Long result) {
assertNotNull(result);
long expected = Long.MAX_VALUE / 2;
- assertEquals(expected, ((Long) result).longValue());
+ assertEquals(expected, result.longValue());
finishTest();
}
});
@@ -459,15 +494,15 @@
public void testLong_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Long.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Long.MAX_VALUE, new AsyncCallback<Long>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Long result) {
assertNotNull(result);
- assertEquals(Long.MAX_VALUE, ((Long) result).longValue());
+ assertEquals(Long.MAX_VALUE, result.longValue());
finishTest();
}
});
@@ -476,15 +511,15 @@
public void testLong_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Long.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Long.MIN_VALUE, new AsyncCallback<Long>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Long result) {
assertNotNull(result);
- assertEquals(Long.MIN_VALUE, ((Long) result).longValue());
+ assertEquals(Long.MIN_VALUE, result.longValue());
finishTest();
}
});
@@ -493,15 +528,16 @@
public void testShort() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo((short) (Short.MAX_VALUE / (short) 2), new AsyncCallback() {
+ final short value = (short) (Short.MAX_VALUE / 2);
+ service.echo(value , new AsyncCallback<Short>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Short result) {
assertNotNull(result);
- assertEquals(Short.MAX_VALUE / 2, ((Short) result).shortValue());
+ assertEquals(value, result.shortValue());
finishTest();
}
});
@@ -510,15 +546,15 @@
public void testShort_MAX_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MAX_VALUE(Short.MAX_VALUE, new AsyncCallback() {
+ service.echo_MAX_VALUE(Short.MAX_VALUE, new AsyncCallback<Short>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Short result) {
assertNotNull(result);
- assertEquals(Short.MAX_VALUE, ((Short) result).shortValue());
+ assertEquals(Short.MAX_VALUE, result.shortValue());
finishTest();
}
});
@@ -527,15 +563,45 @@
public void testShort_MIN_VALUE() {
ValueTypesTestServiceAsync service = getServiceAsync();
delayTestFinishForRpc();
- service.echo_MIN_VALUE(Short.MIN_VALUE, new AsyncCallback() {
+ service.echo_MIN_VALUE(Short.MIN_VALUE, new AsyncCallback<Short>() {
public void onFailure(Throwable caught) {
TestSetValidator.rethrowException(caught);
}
- public void onSuccess(Object result) {
+ public void onSuccess(Short result) {
assertNotNull(result);
- assertEquals(Short.MIN_VALUE, ((Short) result).shortValue());
+ assertEquals(Short.MIN_VALUE, result.shortValue());
+ finishTest();
+ }
+ });
+ }
+
+ private void assertEcho(final BigDecimal value) {
+ ValueTypesTestServiceAsync service = getServiceAsync();
+ delayTestFinishForRpc();
+ service.echo(value, new AsyncCallback<BigDecimal>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(BigDecimal result) {
+ assertEquals(value, result);
+ finishTest();
+ }
+ });
+ }
+
+ private void assertEcho(final BigInteger value) {
+ ValueTypesTestServiceAsync service = getServiceAsync();
+ delayTestFinishForRpc();
+ service.echo(value, new AsyncCallback<BigInteger>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(BigInteger result) {
+ assertEquals(value, result);
finishTest();
}
});
diff --git a/user/test/com/google/gwt/user/client/rpc/ValueTypesTestService.java b/user/test/com/google/gwt/user/client/rpc/ValueTypesTestService.java
index 85868f1..18f3537 100644
--- a/user/test/com/google/gwt/user/client/rpc/ValueTypesTestService.java
+++ b/user/test/com/google/gwt/user/client/rpc/ValueTypesTestService.java
@@ -15,8 +15,11 @@
*/
package com.google.gwt.user.client.rpc;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
/**
- * TODO: document me.
+ * Test sending value types via RPC.
*/
public interface ValueTypesTestService extends RemoteService {
byte echo(byte value);
@@ -33,6 +36,10 @@
short echo(short value);
+ BigDecimal echo(BigDecimal value);
+
+ BigInteger echo(BigInteger value);
+
boolean echo_FALSE(boolean value);
byte echo_MAX_VALUE(byte value);
diff --git a/user/test/com/google/gwt/user/client/rpc/ValueTypesTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/ValueTypesTestServiceAsync.java
index 28d2fb2..74eaa72 100644
--- a/user/test/com/google/gwt/user/client/rpc/ValueTypesTestServiceAsync.java
+++ b/user/test/com/google/gwt/user/client/rpc/ValueTypesTestServiceAsync.java
@@ -15,53 +15,61 @@
*/
package com.google.gwt.user.client.rpc;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
/**
- * TODO: document me.
+ * Async version of {@link ValueTypesTestService}.
*/
public interface ValueTypesTestServiceAsync {
- void echo(byte value, AsyncCallback callback);
- void echo(char value, AsyncCallback callback);
+ void echo(byte value, AsyncCallback<Byte> callback);
- void echo(double value, AsyncCallback callback);
+ void echo(char value, AsyncCallback<Character> callback);
- void echo(float value, AsyncCallback callback);
+ void echo(double value, AsyncCallback<Double> callback);
- void echo(int value, AsyncCallback callback);
+ void echo(float value, AsyncCallback<Float> callback);
- void echo(long value, AsyncCallback callback);
+ void echo(int value, AsyncCallback<Integer> callback);
- void echo(short value, AsyncCallback callback);
+ void echo(long value, AsyncCallback<Long> callback);
- void echo_FALSE(boolean value, AsyncCallback callback);
+ void echo(short value, AsyncCallback<Short> callback);
- void echo_MAX_VALUE(byte value, AsyncCallback callback);
+ void echo(BigDecimal value, AsyncCallback<BigDecimal> callback);
- void echo_MAX_VALUE(char value, AsyncCallback callback);
+ void echo(BigInteger value, AsyncCallback<BigInteger> callback);
- void echo_MAX_VALUE(double value, AsyncCallback callback);
+ void echo_FALSE(boolean value, AsyncCallback<Boolean> callback);
- void echo_MAX_VALUE(float value, AsyncCallback callback);
+ void echo_MAX_VALUE(byte value, AsyncCallback<Byte> callback);
- void echo_MAX_VALUE(int value, AsyncCallback callback);
+ void echo_MAX_VALUE(char value, AsyncCallback<Character> callback);
- void echo_MAX_VALUE(long value, AsyncCallback callback);
+ void echo_MAX_VALUE(double value, AsyncCallback<Double> callback);
- void echo_MAX_VALUE(short value, AsyncCallback callback);
+ void echo_MAX_VALUE(float value, AsyncCallback<Float> callback);
- void echo_MIN_VALUE(byte value, AsyncCallback callback);
+ void echo_MAX_VALUE(int value, AsyncCallback<Integer> callback);
- void echo_MIN_VALUE(char value, AsyncCallback callback);
+ void echo_MAX_VALUE(long value, AsyncCallback<Long> callback);
- void echo_MIN_VALUE(double value, AsyncCallback callback);
+ void echo_MAX_VALUE(short value, AsyncCallback<Short> callback);
- void echo_MIN_VALUE(float value, AsyncCallback callback);
+ void echo_MIN_VALUE(byte value, AsyncCallback<Byte> callback);
- void echo_MIN_VALUE(int value, AsyncCallback callback);
+ void echo_MIN_VALUE(char value, AsyncCallback<Character> callback);
- void echo_MIN_VALUE(long value, AsyncCallback callback);
+ void echo_MIN_VALUE(double value, AsyncCallback<Double> callback);
- void echo_MIN_VALUE(short value, AsyncCallback callback);
+ void echo_MIN_VALUE(float value, AsyncCallback<Float> callback);
- void echo_TRUE(boolean value, AsyncCallback callback);
+ void echo_MIN_VALUE(int value, AsyncCallback<Integer> callback);
+
+ void echo_MIN_VALUE(long value, AsyncCallback<Long> callback);
+
+ void echo_MIN_VALUE(short value, AsyncCallback<Short> callback);
+
+ void echo_TRUE(boolean value, AsyncCallback<Boolean> callback);
}
diff --git a/user/test/com/google/gwt/user/server/rpc/ValueTypesTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/ValueTypesTestServiceImpl.java
index b52f27e..4ce0e7f 100644
--- a/user/test/com/google/gwt/user/server/rpc/ValueTypesTestServiceImpl.java
+++ b/user/test/com/google/gwt/user/server/rpc/ValueTypesTestServiceImpl.java
@@ -17,6 +17,9 @@
import com.google.gwt.user.client.rpc.ValueTypesTestService;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
/**
* Server-side code for ValueTypesTest. Mostly just echoes back the values
* received from the client, but some methods verify the value received to make
@@ -54,6 +57,14 @@
return value;
}
+ public BigDecimal echo(BigDecimal value) {
+ return value;
+ }
+
+ public BigInteger echo(BigInteger value) {
+ return value;
+ }
+
public boolean echo_FALSE(boolean value) {
if (value != false) {
throw new RuntimeException();