diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | fdb2704414a9ed92394ada0d1395e4db86889465 (patch) | |
tree | 9b591a4a50054274a197f02b3ccb51313681879f /math/src | |
download | libcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2 |
Initial Contribution
Diffstat (limited to 'math/src')
38 files changed, 22273 insertions, 0 deletions
diff --git a/math/src/main/java/java/math/BigDecimal.java b/math/src/main/java/java/math/BigDecimal.java new file mode 100644 index 0000000..0989f8a --- /dev/null +++ b/math/src/main/java/java/math/BigDecimal.java @@ -0,0 +1,3140 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +/* + * Since the original Harmony Code of the BigInteger class was strongly modified, + * in order to use the more efficient OpenSSL BIGNUM implementation, + * no android-modification-tags were placed, at all. + */ + +package java.math; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import org.apache.harmony.math.internal.nls.Messages; + +/** + * Class which represents immutable arbritary 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}}. + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +public class BigDecimal extends Number implements Comparable<BigDecimal>, Serializable { + /* Static Fields */ + + /** + * The constant zero as a BigDecimal. + * + * @since 1.2 + */ + public static final BigDecimal ZERO = new BigDecimal(0, 0); + + /** + * The constant one as a BigDecimal. + * + * @since 1.2 + */ + public static final BigDecimal ONE = new BigDecimal(1, 0); + + /** + * The constant ten as a BigDecimal. + * + * @since 1.5 + */ + public static final BigDecimal TEN = new BigDecimal(10, 0); + + /** + * 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; + + /** + * Rounding mode where the values are rounded towards zero. + * + * @see RoundingMode#DOWN + */ + public static final int ROUND_DOWN = 1; + + /** + * Rounding mode to round towards positive infinity. For positive values + * this rounding mode behaves as UP, for negative values as DOWN. + * + * @see RoundingMode#CEILING + */ + public static final int ROUND_CEILING = 2; + + /** + * Rounding mode to round towards negative infinity. For positive values + * this rounding mode behaves as DOWN, for negative values as UP. + * + * @see RoundingMode#FLOOR + */ + public static final int ROUND_FLOOR = 3; + + /** + * Rounding mode where values are rounded towards the nearest neighbour. + * Ties are broken by rounding up. + * + * @see RoundingMode#HALF_UP + */ + public static final int ROUND_HALF_UP = 4; + + /** + * Rounding mode where values are rounded towards the nearest neighbour. + * 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 neighbour. + * Ties are broken by rounding to the even neighbour. + * + * @see RoundingMode#HALF_EVEN + */ + public static final int ROUND_HALF_EVEN = 6; + + /** + * 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. + * + * @see RoundingMode#UNNECESSARY + */ + public static final int ROUND_UNNECESSARY = 7; + + /* Private Fields */ + + /** This is the serialVersionUID used by the sun implementation */ + private static final long serialVersionUID = 6108874887143696463L; + + /** The double closer to <code>Log10(2)</code>. */ + private static final double LOG10_2 = 0.3010299956639812; + + /** The <code>String</code> representation is cached. */ + private transient String toStringImage = null; + + /** Cache for the hash code. */ + private transient int hashCode = 0; + + /** + * An array with powers of five that fit in the type <code>long</code> + * (<code>5^0,5^1,...,5^27</code>) + */ + private static final BigInteger FIVE_POW[]; + + /** + * An array with powers of ten that fit in the type <code>long</code> + * (<code>10^0,10^1,...,10^18</code>) + */ + private static final BigInteger TEN_POW[]; + + /** + * An array with powers of ten that fit in the type <code>long</code> + * (<code>10^0,10^1,...,10^18</code>) + */ + private static final long[] LONG_TEN_POW = new long[] + { 1L, + 10L, + 100L, + 1000L, + 10000L, + 100000L, + 1000000L, + 10000000L, + 100000000L, + 1000000000L, + 10000000000L, + 100000000000L, + 1000000000000L, + 10000000000000L, + 100000000000000L, + 1000000000000000L, + 10000000000000000L, + 100000000000000000L, + 1000000000000000000L, }; + + + private static final long[] LONG_FIVE_POW = new long[] + { 1L, + 5L, + 25L, + 125L, + 625L, + 3125L, + 15625L, + 78125L, + 390625L, + 1953125L, + 9765625L, + 48828125L, + 244140625L, + 1220703125L, + 6103515625L, + 30517578125L, + 152587890625L, + 762939453125L, + 3814697265625L, + 19073486328125L, + 95367431640625L, + 476837158203125L, + 2384185791015625L, + 11920928955078125L, + 59604644775390625L, + 298023223876953125L, + 1490116119384765625L, + 7450580596923828125L, }; + + private static final int[] LONG_FIVE_POW_BIT_LENGTH = new int[LONG_FIVE_POW.length]; + private static final int[] LONG_TEN_POW_BIT_LENGTH = new int[LONG_TEN_POW.length]; + + 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 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]; + + /** An array filled with characters <code>'0'</code>. */ + private static final char[] CH_ZEROS = new char[100]; + + 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<LONG_FIVE_POW_BIT_LENGTH.length; j++) { + LONG_FIVE_POW_BIT_LENGTH[j] = bitLength(LONG_FIVE_POW[j]); + } + for(int j=0; j<LONG_TEN_POW_BIT_LENGTH.length; j++) { + LONG_TEN_POW_BIT_LENGTH[j] = bitLength(LONG_TEN_POW[j]); + } + + // Taking the references of useful powers. + TEN_POW = Multiplication.bigTenPows; + FIVE_POW = Multiplication.bigFivePows; + } + + /** + * The arbitrary precision integer (unscaled value) in the internal + * representation of <code>BigDecimal</code>. + */ + private BigInteger intVal; + + private transient int bitLength; + + private transient long smallValue; + + /** + * The 32-bit integer scale in the internal representation of <code>BigDecimal</code>. + */ + private int scale; + + /** + * 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 = 0; + + /* Constructors */ + + private BigDecimal(long smallValue, int scale){ + this.smallValue = smallValue; + this.scale = scale; + this.bitLength = bitLength(smallValue); + } + + private BigDecimal(int smallValue, int scale){ + this.smallValue = smallValue; + this.scale = scale; + this.bitLength = bitLength(smallValue); + } + + /** + * 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 in == null + * @throws NumberFormatException + * if offset < 0 or len <= 0 or offset+len-1 < 0 or offset+len-1 >= + * in.length + * @throws NumberFormatException + * if scale is out of range + * @throws NumberFormatException + * if in does not contain a valid string representation of a big + * decimal. + */ + public BigDecimal(char[] in, int offset, int len) { + int begin = offset; // first index to be copied + int last = offset + (len - 1); // last index to be copied + String scaleString = null; // buffer for scale + StringBuilder unscaledBuffer; // buffer for unscaled value + long newScale; // the new scale + + if (in == null) { + throw new NullPointerException(); + } + if ((last >= in.length) || (offset < 0) || (len <= 0) || (last < 0)) { + throw new NumberFormatException(); + } + unscaledBuffer = new StringBuilder(len); + int bufLength = 0; + // To skip a possible '+' symbol + if ((offset <= last) && (in[offset] == '+')) { + offset++; + begin++; + } + int counter = 0; + boolean wasNonZero = false; + // Accumulating all digits until a possible decimal point + for (; (offset <= last) && (in[offset] != '.') + && (in[offset] != 'e') && (in[offset] != 'E'); offset++) { + if (!wasNonZero) { + if (in[offset] == '0') { + counter++; + } else { + wasNonZero = true; + } + }; + + } + unscaledBuffer.append(in, begin, offset - begin); + bufLength += offset - begin; + // A decimal point was found + if ((offset <= last) && (in[offset] == '.')) { + offset++; + // Accumulating all digits until a possible exponent + begin = offset; + for (; (offset <= last) && (in[offset] != 'e') + && (in[offset] != 'E'); offset++) { + if (!wasNonZero) { + if (in[offset] == '0') { + counter++; + } else { + wasNonZero = true; + } + }; + } + scale = offset - begin; + bufLength +=scale; + unscaledBuffer.append(in, begin, scale); + } else { + scale = 0; + } + // An exponent was found + if ((offset <= last) && ((in[offset] == 'e') || (in[offset] == 'E'))) { + offset++; + // Checking for a possible sign of scale + begin = offset; + if ((offset <= last) && (in[offset] == '+')) { + offset++; + if ((offset <= last) && (in[offset] != '-')) { + begin++; + } + } + // Accumulating all remaining digits + scaleString = String.valueOf(in, begin, last + 1 - begin); + // Checking if the scale is defined + newScale = (long)scale - Integer.parseInt(scaleString); + scale = (int)newScale; + if (newScale != scale) { + // math.02=Scale out of range. + throw new NumberFormatException(Messages.getString("math.02")); //$NON-NLS-1$ + } + } + // Parsing the unscaled value + if (bufLength < 19) { + smallValue = Long.parseLong(unscaledBuffer.toString()); + bitLength = bitLength(smallValue); + } else { + setUnscaledValue(new BigInteger(unscaledBuffer.toString())); + } + precision = unscaledBuffer.length() - counter; + if (unscaledBuffer.charAt(0) == '-') { + precision --; + } + } + + /** + * 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 in == null + * @throws NumberFormatException + * if offset < 0 or len <= 0 or offset+len-1 < 0 or offset+len-1 >= + * in.length + * @throws NumberFormatException + * if scale is out of range + * @throws NumberFormatException + * if in does not contain a valid string representation of a big + * decimal. + * @throws ArithmeticException + * if mc.precision > 0 and 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. + * + * @param in + * array of characters containing the string representation of + * this {@code BigDecimal}. + * @throws NullPointerException + * if in == null + * @throws NumberFormatException + * if scale is out of range + * @throws NumberFormatException + * if 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. 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 in == null + * @throws NumberFormatException + * if scale is out of range + * @throws NumberFormatException + * if in does not contain a valid string representation of a big + * decimal. + * @throws ArithmeticException + * if mc.precision > 0 and 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 a string + * representation. + * + * @param val + * string containing the string representation of this + * {@code BigDecimal}. + * + * @throws NumberFormatException + * if scale is out of range + * @throws NumberFormatException + * if val does not contain a valid string representation of a big + * decimal. + */ + public BigDecimal(String val) { + this(val.toCharArray(), 0, val.length()); + } + + /** + * 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 scale is out of range + * @throws NumberFormatException + * if val does not contain a valid string representation of a big + * decimal. + * @throws ArithmeticException + * if mc.precision > 0 and 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); + } + + /** + * Constructs a new {@code BigDecimal} instance from the 64bit double + * {@code val}. The constructed big decimal is equivalent to the double. + * For example, new BigDecimal(0.1) is equal to + * 0.1000000000000000055511151231257827021181583404541015625. This happens + * as 0.1 cannot be represented exactly in binary. + * + * To generate a big decimal instance which is equivalent to 0.1 use the + * BigDecimal(String) constructor. + * + * @param val + * double value to be converted to a {@code BigDecimal} instance. + * @throws NumberFormatException + * if 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(Messages.getString("math.03")); //$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 { + BigInt bi = new BigInt(); + bi.putLongInt(mantisa); + bi.shift(-scale); + intVal = new BigInteger(bi); + } + 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 double. + * For example, new BigDecimal(0.1) is equal to + * 0.1000000000000000055511151231257827021181583404541015625. This happens + * as 0.1 cannot be represented exactly in binary. + * + * To generate a big decimal instance which is equivalent to 0.1 use the + * 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 val is infinity or not a number. + * @throws ArithmeticException + * if mc.precision > 0 and 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); + } + + /** + * Constructs a new {@code BigDecimal} instance from the given big integer + * {@code val}. The scale of the result is 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 the given big integer + * {@code val}. The scale of the result is 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 mc.precision > 0 and 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 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. + */ + 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 mc.precision > 0 and mc.roundingMode == UNNECESSARY and + * the new big decimal cannot be represented within the given + * precision without rounding. + */ + public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) { + this(unscaledVal, scale); + 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 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 mc.precision > 0 and mc.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 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 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 mc.precision > 0 and 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); + } + + /* Public Methods */ + + /** + * 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); + } + + /** + * Returns a new {@code BigDecimal} instance whose value is equal to + * {@code unscaledVal}. The scale of the result is 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}. + * + * 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, valueOf(0.1) is converted to (unscaled=1, scale=1), although + * the double 0.1 cannot be represented exactly as a double value. In + * contrast to that, a new {@code BigDecimal(0.1)} instance has the value + * 0.1000000000000000055511151231257827021181583404541015625 with an + * unscaled value 1000000000000000055511151231257827021181583404541015625 + * and the scale 55. + * + * @param val + * double value to be converted to a {@code BigDecimal}. + * @return {@code BigDecimal} instance with the value {@code val}. + * @throws NumberFormatException + * if val is infinite or 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(Messages.getString("math.03")); //$NON-NLS-1$ + } + return new BigDecimal(Double.toString(val)); + } + + /** + * 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 augend == null + */ + public BigDecimal add(BigDecimal augend) { + int 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 < 64) { + 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); + } + } + + private static BigDecimal addAndMult10(BigDecimal thisValue,BigDecimal augend, int diffScale) { + if(diffScale < LONG_TEN_POW.length && + Math.max(thisValue.bitLength,augend.bitLength+LONG_TEN_POW_BIT_LENGTH[diffScale])+1<64) { + return valueOf(thisValue.smallValue+augend.smallValue*LONG_TEN_POW[diffScale],thisValue.scale); + } + else { + BigInt bi = Multiplication.multiplyByTenPow(augend.getUnscaledValue(),diffScale).bigInt; + bi.add(thisValue.getUnscaledValue().bigInt); + return new BigDecimal(new BigInteger(bi), thisValue.scale); + } + } + + /** + * 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 augend == 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; + long diffScale = (long)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.aproxPrecision() < diffScale - 1) { + larger = augend; + smaller = this; + } else if (augend.aproxPrecision() < -diffScale - 1) { + larger = this; + smaller = augend; + } else {// No optimization is done + return add(augend).round(mc); + } + if (mc.getPrecision() >= larger.aproxPrecision()) { + // 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 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 subtrahend == null + */ + public BigDecimal subtract(BigDecimal subtrahend) { + int 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 < 64) { + 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 < LONG_TEN_POW.length && + Math.max(this.bitLength,subtrahend.bitLength+LONG_TEN_POW_BIT_LENGTH[diffScale])+1<64) { + return valueOf(this.smallValue-subtrahend.smallValue*LONG_TEN_POW[diffScale],this.scale); + } + return new BigDecimal(this.getUnscaledValue().subtract( + Multiplication.multiplyByTenPow(subtrahend.getUnscaledValue(),diffScale)), this.scale); + } else {// case s2 > s1 : [ u1 * 10 ^ (s2 - s1) - u2 , s2 ] + diffScale = -diffScale; + if(diffScale < LONG_TEN_POW.length && + Math.max(this.bitLength+LONG_TEN_POW_BIT_LENGTH[diffScale],subtrahend.bitLength)+1<64) { + return valueOf(this.smallValue*LONG_TEN_POW[diffScale]-subtrahend.smallValue,subtrahend.scale); + } + return new BigDecimal(Multiplication.multiplyByTenPow(this.getUnscaledValue(),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 subtrahend == null + */ + public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) { + long diffScale = subtrahend.scale - (long)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.aproxPrecision() < diffScale - 1) { + // Cases where it is unnecessary to subtract two numbers with very different scales + if (mc.getPrecision() < this.aproxPrecision()) { + 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 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 multiplicand == null + */ + public BigDecimal multiply(BigDecimal multiplicand) { + long newScale = (long)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 < 64) { + 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 multiplicand == 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 {@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 divisor == null + * @throws IllegalArgumentException + * if roundingMode is not a valid rounding mode + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if 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 divisor == null or roundingMode == null + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if roundingMode == RoundingMode.UNNECESSARY 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(Messages.getString("math.04")); //$NON-NLS-1$ + } + + long diffScale = ((long)this.scale - divisor.scale) - scale; + if(this.bitLength < 64 && divisor.bitLength < 64 ) { + if(diffScale == 0) { + return dividePrimitiveLongs(this.smallValue, + divisor.smallValue, + scale, + roundingMode ); + } else if(diffScale > 0) { + if(diffScale < LONG_TEN_POW.length && + divisor.bitLength + LONG_TEN_POW_BIT_LENGTH[(int)diffScale] < 64) { + return dividePrimitiveLongs(this.smallValue, + divisor.smallValue*LONG_TEN_POW[(int)diffScale], + scale, + roundingMode); + } + } else { // diffScale < 0 + if(-diffScale < LONG_TEN_POW.length && + this.bitLength + LONG_TEN_POW_BIT_LENGTH[(int)-diffScale] < 64) { + return dividePrimitiveLongs(this.smallValue*LONG_TEN_POW[(int)-diffScale], + divisor.smallValue, + scale, + roundingMode); + } + + + } + } + BigInteger scaledDividend = this.getUnscaledValue(); + BigInteger scaledDivisor = divisor.getUnscaledValue(); // for scaling of 'u2' + + if (diffScale > 0) { + // Multiply 'u2' by: 10^((s1 - s2) - scale) + scaledDivisor = Multiplication.multiplyByTenPow(scaledDivisor, (int)diffScale); + } else if (diffScale < 0) { + // Multiply 'u1' by: 10^(scale - (s1 - s2)) + scaledDividend = Multiplication.multiplyByTenPow(scaledDividend, (int)-diffScale); + } + return divideBigIntegers(scaledDividend, scaledDivisor, scale, roundingMode); + } + + 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() < 63) { // 63 in order to avoid out of long after <<1 + 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().shiftLeft(1).compareTo(scaledDivisor.abs()); + compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, + sign * (5 + compRem), roundingMode); + } + if (compRem != 0) { + if(quotient.bitLength() < 63) { + return valueOf(quotient.longValue() + compRem,scale); + } + quotient = quotient.add(BigInteger.valueOf(compRem)); + return new BigDecimal(quotient, scale); + } + // Constructing the result with the appropriate unscaled value + return new BigDecimal(quotient, scale); + } + + private static BigDecimal 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); + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. + * The scale of the result is the scale of 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 divisor == null + * @throws IllegalArgumentException + * if roundingMode is not a valid rounding mode + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if roundingMode == ROUND_UNNECESSARY and rounding is + * necessary according to the scale of this. + */ + public BigDecimal divide(BigDecimal divisor, int roundingMode) { + return divide(divisor, scale, RoundingMode.valueOf(roundingMode)); + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. + * The scale of the result is the scale of 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 divisor == null or roundingMode == null + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if roundingMode == RoundingMode.UNNECESSARY and rounding is + * necessary according to the scale of this. + */ + public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) { + return divide(divisor, scale, roundingMode); + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. + * The scale of the result is the difference of the scales of this and + * divisor. If the exact result requires more digits, then the scale is + * adjusted accordingly. For example, 1/128 = 0.0078125 which has a scale of + * 7 and precision 5. + * + * @param divisor + * value by which {@code this} is divided. + * @return {@code this / divisor}. + * @throws NullPointerException + * if divisor == null + * @throws ArithmeticException + * if 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[]; + long diffScale = (long)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(Messages.getString("math.04")); //$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(Messages.getString("math.05")); //$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 result is rounded according to the passed context {@code mc}. If the + * passed math context specifies precision 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 divisor == null or mc == null + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if mc.getRoundingMode() == UNNECESSARY and rounding is + * necessary according to 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 */ + long traillingZeros = mc.getPrecision() + 2L + + divisor.aproxPrecision() - aproxPrecision(); + long diffScale = (long)scale - divisor.scale; + long 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].shiftLeft(1).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 the integral part of + * {@code this / divisor}. The quotient is rounded down towards zero to the + * next integer. For example, 0.5/0.2 = 2. + * + * @param divisor + * value by which {@code this} is divided. + * + * @return integral part of {@code this / divisor}. + * + * @throws NullPointerException + * if divisor == null + * @throws ArithmeticException + * if divisor == 0 + */ + public BigDecimal divideToIntegralValue(BigDecimal divisor) { + BigInteger integralValue; // the integer of result + BigInteger powerOfTen; // some power of ten + BigInteger quotAndRem[] = {getUnscaledValue()}; + long newScale = (long)this.scale - divisor.scale; + long tempScale = 0; + int i = 1; + int lastPow = TEN_POW.length - 1; + + if (divisor.isZero()) { + // math.04=Division by zero + throw new ArithmeticException(Messages.getString("math.04")); //$NON-NLS-1$ + } + if ((divisor.aproxPrecision() + newScale > this.aproxPrecision() + 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 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 divisor == null or mc == null. + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if 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; + long diffScale = (long)this.scale - divisor.scale; + long newScale = diffScale; + long 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. */ + long exp = Math.min(-diffScale, Math.max((long)mcPrecision - diffPrecision, 0)); + long 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(Messages.getString("math.06")); //$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]); + long 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(Messages.getString("math.06")); //$NON-NLS-1$ + } + integralValue.scale = toIntScale(newScale); + integralValue.setUnscaledValue(strippedBI); + return integralValue; + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this % divisor}. + * + * The remainder is defined as + * {@code this - this.divideToIntegralValue(divisor) * divisor}. + * + * @param divisor + * value by which {@code this} is divided. + * + * @return {@code this % divisor}. + * + * @throws NullPointerException + * if divisor == null + * @throws ArithmeticException + * if divisor == 0 + */ + public BigDecimal remainder(BigDecimal divisor) { + return divideAndRemainder(divisor)[1]; + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this % divisor}. + * + * The remainder is defined as + * {@code this - this.divideToIntegralValue(divisor) * divisor}. + * + * The specified rounding mode {@code mc} is used for the division only. + * + * @param divisor + * value by which {@code this} is divided. + * @param mc + * rounding mode and precision to be used. + * + * @return {@code this % divisor}. + * + * @throws NullPointerException + * if divisor == null + * @throws ArithmeticException + * if divisor == 0 + * @throws ArithmeticException + * if 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 {@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 divisor == null + * @throws ArithmeticException + * if 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 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 divisor == null + * @throws ArithmeticException + * if 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 {@code this ^ n}. The + * scale of the result is n times the scales of this. x.pow(0) returns 1, + * even if x == 0. + * + * @param n + * exponent to which {@code this} is raised. + * + * @return {@code this ^ n}. + * + * @throws ArithmeticException + * if n < 0 or n > 999999999 + */ + public BigDecimal pow(int n) { + if (n == 0) { + return ONE; + } + if ((n < 0) || (n > 999999999)) { + // math.07=Invalid Operation + throw new ArithmeticException(Messages.getString("math.07")); //$NON-NLS-1$ + } + long newScale = scale * (long)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}. TODO add + * algorithm description + * + * @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 n < 0 or 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(Messages.getString("math.07")); //$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 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 the {@code -this}. The + * scale of the result is the same as the scale of this. + * + * @return {@code -this}. + */ + public BigDecimal negate() { + if(bitLength < 63 || (bitLength == 63 && smallValue!=Long.MIN_VALUE)) { + 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 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 this. + */ + public BigDecimal plus(MathContext mc) { + return round(mc); + } + + /** + * Returns the sign of this {@code BigDecimal}. + * + * @return -1 if {@code this < 0}, 0 if {@code this == 0}, 1 if + * {@code this > 0}. + */ + public int signum() { + if( bitLength < 64) { + return Long.signum( this.smallValue ); + } + return getUnscaledValue().signum(); + } + + private boolean isZero() { + //Watch out: -1 has a bitLength=0 + return bitLength == 0 && this.smallValue != -1; + } + + /** + * 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 scale; + } + + /** + * 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 tue unscaled value. The precision of 0 is 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 bitLength = this.bitLength; + 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 >= 64) { + doubleUnsc = getUnscaledValue().doubleValue(); + } else if (bitLength >= 1) { + doubleUnsc = smallValue; + } + decimalDigits += Math.log10(Math.abs(doubleUnsc)); + } else {// (bitLength >= 1024) + /* To calculate the precision for large numbers + * Note that: 2 ^(bitlength() - 1) <= intVal < 10 ^(precision()) */ + decimalDigits += (bitLength - 1) * LOG10_2; + // If after division the number isn't zero, exists an aditional digit + if (getUnscaledValue().divide(Multiplication.powerOf10(decimalDigits)).signum() != 0) { + decimalDigits++; + } + } + precision = decimalDigits; + return precision; + } + + /** + * Returns the unscaled value (mantissa) of this {@code BigDecimal} instance + * as a {@code BigInteger}. The unscaled value can be computed as this * + * 10^{scale}. + * + * @return unscaled value (this * 10^(scale)). + */ + public BigInteger unscaledValue() { + return getUnscaledValue(); + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this}, rounded + * according to the passed context {@code mc}. + * + * If mc.precision = 0, then no rounding. + * + * If mc.precision > 0 and mc.roundingMode == UNNECESSARY, then an + * 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 this rounded according to the passed context. + * + * @throws ArithmeticException + * if mc.precision > 0 and 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 a new {@code BigDecimal} instance with the specified scale. + * + * If new new scale is greater than the old scale, then additional zeros are + * added to the unscaled value. In this case no rounding is necessary. + * + * If the new scale is smaller than the old scale, then trailing digits are + * removed. If these trailing digits are not zero, then the remaining + * unscaled value has to be rounded. For this rounding operation the + * specified rounding mode is used. + * + * @param newScale + * scale of the result returned. + * @param roundingMode + * rounding mode to be used to round the result. + * + * @return a new {@code BigDecimal} instance with the specified scale. + * + * @throws NullPointerException + * if roundingMode == null + * @throws ArithmeticException + * if 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(); + } + long diffScale = newScale - (long)scale; + // Let be: 'this' = [u,s] + if(diffScale == 0) { + return this; + } + if(diffScale > 0) { + // return [u * 10^(s2 - s), newScale] + if(diffScale < LONG_TEN_POW.length && + (this.bitLength + LONG_TEN_POW_BIT_LENGTH[(int)diffScale]) < 64 ) { + return valueOf(this.smallValue*LONG_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 < 64 && -diffScale < LONG_TEN_POW.length) { + return dividePrimitiveLongs(this.smallValue, LONG_TEN_POW[(int)-diffScale], newScale,roundingMode); + } + return divideBigIntegers(this.getUnscaledValue(),Multiplication.powerOf10(-diffScale),newScale,roundingMode); + } + + /** + * Returns a new {@code BigDecimal} instance with the specified scale. + * + * If new new scale is greater than the old scale, then additional zeros are + * added to the unscaled value. In this case no rounding is necessary. + * + * If the new scale is smaller than the old scale, then trailing digits are + * removed. If these trailing digits are not zero, then the remaining + * unscaled value has to be rounded. For this rounding operation the + * specified rounding mode is used. + * + * @param newScale + * scale of the result returned. + * @param roundingMode + * rounding mode to be used to round the result. + * + * @return a new {@code BigDecimal} instance with the specified scale. + * + * @throws IllegalArgumentException + * if roundingMode is not a valid rounding mode + * @throws ArithmeticException + * if roundingMode == ROUND_UNNECESSARY and rounding is + * necessary according to the given scale. + */ + public BigDecimal setScale(int newScale, int roundingMode) { + return setScale(newScale, RoundingMode.valueOf(roundingMode)); + } + + /** + * Returns a new {@code BigDecimal} instance with the specified scale. If + * new new scale is greater than the old scale, then additional zeros are + * added to the unscaled value. If the new scale is smaller than the old + * scale, then trailing zeros are removed. If the trailing digits are not + * zeros then an ArithmeticException is thrown. + * + * If no exception is thrown, then the following equation holds: + * 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 where the decimal point has + * been moved {@code n} places to the left. If n < 0 then the decimal point + * is moved -n places to the right. + * + * The result is obtained by changing its scale. If the scale of the result + * becomes negative, then its precision is increased such that the scale is + * zero. + * + * Note, that {@code movePointLeft(0)} returns a result which is + * mathematically equivalent, but which has scale >= 0. + * + * @param n + * number of placed the decimal point has to be moved. + * + * @return this * 10^{-n}. + */ + public BigDecimal movePointLeft(int n) { + return movePoint(scale + (long) n); + } + + private BigDecimal movePoint(long 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 < 64) { + return valueOf(smallValue,toIntScale(newScale)); + } + return new BigDecimal(getUnscaledValue(), toIntScale(newScale)); + } + if(-newScale < LONG_TEN_POW.length && + bitLength + LONG_TEN_POW_BIT_LENGTH[(int)-newScale] < 64 ) { + return valueOf(smallValue*LONG_TEN_POW[(int)-newScale],0); + } + return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),(int)-newScale), 0); + } + + /** + * Returns a new {@code BigDecimal} instance where the decimal point has + * been moved {@code n} places to the right. If n < 0 then the decimal point + * is moved -n places to the left. + * + * The result is obtained by changing its scale. If the scale of the result + * becomes negative, then its precision is increased such that the scale is + * zero. + * + * Note, that {@code movePointRight(0)} returns a result which is + * mathematically equivalent, but which has scale >= 0. + * + * @param n + * number of placed the decimal point has to be moved. + * + * @return this * 10^{n}. + */ + public BigDecimal movePointRight(int n) { + return movePoint(scale - (long)n); + } + + /** + * Returns a new {@code BigDecimal} whose value is {@code this} * 10^{@code n}. + * The scale of the result is {@code this.scale()} - n. The precision of the + * result is the precision of {@code this}. + * + * This method has the same effect as movePointLeft, except that the + * precision is not changed. + * + * @param n + * number of placed the decimal point has to be moved. + * + * @return this * 10^{-n}. + */ + public BigDecimal scaleByPowerOfTen(int n) { + long newScale = scale - (long)n; + if(bitLength < 64) { + //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 same value as 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; + long 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)); + } + + /** + * Compares this {@code BigDecimal} with {@code val}. Returns one of the + * three values 1, 0, or -1. The method behaves as if 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 1 if this > val, -1 if this < val, 0 if this == val. + * + * @throws NullPointerException + * if val == null + */ + public int compareTo(BigDecimal val) { + int thisSign = signum(); + int valueSign = val.signum(); + + if( thisSign == valueSign) { + if(this.scale == val.scale && this.bitLength<64 && val.bitLength<64 ) { + return (smallValue < val.smallValue) ? -1 : (smallValue > val.smallValue) ? 1 : 0; + } + long diffScale = (long)this.scale - val.scale; + int diffPrecision = this.aproxPrecision() - val.aproxPrecision(); + 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 {@code true} if {@code x} is a BigDecimal instance and if this + * instance is equal to this {@code BigDecimal}. 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 x is a BigDecimal and 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 < 64 ? (x1.smallValue == smallValue) : intVal + .equals(x1.intVal)); + + } + return false; + } + + /** + * 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 val == null + */ + public BigDecimal min(BigDecimal val) { + return ((compareTo(val) <= 0) ? this : val); + } + + /** + * 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 val == null + */ + public BigDecimal max(BigDecimal val) { + return ((compareTo(val) >= 0) ? this : val); + } + + /** + * Returns a hash code for this {@code BigDecimal}. + * + * @return hash code for this. + */ + @Override + public int hashCode() { + if (hashCode != 0) { + return hashCode; + } + if (bitLength < 64) { + hashCode = (int)(smallValue & 0xffffffff); + hashCode = 33 * hashCode + (int)((smallValue >> 32) & 0xffffffff); + hashCode = 17 * hashCode + scale; + return hashCode; + } + hashCode = 17 * intVal.hashCode() + scale; + return hashCode; + } + + /** + * Returns a canonical string representation of this {@code BigDecimal}. If + * necessary, scientific notation is used. This representation always prints + * all significant digits of this value. + * + * If the scale is negative or if 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) { + toStringImage = Conversion.toDecimalScaledString(smallValue,scale); + return toStringImage; + } + String intString = getUnscaledValue().toString(); + if (scale == 0) { + return intString; + } + int begin = (getUnscaledValue().signum() < 0) ? 2 : 1; + int end = intString.length(); + long exponent = -(long)scale + end - begin; + StringBuffer result = new StringBuffer(); + + result.append(intString); + if ((scale > 0) && (exponent >= -6)) { + if (exponent >= 0) { + result.insert(end - 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(exponent)); + } + toStringImage = result.toString(); + return toStringImage; + } + + /** + * Returns a string representation of this {@code BigDecimal}. This + * representation always prints all significant digits of this value. + * + * If the scale is negative or if 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(); + long exponent = -(long)scale + end - begin; + StringBuffer result = new StringBuffer(intString); + + if ((scale > 0) && (exponent >= -6)) { + if (exponent >= 0) { + result.insert(end - 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(exponent)); + } + } + return result.toString(); + } + + /** + * Returns a string representation of this {@code BigDecimal}. No + * scientific notation is used. This methods adds zeros where necessary. + * + * If this string representation is used to create a new instance, this + * instance is generally not identical to {@code this} as the precision + * changes. + * + * x.equals(new BigDecimal(x.toPlainString()) usually returns false. + * + * x.compareTo(new BigDecimal(x.toPlainString()) returns 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; + int delta = scale; + // We take space for all digits, plus a possible decimal point, plus 'scale' + StringBuffer result = new StringBuffer(intStr.length() + 1 + Math.abs(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, delta); + result.append(intStr.substring(begin)); + } else { + delta = begin - delta; + result.append(intStr.substring(begin, delta)); + result.append('.'); + result.append(intStr.substring(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, -delta); + } + return result.toString(); + } + + /** + * 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(-(long)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(-(long)scale)); + } else {// (scale > 0) + BigInteger[] integerAndFraction; + // An optimization before do a heavy division + if ((scale > aproxPrecision()) || (scale > getUnscaledValue().getLowestSetBit())) { + // math.08=Rounding necessary + throw new ArithmeticException(Messages.getString("math.08")); //$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(Messages.getString("math.08")); //$NON-NLS-1$ + } + return integerAndFraction[0]; + } + } + + /** + * 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 > aproxPrecision()) ? 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 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 > aproxPrecision()) ? 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 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 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); + } + + /** + * Returns this {@code BigDecimal} as a float value. If {@code this} is too + * big to be represented as an float, then {@code Float.POSITIVE_INFINITY} + * or {@code Float.NEGATIVE_INFINITY} is returned. + * + * Note, that if the unscaled value has more than 24 significant digits, + * then this decimal cannot be represented exactly in a float variable. In + * this case the result is rounded. + * + * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be + * represented exactly as a float, and thus x1.equals(new + * BigDecimal(x1.folatValue()) returns false for this case. + * + * Similarly, if the instance {@code new BigDecimal(16777217)} is converted + * to a float, the result is 1.6777216E7. + * + * @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(); + long powerOfTwo = this.bitLength - (long)(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 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. + * + * Note, that if the unscaled value has more than 53 significant digits, + * then this decimal cannot be represented exactly in a double variable. In + * this case the result is rounded. + * + * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be + * represented exactly as a double, and thus x1.equals(new + * BigDecimal(x1.doubleValue()) returns false for this case. + * + * Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is + * converted to a double, the result is 9.007199254740992E15. + * + * @return this {@code BigDecimal} as a double value. + */ + @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].shiftLeft(1).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 the unit in the last place (ULP) of this {@code BigDecimal} + * instance. An ULP is the distance to the nearest big decimal with the same + * precision. + * + * The amount of a rounding error in the evaluation of a floating-point + * operation is often expressed in ULPs. An error of 1 ULP is often seen as + * a tolerable error. + * + * For class BigDecimal, the ULP of a number is simply 10^{-scale}. + * + * For example, {@code new BigDecimal(0.1).ulp()} returns {@code 1E-55}. + * + * @return unit in the last place (ULP) of this {@code BigDecimal} instance. + */ + public BigDecimal ulp() { + return valueOf(1, scale); + } + + /* Private Methods */ + + /** + * It does all rounding work of the public method + * <code>round(MathContext)</code>, performing an inplace rounding + * without creating a new object. + * + * @param mc + * the <code>MathContext</code> for perform the rounding. + * @see #round(MathContext) + */ + private void inplaceRound(MathContext mc) { + int mcPrecision = mc.getPrecision(); + if (aproxPrecision() - 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 < 64) { + smallRound(mc, discardedPrecision); + return; + } + // Getting the integer part and the discarded fraction + BigInteger sizeOfFraction = Multiplication.powerOf10(discardedPrecision); + BigInteger[] integerAndFraction = getUnscaledValue().divideAndRemainder(sizeOfFraction); + long newScale = (long)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().shiftLeft(1).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 static int longCompareTo(long value1, long value2) { + return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0); + } + + /** + * This method implements an efficient rounding for numbers which unscaled + * value fits in the type <code>long</code>. + * + * @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_TEN_POW[discardedPrecision]; + long newScale = (long)scale - discardedPrecision; + long unscaledVal = smallValue; + // 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; + } + + /** + * Return an increment that can be -1,0 or 1, depending of + * <code>roundingMode</code>. + * + * @param parityBit + * can be 0 or 1, it's only used in the case + * <code>HALF_EVEN</code>. + * @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(Messages.getString("math.08")); //$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; + } + + /** + * If <code>intVal</code> 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</code>, 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</code> + * when is possible. + * @throws <code>ArithmeticException</code> 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(Messages.getString("math.08")); //$NON-NLS-1$ + } + + /** + * 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()</code> or <code>precision()-1</code> + * in the worst case. + * + * @return an approximation of <code>precision()</code> value + */ + private int aproxPrecision() { + // return ((precision > 0) + // ? precision + // : (int)((this.bitLength - 1) * LOG10_2)) + 1; + return precision > 0 + ? precision + : (int) ((this.bitLength - 1) * LOG10_2) + 1; + } + + /** + * It tests if a scale of type <code>long</code> fits in 32 bits. It + * returns the same scale being casted to <code>int</code> type when is + * possible, otherwise throws an exception. + * + * @param longScale + * a 64 bit scale. + * @return a 32 bit scale when is possible. + * @throws <code>ArithmeticException</code> when <code>scale</code> doesn't + * fit in <code>int</code> type. + * @see #scale + */ + private static int toIntScale(long longScale) { + if (longScale < Integer.MIN_VALUE) { + // math.09=Overflow + throw new ArithmeticException(Messages.getString("math.09")); //$NON-NLS-1$ + } else if (longScale > Integer.MAX_VALUE) { + // math.0A=Underflow + throw new ArithmeticException(Messages.getString("math.0A")); //$NON-NLS-1$ + } else { + return (int)longScale; + } + } + + /** + * It returns the value 0 with the most approximated scale of type + * <code>int</code>. if <code>longScale > Integer.MAX_VALUE</code> the + * scale will be <code>Integer.MAX_VALUE</code>; if + * <code>longScale < Integer.MIN_VALUE</code> the scale will be + * <code>Integer.MIN_VALUE</code>; otherwise <code>longScale</code> is + * casted to the type <code>int</code>. + * + * @param longScale + * the scale to which the value 0 will be scaled. + * @return the value 0 scaled by the closer scale of type <code>int</code>. + * @see #scale + */ + private static BigDecimal zeroScaledBy(long longScale) { + if (longScale == (int) longScale) { + return valueOf(0,(int)longScale); + } + if (longScale >= 0) { + return new BigDecimal( 0, Integer.MAX_VALUE); + } + return new BigDecimal( 0, Integer.MIN_VALUE); + } + + /** + * Assignes all transient fields upon deserialization of a + * {@code BigDecimal} instance (bitLength and smallValue). The transient + * field precision is assigned lazily. + */ + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + + this.bitLength = intVal.bitLength(); + if (this.bitLength < 64) { + this.smallValue = intVal.longValue(); + } + } + + /** + * Prepares this {@code BigDecimal} for serialization, i.e. the + * non-transient field {@code intVal} is assigned. + */ + private void writeObject(ObjectOutputStream out) throws IOException { + getUnscaledValue(); + out.defaultWriteObject(); + } + + private BigInteger getUnscaledValue() { + if(intVal == null) { + intVal = BigInteger.valueOf(smallValue); + } + return intVal; + } + + private void setUnscaledValue(BigInteger unscaledValue) { + this.intVal = unscaledValue; + this.bitLength = unscaledValue.bitLength(); + if(this.bitLength < 64) { + this.smallValue = unscaledValue.longValue(); + } + } + + private static int bitLength(long smallValue) { + if(smallValue < 0) { + smallValue = ~smallValue; + } + return 64 - Long.numberOfLeadingZeros(smallValue); + } + + private static int bitLength(int smallValue) { + if(smallValue < 0) { + smallValue = ~smallValue; + } + return 32 - Integer.numberOfLeadingZeros(smallValue); + } + +} diff --git a/math/src/main/java/java/math/BigInt.java b/math/src/main/java/java/math/BigInt.java new file mode 100644 index 0000000..4582e13 --- /dev/null +++ b/math/src/main/java/java/math/BigInt.java @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.math; + +import org.apache.harmony.math.internal.nls.Messages; +import org.openssl.NativeBN; + +import java.util.Random; + +/** + * In contrast to BigIntegers this class doesn't fake two's complement representation. + * Any Bit-Operations, including Shifting, solely regard the unsigned magnitude. + * Moreover BigInt objects are mutable and offer efficient in-place-operations. + **/ + +class BigInt +// extends Number +// implements Comparable<BigInt>, +// Serializable +{ + + class Context { + int bnctx; + Context() { + bnctx = NativeBN.BN_CTX_new(); + } + } + static BigInt dummy; + static Context defaultContext; + + static { + dummy = new BigInt(); + defaultContext = dummy.new Context(); + } + + static int getCtx (Context t) { + return (t != null) ? t.bnctx : defaultContext.bnctx; + } + + /** This is the serialVersionUID used by the sun implementation */ + private static final long serialVersionUID = -8287574255936472291L; + + /* Fields used for the internal representation. */ + transient int bignum = 0; + + + public void dispose() { + if (this.bignum != 0) { + NativeBN.BN_free(this.bignum); + this.bignum = 0; + } + } + + @Override + protected void finalize() { + dispose(); + } + + @Override + public String toString() { + return this.decString(); + } + + public int getNativeBIGNUM() { + return this.bignum; + } + + public static int consumeErrors(StringBuilder sb) { + int cnt = 0; + int e, reason; + boolean first = true; + while ((e = NativeBN.ERR_get_error()) != 0) { + reason = e & 255; + if (reason == 103) { + // math.17=BigInteger divide by zero + throw new ArithmeticException(Messages.getString("math.17")); //$NON-NLS-1$ + } + if (reason == 108) { + // math.19=BigInteger not invertible. + throw new ArithmeticException(Messages.getString("math.19")); //$NON-NLS-1$ + } + if (reason == 65) { + throw new OutOfMemoryError(); + } + if (!first) { sb.append(" *** "); first = false; } + sb.append(e).append(": "); + String s = NativeBN.ERR_error_string(e); + sb.append(s); + cnt++; + } + return cnt; + } + + private static void Check(boolean success) { + if (!success) { + StringBuilder sb = new StringBuilder("(openssl)ERR: "); + int cnt = consumeErrors(sb); + if (cnt > 0) + throw new ArithmeticException(sb.toString()); + } + } + + + private void makeValid() { + if (this.bignum == 0) { + this.bignum = NativeBN.BN_new(); + Check(this.bignum != 0); + } + } + + private static BigInt newBigInt() { + BigInt bi = new BigInt(); + bi.bignum = NativeBN.BN_new(); + Check(bi.bignum != 0); + return bi; + } + + + public static int cmp(BigInt a, BigInt b) { + return NativeBN.BN_cmp(a.bignum, b.bignum); + } + + + public void putCopy(BigInt from) { + this.makeValid(); + Check(NativeBN.BN_copy(this.bignum, from.bignum)); + } + + public BigInt copy() { + BigInt bi = new BigInt(); + bi.putCopy(this); + return bi; + } + + + public void putLongInt(long val) { + this.makeValid(); + Check(NativeBN.putLongInt(this.bignum, val)); + } + + public void putULongInt(long val, boolean neg) { + this.makeValid(); + Check(NativeBN.putULongInt(this.bignum, val, neg)); + } + + public void putDecString(String str) { + if (str == null) throw new NullPointerException(); + if (str.length() == 0) { + // math.12=Zero length BigInteger + throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$ + } + this.makeValid(); + int usedLen = NativeBN.BN_dec2bn(this.bignum, str); + Check((usedLen > 0)); + if (usedLen < str.length()) { + throw new NumberFormatException(str); + } + } + + public void putHexString(String str) { + if (str == null) throw new NullPointerException(); + if (str.length() == 0) { + // math.12=Zero length BigInteger + throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$ + } + this.makeValid(); + int usedLen = NativeBN.BN_hex2bn(this.bignum, str); + Check((usedLen > 0)); + if (usedLen < str.length()) { + throw new NumberFormatException(str); + } + } + + public void putBigEndian(byte[] a, boolean neg) { + this.makeValid(); + Check(NativeBN.BN_bin2bn(a, a.length, neg, this.bignum)); + } + + public void putLittleEndianInts(int[] a, boolean neg) { + this.makeValid(); + Check(NativeBN.litEndInts2bn(a, a.length, neg, this.bignum)); + } + + public void putBigEndianTwosComplement(byte[] a) { + this.makeValid(); + Check(NativeBN.twosComp2bn(a, a.length, this.bignum)); + } + + + public long longInt() { + return NativeBN.longInt(this.bignum); + } + + public String decString() { + String str = NativeBN.BN_bn2dec(this.bignum); + return str; + } + + public String hexString() { + String str = NativeBN.BN_bn2hex(this.bignum); + return str; + } + + public byte[] bigEndianMagnitude() { + byte[] a = NativeBN.BN_bn2bin(this.bignum, null); + return a; + } + + public int[] littleEndianIntsMagnitude() { + int[] a = NativeBN.bn2litEndInts(this.bignum, null); + return a; + } + + public byte[] bigEndianTwosComplement() { + byte[] a = NativeBN.bn2twosComp(this.bignum, null); + return a; + } + + + public int sign() { + return NativeBN.sign(this.bignum); + } + + public void setSign(int val) { + if (val > 0) NativeBN.BN_set_negative(this.bignum, 0); + else if (val < 0) NativeBN.BN_set_negative(this.bignum, 1); + } + + + public boolean twosCompFitsIntoBytes(int byteCnt) { + return NativeBN.twosCompFitsIntoBytes(this.bignum, byteCnt); + } + + public int bitLength() { + return NativeBN.bitLength(this.bignum); + } + + public boolean isBitSet(int n) { + return NativeBN.BN_is_bit_set(this.bignum, n); + } + + public void modifyBit(int n, int op) { + // op: 0 = reset; 1 = set; -1 = flip + Check(NativeBN.modifyBit(this.bignum, n, op)); + } + + + // n > 0: shift left (multiply) + public static BigInt shift(BigInt a, int n) { + BigInt r = newBigInt(); + Check(NativeBN.BN_lshift(r.bignum, a.bignum, n)); + return r; + } + + public void shift(int n) { + Check(NativeBN.BN_lshift(this.bignum, this.bignum, n)); + } + + public void addPositiveInt(int w) { + Check(NativeBN.BN_add_word(this.bignum, w)); + } + + public void subtractPositiveInt(int w) { + Check(NativeBN.BN_sub_word(this.bignum, w)); + } + + public void multiplyByPositiveInt(int w) { + Check(NativeBN.BN_mul_word(this.bignum, w)); + } + + public int divideByPositiveInt(int w) { + int rem = NativeBN.BN_div_word(this.bignum, w); + Check(rem != -1); + return rem; + } + + public static int remainderByPositiveInt(BigInt a, int w) { + int rem = NativeBN.BN_mod_word(a.bignum, w); + Check(rem != -1); + return rem; + } + + public static BigInt addition(BigInt a, BigInt b) { + BigInt r = newBigInt(); + Check(NativeBN.BN_add(r.bignum, a.bignum, b.bignum)); + return r; + } + + public void add(BigInt a) { + Check(NativeBN.BN_add(this.bignum, this.bignum, a.bignum)); + } + + public static BigInt subtraction(BigInt a, BigInt b) { + BigInt r = newBigInt(); + Check(NativeBN.BN_sub(r.bignum, a.bignum, b.bignum)); + return r; + } + + + public static BigInt gcd(BigInt a, BigInt b, Context t) { + BigInt r = newBigInt(); + Check(NativeBN.BN_gcd(r.bignum, a.bignum, b.bignum, getCtx(t))); + return r; + } + + public static BigInt product(BigInt a, BigInt b, Context t) { + BigInt r = newBigInt(); + Check(NativeBN.BN_mul(r.bignum, a.bignum, b.bignum, getCtx(t))); + return r; + } + + public void multiplyBy(BigInt a, Context t) { + Check(NativeBN.BN_mul(this.bignum, this.bignum, a.bignum, getCtx(t))); + } + + public static BigInt bigExp(BigInt a, BigInt p, Context t) { + // Sign of p is ignored! + BigInt r = newBigInt(); + Check(NativeBN.BN_exp(r.bignum, a.bignum, p.bignum, getCtx(t))); + return r; + } + + public static BigInt exp(BigInt a, int p, Context t) { + // Sign of p is ignored! + BigInt power = new BigInt(); + power.putLongInt(p); + return bigExp(a, power, t); + // OPTIONAL: +// public int BN_sqr(BigInteger r, BigInteger a, BN_CTX ctx); + // int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx); + } + + public static void division(BigInt dividend, BigInt divisor, Context t, + BigInt quotient, BigInt remainder) { + int quot, rem; + if (quotient != null) { + quotient.makeValid(); + quot = quotient.bignum; + } + else quot = 0; + if (remainder != null) { + remainder.makeValid(); + rem = remainder.bignum; + } + else rem = 0; + Check(NativeBN.BN_div(quot, rem, dividend.bignum, divisor.bignum, getCtx(t))); + } + + public static BigInt modulus(BigInt a, BigInt m, Context t) { + // Sign of p is ignored! ? + BigInt r = newBigInt(); + Check(NativeBN.BN_nnmod(r.bignum, a.bignum, m.bignum, getCtx(t))); + return r; + } + + public static BigInt modExp(BigInt a, BigInt p, BigInt m, Context t) { + // Sign of p is ignored! + BigInt r = newBigInt(); + Check(NativeBN.BN_mod_exp(r.bignum, a.bignum, p.bignum, m.bignum, getCtx(t))); + + // OPTIONAL: + // int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); + return r; + } + + + public static BigInt modInverse(BigInt a, BigInt m, Context t) { + BigInt r = newBigInt(); + Check(NativeBN.BN_mod_inverse(r.bignum, a.bignum, m.bignum, getCtx(t))); + return r; + } + + + public static BigInt generatePrimeDefault(int bitLength, Random rnd, Context t) { + BigInt r = newBigInt(); + Check(NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0)); + return r; + } + + public boolean isPrime(int certainty, Random rnd, Context t) { + return NativeBN.BN_is_prime_ex(bignum, certainty, getCtx(t), 0); + } +} diff --git a/math/src/main/java/java/math/BigInteger.java b/math/src/main/java/java/math/BigInteger.java new file mode 100644 index 0000000..c66dff8 --- /dev/null +++ b/math/src/main/java/java/math/BigInteger.java @@ -0,0 +1,1510 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +/* + * Since the original Harmony Code of the BigInteger class was strongly modified, + * in order to use the more efficient OpenSSL BIGNUM implementation, + * no android-modification-tags were placed, at all. + */ + +package java.math; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Random; +import java.io.Serializable; + +import org.apache.harmony.math.internal.nls.Messages; + +/** + * Class which represents immutable arbitrary precision integer numbers. + * This class provides methods for arithmetic operations and methods + * for the comparison of two instances. + */ +public class BigInteger extends Number implements Comparable<BigInteger>, + Serializable { + + /** This is the serialVersionUID used by the sun implementation */ + private static final long serialVersionUID = -8287574255936472291L; + + transient BigInt bigInt; + transient private boolean bigIntIsValid = false; + transient private boolean oldReprIsValid = false; + + void establishOldRepresentation(String caller) { + if (!oldReprIsValid) { +// System.out.print(" establishing OLD Repr NOW for "); +// System.out.println(caller); + sign = bigInt.sign(); + if (sign != 0) digits = bigInt.littleEndianIntsMagnitude(); + else digits = new int[] { 0 }; + numberLength = digits.length; + oldReprIsValid = true; + } + } + + // The name is confusing: + // This method is called whenever the old representation has been written. + // It ensures that the new representation will be established on demand. + // + BigInteger withNewRepresentation(String caller) { +// System.out.print("BigInteger.withNewRepresentation called by "); +// System.out.println(caller); + bigIntIsValid = false; + return this; + } + + void validate(String caller, String param) { + if (bigIntIsValid) { + if (bigInt == null) + System.out.print("Claiming bigIntIsValid BUT bigInt == null, "); + else if (bigInt.getNativeBIGNUM() == 0) + System.out.print("Claiming bigIntIsValid BUT bigInt.bignum == 0, "); + } + else { +// System.out.print("Validating for "); +// System.out.print(caller); +// System.out.print(" @ "); +// System.out.print(param); +// System.out.print(": "); +// System.out.print("bigInt is NOT valid, "); +// if (bigInt == null) System.out.print("bigInt == null, "); +// else if (bigInt.getNativeBIGNUM() == 0) System.out.print("bigInt.bignum == 0, "); + if (oldReprIsValid) { + // establishNewRepresentation(); +// System.out.println(" establishing NEW Repr FROM OLD NOW!"); +// if (bigInt != null) { +// System.out.println(" EVENTHOUGH A NEW REPR ALREADY EXISTS!!!"); +// } + if (bigInt == null) bigInt = new BigInt(); + bigInt.putLittleEndianInts(digits, (sign < 0)); + bigIntIsValid = true; + } + else { +// System.out.println("AND oldRepr is NOT valid, either!"); + throw new IllegalArgumentException(caller + ":" + param); + } + } + } + + static void validate1(String caller, BigInteger a) { +// System.out.print("Validating for "); +// System.out.println(caller); + a.validate(caller, "1"); + } + + static void validate2(String caller, BigInteger a, BigInteger b) { +// System.out.print("Validating for "); +// System.out.println(caller); + a.validate(caller, "1"); + b.validate(caller, "2"); + } + + static void validate3(String caller, BigInteger a, BigInteger b, BigInteger c) { +// System.out.print("Validating for "); +// System.out.println(caller); + a.validate(caller, "1"); + b.validate(caller, "2"); + c.validate(caller, "3"); + } + + static void validate4(String caller, BigInteger a, BigInteger b, BigInteger c, BigInteger d) { +// System.out.print("Validating for "); +// System.out.println(caller); + a.validate(caller, "1"); + b.validate(caller, "2"); + c.validate(caller, "3"); + d.validate(caller, "4"); + } + + /** The magnitude of this in the little-endian representation. */ + 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; + + + /* Static Fields */ + + /** + * The {@code BigInteger} constant 0. + * + * @since 1.2 + */ + public static final BigInteger ZERO = new BigInteger(0, 0); + + /** + * The {@code BigInteger} constatn 1. + * + * @since 1.2 + */ + public static final BigInteger ONE = new BigInteger(1, 1); + + /** + * The {@code BigInteger} constant 10. + * + * @since 1.5 + */ + public static final BigInteger TEN = new BigInteger(1, 10); + + /** The {@code BigInteger} constant -1. */ + static final BigInteger MINUS_ONE = new BigInteger(-1, 1); + + /** 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; + + /** 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 }; + + /**/ + private transient int firstNonzeroDigit = -2; + + + /* Serialized Fields */ + + /** sign field, used for serialization */ + private int signum; + + /** absolute value field, used for serialization */ + private byte[] magnitude; + + /** Cache for the hash code. */ + private transient int hashCode = 0; + + + /* Package Constructors */ + + BigInteger(BigInt a) { + bigInt = a; + bigIntIsValid = true; + validate("BigInteger(BigInt)", "this"); + // !oldReprIsValid + } + + BigInteger(int sign, long value) { + bigInt = new BigInt(); + bigInt.putULongInt(value, (sign < 0)); + bigIntIsValid = true; + // !oldReprIsValid + } + + + /** + * 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; + oldReprIsValid = true; + withNewRepresentation("BigInteger(int sign, int numberLength, int[] digits)"); + } + + + /* Public Constructors */ + + /** + * Constructs a random non-negative {@code BigInteger} instance in the range + * [0, 2^(numBits)-1]. + * + * @param numBits + * maximum lenght of the new {@code BigInteger} in bits. + * @param rnd + * random generator used to generate the new {@code BigInteger}. + * @throws IllegalArgumentException + * if numBits < 0 + */ + public BigInteger(int numBits, Random rnd) { + if (numBits < 0) { + // math.1B=numBits must be non-negative + throw new IllegalArgumentException(Messages.getString("math.1B")); //$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(); + } + oldReprIsValid = true; + withNewRepresentation("BigInteger(int numBits, Random rnd)"); + } + + /** + * Constructs 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^certainty). + * + * @param bitLength + * lenght of the new {@code BigInteger} in bits. + * @param certainty + * tolerated primality uncertainty. + * @param rnd + * random generator used to generate the new {@code BigInteger}. + * @throws IllegalArgumentException + * if bitLength < 2 + */ + public BigInteger(int bitLength, int certainty, Random rnd) { + if (bitLength < 2) { + // math.1C=bitLength < 2 + throw new ArithmeticException(Messages.getString("math.1C")); //$NON-NLS-1$ + } + bigInt = BigInt.generatePrimeDefault(bitLength, rnd, null); + bigIntIsValid = true; + // !oldReprIsValid + } + + /** + * 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 val == null. + * @throws NumberFormatException + * if val is not a valid representation of a {@code BigInteger}. + */ + public BigInteger(String val) { + bigInt = new BigInt(); + bigInt.putDecString(val); + bigIntIsValid = true; + // !oldReprIsValid + } + + /** + * 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 val == null + * @throws NumberFormatException + * if val is not a valid representation of a {@code BigInteger} + * or if radix < Character.MIN_RADIX or radix > + * Character.MAX_RADIX. + */ + public BigInteger(String val, int radix) { + if (val == null) { + throw new NullPointerException(); + } + if (radix == 10) { + bigInt = new BigInt(); + bigInt.putDecString(val); + bigIntIsValid = true; + // !oldReprIsValid + } else if (radix == 16) { + bigInt = new BigInt(); + bigInt.putHexString(val); + bigIntIsValid = true; + // !oldReprIsValid + } else { + if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX)) { + // math.11=Radix out of range + throw new NumberFormatException(Messages.getString("math.11")); //$NON-NLS-1$ + } + if (val.length() == 0) { + // math.12=Zero length BigInteger + throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$ + } + this.setFromString(this, val, radix); + // oldReprIsValid == true; + } + } + + /** + * 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 magnitude == null + * @throws NumberFormatException + * if the sign is not one of -1, 0, 1 or if the sign is zero and + * the magnitute 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(Messages.getString("math.13")); //$NON-NLS-1$ + } + if (signum == 0) { + for (byte element : magnitude) { + if (element != 0) { + // math.14=signum-magnitude mismatch + throw new NumberFormatException(Messages.getString("math.14")); //$NON-NLS-1$ + } + } + } + bigInt = new BigInt(); + bigInt.putBigEndian(magnitude, (signum < 0)); + bigIntIsValid = true; + } + + /** + * 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 val == null + * @throws NumberFormatException + * if the lenght of val == 0. + */ + public BigInteger(byte[] val) { + if (val.length == 0) { + // math.12=Zero length BigInteger + throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$ + } + bigInt = new BigInt(); + bigInt.putBigEndianTwosComplement(val); + bigIntIsValid = true; + } + + + /* Public Methods */ + + /** + * Creates a new {@code BigInteger} whose value is equal to the specified + * {@code long} argument. + * + * @param val + * the value of the new {@code BigInteger}. + * @return {@code BigInteger} instance with the value {@code val}. + */ + 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); + } + } + + /** + * Returns the two's complement representation of this BigInteger in a byte + * array. + * + * @return two's complement representation of {@code this}. + */ + public byte[] toByteArray() { +// validate1("toByteArray()", this); +// return bigInt.bigEndianTwosComplement(); + return twosComplement(); + } + + /** + * Returns a (new) {@code BigInteger} whose value is the absolute value of + * {@code this}. + * + * @return {@code abs(this)} + */ + public BigInteger abs() { + validate1("abs()", this); + if (bigInt.sign() >= 0) return this; + else { + BigInt a = bigInt.copy(); + a.setSign(1); + return new BigInteger(a); + } + } + + /** + * Returns a new {@code BigInteger} whose value is the {@code -this}. + * + * @return {@code -this}. + */ + public BigInteger negate() { + validate1("negate()", this); + int sign = bigInt.sign(); + if (sign == 0) return this; + else { + BigInt a = bigInt.copy(); + a.setSign(-sign); + return new BigInteger(a); + } + } + + /** + * 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 val == null + */ + public BigInteger add(BigInteger val) { + validate2("add", this, val); + if (val.bigInt.sign() == 0) return this; + if (bigInt.sign() == 0) return val; + return new BigInteger(BigInt.addition(bigInt, val.bigInt)); + } + + /** + * 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 val == null + */ + public BigInteger subtract(BigInteger val) { + validate2("subtract", this, val); + if (val.bigInt.sign() == 0) return this; + else return new BigInteger(BigInt.subtraction(bigInt, val.bigInt)); + } + + /** + * Returns the sign of this {@code BigInteger}. + * + * @return -1 if {@code this < 0}, 0 if {@code this == 0}, 1 if + * {@code this > 0}. + */ + public int signum() { + // Optimization to avoid unnecessary duplicate representation: + if (oldReprIsValid) return sign; + // else: + validate1("signum", this); + return bigInt.sign(); + } + + /** + * 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. + * + * @param n + * shift distance. + * @return this >> n if n >= 0; this << (-n) otherwise. + */ + public BigInteger shiftRight(int n) { + return shiftLeft(-n); + } + + /** + * Returns a new {@code BigInteger} whose value is {@code this << n}. The + * result is equvalent 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))}. + * + * @param n + * shift distance. + * @return this << n if n >= 0; this >> (-n) otherwise. + */ + public BigInteger shiftLeft(int n) { + if (n == 0) return this; + int sign = signum(); + if (sign == 0) return this; + if ((sign > 0) || (n >= 0)) { + validate1("shiftLeft", this); + return new BigInteger(BigInt.shift(bigInt, n)); + } + else { + // Negative numbers faking 2's complement: + // Not worth optimizing this: + // Sticking to Harmony Java implementation. + // + return BitLevel.shiftRight(this, -n); + } + } + + /** + * Returns the number of bits of the binary representation of {@code this} + * without the sign bit. For positive values this is equivalent to the + * number of bits, and for negative values this is equivalent to the number + * of bits used to represent -value-1. + * mc: In other words: the number a can be coded in + * a.bitLength() + 1 bits two's complement. + * E.g. for a.bitLength() == 31, an int will hold a correctly and + * for a.bitLength() == 32 an int will NOT hold a correctly. + * + * @return number of bits of the binary representation of {@code this} + * without the sign bit. + */ + public int bitLength() { + // Optimization to avoid unnecessary duplicate representation: + if (!bigIntIsValid && oldReprIsValid) return BitLevel.bitLength(this); + // else: + validate1("bitLength", this); + return bigInt.bitLength(); + } + + /** + * Tests whether the bit at position n in {@code this} is set. The result is + * equivalent to {@code this & (2^n) != 0}. + * + * @param n + * position where the bit in {@code this} has to be inspected. + * @return {@code this & (2^n) != 0}. + * @throws ArithmeticException + * if n < 0 + */ + public boolean testBit(int n) { + if (n < 0) { + // math.15=Negative bit address + throw new ArithmeticException(Messages.getString("math.15")); //$NON-NLS-1$ + } + int sign = signum(); + if ((sign > 0) && bigIntIsValid && !oldReprIsValid) { + validate1("testBit", this); + return bigInt.isBitSet(n); + } + else { + // Negative numbers faking 2's complement: + // Not worth optimizing this: + // Sticking to Harmony Java implementation. + // + establishOldRepresentation("testBit"); + if (n == 0) { + return ((digits[0] & 1) != 0); + } + int intCount = n >> 5; + if (intCount >= numberLength) { + return (sign < 0); + } + int digit = digits[intCount]; + int i; + 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 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}. + * + * @param n + * position where the bit in {@code this} has to be set. + * @return {@code this | 2^n}. + * @throws ArithmeticException + * if n < 0 + */ + public BigInteger setBit(int n) { +// validate1("setBit", this); +// BigInt a = bigInt.copy(); +// a.modifyBit(n, 1); +// return new BigInteger(a); + + establishOldRepresentation("setBit"); + if( !testBit( n ) ){ + return BitLevel.flipBit(this, n); + }else{ + return 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)}. + * + * @param n + * position where the bit in {@code this} has to be cleared. + * @return {@code this & ~(2^n)}. + * @throws ArithmeticException + * if n < 0 + */ + public BigInteger clearBit(int n) { +// validate1("clearBit", this); +// BigInt a = bigInt.copy(); +// a.modifyBit(n, 0); +// return new BigInteger(a); + + establishOldRepresentation("clearBit"); + if( testBit( n ) ){ + return BitLevel.flipBit(this, n); + }else{ + return this; + } + } + + /** + * 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}. + * + * @param n + * position where the bit in {@code this} has to be flipped. + * @return {@code this ^ 2^n}. + * @throws ArithmeticException + * if n < 0 + */ + public BigInteger flipBit(int n) { +// validate1("flipBit", this); +// BigInt a = bigInt.copy(); +// a.modifyBit(n, -1); +// return new BigInteger(a); + + establishOldRepresentation("flipBit"); + if (n < 0) { + // math.15=Negative bit address + throw new ArithmeticException(Messages.getString("math.15")); //$NON-NLS-1$ + } + return BitLevel.flipBit(this, n); + } + + /** + * 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. + * + * @return position of lowest bit if this != 0, -1 otherwise. + */ + public int getLowestSetBit() { + establishOldRepresentation("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 the number of bits in the binary representation of {@code this} + * wich 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 netative the result is equivalent to + * the number of bits set in the binary representation of {@code -this-1}. + * + * @return number of bits in the binary representation of {@code this} wich + * differ from the sign bit. + */ + public int bitCount() { + establishOldRepresentation("bitCount"); + return BitLevel.bitCount(this); + } + + /** + * Returns a new {@code BigInteger} whose value is {@code ~this}. The + * result of this operation is {@code -this-1}. + * + * @return {@code ~this}. + */ + public BigInteger not() { + this.establishOldRepresentation("not"); + return Logical.not(this).withNewRepresentation("not"); + } + + /** + * Returns a new {@code BigInteger} whose value is {@code this & val}. + * + * @param val + * value to be and'ed with {@code this}. + * @return {@code this & val}. + * @throws NullPointerException + * if val == null + */ + public BigInteger and(BigInteger val) { + this.establishOldRepresentation("and1"); + val.establishOldRepresentation("and2"); + return Logical.and(this, val).withNewRepresentation("and"); + } + + /** + * Returns a new {@code BigInteger} whose value is {@code this | val}. + * + * @param val + * value to be or'ed with {@code this}. + * @return {@code this | val}. + * @throws NullPointerException + * if val == null + */ + public BigInteger or(BigInteger val) { + this.establishOldRepresentation("or1"); + val.establishOldRepresentation("or2"); + return Logical.or(this, val).withNewRepresentation("or"); + } + + /** + * Returns a new {@code BigInteger} whose value is {@code this ^ val}. + * + * @param val + * value to be xor'ed with {@code this}. + * @return {@code this ^ val}. + * @throws NullPointerException + * if val == null + */ + public BigInteger xor(BigInteger val) { + this.establishOldRepresentation("xor1"); + val.establishOldRepresentation("xor2"); + return Logical.xor(this, val).withNewRepresentation("xor"); + } + + /** + * 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())}. + * + * @param val + * value to be not'ed and then and'ed with {@code this}. + * @return {@code this & ~val}. + * @throws NullPointerException + * if val == null + */ + public BigInteger andNot(BigInteger val) { + this.establishOldRepresentation("andNot1"); + val.establishOldRepresentation("andNot2"); + return Logical.andNot(this, val).withNewRepresentation("andNot"); + } + + /** + * 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() { + if (bigIntIsValid && (bigInt.twosCompFitsIntoBytes(4))) { + return (int)bigInt.longInt(); + } + else { + this.establishOldRepresentation("intValue()"); + return (sign * digits[0]); + } + } + + /** + * 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() { + if (bigIntIsValid && (bigInt.twosCompFitsIntoBytes(8))) { + establishOldRepresentation("longValue()"); + return bigInt.longInt(); + } + else { + establishOldRepresentation("longValue()"); + long value = (numberLength > 1) ? (((long) digits[1]) << 32) + | (digits[0] & 0xFFFFFFFFL) : (digits[0] & 0xFFFFFFFFL); + return (sign * value); + } + } + + /** + * 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() { + establishOldRepresentation("floatValue()"); + return (float) doubleValue(); + } + + /** + * 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 [-Dobule.MAX_VALUE, + * Dobule.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() { + establishOldRepresentation("doubleValue()"); + return Conversion.bigInteger2Double(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 1 if this > val, -1 if this < val, 0 if this == val. + * @throws NullPointerException + * if val == null + */ + public int compareTo(BigInteger val) { + validate2("compareTo", this, val); + return BigInt.cmp(bigInt, val.bigInt); + } + + /** + * Returns the minimum of this {@code BigInteger} and {@code val}. + * + * @param val + * value to be used to compute the minimum with this. + * @return {@code min(this, val}. + * @throws NullPointerException + * if val == null + */ + public BigInteger min(BigInteger val) { + return ((this.compareTo(val) == -1) ? this : val); + } + + /** + * Returns the maximum of this {@code BigInteger} and {@code val}. + * + * @param val + * value to be used to compute the maximum with this. + * @return {@code max(this, val}. + * @throws NullPointerException + * if val == null + */ + public BigInteger max(BigInteger val) { + return ((this.compareTo(val) == 1) ? this : val); + } + + /** + * Returns a hash code for this {@code BigInteger}. + * + * @return hash code for this. + */ + @Override + public int hashCode() { + validate1("hashCode", this); + if (hashCode != 0) { + return hashCode; + } + establishOldRepresentation("hashCode"); + for (int i = 0; i < digits.length; i ++) { + hashCode = (int)(hashCode * 33 + (digits[i] & 0xffffffff)); + } + hashCode = hashCode * sign; + return hashCode; + } + + /** + * 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 x is a BigInteger and this == x. + */ + @Override + public boolean equals(Object x) { + if (this == x) { + return true; + } + if (x instanceof BigInteger) { + return this.compareTo((BigInteger)x) == 0; + } + return false; + } + + /** + * 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() { + validate1("toString()", this); + return bigInt.decString(); + } + + /** + * Returns a string containing a string representation of this + * {@code BigInteger} with base radix. If radix < Character.MIN_RADIX or + * radix > Character.MAX_RADIX then a decimal representation is returned. + * The characters of the string representation are generated with method + * {@code 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) { + validate1("toString(int radix)", this); + if (radix == 10) { + return bigInt.decString(); +// } else if (radix == 16) { +// return bigInt.hexString(); + } else { + establishOldRepresentation("toString(int radix)"); + return Conversion.bigInteger2String(this, radix); + } + } + + /** + * Returns a new {@code BigInteger} whose value is greatest common divisor + * of {@code this} and {@code val}. If this==0 and 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 val == null + */ + public BigInteger gcd(BigInteger val) { + validate2("gcd", this, val); + return new BigInteger(BigInt.gcd(bigInt, val.bigInt, null)); + } + + /** + * 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 val == null + */ + public BigInteger multiply(BigInteger val) { + validate2("multiply", this, val); + return new BigInteger(BigInt.product(bigInt, val.bigInt, null)); + } + + /** + * 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 exp < 0 + */ + public BigInteger pow(int exp) { + if (exp < 0) { + // math.16=Negative exponent + throw new ArithmeticException(Messages.getString("math.16")); //$NON-NLS-1$ + } + validate1("pow", this); + return new BigInteger(BigInt.exp(bigInt, exp, null)); + } + + /** + * 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 divisor == null + * @throws ArithmeticException + * if divisor == 0 + * @see #divide + * @see #remainder + */ + public BigInteger[] divideAndRemainder(BigInteger divisor) { + validate2("divideAndRemainder", this, divisor); + BigInt quotient = new BigInt(); + BigInt remainder = new BigInt(); + BigInt.division(bigInt, divisor.bigInt, null, quotient, remainder); + BigInteger[] a = new BigInteger[2]; + a[0] = new BigInteger(quotient); + a[1] = new BigInteger(remainder); + a[0].validate("divideAndRemainder", "quotient"); + a[1].validate("divideAndRemainder", "remainder"); + return a; + } + + /** + * 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 divisor == null + * @throws ArithmeticException + * if divisor == 0 + */ + public BigInteger divide(BigInteger divisor) { + validate2("divide", this, divisor); + BigInt quotient = new BigInt(); + BigInt.division(bigInt, divisor.bigInt, null, quotient, null); + return new BigInteger(quotient); + } + + /** + * 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 divisor == null + * @throws ArithmeticException + * if divisor == 0 + */ + public BigInteger remainder(BigInteger divisor) { + validate2("remainder", this, divisor); + BigInt remainder = new BigInt(); + BigInt.division(bigInt, divisor.bigInt, null, null, remainder); + return new BigInteger(remainder); + } + + /** + * 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 this mod m}. + * @throws NullPointerException + * if m == null + * @throws ArithmeticException + * if m < 0 or if this is not relatively prime to m + */ + public BigInteger modInverse(BigInteger m) { + if (m.signum() <= 0) { + // math.18=BigInteger: modulus not positive + throw new ArithmeticException(Messages.getString("math.18")); //$NON-NLS-1$ + } + validate2("modInverse", this, m); + return new BigInteger(BigInt.modInverse(bigInt, m.bigInt, null)); + } + + /** + * 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 m == null or exponent == null + * @throws ArithmeticException + * if m < 0 or if exponent<0 and this is not relatively prime + * to m + */ + public BigInteger modPow(BigInteger exponent, BigInteger m) { + if (m.signum() <= 0) { + // math.18=BigInteger: modulus not positive + throw new ArithmeticException(Messages.getString("math.18")); //$NON-NLS-1$ + } + BigInteger base; + if (exponent.signum() < 0) { + base = modInverse(m); +// exponent = exponent.negate(); // Not needed as sign is ignored anyway! + } else { + base = this; + } + validate3("modPow", base, exponent, m); + return new BigInteger(BigInt.modExp(base.bigInt, exponent.bigInt, m.bigInt, null)); + } + + /** + * 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 m == null + * @throws ArithmeticException + * if m < 0 + */ + public BigInteger mod(BigInteger m) { + if (m.signum() <= 0) { + // math.18=BigInteger: modulus not positive + throw new ArithmeticException(Messages.getString("math.18")); //$NON-NLS-1$ + } + validate2("mod", this, m); + return new BigInteger(BigInt.modulus(bigInt, m.bigInt, null)); + } + + /** + * 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 ture}, if {@code this} is probably prime, false + * otherwise. + */ + public boolean isProbablePrime(int certainty) { + validate1("isProbablePrime", this); + return bigInt.isPrime(certainty, null, null); + } + + /** + * 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^100). + * + * @return smallest integer > {@code this} pwhich is robably prime. + * @throws ArithmeticException + * if this < 0 + */ + public BigInteger nextProbablePrime() { + if (sign < 0) { + // math.1A=start < 0: {0} + throw new ArithmeticException(Messages.getString("math.1A", this)); //$NON-NLS-1$ + } + return Primality.nextProbablePrime(this); + } + + /** + * 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^100). + * + * @param bitLength + * lenght 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 bitLength < 2 + */ + public static BigInteger probablePrime(int bitLength, Random rnd) { +// System.out.println("probablePrime"); + return new BigInteger(bitLength, 100, rnd); + } + + + + + /* Private Methods */ + + /** + * Returns the two's complement representation of this BigInteger in a byte + * array. + * + * @return two's complement representation of {@code this}. + */ + private byte[] twosComplement() { + establishOldRepresentation("twosComplement()"); + 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; + } + + + static int multiplyByInt(int res[], int a[], final int aSize, final int factor) { + long carry = 0; + + for (int i = 0; i < aSize; i++) { + carry += (a[i] & 0xFFFFFFFFL) * (factor & 0xFFFFFFFFL); + res[i] = (int)carry; + carry >>>= 32; + } + return (int)carry; + } + + 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; + } + + /** @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 = multiplyByInt(digits, digits, digitIndex, bigRadix); + newDigit += inplaceAdd(digits, digitIndex, bigRadixDigit); + digits[digitIndex++] = newDigit; + } + numberLength = digitIndex; + bi.sign = sign; + bi.numberLength = numberLength; + bi.digits = digits; + bi.cutOffLeadingZeroes(); + bi.oldReprIsValid = true; + bi.withNewRepresentation("Cordoba-BigInteger: private static setFromString"); + } + + + /** Decreases {@code numberLength} if there are zero high elements. */ + final void cutOffLeadingZeroes() { + while ((numberLength > 0) && (digits[--numberLength] == 0)) { + ; + } + if (digits[numberLength++] == 0) { + sign = 0; + } + } + + /** Tests if {@code this.abs()} is equals to {@code ONE} */ + boolean isOne() { +// System.out.println("isOne"); + return ((numberLength == 1) && (digits[0] == 1)); + } + + + int getFirstNonzeroDigit(){ +// validate1("Cordoba-BigInteger: getFirstNonzeroDigit", this); + if( firstNonzeroDigit == -2 ){ + int i; + if( this.sign == 0 ){ + i = -1; + } else{ + for(i=0; digits[i]==0; i++) + ; + } + firstNonzeroDigit = i; + } + return firstNonzeroDigit; + } + + /* + * Returns a copy of the current instance to achieve immutability + */ +// mc: Only used by Primality.nextProbablePrime() + BigInteger copy() { + establishOldRepresentation("copy()"); + int[] copyDigits = new int[numberLength]; + System.arraycopy(digits, 0, copyDigits, 0, numberLength); + return new BigInteger(sign, numberLength, copyDigits); + } + + /** + * Assignes all transient fields upon deserialization of a + * {@code BigInteger} instance. + */ + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + bigInt = new BigInt(); + bigInt.putBigEndian(magnitude, (signum < 0)); + bigIntIsValid = true; + // !oldReprIsValid + } + + /** + * Prepares this {@code BigInteger} for serialization, i.e. the + * non-transient fields {@code signum} and {@code magnitude} are assigned. + */ + private void writeObject(ObjectOutputStream out) throws IOException { + validate("writeObject", "this"); + signum = bigInt.sign(); +// if (magnitude == null) + magnitude = bigInt.bigEndianMagnitude(); + out.defaultWriteObject(); + } + + + void unCache(){ + firstNonzeroDigit = -2; + } +} diff --git a/math/src/main/java/java/math/BitLevel.java b/math/src/main/java/java/math/BitLevel.java new file mode 100644 index 0000000..1ba019e --- /dev/null +++ b/math/src/main/java/java/math/BitLevel.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +/* + * Since the original Harmony Code of the BigInteger class was strongly modified, + * in order to use the more efficient OpenSSL BIGNUM implementation, + * no android-modification-tags were placed, at all. + */ + +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. + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +class BitLevel { + + /** Just to denote that this class can't be instantiated. */ + private BitLevel() {} + + + /** @see BigInteger#bitLength() */ + static int bitLength(BigInteger val) { + val.establishOldRepresentation("BitLevel.bitLength"); + 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) { + highDigit--; + } + } + // Subtracting all sign bits + bLength -= Integer.numberOfLeadingZeros(highDigit); + return bLength; + } + + /** @see BigInteger#bitCount() */ + static int bitCount(BigInteger val) { + val.establishOldRepresentation("BitLevel.bitCount"); + 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; + } + + /** + * 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) { + val.establishOldRepresentation("BitLevel.testBit"); + // PRE: 0 <= n < val.bitLength() + return ((val.digits[n >> 5] & (1 << (n & 31))) != 0); + } + + /** + * 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#shiftRight(int) */ + static BigInteger shiftRight(BigInteger source, int count) { + source.establishOldRepresentation("BitLevel.shiftRight"); + 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; + } + + /** + * Performs {@code val >>= count} where {@code val} is a positive number. + */ + static void inplaceShiftRight(BigInteger val, int count) { + val.establishOldRepresentation("BitLevel.inplaceShiftRight"); + 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(); + } + + /** + * 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 flipBit on the BigInteger, returning a BigInteger with the the + * specified bit flipped. + * @param intCount: the index of the element of the digits array where the operation will be performed + * @param bitNumber: the bit's position in the intCount element + */ + static BigInteger flipBit(BigInteger val, int n){ + val.establishOldRepresentation("BitLevel.flipBit"); + 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; + } +} diff --git a/math/src/main/java/java/math/Conversion.java b/math/src/main/java/java/math/Conversion.java new file mode 100644 index 0000000..945af8f --- /dev/null +++ b/math/src/main/java/java/math/Conversion.java @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +package java.math; + +/** + * Static library that provides {@link BigInteger} base conversion from/to any + * integer represented in an {@link java.lang.String} Object. + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +class Conversion { + + /** Just to denote that this class can't be instantiated */ + private Conversion() {} + + /** + * 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 }; + + /** + * 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 }; + + + /** @see BigInteger#toString(int) */ + static String bigInteger2String(BigInteger val, int radix) { + val.establishOldRepresentation("Conversion.bigInteger2String"); + 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--) { + ; + } + 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); + } + + /** + * 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) { + val.establishOldRepresentation("Conversion.toDecimalScaledString"); + 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: + StringBuffer result1 = new StringBuffer(); + 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; + StringBuffer result1 = new StringBuffer(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: + StringBuffer result1 = new StringBuffer(); + 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; + StringBuffer result1 = new StringBuffer(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(); + } + + 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)); + } + + /** @see BigInteger#doubleValue() */ + static double bigInteger2Double(BigInteger val) { + val.establishOldRepresentation("Conversion.bigInteger2Double"); + // 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/math/src/main/java/java/math/Division.java b/math/src/main/java/java/math/Division.java new file mode 100644 index 0000000..36c7c79 --- /dev/null +++ b/math/src/main/java/java/math/Division.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +/* + * Since the original Harmony Code of the BigInteger class was strongly modified, + * in order to use the more efficient OpenSSL BIGNUM implementation, + * no android-modification-tags were placed, at all. + */ + +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> + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +class Division { + + /** + * 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 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; + } + + /** + * 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) { + dividend.establishOldRepresentation("Division.remainder"); + return remainderArrayByInt(dividend.digits, dividend.numberLength, + divisor); + } + + /** + * 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); + } + + /** + * 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) { + val.establishOldRepresentation("Division.divideAndRemainderByInteger"); + // 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 }; + } + +} diff --git a/math/src/main/java/java/math/Logical.java b/math/src/main/java/java/math/Logical.java new file mode 100644 index 0000000..3855aeb --- /dev/null +++ b/math/src/main/java/java/math/Logical.java @@ -0,0 +1,802 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.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> + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +class Logical { + + /** Just to denote that this class can't be instantiated. */ + + private Logical() {} + + + /** @see BigInteger#not() */ + 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++) { + ; + } + } else { + for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) { + ; + } + 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#and(BigInteger) */ + 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 = 1, magnitude = val.magnitude & that.magnitude*/ + 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; + } + + /** @return sign = positive.magnitude & magnitude = -negative.magnitude */ + 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)*/ + 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++) + ; + 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) */ + 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*/ + 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)*/ + 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 = -(-negative.magnitude & ~positive.magnitude)*/ + 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++) + ; // 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)*/ + 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; + } + + /** @see BigInteger#or(BigInteger) */ + 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 = longer.magnitude | shorter.magnitude*/ + 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; + } + + /** @return sign = -1, magnitude = -(-val.magnitude | -that.magnitude) */ + 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 = -(positive.magnitude | -negative.magnitude) */ + 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; + } + + /** @see BigInteger#xor(BigInteger) */ + 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 = 0, magnitude = longer.magnitude | shorter.magnitude */ + 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; + } + + /** @return sign = 0, magnitude = -val.magnitude ^ -that.magnitude */ + 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 = 1, magnitude = -(positive.magnitude ^ -negative.magnitude)*/ + 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++) + ; + if (digit == 0) { + // shorter has only the remaining virtual sign bits + for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++) + ; + for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++) + ; + 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; + } +} diff --git a/math/src/main/java/java/math/MathContext.java b/math/src/main/java/java/math/MathContext.java new file mode 100644 index 0000000..5a483f1 --- /dev/null +++ b/math/src/main/java/java/math/MathContext.java @@ -0,0 +1,312 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.math; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.io.StreamCorruptedException; + +import org.apache.harmony.math.internal.nls.Messages; + +/** + * Immutable objects describing settings as rounding mode and digit precision + * for the numerical operations provided by class {@code BigDecimal}. + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +public final class MathContext implements Serializable { + + /* Fields */ + + /** + * A MathContext wich corresponds to the IEEE 754r single decimal precision format: + * 7 digit preicision and HALF_EVEN rounding. + */ + public static final MathContext DECIMAL32 = new MathContext(7, + RoundingMode.HALF_EVEN); + + /** + * A MathContext wich corresponds to the IEEE 754r double decimal precision format: + * 16 digit preicision and HALF_EVEN rounding. + */ + public static final MathContext DECIMAL64 = new MathContext(16, + RoundingMode.HALF_EVEN); + + /** + * A MathContext wich corresponds to the IEEE 754r quadruple decimal precision format: + * 34 digit preicision and HALF_EVEN rounding. + */ + public static final MathContext DECIMAL128 = new MathContext(34, + RoundingMode.HALF_EVEN); + + /** + * A MathContext for unlimited precision with HALF_UP rounding. + */ + public static final MathContext UNLIMITED = new MathContext(0, + RoundingMode.HALF_UP); + + /** 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; + + /** + * 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 final static 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 final static char[] chRoundingMode = { 'r', 'o', 'u', 'n', 'd', + 'i', 'n', 'g', 'M', 'o', 'd', 'e', '=' }; + + /* Constructors */ + + /** + * Constructs a new MathContext with the specified precision and with + * the rounding mode 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 MathContext + * @throws IllegalArgumentException if precision < 0. + */ + public MathContext(int precision) { + this(precision, RoundingMode.HALF_UP); + } + + /** + * Constructs a new 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 MathContext + * @param roundingMode the rounding mode for the new MathContext + * @throws IllegalArgumentException if precision < 0. + * @throws NullPointerException if roundingMode is null. + */ + public MathContext(int precision, RoundingMode roundingMode) { + if (precision < 0) { + // math.0C=Digits < 0 + throw new IllegalArgumentException(Messages.getString("math.0C")); //$NON-NLS-1$ + } + if (roundingMode == null) { + // math.0D=null RoundingMode + throw new NullPointerException(Messages.getString("math.0D")); //$NON-NLS-1$ + } + this.precision = precision; + this.roundingMode = roundingMode; + } + + /** + * Constructs a new 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 toString() method. + * + * @param val a string describing the precision and rounding mode for the new 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(Messages.getString("math.0E")); //$NON-NLS-1$ + } + // Parsing "precision=" String + for (i = 0; (i < chPrecision.length) && (charVal[i] == chPrecision[i]); i++) { + ; + } + + if (i < chPrecision.length) { + // math.0E=bad string format + throw new IllegalArgumentException(Messages.getString("math.0E")); //$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(Messages.getString("math.0E")); //$NON-NLS-1$ + } + this.precision = 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(Messages.getString("math.0E")); //$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(Messages.getString("math.0E")); //$NON-NLS-1$ + } + i++; + } while (true); + // Parsing "roundingMode=" + for (j = 0; (j < chRoundingMode.length) + && (charVal[i] == chRoundingMode[j]); i++, j++) { + ; + } + + if (j < chRoundingMode.length) { + // math.0E=bad string format + throw new IllegalArgumentException(Messages.getString("math.0E")); //$NON-NLS-1$ + } + // Parsing the value for "roundingMode"... + this.roundingMode = RoundingMode.valueOf(String.valueOf(charVal, i, + charVal.length - i)); + } + + /* Public Methods */ + + /** + * 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. The rounding mode is one of RoundingMode.UP, + * RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR, + * RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN, + * or oundingMode.UNNECESSARY. + * + * @return the rounding mode. + */ + public RoundingMode getRoundingMode() { + return roundingMode; + } + + /** + * Returns true if x is a MathContext with the same precision setting + * and the same rounding mode as this MathContext instance. + * + * @param x object to be compared + * @return true if this MathContext instance is equal to the x argument; false otherwise. + */ + @Override + public boolean equals(Object x) { + return ((x instanceof MathContext) + && (((MathContext) x).getPrecision() == precision) && (((MathContext) x) + .getRoundingMode() == roundingMode)); + } + + /** + * Returns the hash code for this MathContext instance. + * + * @return the hash code for this 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 MathContext instance. + * The string has the form + * + * "precision=<precision> roundingMode=<roundingMode>" + * + * where <precision> is an int describing the number of digits used for + * operations and <roundingMode> is the string representation of the + * rounding mode. + * + * @return a string representation for this MathContext instance. + */ + @Override + public String toString() { + StringBuffer sb = new StringBuffer(45); + + sb.append(chPrecision); + sb.append(precision); + sb.append(' '); + sb.append(chRoundingMode); + sb.append(roundingMode); + return sb.toString(); + } + + /** + * Makes checks upon deserialization of a {@code MathContext} instance. + * Checks whether precision >= 0 and the roundingMode != null + * + * @throws StreamCorruptedException + * if precision < 0 + * @throws StreamCorruptedException + * if roundingMode == null + */ + private void readObject(ObjectInputStream s) throws IOException, + ClassNotFoundException { + s.defaultReadObject(); + if (precision < 0) { + // math.0F=bad precision value + throw new StreamCorruptedException(Messages.getString("math.0F")); //$NON-NLS-1$ + } + if (roundingMode == null) { + // math.10=null roundingMode + throw new StreamCorruptedException(Messages.getString("math.10")); //$NON-NLS-1$ + } + } + +} diff --git a/math/src/main/java/java/math/Multiplication.java b/math/src/main/java/java/math/Multiplication.java new file mode 100644 index 0000000..2eb3229 --- /dev/null +++ b/math/src/main/java/java/math/Multiplication.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +/* + * Since the original Harmony Code of the BigInteger class was strongly modified, + * in order to use the more efficient OpenSSL BIGNUM implementation, + * no android-modification-tags were placed, at all. + */ + +package java.math; + +import org.apache.harmony.math.internal.nls.Messages; + +/** + * Static library that provides all multiplication of {@link BigInteger} methods. + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +class Multiplication { + + /** Just to denote that this class can't be instantiated. */ + private Multiplication() {} + + /** + * 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 + }; + + /** + * 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 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 the first powers of five in {@code BigInteger} version. + * ({@code 5^0,5^1,...,5^31}) + */ + static final BigInteger bigFivePows[] = new BigInteger[32]; + + + 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); + } + } + + /** + * 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) { + BigInt bi = val.bigInt.copy(); + bi.multiplyByPositiveInt(factor); + return new BigInteger(bi); + } + + /** + * 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, long exp) { + // PRE: exp >= 0 + return ((exp < tenPows.length) + ? multiplyByPositiveInt(val, tenPows[(int)exp]) + : val.multiply(powerOf10(exp))); + } + + /** + * 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(long 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)] + */ + long byteArraySize = 1 + (long)(exp / 2.4082399653118496); + + if (byteArraySize > Runtime.getRuntime().freeMemory()) { + // math.01=power of ten too big + throw new OutOfMemoryError(Messages.getString("math.01")); //$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 = 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 = 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; + } + + /** + * 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)); + } + } +} diff --git a/math/src/main/java/java/math/Primality.java b/math/src/main/java/java/math/Primality.java new file mode 100644 index 0000000..e17aafd --- /dev/null +++ b/math/src/main/java/java/math/Primality.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +/* + * Since the original Harmony Code of the BigInteger class was strongly modified, + * in order to use the more efficient OpenSSL BIGNUM implementation, + * no android-modification-tags were placed, at all. + */ + +package java.math; + +import java.util.Arrays; +import java.util.Random; + +class Primality { + + /** Just to denote that this class can't be instantiated. */ + private Primality() {} + + /* Private Fields */ + + /** 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 10 bits. */ + private static final BigInteger BIprimes[] = new BigInteger[primes.length]; + +// /** +// * 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 } }; + + static {// To initialize the dual table of BigInteger primes + for (int i = 0; i < primes.length; i++) { + BIprimes[i] = BigInteger.valueOf(primes[i]); + } + } + + + /* Package Methods */ + + /** + * 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]; + BigInt startPoint; + BigInt probPrime; + BigInt ni = n.bigInt; + // If n < "last prime of table" searches next prime in the table + if (ni.bitLength() <= 10) { + int l = (int)ni.longInt(); + if (l < primes[primes.length - 1]) { + for (i = 0; l >= primes[i]; i++) {} + return BIprimes[i]; + } + } + /* + * Creates a "N" enough big to hold the next probable prime Note that: N < + * "next prime" < 2*N + */ + startPoint = ni.copy(); + probPrime = new BigInt(); + + // To fix N to the "next odd number" + ni.addPositiveInt(BigInt.remainderByPositiveInt(ni, 2) + 1); + +// // To set the improved certainty of Miller-Rabin +// j = startPoint.bitLength(); +// for (certainty = 2; j < BITS[certainty]; certainty++) { +// ; +// } + + // To calculate modules: N mod p1, N mod p2, ... for first primes. + for (i = 0; i < primes.length; i++) { + modules[i] = BigInt.remainderByPositiveInt(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.putCopy(startPoint); + probPrime.addPositiveInt(j); + if (probPrime.isPrime(100, null, null)) { + return new BigInteger(probPrime); + } + } + } + startPoint.addPositiveInt(gapSize); + } + } + +} diff --git a/math/src/main/java/java/math/RoundingMode.java b/math/src/main/java/java/math/RoundingMode.java new file mode 100644 index 0000000..8aac012 --- /dev/null +++ b/math/src/main/java/java/math/RoundingMode.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.math; + +import org.apache.harmony.math.internal.nls.Messages; + +/** + * An enum to specify the rounding behaviour for operations whose results + * cannot be represented exactly. + * + * @author Intel Middleware Product Division + * @author Instituto Tecnologico de Cordoba + */ +public enum RoundingMode { + + /** + * Rounding mode where positive values are rounded towards positive infinity + * and negative values towards negative infinity. + * + * Rule: x.round().abs() >= x.abs() + */ + UP(BigDecimal.ROUND_UP), + + /** + * Rounding mode where the values are rounded towards zero. + * + * Rule: x.round().abs() <= x.abs() + */ + DOWN(BigDecimal.ROUND_DOWN), + + /** + * Rounding mode to round towards positive infinity. For positive values + * this rounding mode behaves as UP, for negative values as + * DOWN. + * + * Rule: x.round() >= x + */ + CEILING(BigDecimal.ROUND_CEILING), + + /** + * Rounding mode to round towards negative infinity. For positive values + * this rounding mode behaves as DOWN, for negative values as UP. + * + * Rule: x.round() <= x + */ + FLOOR(BigDecimal.ROUND_FLOOR), + + /** + * Rounding mode where values are rounded towards the nearest neighbour. + * Ties are broken by rounding up. + */ + HALF_UP(BigDecimal.ROUND_HALF_UP), + + /** + * Rounding mode where values are rounded towards the nearest neighbour. + * Ties are broken by rounding down. + */ + HALF_DOWN(BigDecimal.ROUND_HALF_DOWN), + + /** + * Rounding mode where values are rounded towards the nearest neighbour. + * Ties are broken by rounding to the even neighbour. + */ + HALF_EVEN(BigDecimal.ROUND_HALF_EVEN), + + /** + * Rounding mode where the rounding operations throws an ArithmeticException + * for the case that rounding is necessary, i.e. for the case that the value + * cannot be represented exactly. + */ + UNNECESSARY(BigDecimal.ROUND_UNNECESSARY); + + /** The old constant of <code>BigDecimal</code>. */ + private final int bigDecimalRM; + + /** It sets the old constant. */ + RoundingMode(int rm) { + bigDecimalRM = rm; + } + + /** + * Converts rounding mode constants from class BigDecimal into + * RoundingMode values. + * + * @param rM rounding mode constant as defined in class BigDecimal + * @return corresponding rounding mode object + */ + public static RoundingMode valueOf(int rM) { + switch (rM) { + 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(Messages.getString("math.00")); //$NON-NLS-1$ + } + } +} diff --git a/math/src/main/java/java/math/package.html b/math/src/main/java/java/math/package.html new file mode 100644 index 0000000..2d25ed0 --- /dev/null +++ b/math/src/main/java/java/math/package.html @@ -0,0 +1,15 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> +</head> +<html> +<body> +<p> +This package provides arbitrary-precision integers and decimals. +Class {@link java.math.BigInteger} provides integers which are limited by the available memory only. +Class {@link java.math.BigDecimal} provides arbitrary-precision signed decimal numbers. These numbers +are suitable for currency calculations. The user has full control over the rounding behavior (comparable +with the IEEE754R rounding modes. +</p> +</body> +</html> diff --git a/math/src/main/java/org/apache/harmony/math/internal/nls/Messages.java b/math/src/main/java/org/apache/harmony/math/internal/nls/Messages.java new file mode 100644 index 0000000..b1682a9 --- /dev/null +++ b/math/src/main/java/org/apache/harmony/math/internal/nls/Messages.java @@ -0,0 +1,132 @@ +/* + * 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. + */ + +/* + * THE FILE HAS BEEN AUTOGENERATED BY MSGTOOL TOOL. + * All changes made to this file manually will be overwritten + * if this tool runs again. Better make changes in the template file. + */ + +package org.apache.harmony.math.internal.nls; + +// BEGIN android-added +import org.apache.harmony.luni.util.MsgHelp; +// END android-added + +/** + * This class retrieves strings from a resource bundle and returns them, + * formatting them with MessageFormat when required. + * <p> + * It is used by the system classes to provide national language support, by + * looking up messages in the <code> + * org.apache.harmony.math.internal.nls.messages + * </code> + * resource bundle. Note that if this file is not available, or an invalid key + * is looked up, or resource bundle support is not available, the key itself + * will be returned as the associated message. This means that the <em>KEY</em> + * should a reasonable human-readable (english) string. + * + */ +public class Messages { + + // BEGIN android-changed + private static final String sResource = + "org.apache.harmony.math.internal.nls.messages"; + // END android-changed + + /** + * Retrieves a message which has no arguments. + * + * @param msg + * String the key to look up. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg) { + // BEGIN android-changed + return MsgHelp.getString(sResource, msg); + // END android-changed + } + + /** + * Retrieves a message which takes 1 argument. + * + * @param msg + * String the key to look up. + * @param arg + * Object the object to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, Object arg) { + return getString(msg, new Object[] { arg }); + } + + /** + * Retrieves a message which takes 1 integer argument. + * + * @param msg + * String the key to look up. + * @param arg + * int the integer to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, int arg) { + return getString(msg, new Object[] { Integer.toString(arg) }); + } + + /** + * Retrieves a message which takes 1 character argument. + * + * @param msg + * String the key to look up. + * @param arg + * char the character to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, char arg) { + return getString(msg, new Object[] { String.valueOf(arg) }); + } + + /** + * Retrieves a message which takes 2 arguments. + * + * @param msg + * String the key to look up. + * @param arg1 + * Object an object to insert in the formatted output. + * @param arg2 + * Object another object to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, Object arg1, Object arg2) { + return getString(msg, new Object[] { arg1, arg2 }); + } + + /** + * Retrieves a message which takes several arguments. + * + * @param msg + * String the key to look up. + * @param args + * Object[] the objects to insert in the formatted output. + * @return String the message for that key in the system message bundle. + */ + static public String getString(String msg, Object[] args) { + // BEGIN android-changed + return MsgHelp.getString(sResource, msg, args); + // END android-changed + } +} diff --git a/math/src/main/java/org/apache/harmony/math/internal/nls/messages.properties b/math/src/main/java/org/apache/harmony/math/internal/nls/messages.properties new file mode 100644 index 0000000..0a40a43 --- /dev/null +++ b/math/src/main/java/org/apache/harmony/math/internal/nls/messages.properties @@ -0,0 +1,45 @@ +# 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. + +# messages for EN locale +math.00=Invalid rounding mode +math.01=power of ten too big +math.02=Scale out of range. +math.03=Infinite or NaN +math.04=Division by zero +math.05=Non-terminating decimal expansion; no exact representable decimal result. +math.06=Division impossible +math.07=Invalid Operation +math.08=Rounding necessary +math.09=Overflow +math.0A=Underflow +math.0B=null unscaled value +math.0C=Digits < 0 +math.0D=null RoundingMode +math.0E=bad string format +math.0F=bad precision value +math.10=null roundingMode +math.1B=numBits must be non-negative +math.1C=bitLength < 2 +math.11=Radix out of range +math.12=Zero length BigInteger +math.13=Invalid signum value +math.14=signum-magnitude mismatch +math.15=Negative bit address +math.16=Negative exponent +math.17=BigInteger divide by zero +math.18=BigInteger: modulus not positive +math.19=BigInteger not invertible. +math.1A=start < 0: {0} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java new file mode 100644 index 0000000..aa0bac1 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java @@ -0,0 +1,1759 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.tests.java.math; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +import junit.framework.TestCase; + +/** + * Class: java.math.BigDecimal + * Methods: add, subtract, multiply, divide + */ +public class BigDecimalArithmeticTest extends TestCase { + + /** + * 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 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()); + } + + /** + * 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 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 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 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 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 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()); + } + + /** + * 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 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()); + } + + /** + * 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 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 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 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 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()); + } + + /** + * 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()); + } + + /** + * 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 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 + */ + 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 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 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 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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 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 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: 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()); + } + + /** + * 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: 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_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()); + } + + /** + * 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 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_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_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_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_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 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 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_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_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 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 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_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_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 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 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_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 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, 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(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 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 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_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 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, 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, 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 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 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_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 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()); + } + + /** + * 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 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()); + } + + /** + * 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()); + } + + /** + * 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 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()); + } + + /** + * 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()); + } + + /** + * 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_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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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 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 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()); + } + +// ANDROID ADDED + + /** + * @tests java.math.BigDecimal#add(java.math.BigDecimal) + */ + public void test_addBigDecimal() { + BigDecimal add1 = new BigDecimal("23.456"); + BigDecimal add2 = new BigDecimal("3849.235"); + BigDecimal sum = add1.add(add2); + assertTrue("the sum of 23.456 + 3849.235 is wrong", sum.unscaledValue().toString().equals( + "3872691") + && sum.scale() == 3); + assertTrue("the sum of 23.456 + 3849.235 is not printed correctly", sum.toString().equals( + "3872.691")); + BigDecimal add3 = new BigDecimal(12.34E02D); + assertTrue("the sum of 23.456 + 12.34E02 is not printed correctly", (add1.add(add3)) + .toString().equals("1257.456")); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.MathContext) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeUP() { + String a = "-37361671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.UP; + String c = "-1"; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + BigDecimal result = aNumber.divide(bNumber, rm); + assertEquals("incorrect value", c, result.toString()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeDOWN() { + String a = "-37361671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.DOWN; + String c = "0"; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + BigDecimal result = aNumber.divide(bNumber, rm); + assertEquals("incorrect value", c, result.toString()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeCEILING() { + String a = "3736186567876876578956958765675671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.CEILING; + String c = "50000260373164286401361914"; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + BigDecimal result = aNumber.divide(bNumber, rm); + assertEquals("incorrect value", c, result.toString()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeFLOOR() { + String a = "3736186567876876578956958765675671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.FLOOR; + String c = "50000260373164286401361913"; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + BigDecimal result = aNumber.divide(bNumber, rm); + assertEquals("incorrect value", c, result.toString()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeHALF_UP() { + String a = "3736186567876876578956958765675671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.HALF_UP; + String c = "50000260373164286401361913"; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + BigDecimal result = aNumber.divide(bNumber, rm); + assertEquals("incorrect value", c, result.toString()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeHALF_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()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingModeHALF_EVEN() { + String a = "3736186567876876578956958765675671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.HALF_EVEN; + String c = "50000260373164286401361913"; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + BigDecimal result = aNumber.divide(bNumber, rm); + assertEquals("incorrect value", c, result.toString()); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, + * java.math.RoundingMode) divide(BigDecimal, RoundingMode) + */ + public void test_DivideBigDecimalRoundingExc() { + String a = "3736186567876876578956958765675671119238118911893939591735"; + String b = "74723342238476237823787879183470"; + RoundingMode rm = RoundingMode.UNNECESSARY; + BigDecimal aNumber = new BigDecimal(new BigInteger(a)); + BigDecimal bNumber = new BigDecimal(new BigInteger(b)); + try { + aNumber.divide(bNumber, rm); + fail("ArithmeticException is not thrown for RoundingMode.UNNECESSARY divider"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + try { + bNumber = new BigDecimal(0); + aNumber.divide(bNumber, rm); + fail("ArithmeticException is not thrown for zero divider"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java new file mode 100644 index 0000000..b0b5e22 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java @@ -0,0 +1,504 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +import junit.framework.TestCase; + +/** + * Class: java.math.BigDecimal + * Methods: abs, compareTo, equals, hashCode, + * max, min, negate, signum + */ +public class BigDecimalCompareTest extends TestCase { + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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 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)); + } + + /** + * 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)); + } + + /** + * 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)); + } + + /** + * 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()); + } + + /** + * 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(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()); + } + + /** + * 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()); + } + + /** + * negate(MathContext) for a positive BigDecimal + */ + public void testNegateMathContextPositive() { + 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(MathContext) for a negative BigDecimal + */ + public void testNegateMathContextNegative() { + 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()); + } + + /** + * 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 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 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/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java new file mode 100644 index 0000000..c0e30a2 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java @@ -0,0 +1,763 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +import junit.framework.TestCase; + +/** + * Class: java.math.BigDecimal + * Methods: constructors and fields + */ +public class BigDecimalConstructorsTest extends TestCase { + /** + * 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); + } + + /** + * 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, 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(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(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() { + try { + // Regression for HARMONY-783 + new BigDecimal(new char[] {}, MathContext.DECIMAL32); + fail("NumberFormatException has not been thrown"); + } catch (NumberFormatException e) { + } + } + + /** + * 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 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(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) + */ + public void testConstrDouble() { + double a = 732546982374982347892379283571094797.287346782359284756; + int aScale = 0; + BigInteger bA = new BigInteger("732546982374982285073458350476230656"); + BigDecimal aNumber = new BigDecimal(a); + assertEquals("incorrect value", bA, aNumber.unscaledValue()); + assertEquals("incorrect scale", aScale, aNumber.scale()); + } + + /** + * new BigDecimal(double, MathContext) + */ + public void testConstrDoubleMathContext() { + double a = 732546982374982347892379283571094797.287346782359284756; + int precision = 21; + RoundingMode rm = RoundingMode.CEILING; + MathContext mc = new MathContext(precision, rm); + String res = "732546982374982285074"; + int resScale = -15; + BigDecimal result = new BigDecimal(a, mc); + assertEquals("incorrect value", res, result.unscaledValue().toString()); + assertEquals("incorrect scale", resScale, result.scale()); + } + + /** + * new BigDecimal(0.1) + */ + public void testConstrDouble01() { + double a = 1.E-1; + int aScale = 55; + BigInteger bA = new BigInteger("1000000000000000055511151231257827021181583404541015625"); + BigDecimal aNumber = new BigDecimal(a); + assertEquals("incorrect value", bA, aNumber.unscaledValue()); + assertEquals("incorrect scale", aScale, aNumber.scale()); + } + + /** + * new BigDecimal(0.555) + */ + public void testConstrDouble02() { + double a = 0.555; + int aScale = 53; + BigInteger bA = new BigInteger("55500000000000004884981308350688777863979339599609375"); + BigDecimal aNumber = new BigDecimal(a); + assertEquals("incorrect value", bA, aNumber.unscaledValue()); + assertEquals("incorrect scale", aScale, aNumber.scale()); + } + + /** + * new BigDecimal(-0.1) + */ + public void testConstrDoubleMinus01() { + double a = -1.E-1; + int aScale = 55; + BigInteger bA = new BigInteger("-1000000000000000055511151231257827021181583404541015625"); + BigDecimal aNumber = new BigDecimal(a); + assertEquals("incorrect value", bA, aNumber.unscaledValue()); + assertEquals("incorrect scale", aScale, aNumber.scale()); + } + + /** + * 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(double value) when value is denormalized + */ + public void testConstrDoubleDenormalized() { + double a = 2.274341322658976E-309; + int aScale = 1073; + BigInteger bA = new BigInteger("227434132265897633950269241702666687639731047124115603942986140264569528085692462493371029187342478828091760934014851133733918639492582043963243759464684978401240614084312038547315281016804838374623558434472007664427140169018817050565150914041833284370702366055678057809362286455237716100382057360123091641959140448783514464639706721250400288267372238950016114583259228262046633530468551311769574111763316146065958042194569102063373243372766692713192728878701004405568459288708477607744497502929764155046100964958011009313090462293046650352146796805866786767887226278836423536035611825593567576424943331337401071583562754098901412372708947790843318760718495117047155597276492717187936854356663665005157041552436478744491526494952982062613955349661409854888916015625"); + BigDecimal aNumber = new BigDecimal(a); + assertEquals("incorrect value", bA, aNumber.unscaledValue()); + assertEquals("incorrect scale", aScale, aNumber.scale()); + } + + /** + * new BigDecimal(String value) + * when value is not a valid representation of BigDecimal. + */ + public void testConstrStringException() { + String a = "-238768.787678287a+10"; + try { +// BEGIN android-modified + BigDecimal bd = new BigDecimal(a); + fail("NumberFormatException has not been caught: " + bd.toString()); +// END android-modified + } 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); 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 + */ + 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 + * 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()); + } + + /** + * 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, 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()); + } + +// ANDROID ADDED + + /** + * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger, int) + */ + public void test_Constructor_java_math_BigInteger_int() { + BigInteger value = new BigInteger("12345908"); + BigDecimal big = new BigDecimal(value); + assertTrue("the BigDecimal value is not initialized properly", + big.unscaledValue().equals(value) + && big.scale() == 0); + + BigInteger value2 = new BigInteger("12334560000"); + BigDecimal big2 = new BigDecimal(value2, 5); + assertTrue("the BigDecimal value is not initialized properly", + big2.unscaledValue().equals(value2) + && big2.scale() == 5); + assertTrue("the BigDecimal value is not represented properly", big2.toString().equals( + "123345.60000")); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(double) + */ + public void test_Constructor_Double() { + BigDecimal big = new BigDecimal(123E04); + assertTrue("the BigDecimal value taking a double argument is not initialized properly", big + .toString().equals("1230000")); + big = new BigDecimal(1.2345E-12); + assertTrue("the double representation is not correct for 1.2345E-12", + big.doubleValue() == 1.2345E-12); + big = new BigDecimal(-12345E-3); + assertTrue("the double representation is not correct for -12345E-3", + big.doubleValue() == -12.345); + big = new BigDecimal(5.1234567897654321e138); + assertTrue("the double representation is not correct for 5.1234567897654321e138", big + .doubleValue() == 5.1234567897654321E138 + && big.scale() == 0); + big = new BigDecimal(0.1); + assertTrue("the double representation of 0.1 bigDecimal is not correct", + big.doubleValue() == 0.1); + big = new BigDecimal(0.00345); + assertTrue("the double representation of 0.00345 bigDecimal is not correct", big + .doubleValue() == 0.00345); + // regression test for HARMONY-2429 + big = new BigDecimal(-0.0); + assertTrue("the double representation of -0.0 bigDecimal is not correct", big.scale() == 0); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(java.lang.String) + */ + public void test_Constructor_java_lang_String() throws NumberFormatException { + BigDecimal big = new BigDecimal("345.23499600293850"); + assertTrue("the BigDecimal value is not initialized properly", big.toString().equals( + "345.23499600293850") + && big.scale() == 14); + big = new BigDecimal("-12345"); + assertTrue("the BigDecimal value is not initialized properly", big.toString().equals( + "-12345") + && big.scale() == 0); + big = new BigDecimal("123."); + assertTrue("the BigDecimal value is not initialized properly", big.toString().equals("123") + && big.scale() == 0); + + } + +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java new file mode 100644 index 0000000..ecc1dfa --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java @@ -0,0 +1,1174 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.math.MathContext; + +/** + * Class: java.math.BigDecimal + * Methods: doubleValue, floatValue, intValue, longValue, + * valueOf, toString, toBigInteger + */ +public class BigDecimalConvertTest extends TestCase { + /** + * 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 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); + } + + /** + * 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 negative BigDecimal + */ + 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 small positive BigDecimal + */ + 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); + } + + /** + * Float value of a negative BigDecimal + */ + public void testFloatValueNeg() { + String a = "-1238096483923847.6356789029578E+21"; + BigDecimal aNumber = new BigDecimal(a); + float result = -1.2380965E36F; + assertTrue("incorrect value", aNumber.floatValue() == result); + } + + /** + * Float value of a positive BigDecimal + */ + public void testFloatValuePos() { + String a = "1238096483923847.6356789029578E+21"; + BigDecimal aNumber = new BigDecimal(a); + float result = 1.2380965E36F; + assertTrue("incorrect value", aNumber.floatValue() == result); + } + + /** + * 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); + } + + /** + * 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 negative BigDecimal + */ + 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 small positive BigDecimal + */ + 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); + } + + /** + * Integer value of a negative BigDecimal + */ + public void testIntValueNeg() { + String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + int result = 218520473; + assertTrue("incorrect value", aNumber.intValue() == result); + } + + /** + * Integer value of a positive BigDecimal + */ + public void testIntValuePos() { + String a = "123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + int result = -218520473; + assertTrue("incorrect value", aNumber.intValue() == result); + } + + /** + * 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); + } + + /** + * 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); + } + + /** + * 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()); + } + + /** + * 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 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 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)); + } + + /** + * 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 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 testToEngineeringStringNeg() { + 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 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 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 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 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)); + } + + /** + * 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 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)); + } + + /** + * 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 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 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 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 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 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 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.987885"; + int resScale = 6; + assertEquals("incorrect value", res, result.toString()); + assertEquals("incorrect scale", resScale, result.scale()); + } + + /** + * 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; + } + } + +// ANDROID ADDED + + /** + * @tests java.math.BigDecimal#intValueExact() Integer value of a negative + * BigDecimal + */ + public void test_IntValueExactNeg() { + String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.intValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#intValueExact() Integer value of a positive + * BigDecimal + */ + public void test_IntValueExactPos() { + String a = "123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.intValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#intValueExact() Integer value of a negative + * BigDecimal + */ + public void test_IntValueExactFloatNeg() { + BigDecimal aNumber = new BigDecimal("-2147483647.999"); + try { + aNumber.intValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#intValueExact() Integer value of a positive + * BigDecimal + */ + public void test_IntValueExactFloatPos() { + float a = 2147483646.99999F; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.intValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#intValueExact() Integer value of a positive + * BigDecimal + */ + public void test_IntValueExactLongPos() { + long a = 2147483647L; + BigDecimal aNumber = new BigDecimal(a); + int iNumber = aNumber.intValueExact(); + assertTrue("incorrect value", iNumber == a); + } + + /** + * @tests java.math.BigDecimal#intValueExact() Integer value of a positive + * BigDecimal + */ + public void test_IntValueExactLongNeg() { + long a = -2147483648L; + BigDecimal aNumber = new BigDecimal(a); + int iNumber = aNumber.intValueExact(); + assertTrue("incorrect value", iNumber == a); + } + + /** + * @tests java.math.BigDecimal#longValueExact() Long value of a negative + * BigDecimal + */ + public void test_LongValueExactNeg() { + String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.longValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling longValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#longValueExact() Long value of a positive + * BigDecimal + */ + public void test_LongValueExactPos() { + String a = "123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.longValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling longValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#longValueExact() Long value of a negative + * BigDecimal + */ + public void test_LongValueExactFloatNeg() { + BigDecimal aNumber = new BigDecimal("-9223372036854775807.99999"); + try { + aNumber.longValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling longValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @tests java.math.BigDecimal#longValueExact() Long value of a positive + * BigDecimal + */ + public void test_LongValueExactFloatPos() { + float a = 9223372036854775806.99999F; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.longValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling longValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert pisitive BigDesimal + * to byte type + */ + public void test_ByteValueExactPos() { + int i = 127; + BigDecimal bdNumber = new BigDecimal(i); + byte bNumber = bdNumber.byteValueExact(); + assertTrue("incorrect byteValueExact", i == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert negative BigDesimal + * to byte type + */ + public void test_ByteValueExactNeg() { + String sNumber = "-127.56789"; + int iNumber = -128; + int iPresition = 3; + MathContext mc = new MathContext(iPresition, RoundingMode.UP); + BigDecimal bdNumber = new BigDecimal(sNumber, mc); + byte bNumber = bdNumber.byteValueExact(); + assertTrue("incorrect byteValueExact", iNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from char array to byte type + */ + + public void test_ByteValueExactCharZero() { + char[] cNumber = { + '-', '0', '.', '0' + }; + int iNumber = 0; + int iPresition = 5; + MathContext mc = new MathContext(iPresition, RoundingMode.HALF_DOWN); + BigDecimal bdNumber = new BigDecimal(cNumber, mc); + byte bNumber = bdNumber.byteValueExact(); + assertTrue("incorrect byteValueExact", iNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from String to byte type + */ + + public void test_ByteValueExactStringZero() { + String sNumber = "00000000000000"; + int iNumber = 0; + int iPresition = 0; + MathContext mc = new MathContext(iPresition, RoundingMode.HALF_UP); + BigDecimal bdNumber = new BigDecimal(sNumber, mc); + byte bNumber = bdNumber.byteValueExact(); + assertTrue("incorrect byteValueExact", iNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from double to byte type + */ + + public void test_ByteValueExactDoubleMax() { + double dNumber = Double.MAX_VALUE; + BigDecimal bdNumber = new BigDecimal(dNumber); + try { + bdNumber.byteValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling byteValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from double to byte type + */ + + public void test_ByteValueExactDoubleMin() { + double dNumber = Double.MIN_VALUE; + BigDecimal bdNumber = new BigDecimal(dNumber); + try { + bdNumber.byteValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling byteValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from float to byte type + */ + + public void test_ByteValueExactFloatPos() { + float fNumber = 123.5445F; + BigDecimal bdNumber = new BigDecimal(fNumber); + try { + bdNumber.byteValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling byteValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from float to byte type + */ + + public void test_ByteValueExactFloatNeg() { + float fNumber = -12.987654321F; + BigDecimal bdNumber = new BigDecimal(fNumber); + try { + bdNumber.byteValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling byteValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from double to byte type + */ + + public void test_ByteValueExactDouble() { + double dNumber = 123.0000D; + BigDecimal bdNumber = new BigDecimal(dNumber); + byte bNumber = bdNumber.byteValueExact(); + assertTrue("incorrect byteValueExact", dNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from long to byte type + */ + + public void test_ByteValueExactLongMin() { + long lNumber = Long.MIN_VALUE; + BigDecimal bdNumber = new BigDecimal(lNumber); + try { + bdNumber.byteValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling byteValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + + /** + * @test java.math.BigDecimal#byteValueExact() Convert BigDesimal created + * from int to byte type + */ + + public void test_ByteValueExactIntMax() { + int iNumber = Integer.MAX_VALUE; + BigDecimal bdNumber = new BigDecimal(iNumber); + try { + bdNumber.byteValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling byteValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected + } + } + + /** + * @test java.math.BigDecimal#byteValue() Convert pisitive BigDesimal to + * byte type + */ + public void test_ByteValuePos() { + int i = 127; + BigDecimal bdNumber = new BigDecimal(i); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", i == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert negative BigDesimal to + * byte type + */ + public void test_ByteValueNeg() { + String sNumber = "-127.56789"; + int iNumber = -128; + int iPresition = 3; + MathContext mc = new MathContext(iPresition, RoundingMode.UP); + BigDecimal bdNumber = new BigDecimal(sNumber, mc); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValueExact", iNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * char array to byte type + */ + + public void test_ByteValueCharZero() { + char[] cNumber = { + '-', '0', '.', '0' + }; + int iNumber = 0; + int iPresition = 0; + MathContext mc = new MathContext(iPresition, RoundingMode.HALF_UP); + BigDecimal bdNumber = new BigDecimal(cNumber, mc); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", iNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * String to byte type + */ + + public void test_ByteValueStringZero() { + String sNumber = "00000"; + int iNumber = 0; + int iPresition = 0; + MathContext mc = new MathContext(iPresition, RoundingMode.HALF_UP); + BigDecimal bdNumber = new BigDecimal(sNumber, mc); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", iNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * double to byte type + */ + + public void test_ByteValueDoubleMax() { + double dNumber = Double.MAX_VALUE; + BigDecimal bdNumber = new BigDecimal(dNumber); + int result = 0; + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", bNumber == result); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * double to byte type + */ + + public void test_ByteValueDoubleMin() { + double dNumber = Double.MIN_VALUE; + BigDecimal bdNumber = new BigDecimal(dNumber); + int result = 0; + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", bNumber == result); + } + + /** + * @test_ java.math.BigDecimal#byteValue() Convert BigDesimal created from + * float to byte type + */ + + public void test_ByteValueFloatNeg() { + float fNumber = -12.987654321F; + byte bValue = -12; + BigDecimal bdNumber = new BigDecimal(fNumber); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", bNumber == bValue); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * double to byte type + */ + + public void test_ByteValueDouble() { + double dNumber = 123.0000D; + BigDecimal bdNumber = new BigDecimal(dNumber); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", dNumber == bNumber); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * long to byte type + */ + + public void test_ByteValueLongMin() { + long lNumber = Long.MIN_VALUE; + int result = 0; + BigDecimal bdNumber = new BigDecimal(lNumber); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", bNumber == result); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * int to byte type + */ + + public void test_ByteValueIntMin() { + int iNumber = Integer.MIN_VALUE; + int result = 0; + BigDecimal bdNumber = new BigDecimal(iNumber); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", bNumber == result); + } + + /** + * @test java.math.BigDecimal#byteValue() Convert BigDesimal created from + * int to byte type + */ + + public void test_ByteValueIntMax() { + int iNumber = Integer.MAX_VALUE; + int result = -1; + BigDecimal bdNumber = new BigDecimal(iNumber); + byte bNumber = bdNumber.byteValue(); + assertTrue("incorrect byteValue", bNumber == result); + } + + /** + * @test java.math.BigDecimal#shortValue() Short value of a negative + * BigDecimal + */ + public void test_ShortValueNeg() { + String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + int result = 23449; + assertTrue("incorrect value", aNumber.shortValue() == result); + } + + /** + * @test java.math.BigDecimal#shortValue() Short value of a positive + * BigDecimal + */ + public void test_ShortValuePos() { + String a = "123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + int result = -23449; + assertTrue("incorrect value", aNumber.shortValue() == result); + } + + /** + * @test java.math.BigDecimal#shortValueExact() Short value of a negative + * BigDecimal + */ + public void test_ShortValueExactNeg() { + String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.shortValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @test java.math.BigDecimal#shortValueExact() Short value of a positive + * BigDecimal + */ + public void test_ShortValueExactPos() { + String a = "123809648392384754573567356745735.63567890295784902768787678287E+21"; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.shortValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @test java.math.BigDecimal#shortValueExact() Short value of a negative + * BigDecimal + */ + public void test_ShortValueExactFloatNeg() { + BigDecimal aNumber = new BigDecimal("-32766.99999"); + try { + aNumber.shortValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @test java.math.BigDecimal#shortValueExact() Short value of a positive + * BigDecimal + */ + public void test_ShortValueExactFloatPos() { + float a = 32767.99999F; + BigDecimal aNumber = new BigDecimal(a); + try { + aNumber.shortValueExact(); + fail("java.lang.ArithmeticException isn't thrown after calling intValueExact"); + } catch (java.lang.ArithmeticException ae) { + // expected; + } + } + + /** + * @test java.math.BigDecimal#shortValueExact() Short value of a positive + * BigDecimal + */ + public void test_ShortValueExactLongPos() { + long a = 12345L; + BigDecimal aNumber = new BigDecimal(a); + short shNumber = aNumber.shortValueExact(); + assertTrue("incorrect value", shNumber == a); + } + + /** + * @test java.math.BigDecimal#shortValueExact() Short value of a positive + * BigDecimal + */ + public void test_ShortValueExactLongNeg() { + long a = -12345L; + BigDecimal aNumber = new BigDecimal(a); + int iNumber = aNumber.shortValueExact(); + assertTrue("incorrect value", iNumber == a); + } + + /** + * @tests java.math.BigDecimal#stripTrailingZeros() stripTrailingZeros() for + * BigDecimal with zero + */ + public void test_stripTrailingZerosZeros() { + + BigDecimal bdNumber = new BigDecimal("0000000"); + BigDecimal result = bdNumber.stripTrailingZeros(); + assertEquals("incorrect value", result.unscaledValue(), bdNumber.unscaledValue()); + assertTrue("incorrect value", result.scale() == 0); + + bdNumber = new BigDecimal(0); + result = bdNumber.stripTrailingZeros(); + assertEquals("incorrect value", result.unscaledValue(), bdNumber.unscaledValue()); + assertTrue("incorrect value", result.scale() == 0); + + bdNumber = new BigDecimal(0.000000); + result = bdNumber.stripTrailingZeros(); + assertEquals("incorrect value", result.unscaledValue(), bdNumber.unscaledValue()); + assertTrue("incorrect value", result.scale() == 0); + } + + /** + * @tests java.math.BigDecimal#stripTrailingZeros() stripTrailingZeros() for + * positive BigDecimal + */ + public void test_stripTrailingZeros() { + + String s = "00000000100000000100000000.000000000100000000"; + int iScale = 10; + BigDecimal bdValue = new BigDecimal("1000000001000000000000000001"); + BigDecimal bdNumber = new BigDecimal(s); + BigDecimal bdResult = bdNumber.stripTrailingZeros(); + assertEquals("incorrect value", bdResult.unscaledValue(), bdValue.unscaledValue()); + assertTrue("incorrect value", bdResult.scale() == iScale); + + s = "1000.0"; + iScale = -3; + BigDecimal bd = new BigDecimal("1"); + bdNumber = new BigDecimal(s); + bdResult = bdNumber.stripTrailingZeros(); + assertEquals("incorrect value", bdResult.unscaledValue(), bd.unscaledValue()); + assertTrue("incorrect value", bdResult.scale() == iScale); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java new file mode 100644 index 0000000..0b0d165 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java @@ -0,0 +1,376 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.*; + +/** + * Class: java.math.BigDecimal + * Methods: movePointLeft, movePointRight, scale, setScale, unscaledValue * + */ +public class BigDecimalScaleOperationsTest extends TestCase { + /** + * 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); + } + +/// ANDROID ADDED + + /** + * check that setScale with a scale greater to the existing scale does not + * change the value. + */ + public void testSetScale() { + BigDecimal x1 = new BigDecimal(1.23400); + BigDecimal x2 = x1.setScale(75); + + assertEquals(0, x1.compareTo(x2)); + assertEquals(0, x2.compareTo(x1)); + + x1.precision(); + + assertEquals(0, x1.compareTo(x2)); + assertEquals(0, x2.compareTo(x1)); + + x2.precision(); + + assertEquals(0, x1.compareTo(x2)); + assertEquals(0, x2.compareTo(x1)); + } + + +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java new file mode 100644 index 0000000..7049cf4 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java @@ -0,0 +1,496 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Method: add + */ +public class BigIntegerAddTest extends TestCase { + /** + * 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/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java new file mode 100644 index 0000000..43d0556 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java @@ -0,0 +1,433 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Method: and + */ +public class BigIntegerAndTest extends TestCase { + /** + * 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 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 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()); + } + + /** + * 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 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()); + } + + /** + * 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 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 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 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 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 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 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 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 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 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()); + } + + /** + * 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()); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java new file mode 100644 index 0000000..b700d62 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java @@ -0,0 +1,534 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Methods: abs, compareTo, equals, max, min, negate, signum + */ +public class BigIntegerCompareTest extends TestCase { + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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 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 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 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 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 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 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 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 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 ZERO. + */ + public void testCompareToZeroZero() { + BigInteger aNumber = BigInteger.ZERO; + BigInteger bNumber = BigInteger.ZERO; + assertEquals(0, aNumber.compareTo(bNumber)); + } + + /** + * 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)); + } + + /** + * 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 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(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)); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertTrue("incorrect sign", result.signum() == 1); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertTrue("incorrect sign", result.signum() == 1); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 1, result.signum()); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertTrue("incorrect sign", result.signum() == 0); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 1, result.signum()); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertTrue("incorrect sign", result.signum() == 1); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertTrue("incorrect sign", result.signum() == 0); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertTrue("incorrect sign", result.signum() == -1); + } + + /** + * 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]); + } + 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 0, result.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 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 ZERO. + */ + public void testSignumZero() { + BigInteger aNumber = BigInteger.ZERO; + assertEquals("incorrect sign", 0, aNumber.signum()); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java new file mode 100644 index 0000000..ad9b118 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java @@ -0,0 +1,857 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +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 TestCase { + /** + * 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 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 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 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 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 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 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 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 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 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 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()); + } + + /** + * 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 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 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 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 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 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); + } + +// Commented out as BIGNUM returns no Primes smaller than 16 bits. +// BEGIN android-removed +// +// /** +// * 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); +//System.out.println(aNumber); +//System.out.println(aNumber.bitLength()); +// assertTrue("incorrect bitLength", aNumber.bitLength() == bitLen); +// int num = aNumber.intValue(); +// assertTrue("incorrect value", num == 2 || num == 3); +// } +// END android-removed + +// ANDROID ADDED + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrString1() { + String s = "0"; + BigInteger bi_s = new BigInteger(s); + assertTrue("the BigInteger value is not initialized properly", bi_s.intValue() == 0); + assertEquals("the BigInteger value is not initialized properly", bi_s.toString(), s); + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrString2() { + String s = "-2147483648"; + BigInteger bi_s = new BigInteger(s); + assertTrue("the BigInteger value is not initialized properly", + bi_s.intValue() == Integer.MIN_VALUE); + assertEquals("the BigInteger value is not initialized properly", bi_s.toString(), s); + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrString3() { + String s = "2147483647"; + BigInteger bi_s = new BigInteger(s); + assertTrue("the BigInteger value is not initialized properly", + bi_s.intValue() == Integer.MAX_VALUE); + assertEquals("the BigInteger value is not initialized properly", bi_s.toString(), s); + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrStringExc1() { + try { + new BigInteger("01234 56"); + fail("NumberFormatException has not been caught"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrStringExc2() { + try { + new BigInteger("1234#56"); + fail("NumberFormatException has not been caught"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrStringExc3() { + try { + new BigInteger("1234.56"); + fail("NumberFormatException has not been caught"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstrStringExc4() { + try { + new BigInteger("1E+1"); + fail("NumberFormatException has not been caught"); + } catch (NumberFormatException e) { + } + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java new file mode 100644 index 0000000..70966b5 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java @@ -0,0 +1,793 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Methods: intValue, longValue, toByteArray(), valueOf(long val), + * floatValue(), doubleValue() + */ +public class BigIntegerConvertTest extends TestCase { + /** + * 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 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 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 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); + } + /** + * 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. + */ + 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. + * 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. + * 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 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. + * 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 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 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 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); + } + + /** + * Return the float value of ZERO. + */ + public void testFloatValueZero() { + String a = "0"; + float result = 0.0f; + float aNumber = new BigInteger(a).floatValue(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * Convert a negative number to a doufloatble 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * Convert a positive number to a float value. + * The exponent is 1023 and the mantissa is all 1s. + * The rounding bit is 0. + * The result is Float.MAX_VALUE. + */ + public void testFloatValuePosMaxValue() { + byte[] a = {0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + int aSign = 1; + float aNumber = new BigInteger(aSign, a).floatValue(); + assertTrue(aNumber == Float.MAX_VALUE); + } + + /** + * Convert a negative number to a float value. + * The exponent is 1023 and the mantissa is all 1s. + * The rounding bit is 0. + * The result is -Float.MAX_VALUE. + */ + public void testFloatValueNegMaxValue() { + byte[] a = {0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + int aSign = -1; + float aNumber = new BigInteger(aSign, a).floatValue(); + assertTrue(aNumber == -Float.MAX_VALUE); + } + + /** + * 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(); + assertTrue(aNumber == Float.POSITIVE_INFINITY); + } + + /** + * Convert a positive number to a float value. + * The number's bit length is greater than 127. + */ + public void testFloatValuePositiveInfinity2() { + String a = "2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863"; + float aNumber = new BigInteger(a).floatValue(); + assertTrue(aNumber == Float.POSITIVE_INFINITY); + } + + /** + * 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(); + assertTrue(aNumber == Float.NEGATIVE_INFINITY); + } + + /** + * 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(); + assertTrue(aNumber == Float.NEGATIVE_INFINITY); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == Float.NEGATIVE_INFINITY); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == resInt); + } + + /** + * 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(); + assertTrue(aNumber == resInt); + } + + /** + * 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(); + assertTrue(aNumber == resInt); + } + + /** + * 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(); + assertTrue(aNumber == resInt); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == resInt); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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(); + assertTrue(aNumber == result); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 0, aNumber.signum()); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java new file mode 100644 index 0000000..10bf147 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java @@ -0,0 +1,671 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Methods: divide, remainder, mod, and divideAndRemainder + */ +public class BigIntegerDivideTest extends TestCase { + /** + * 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 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()); + } + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } + + /** + * 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 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()); + } + + /** + * 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()); + } + + /** + * 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()); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java new file mode 100644 index 0000000..f6c17a8 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java @@ -0,0 +1,81 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import java.math.BigInteger; + +import junit.framework.TestCase; + +/** + * Class: java.math.BigInteger + * Method: hashCode() + */ +public class BigIntegerHashCodeTest extends TestCase { + /** + * 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 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 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/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java new file mode 100644 index 0000000..b2bd801 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java @@ -0,0 +1,325 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Methods: modPow, modInverse, and gcd + */ +public class BigIntegerModPowTest extends TestCase { + /** + * 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: 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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 1, result.signum()); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[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: 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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 1, result.signum()); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 1, result.signum()); + } + + /** + * 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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[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++) { + assertTrue(resBytes[i] == rBytes[i]); + } + assertEquals("incorrect sign", 1, result.signum()); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java new file mode 100644 index 0000000..cbd15e9 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java @@ -0,0 +1,390 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Method: multiply + */ +public class BigIntegerMultiplyTest extends TestCase { + /** + * 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 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 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 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 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 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 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/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java new file mode 100644 index 0000000..3305571 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java @@ -0,0 +1,193 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Methods: and, andNot + */ +public class BigIntegerNotTest extends TestCase { + /** + * 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 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 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 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()); + } + + /** + * 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 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 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()); + } +}
\ No newline at end of file diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java new file mode 100644 index 0000000..3a05e31 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java @@ -0,0 +1,1452 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Methods: bitLength, shiftLeft, shiftRight, + * clearBit, flipBit, setBit, testBit + */ +public class BigIntegerOperateBitsTest extends TestCase { + /** + * bitCount() of zero. + */ + public void testBitCountZero() { + BigInteger aNumber = new BigInteger("0"); + assertEquals(0, aNumber.bitCount()); + } + + /** + * 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()); + } + + /** + * bitLength() of zero. + */ + public void testBitLengthZero() { + BigInteger aNumber = new BigInteger("0"); + assertEquals(0, 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 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()); + } + + /** + * 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) 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()); + } + + /** + * 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()); + } + + /** + * 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) 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()); + } + + /** + * 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()); + } + + /** + * 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) 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()); + } + + /** + * 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) 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: 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()); + } + + /** + * 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 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 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 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 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)); + } + + /** + * 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)); + } + +// ANDROID ADDED + + /** + * @tests java.math.BigInteger#getLowestSetBit() getLowestSetBit for + * negative BigInteger + */ + public void test_getLowestSetBitNeg() { + byte aBytes[] = { + -1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26 + }; + int aSign = -1; + int iNumber = 1; + BigInteger aNumber = new BigInteger(aSign, aBytes); + int result = aNumber.getLowestSetBit(); + assertTrue("incorrect value", result == iNumber); + } + + /** + * @tests java.math.BigInteger#getLowestSetBit() getLowestSetBit for + * positive BigInteger + */ + public void test_getLowestSetBitPos() { + byte aBytes[] = { + -1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26 + }; + int aSign = 1; + int iNumber = 1; + BigInteger aNumber = new BigInteger(aSign, aBytes); + int result = aNumber.getLowestSetBit(); + assertTrue("incorrect value", result == iNumber); + + byte[] aBytes_ = { + 127, 0, 3 + }; + iNumber = 0; + aNumber = new BigInteger(aSign, aBytes_); + result = aNumber.getLowestSetBit(); + assertTrue("incorrect value", result == iNumber); + + byte[] aBytes__ = { + -128, 0, 0 + }; + iNumber = 23; + aNumber = new BigInteger(aSign, aBytes__); + result = aNumber.getLowestSetBit(); + assertTrue("incorrect value", result == iNumber); + } + + /** + * @tests java.math.BigInteger#getLowestSetBit() getLowestSetBit for zero + * BigInteger + */ + public void test_getLowestSetBitZero() { + byte[] aBytes = { + 0 + }; + int aSign = 0; + int iNumber = -1; + BigInteger aNumber = new BigInteger(aSign, aBytes); + int result = aNumber.getLowestSetBit(); + assertTrue("incorrect value", result == iNumber); + + byte[] aBytes_ = { + 0, 0, 0 + }; + iNumber = -1; + aNumber = new BigInteger(aSign, aBytes_); + result = aNumber.getLowestSetBit(); + assertTrue("incorrect value", result == iNumber); + } + +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java new file mode 100644 index 0000000..4b5ae83 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java @@ -0,0 +1,420 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Method: or + */ +public class BigIntegerOrTest extends TestCase { + /** + * 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 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 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()); + } + + /** + * 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 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()); + } + + /** + * 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 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 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 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 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 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 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 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 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 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()); + } + + 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); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java new file mode 100644 index 0000000..f0a6332 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java @@ -0,0 +1,548 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Method: subtract + */ +public class BigIntegerSubtractTest extends TestCase { + /** + * 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 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 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()); + } + + /** + * 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 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()); + } +} + diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java new file mode 100644 index 0000000..8a4b0e4 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java @@ -0,0 +1,228 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import java.math.BigInteger; + +import junit.framework.TestCase; + +/** + * Class: java.math.BigInteger + * Method: toString(int radix) + */ +public class BigIntegerToStringTest extends TestCase { + /** + * 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)); + } + + /** + * 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 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 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)); + } + +// ANDROID ADDED + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString1() { + + String s = "0000000000"; + BigInteger bi = new BigInteger(s); + String sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, "0"); + } + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString2() { + String s = "1234567890987654321"; + BigInteger bi = new BigInteger(s); + String sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, s); + } + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString3() { + String s = "-1234567890987654321"; + BigInteger bi = new BigInteger(s); + String sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, s); + } + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString4() { + String s = "12345678901234"; + long l = 12345678901234L; + BigInteger bi = BigInteger.valueOf(l); + String sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, s); + } + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString5() { + String s = "-12345678901234"; + long l = -12345678901234L; + BigInteger bi = BigInteger.valueOf(l); + String sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, s); + } + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString() { + byte aBytes[] = { + 12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91 + }; + String s = "247856948764430159964673417020251"; + BigInteger bi = new BigInteger(aBytes); + String sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, s); + byte aBytes_[] = { + -12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91 + }; + s = "-238920881723209930210060613844133"; + bi = new BigInteger(aBytes_); + sBI = bi.toString(); + assertEquals("toString method returns incorrect value instead of " + s, sBI, s); + } +} diff --git a/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java new file mode 100644 index 0000000..1e87786 --- /dev/null +++ b/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java @@ -0,0 +1,278 @@ +/* + * 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. + */ +/** + * @author Elena Semukhina + * @version $Revision$ + */ + +package org.apache.harmony.tests.java.math; + +import junit.framework.TestCase; +import java.math.BigInteger; + +/** + * Class: java.math.BigInteger + * Method: xor + */ +public class BigIntegerXorTest extends TestCase { + /** + * 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 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 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 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 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())); + } + + /** + * 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 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 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 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 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 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 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 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 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 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())); + } +} diff --git a/math/src/test/java/tests/api/java/math/AllTests.java b/math/src/test/java/tests/api/java/math/AllTests.java new file mode 100644 index 0000000..2888ba0 --- /dev/null +++ b/math/src/test/java/tests/api/java/math/AllTests.java @@ -0,0 +1,39 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.math; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Test suite that includes all tests for the Math project. + */ +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } + + public static Test suite() { + TestSuite suite = new TestSuite("Tests for java.math"); + // $JUnit-BEGIN$ + suite.addTestSuite(BigDecimalTest.class); + suite.addTestSuite(BigIntegerTest.class); + // $JUnit-END$ + return suite; + } +} diff --git a/math/src/test/java/tests/api/java/math/BigDecimalTest.java b/math/src/test/java/tests/api/java/math/BigDecimalTest.java new file mode 100644 index 0000000..ac67ac9 --- /dev/null +++ b/math/src/test/java/tests/api/java/math/BigDecimalTest.java @@ -0,0 +1,953 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.math; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + + +public class BigDecimalTest extends junit.framework.TestCase { + BigInteger value = new BigInteger("12345908"); + + BigInteger value2 = new BigInteger("12334560000"); + + /** + * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger) + */ + public void test_ConstructorLjava_math_BigInteger() { + BigDecimal big = new BigDecimal(value); + assertTrue("the BigDecimal value is not initialized properly", big + .unscaledValue().equals(value) + && big.scale() == 0); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger, int) + */ + public void test_ConstructorLjava_math_BigIntegerI() { + BigDecimal big = new BigDecimal(value2, 5); + assertTrue("the BigDecimal value is not initialized properly", big + .unscaledValue().equals(value2) + && big.scale() == 5); + assertTrue("the BigDecimal value is not represented properly", big + .toString().equals("123345.60000")); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(double) + */ + public void test_ConstructorD() { + BigDecimal big = new BigDecimal(123E04); + assertTrue( + "the BigDecimal value taking a double argument is not initialized properly", + big.toString().equals("1230000")); + big = new BigDecimal(1.2345E-12); + assertTrue("the double representation is not correct", big + .doubleValue() == 1.2345E-12); + big = new BigDecimal(-12345E-3); + assertTrue("the double representation is not correct", big + .doubleValue() == -12.345); + big = new BigDecimal(5.1234567897654321e138); + assertTrue("the double representation is not correct", big + .doubleValue() == 5.1234567897654321E138 + && big.scale() == 0); + big = new BigDecimal(0.1); + assertTrue( + "the double representation of 0.1 bigDecimal is not correct", + big.doubleValue() == 0.1); + big = new BigDecimal(0.00345); + assertTrue( + "the double representation of 0.00345 bigDecimal is not correct", + big.doubleValue() == 0.00345); + // regression test for HARMONY-2429 + big = new BigDecimal(-0.0); + assertTrue( + "the double representation of -0.0 bigDecimal is not correct", + big.scale() == 0); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(java.lang.String) + */ + public void test_ConstructorLjava_lang_String() throws NumberFormatException { + BigDecimal big = new BigDecimal("345.23499600293850"); + assertTrue("the BigDecimal value is not initialized properly", big + .toString().equals("345.23499600293850") + && big.scale() == 14); + big = new BigDecimal("-12345"); + assertTrue("the BigDecimal value is not initialized properly", big + .toString().equals("-12345") + && big.scale() == 0); + big = new BigDecimal("123."); + assertTrue("the BigDecimal value is not initialized properly", big + .toString().equals("123") + && big.scale() == 0); + + new BigDecimal("1.234E02"); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(java.lang.String) + */ + public void test_constructor_String_plus_exp() { + /* + * BigDecimal does not support a + sign in the exponent when converting + * from a String + */ + new BigDecimal(+23e-0); + new BigDecimal(-23e+0); + } + + /** + * @tests java.math.BigDecimal#BigDecimal(java.lang.String) + */ + public void test_constructor_String_empty() { + try { + new BigDecimal(""); + fail("NumberFormatException expected"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigDecimal#BigDecimal(java.lang.String) + */ + public void test_constructor_String_plus_minus_exp() { + try { + new BigDecimal("+35e+-2"); + fail("NumberFormatException expected"); + } catch (NumberFormatException e) { + } + + try { + new BigDecimal("-35e-+2"); + fail("NumberFormatException expected"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigDecimal#BigDecimal(char[]) + */ + public void test_constructor_CC_plus_minus_exp() { + try { + new BigDecimal("+35e+-2".toCharArray()); + fail("NumberFormatException expected"); + } catch (NumberFormatException e) { + } + + try { + new BigDecimal("-35e-+2".toCharArray()); + fail("NumberFormatException expected"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigDecimal#abs() + */ + public void test_abs() { + BigDecimal big = new BigDecimal("-1234"); + BigDecimal bigabs = big.abs(); + assertTrue("the absolute value of -1234 is not 1234", bigabs.toString() + .equals("1234")); + big = new BigDecimal(new BigInteger("2345"), 2); + bigabs = big.abs(); + assertTrue("the absolute value of 23.45 is not 23.45", bigabs + .toString().equals("23.45")); + } + + /** + * @tests java.math.BigDecimal#add(java.math.BigDecimal) + */ + public void test_addLjava_math_BigDecimal() { + BigDecimal add1 = new BigDecimal("23.456"); + BigDecimal add2 = new BigDecimal("3849.235"); + BigDecimal sum = add1.add(add2); + assertTrue("the sum of 23.456 + 3849.235 is wrong", sum.unscaledValue() + .toString().equals("3872691") + && sum.scale() == 3); + assertTrue("the sum of 23.456 + 3849.235 is not printed correctly", sum + .toString().equals("3872.691")); + BigDecimal add3 = new BigDecimal(12.34E02D); + assertTrue("the sum of 23.456 + 12.34E02 is not printed correctly", + (add1.add(add3)).toString().equals("1257.456")); + } + + /** + * @tests java.math.BigDecimal#compareTo(java.math.BigDecimal) + */ + public void test_compareToLjava_math_BigDecimal() { + BigDecimal comp1 = new BigDecimal("1.00"); + BigDecimal comp2 = new BigDecimal(1.000000D); + assertTrue("1.00 and 1.000000 should be equal", + comp1.compareTo(comp2) == 0); + BigDecimal comp3 = new BigDecimal("1.02"); + assertTrue("1.02 should be bigger than 1.00", + comp3.compareTo(comp1) == 1); + BigDecimal comp4 = new BigDecimal(0.98D); + assertTrue("0.98 should be less than 1.00", + comp4.compareTo(comp1) == -1); + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, int) + */ + public void test_divideLjava_math_BigDecimalI() { + BigDecimal divd1 = new BigDecimal(value, 2); + BigDecimal divd2 = new BigDecimal("2.335"); + BigDecimal divd3 = divd1.divide(divd2, BigDecimal.ROUND_UP); + assertTrue("123459.08/2.335 is not correct", divd3.toString().equals( + "52873.27") + && divd3.scale() == divd1.scale()); + assertTrue( + "the unscaledValue representation of 123459.08/2.335 is not correct", + divd3.unscaledValue().toString().equals("5287327")); + divd2 = new BigDecimal(123.4D); + divd3 = divd1.divide(divd2, BigDecimal.ROUND_DOWN); + assertTrue("123459.08/123.4 is not correct", divd3.toString().equals( + "1000.47") + && divd3.scale() == 2); + divd2 = new BigDecimal(000D); + + try { + divd1.divide(divd2, BigDecimal.ROUND_DOWN); + fail("divide by zero is not caught"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigDecimal#divide(java.math.BigDecimal, int, int) + */ + public void test_divideLjava_math_BigDecimalII() { + BigDecimal divd1 = new BigDecimal(value2, 4); + BigDecimal divd2 = new BigDecimal("0.0023"); + BigDecimal divd3 = divd1.divide(divd2, 3, BigDecimal.ROUND_HALF_UP); + assertTrue("1233456/0.0023 is not correct", divd3.toString().equals( + "536285217.391") + && divd3.scale() == 3); + divd2 = new BigDecimal(1345.5E-02D); + divd3 = divd1.divide(divd2, 0, BigDecimal.ROUND_DOWN); + assertTrue( + "1233456/13.455 is not correct or does not have the correct scale", + divd3.toString().equals("91672") && divd3.scale() == 0); + divd2 = new BigDecimal(0000D); + + try { + divd1.divide(divd2, 4, BigDecimal.ROUND_DOWN); + fail("divide by zero is not caught"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigDecimal#doubleValue() + */ + public void test_doubleValue() { + BigDecimal bigDB = new BigDecimal(-1.234E-112); +// Commenting out this part because it causes an endless loop (see HARMONY-319 and HARMONY-329) +// assertTrue( +// "the double representation of this BigDecimal is not correct", +// bigDB.doubleValue() == -1.234E-112); + bigDB = new BigDecimal(5.00E-324); + assertTrue("the double representation of bigDecimal is not correct", + bigDB.doubleValue() == 5.00E-324); + bigDB = new BigDecimal(1.79E308); + assertTrue("the double representation of bigDecimal is not correct", + bigDB.doubleValue() == 1.79E308 && bigDB.scale() == 0); + bigDB = new BigDecimal(-2.33E102); + assertTrue( + "the double representation of bigDecimal -2.33E102 is not correct", + bigDB.doubleValue() == -2.33E102 && bigDB.scale() == 0); + bigDB = new BigDecimal(Double.MAX_VALUE); + bigDB = bigDB.add(bigDB); + assertTrue( + "a + number out of the double range should return infinity", + bigDB.doubleValue() == Double.POSITIVE_INFINITY); + bigDB = new BigDecimal(-Double.MAX_VALUE); + bigDB = bigDB.add(bigDB); + assertTrue( + "a - number out of the double range should return neg infinity", + bigDB.doubleValue() == Double.NEGATIVE_INFINITY); + } + + /** + * @tests java.math.BigDecimal#equals(java.lang.Object) + */ + public void test_equalsLjava_lang_Object() { + BigDecimal equal1 = new BigDecimal(1.00D); + BigDecimal equal2 = new BigDecimal("1.0"); + assertFalse("1.00 and 1.0 should not be equal", + equal1.equals(equal2)); + equal2 = new BigDecimal(1.01D); + assertFalse("1.00 and 1.01 should not be equal", + equal1.equals(equal2)); + equal2 = new BigDecimal("1.00"); + assertFalse("1.00D and 1.00 should not be equal", + equal1.equals(equal2)); + BigInteger val = new BigInteger("100"); + equal1 = new BigDecimal("1.00"); + equal2 = new BigDecimal(val, 2); + assertTrue("1.00(string) and 1.00(bigInteger) should be equal", equal1 + .equals(equal2)); + equal1 = new BigDecimal(100D); + equal2 = new BigDecimal("2.34576"); + assertFalse("100D and 2.34576 should not be equal", equal1 + .equals(equal2)); + assertFalse("bigDecimal 100D does not equal string 23415", equal1 + .equals("23415")); + } + + /** + * @tests java.math.BigDecimal#floatValue() + */ + public void test_floatValue() { + BigDecimal fl1 = new BigDecimal("234563782344567"); + assertTrue("the float representation of bigDecimal 234563782344567", + fl1.floatValue() == 234563782344567f); + BigDecimal fl2 = new BigDecimal(2.345E37); + assertTrue("the float representation of bigDecimal 2.345E37", fl2 + .floatValue() == 2.345E37F); + fl2 = new BigDecimal(-1.00E-44); + assertTrue("the float representation of bigDecimal -1.00E-44", fl2 + .floatValue() == -1.00E-44F); + fl2 = new BigDecimal(-3E12); + assertTrue("the float representation of bigDecimal -3E12", fl2 + .floatValue() == -3E12F); + fl2 = new BigDecimal(Double.MAX_VALUE); + assertTrue( + "A number can't be represented by float should return infinity", + fl2.floatValue() == Float.POSITIVE_INFINITY); + fl2 = new BigDecimal(-Double.MAX_VALUE); + assertTrue( + "A number can't be represented by float should return infinity", + fl2.floatValue() == Float.NEGATIVE_INFINITY); + + } + + /** + * @tests java.math.BigDecimal#hashCode() + */ + public void test_hashCode() { + // anything that is equal must have the same hashCode + BigDecimal hash = new BigDecimal("1.00"); + BigDecimal hash2 = new BigDecimal(1.00D); + assertTrue("the hashCode of 1.00 and 1.00D is equal", + hash.hashCode() != hash2.hashCode() && !hash.equals(hash2)); + hash2 = new BigDecimal("1.0"); + assertTrue("the hashCode of 1.0 and 1.00 is equal", + hash.hashCode() != hash2.hashCode() && !hash.equals(hash2)); + BigInteger val = new BigInteger("100"); + hash2 = new BigDecimal(val, 2); + assertTrue("hashCode of 1.00 and 1.00(bigInteger) is not equal", hash + .hashCode() == hash2.hashCode() + && hash.equals(hash2)); + hash = new BigDecimal(value, 2); + hash2 = new BigDecimal("-1233456.0000"); + assertTrue("hashCode of 123459.08 and -1233456.0000 is not equal", hash + .hashCode() != hash2.hashCode() + && !hash.equals(hash2)); + hash2 = new BigDecimal(value.negate(), 2); + assertTrue("hashCode of 123459.08 and -123459.08 is not equal", hash + .hashCode() != hash2.hashCode() + && !hash.equals(hash2)); + } + + /** + * @tests java.math.BigDecimal#intValue() + */ + public void test_intValue() { + BigDecimal int1 = new BigDecimal(value, 3); + assertTrue("the int value of 12345.908 is not 12345", + int1.intValue() == 12345); + int1 = new BigDecimal("1.99"); + assertTrue("the int value of 1.99 is not 1", int1.intValue() == 1); + int1 = new BigDecimal("23423419083091823091283933"); + // ran JDK and found representation for the above was -249268259 + assertTrue("the int value of 23423419083091823091283933 is wrong", int1 + .intValue() == -249268259); + int1 = new BigDecimal(-1235D); + assertTrue("the int value of -1235 is not -1235", + int1.intValue() == -1235); + } + + /** + * @tests java.math.BigDecimal#longValue() + */ + public void test_longValue() { + BigDecimal long1 = new BigDecimal(value2.negate(), 0); + assertTrue("the long value of 12334560000 is not 12334560000", long1 + .longValue() == -12334560000L); + long1 = new BigDecimal(-1345.348E-123D); + assertTrue("the long value of -1345.348E-123D is not zero", long1 + .longValue() == 0); + long1 = new BigDecimal("31323423423419083091823091283933"); + // ran JDK and found representation for the above was + // -5251313250005125155 + assertTrue( + "the long value of 31323423423419083091823091283933 is wrong", + long1.longValue() == -5251313250005125155L); + } + + /** + * @tests java.math.BigDecimal#max(java.math.BigDecimal) + */ + public void test_maxLjava_math_BigDecimal() { + BigDecimal max1 = new BigDecimal(value2, 1); + BigDecimal max2 = new BigDecimal(value2, 4); + assertTrue("1233456000.0 is not greater than 1233456", max1.max(max2) + .equals(max1)); + max1 = new BigDecimal(-1.224D); + max2 = new BigDecimal(-1.2245D); + assertTrue("-1.224 is not greater than -1.2245", max1.max(max2).equals( + max1)); + max1 = new BigDecimal(123E18); + max2 = new BigDecimal(123E19); + assertTrue("123E19 is the not the max", max1.max(max2).equals(max2)); + } + + /** + * @tests java.math.BigDecimal#min(java.math.BigDecimal) + */ + public void test_minLjava_math_BigDecimal() { + BigDecimal min1 = new BigDecimal(-12345.4D); + BigDecimal min2 = new BigDecimal(-12345.39D); + assertTrue("-12345.39 should have been returned", min1.min(min2) + .equals(min1)); + min1 = new BigDecimal(value2, 5); + min2 = new BigDecimal(value2, 0); + assertTrue("123345.6 should have been returned", min1.min(min2).equals( + min1)); + } + + /** + * @tests java.math.BigDecimal#movePointLeft(int) + */ + public void test_movePointLeftI() { + BigDecimal movePtLeft = new BigDecimal("123456265.34"); + BigDecimal alreadyMoved = movePtLeft.movePointLeft(5); + assertTrue("move point left 5 failed", alreadyMoved.scale() == 7 + && alreadyMoved.toString().equals("1234.5626534")); + movePtLeft = new BigDecimal(value2.negate(), 0); + alreadyMoved = movePtLeft.movePointLeft(12); + assertTrue("move point left 12 failed", alreadyMoved.scale() == 12 + && alreadyMoved.toString().equals("-0.012334560000")); + movePtLeft = new BigDecimal(123E18); + alreadyMoved = movePtLeft.movePointLeft(2); + assertTrue("move point left 2 failed", + alreadyMoved.scale() == movePtLeft.scale() + 2 + && alreadyMoved.doubleValue() == 1.23E18); + movePtLeft = new BigDecimal(1.123E-12); + alreadyMoved = movePtLeft.movePointLeft(3); + assertTrue("move point left 3 failed", + alreadyMoved.scale() == movePtLeft.scale() + 3 + && alreadyMoved.doubleValue() == 1.123E-15); + movePtLeft = new BigDecimal(value, 2); + alreadyMoved = movePtLeft.movePointLeft(-2); + assertTrue("move point left -2 failed", + alreadyMoved.scale() == movePtLeft.scale() - 2 + && alreadyMoved.toString().equals("12345908")); + } + + /** + * @tests java.math.BigDecimal#movePointRight(int) + */ + public void test_movePointRightI() { + BigDecimal movePtRight = new BigDecimal("-1.58796521458"); + BigDecimal alreadyMoved = movePtRight.movePointRight(8); + assertTrue("move point right 8 failed", alreadyMoved.scale() == 3 + && alreadyMoved.toString().equals("-158796521.458")); + movePtRight = new BigDecimal(value, 2); + alreadyMoved = movePtRight.movePointRight(4); + assertTrue("move point right 4 failed", alreadyMoved.scale() == 0 + && alreadyMoved.toString().equals("1234590800")); + movePtRight = new BigDecimal(134E12); + alreadyMoved = movePtRight.movePointRight(2); + assertTrue("move point right 2 failed", alreadyMoved.scale() == 0 + && alreadyMoved.toString().equals("13400000000000000")); + movePtRight = new BigDecimal(-3.4E-10); + alreadyMoved = movePtRight.movePointRight(5); + assertTrue("move point right 5 failed", + alreadyMoved.scale() == movePtRight.scale() - 5 + && alreadyMoved.doubleValue() == -0.000034); + alreadyMoved = alreadyMoved.movePointRight(-5); + assertTrue("move point right -5 failed", alreadyMoved + .equals(movePtRight)); + } + + /** + * @tests java.math.BigDecimal#multiply(java.math.BigDecimal) + */ + public void test_multiplyLjava_math_BigDecimal() { + BigDecimal multi1 = new BigDecimal(value, 5); + BigDecimal multi2 = new BigDecimal(2.345D); + BigDecimal result = multi1.multiply(multi2); + assertTrue("123.45908 * 2.345 is not correct: " + result, result + .toString().startsWith("289.51154260") + && result.scale() == multi1.scale() + multi2.scale()); + multi1 = new BigDecimal("34656"); + multi2 = new BigDecimal("-2"); + result = multi1.multiply(multi2); + assertTrue("34656 * 2 is not correct", result.toString().equals( + "-69312") + && result.scale() == 0); + multi1 = new BigDecimal(-2.345E-02); + multi2 = new BigDecimal(-134E130); + result = multi1.multiply(multi2); + assertTrue("-2.345E-02 * -134E130 is not correct " + result.doubleValue(), + result.doubleValue() == 3.1422999999999997E130 + && result.scale() == multi1.scale() + multi2.scale()); + multi1 = new BigDecimal("11235"); + multi2 = new BigDecimal("0"); + result = multi1.multiply(multi2); + assertTrue("11235 * 0 is not correct", result.doubleValue() == 0 + && result.scale() == 0); + multi1 = new BigDecimal("-0.00234"); + multi2 = new BigDecimal(13.4E10); + result = multi1.multiply(multi2); + assertTrue("-0.00234 * 13.4E10 is not correct", + result.doubleValue() == -313560000 + && result.scale() == multi1.scale() + multi2.scale()); + } + + /** + * @tests java.math.BigDecimal#negate() + */ + public void test_negate() { + BigDecimal negate1 = new BigDecimal(value2, 7); + assertTrue("the negate of 1233.4560000 is not -1233.4560000", negate1 + .negate().toString().equals("-1233.4560000")); + negate1 = new BigDecimal("-23465839"); + assertTrue("the negate of -23465839 is not 23465839", negate1.negate() + .toString().equals("23465839")); + negate1 = new BigDecimal(-3.456E6); + assertTrue("the negate of -3.456E6 is not 3.456E6", negate1.negate() + .negate().equals(negate1)); + } + + /** + * @tests java.math.BigDecimal#scale() + */ + public void test_scale() { + BigDecimal scale1 = new BigDecimal(value2, 8); + assertTrue("the scale of the number 123.34560000 is wrong", scale1 + .scale() == 8); + BigDecimal scale2 = new BigDecimal("29389."); + assertTrue("the scale of the number 29389. is wrong", + scale2.scale() == 0); + BigDecimal scale3 = new BigDecimal(3.374E13); + assertTrue("the scale of the number 3.374E13 is wrong", + scale3.scale() == 0); + BigDecimal scale4 = new BigDecimal("-3.45E-203"); + // note the scale is calculated as 15 digits of 345000.... + exponent - + // 1. -1 for the 3 + assertTrue("the scale of the number -3.45E-203 is wrong: " + + scale4.scale(), scale4.scale() == 205); + scale4 = new BigDecimal("-345.4E-200"); + assertTrue("the scale of the number -345.4E-200 is wrong", scale4 + .scale() == 201); + } + + /** + * @tests java.math.BigDecimal#setScale(int) + */ + public void test_setScaleI() { + // rounding mode defaults to zero + BigDecimal setScale1 = new BigDecimal(value, 3); + BigDecimal setScale2 = setScale1.setScale(5); + BigInteger setresult = new BigInteger("1234590800"); + assertTrue("the number 12345.908 after setting scale is wrong", + setScale2.unscaledValue().equals(setresult) + && setScale2.scale() == 5); + + try { + setScale2 = setScale1.setScale(2, BigDecimal.ROUND_UNNECESSARY); + fail("arithmetic Exception not caught as a result of loosing precision"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigDecimal#setScale(int, int) + */ + public void test_setScaleII() { + BigDecimal setScale1 = new BigDecimal(2.323E102); + BigDecimal setScale2 = setScale1.setScale(4); + assertTrue("the number 2.323E102 after setting scale is wrong", + setScale2.scale() == 4); + assertTrue("the representation of the number 2.323E102 is wrong", + setScale2.doubleValue() == 2.323E102); + setScale1 = new BigDecimal("-1.253E-12"); + setScale2 = setScale1.setScale(17, BigDecimal.ROUND_CEILING); + assertTrue("the number -1.253E-12 after setting scale is wrong", + setScale2.scale() == 17); + assertTrue( + "the representation of the number -1.253E-12 after setting scale is wrong, " + setScale2.toString(), + setScale2.toString().equals("-1.25300E-12")); + + // testing rounding Mode ROUND_CEILING + setScale1 = new BigDecimal(value, 4); + setScale2 = setScale1.setScale(1, BigDecimal.ROUND_CEILING); + assertTrue( + "the number 1234.5908 after setting scale to 1/ROUND_CEILING is wrong", + setScale2.toString().equals("1234.6") && setScale2.scale() == 1); + BigDecimal setNeg = new BigDecimal(value.negate(), 4); + setScale2 = setNeg.setScale(1, BigDecimal.ROUND_CEILING); + assertTrue( + "the number -1234.5908 after setting scale to 1/ROUND_CEILING is wrong", + setScale2.toString().equals("-1234.5") + && setScale2.scale() == 1); + + // testing rounding Mode ROUND_DOWN + setScale2 = setNeg.setScale(1, BigDecimal.ROUND_DOWN); + assertTrue( + "the number -1234.5908 after setting scale to 1/ROUND_DOWN is wrong", + setScale2.toString().equals("-1234.5") + && setScale2.scale() == 1); + setScale1 = new BigDecimal(value, 4); + setScale2 = setScale1.setScale(1, BigDecimal.ROUND_DOWN); + assertTrue( + "the number 1234.5908 after setting scale to 1/ROUND_DOWN is wrong", + setScale2.toString().equals("1234.5") && setScale2.scale() == 1); + + // testing rounding Mode ROUND_FLOOR + setScale2 = setScale1.setScale(1, BigDecimal.ROUND_FLOOR); + assertTrue( + "the number 1234.5908 after setting scale to 1/ROUND_FLOOR is wrong", + setScale2.toString().equals("1234.5") && setScale2.scale() == 1); + setScale2 = setNeg.setScale(1, BigDecimal.ROUND_FLOOR); + assertTrue( + "the number -1234.5908 after setting scale to 1/ROUND_FLOOR is wrong", + setScale2.toString().equals("-1234.6") + && setScale2.scale() == 1); + + // testing rounding Mode ROUND_HALF_DOWN + setScale2 = setScale1.setScale(3, BigDecimal.ROUND_HALF_DOWN); + assertTrue( + "the number 1234.5908 after setting scale to 3/ROUND_HALF_DOWN is wrong", + setScale2.toString().equals("1234.591") + && setScale2.scale() == 3); + setScale1 = new BigDecimal(new BigInteger("12345000"), 5); + setScale2 = setScale1.setScale(1, BigDecimal.ROUND_HALF_DOWN); + assertTrue( + "the number 123.45908 after setting scale to 1/ROUND_HALF_DOWN is wrong", + setScale2.toString().equals("123.4") && setScale2.scale() == 1); + setScale2 = new BigDecimal("-1234.5000").setScale(0, + BigDecimal.ROUND_HALF_DOWN); + assertTrue( + "the number -1234.5908 after setting scale to 0/ROUND_HALF_DOWN is wrong", + setScale2.toString().equals("-1234") && setScale2.scale() == 0); + + // testing rounding Mode ROUND_HALF_EVEN + setScale1 = new BigDecimal(1.2345789D); + setScale2 = setScale1.setScale(4, BigDecimal.ROUND_HALF_EVEN); + assertTrue( + "the number 1.2345789 after setting scale to 4/ROUND_HALF_EVEN is wrong", + setScale2.doubleValue() == 1.2346D && setScale2.scale() == 4); + setNeg = new BigDecimal(-1.2335789D); + setScale2 = setNeg.setScale(2, BigDecimal.ROUND_HALF_EVEN); + assertTrue( + "the number -1.2335789 after setting scale to 2/ROUND_HALF_EVEN is wrong", + setScale2.doubleValue() == -1.23D && setScale2.scale() == 2); + setScale2 = new BigDecimal("1.2345000").setScale(3, + BigDecimal.ROUND_HALF_EVEN); + assertTrue( + "the number 1.2345789 after setting scale to 3/ROUND_HALF_EVEN is wrong", + setScale2.doubleValue() == 1.234D && setScale2.scale() == 3); + setScale2 = new BigDecimal("-1.2345000").setScale(3, + BigDecimal.ROUND_HALF_EVEN); + assertTrue( + "the number -1.2335789 after setting scale to 3/ROUND_HALF_EVEN is wrong", + setScale2.doubleValue() == -1.234D && setScale2.scale() == 3); + + // testing rounding Mode ROUND_HALF_UP + setScale1 = new BigDecimal("134567.34650"); + setScale2 = setScale1.setScale(3, BigDecimal.ROUND_HALF_UP); + assertTrue( + "the number 134567.34658 after setting scale to 3/ROUND_HALF_UP is wrong", + setScale2.toString().equals("134567.347") + && setScale2.scale() == 3); + setNeg = new BigDecimal("-1234.4567"); + setScale2 = setNeg.setScale(0, BigDecimal.ROUND_HALF_UP); + assertTrue( + "the number -1234.4567 after setting scale to 0/ROUND_HALF_UP is wrong", + setScale2.toString().equals("-1234") && setScale2.scale() == 0); + + // testing rounding Mode ROUND_UNNECESSARY + try { + setScale1.setScale(3, BigDecimal.ROUND_UNNECESSARY); + fail("arithmetic Exception not caught for round unnecessary"); + } catch (ArithmeticException e) { + } + + // testing rounding Mode ROUND_UP + setScale1 = new BigDecimal("100000.374"); + setScale2 = setScale1.setScale(2, BigDecimal.ROUND_UP); + assertTrue( + "the number 100000.374 after setting scale to 2/ROUND_UP is wrong", + setScale2.toString().equals("100000.38") + && setScale2.scale() == 2); + setNeg = new BigDecimal(-134.34589D); + setScale2 = setNeg.setScale(2, BigDecimal.ROUND_UP); + assertTrue( + "the number -134.34589 after setting scale to 2/ROUND_UP is wrong", + setScale2.doubleValue() == -134.35D && setScale2.scale() == 2); + + // testing invalid rounding modes + try { + setScale2 = setScale1.setScale(0, -123); + fail("IllegalArgumentException is not caught for wrong rounding mode"); + } catch (IllegalArgumentException e) { + } + } + + /** + * @tests java.math.BigDecimal#signum() + */ + public void test_signum() { + BigDecimal sign = new BigDecimal(123E-104); + assertTrue("123E-104 is not positive in signum()", sign.signum() == 1); + sign = new BigDecimal("-1234.3959"); + assertTrue("-1234.3959 is not negative in signum()", + sign.signum() == -1); + sign = new BigDecimal(000D); + assertTrue("000D is not zero in signum()", sign.signum() == 0); + } + + /** + * @tests java.math.BigDecimal#subtract(java.math.BigDecimal) + */ + public void test_subtractLjava_math_BigDecimal() { + BigDecimal sub1 = new BigDecimal("13948"); + BigDecimal sub2 = new BigDecimal("2839.489"); + BigDecimal result = sub1.subtract(sub2); + assertTrue("13948 - 2839.489 is wrong: " + result, result.toString() + .equals("11108.511") + && result.scale() == 3); + BigDecimal result2 = sub2.subtract(sub1); + assertTrue("2839.489 - 13948 is wrong", result2.toString().equals( + "-11108.511") + && result2.scale() == 3); + assertTrue("13948 - 2839.489 is not the negative of 2839.489 - 13948", + result.equals(result2.negate())); + sub1 = new BigDecimal(value, 1); + sub2 = new BigDecimal("0"); + result = sub1.subtract(sub2); + assertTrue("1234590.8 - 0 is wrong", result.equals(sub1)); + sub1 = new BigDecimal(1.234E-03); + sub2 = new BigDecimal(3.423E-10); + result = sub1.subtract(sub2); + assertTrue("1.234E-03 - 3.423E-10 is wrong, " + result.doubleValue(), + result.doubleValue() == 0.0012339996577); + sub1 = new BigDecimal(1234.0123); + sub2 = new BigDecimal(1234.0123000); + result = sub1.subtract(sub2); + assertTrue("1234.0123 - 1234.0123000 is wrong, " + result.doubleValue(), + result.doubleValue() == 0.0); + } + + /** + * @tests java.math.BigDecimal#toBigInteger() + */ + public void test_toBigInteger() { + BigDecimal sub1 = new BigDecimal("-29830.989"); + BigInteger result = sub1.toBigInteger(); + + assertTrue("the bigInteger equivalent of -29830.989 is wrong", result + .toString().equals("-29830")); + sub1 = new BigDecimal(-2837E10); + result = sub1.toBigInteger(); + assertTrue("the bigInteger equivalent of -2837E10 is wrong", result + .doubleValue() == -2837E10); + sub1 = new BigDecimal(2.349E-10); + result = sub1.toBigInteger(); + assertTrue("the bigInteger equivalent of 2.349E-10 is wrong", result + .equals(BigInteger.ZERO)); + sub1 = new BigDecimal(value2, 6); + result = sub1.toBigInteger(); + assertTrue("the bigInteger equivalent of 12334.560000 is wrong", result + .toString().equals("12334")); + } + + /** + * @tests java.math.BigDecimal#toString() + */ + public void test_toString() { + BigDecimal toString1 = new BigDecimal("1234.000"); + assertTrue("the toString representation of 1234.000 is wrong", + toString1.toString().equals("1234.000")); + toString1 = new BigDecimal("-123.4E-5"); + assertTrue("the toString representation of -123.4E-5 is wrong: " + + toString1, toString1.toString().equals("-0.001234")); + toString1 = new BigDecimal("-1.455E-20"); + assertTrue("the toString representation of -1.455E-20 is wrong", + toString1.toString().equals("-1.455E-20")); + toString1 = new BigDecimal(value2, 4); + assertTrue("the toString representation of 1233456.0000 is wrong", + toString1.toString().equals("1233456.0000")); + } + + /** + * @tests java.math.BigDecimal#unscaledValue() + */ + public void test_unscaledValue() { + BigDecimal unsVal = new BigDecimal("-2839485.000"); + assertTrue("the unscaledValue of -2839485.000 is wrong", unsVal + .unscaledValue().toString().equals("-2839485000")); + unsVal = new BigDecimal(123E10); + assertTrue("the unscaledValue of 123E10 is wrong", unsVal + .unscaledValue().toString().equals("1230000000000")); + unsVal = new BigDecimal("-4.56E-13"); + assertTrue("the unscaledValue of -4.56E-13 is wrong: " + + unsVal.unscaledValue(), unsVal.unscaledValue().toString() + .equals("-456")); + unsVal = new BigDecimal(value, 3); + assertTrue("the unscaledValue of 12345.908 is wrong", unsVal + .unscaledValue().toString().equals("12345908")); + + } + + /** + * @tests java.math.BigDecimal#valueOf(long) + */ + public void test_valueOfJ() { + BigDecimal valueOfL = BigDecimal.valueOf(9223372036854775806L); + assertTrue("the bigDecimal equivalent of 9223372036854775806 is wrong", + valueOfL.unscaledValue().toString().equals( + "9223372036854775806") + && valueOfL.scale() == 0); + assertTrue( + "the toString representation of 9223372036854775806 is wrong", + valueOfL.toString().equals("9223372036854775806")); + valueOfL = BigDecimal.valueOf(0L); + assertTrue("the bigDecimal equivalent of 0 is wrong", valueOfL + .unscaledValue().toString().equals("0") + && valueOfL.scale() == 0); + } + + /** + * @tests java.math.BigDecimal#valueOf(long, int) + */ + public void test_valueOfJI() { + BigDecimal valueOfJI = BigDecimal.valueOf(9223372036854775806L, 5); + assertTrue( + "the bigDecimal equivalent of 92233720368547.75806 is wrong", + valueOfJI.unscaledValue().toString().equals( + "9223372036854775806") + && valueOfJI.scale() == 5); + assertTrue( + "the toString representation of 9223372036854775806 is wrong", + valueOfJI.toString().equals("92233720368547.75806")); + valueOfJI = BigDecimal.valueOf(1234L, 8); + assertTrue( + "the bigDecimal equivalent of 92233720368547.75806 is wrong", + valueOfJI.unscaledValue().toString().equals("1234") + && valueOfJI.scale() == 8); + assertTrue( + "the toString representation of 9223372036854775806 is wrong", + valueOfJI.toString().equals("0.00001234")); + valueOfJI = BigDecimal.valueOf(0, 3); + assertTrue( + "the bigDecimal equivalent of 92233720368547.75806 is wrong", + valueOfJI.unscaledValue().toString().equals("0") + && valueOfJI.scale() == 3); + assertTrue( + "the toString representation of 9223372036854775806 is wrong", + valueOfJI.toString().equals("0.000")); + + } + + public void test_BigDecimal_serialization() throws Exception { + // Regression for HARMONY-1896 + char[] in = { '1', '5', '6', '7', '8', '7', '.', '0', '0' }; + BigDecimal bd = new BigDecimal(in, 0, 9); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(bd); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bis); + BigDecimal nbd = (BigDecimal) ois.readObject(); + + assertEquals(bd.intValue(), nbd.intValue()); + assertEquals(bd.doubleValue(), nbd.doubleValue(), 0.0); + assertEquals(bd.toString(), nbd.toString()); + } + + /** + * @tests java.math.BigDecimal#stripTrailingZero(long) + */ + public void test_stripTrailingZero() { + BigDecimal sixhundredtest = new BigDecimal("600.0"); + assertTrue("stripTrailingZero failed for 600.0", + ((sixhundredtest.stripTrailingZeros()).scale() == -2) + ); + + /* Single digit, no trailing zero, odd number */ + BigDecimal notrailingzerotest = new BigDecimal("1"); + assertTrue("stripTrailingZero failed for 1", + ((notrailingzerotest.stripTrailingZeros()).scale() == 0) + ); + + /* Zero */ + //regression for HARMONY-4623, NON-BUG DIFF with RI + BigDecimal zerotest = new BigDecimal("0.0000"); + assertTrue("stripTrailingZero failed for 0.0000", + ((zerotest.stripTrailingZeros()).scale() == 0) + ); + } + + public void testMathContextConstruction() { + String a = "-12380945E+61"; + BigDecimal aNumber = new BigDecimal(a); + int precision = 6; + RoundingMode rm = RoundingMode.HALF_DOWN; + MathContext mcIntRm = new MathContext(precision, rm); + MathContext mcStr = new MathContext("precision=6 roundingMode=HALF_DOWN"); + MathContext mcInt = new MathContext(precision); + BigDecimal res = aNumber.abs(mcInt); + assertEquals("MathContext Constructer with int precision failed", + res, + new BigDecimal("1.23809E+68")); + + assertEquals("Equal MathContexts are not Equal ", + mcIntRm, + mcStr); + + assertEquals("Different MathContext are reported as Equal ", + mcInt.equals(mcStr), + false); + + assertEquals("Equal MathContexts have different hashcodes ", + mcIntRm.hashCode(), + mcStr.hashCode()); + + assertEquals("MathContext.toString() returning incorrect value", + mcIntRm.toString(), + "precision=6 roundingMode=HALF_DOWN"); + } + +} diff --git a/math/src/test/java/tests/api/java/math/BigIntegerTest.java b/math/src/test/java/tests/api/java/math/BigIntegerTest.java new file mode 100644 index 0000000..5a4fae7 --- /dev/null +++ b/math/src/test/java/tests/api/java/math/BigIntegerTest.java @@ -0,0 +1,1065 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.math; + +import java.math.BigInteger; +import java.util.Random; + +public class BigIntegerTest extends junit.framework.TestCase { + + BigInteger minusTwo = new BigInteger("-2", 10); + + BigInteger minusOne = new BigInteger("-1", 10); + + BigInteger zero = new BigInteger("0", 10); + + BigInteger one = new BigInteger("1", 10); + + BigInteger two = new BigInteger("2", 10); + + BigInteger ten = new BigInteger("10", 10); + + BigInteger sixteen = new BigInteger("16", 10); + + BigInteger oneThousand = new BigInteger("1000", 10); + + BigInteger aZillion = new BigInteger( + "100000000000000000000000000000000000000000000000000", 10); + + BigInteger twoToTheTen = new BigInteger("1024", 10); + + BigInteger twoToTheSeventy = two.pow(70); + + Random rand = new Random(); + + BigInteger bi; + + BigInteger bi1; + + BigInteger bi2; + + BigInteger bi3; + + BigInteger bi11; + + BigInteger bi22; + + BigInteger bi33; + + BigInteger bi12; + + BigInteger bi23; + + BigInteger bi13; + + BigInteger largePos; + + BigInteger smallPos; + + BigInteger largeNeg; + + BigInteger smallNeg; + + BigInteger[][] booleanPairs; + + /** + * @tests java.math.BigInteger#BigInteger(int, java.util.Random) + */ + public void test_ConstructorILjava_util_Random() { + // regression test for HARMONY-1047 + try { + new BigInteger(Integer.MAX_VALUE, (Random)null); + fail("NegativeArraySizeException expected"); + } catch (NegativeArraySizeException e) { + // PASSED + } + + bi = new BigInteger(70, rand); + bi2 = new BigInteger(70, rand); + assertTrue("Random number is negative", bi.compareTo(zero) >= 0); + assertTrue("Random number is too big", + bi.compareTo(twoToTheSeventy) < 0); + assertTrue( + "Two random numbers in a row are the same (might not be a bug but it very likely is)", + !bi.equals(bi2)); + assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO)); + } + +// mc: Commented out as BIGNUM returns no Primes smaller than 16 bits. +// BEGIN android-removed +// +// /** +// * @tests java.math.BigInteger#BigInteger(int, int, java.util.Random) +// */ +// public void test_ConstructorIILjava_util_Random() { +// bi = new BigInteger(10, 5, rand); +// bi2 = new BigInteger(10, 5, rand); +// assertTrue("Random number one is negative", bi.compareTo(zero) >= 0); +// assertTrue("Random number one is too big", +// bi.compareTo(twoToTheTen) < 0); +// assertTrue("Random number two is negative", bi2.compareTo(zero) >= 0); +// assertTrue("Random number two is too big", +// bi2.compareTo(twoToTheTen) < 0); +// +// Random rand = new Random(); +// BigInteger bi; +// int certainty[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, +// Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -2, -1 }; +// for (int i = 2; i <= 20; i++) { +// for (int c = 0; c < certainty.length; c++) { +// bi = new BigInteger(i, c, rand); // Create BigInteger +// assertTrue("Bit length incorrect", bi.bitLength() == i); +// } +// } +// } +// END android-removed + + /** + * @tests java.math.BigInteger#BigInteger(byte[]) + */ + public void test_Constructor$B() { + byte[] myByteArray; + myByteArray = new byte[] { (byte) 0x00, (byte) 0xFF, (byte) 0xFE }; + bi = new BigInteger(myByteArray); + assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO + .setBit(16).subtract(two))); + myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE }; + bi = new BigInteger(myByteArray); + assertTrue("Incorrect value for neg number", bi.equals(minusTwo)); + } + + /** + * @tests java.math.BigInteger#BigInteger(int, byte[]) + */ + public void test_ConstructorI$B() { + byte[] myByteArray; + myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE }; + bi = new BigInteger(1, myByteArray); + assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO + .setBit(16).subtract(two))); + bi = new BigInteger(-1, myByteArray); + assertTrue("Incorrect value for neg number", bi.equals(BigInteger.ZERO + .setBit(16).subtract(two).negate())); + myByteArray = new byte[] { (byte) 0, (byte) 0 }; + bi = new BigInteger(0, myByteArray); + assertTrue("Incorrect value for zero", bi.equals(zero)); + myByteArray = new byte[] { (byte) 1 }; + try { + new BigInteger(0, myByteArray); + fail("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + // correct + } + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_constructor_String_empty() { + try { + new BigInteger(""); + fail("Expected NumberFormatException for new BigInteger(\"\")"); + } catch (NumberFormatException e) { + } + } + + /** + * @tests java.math.BigInteger#toByteArray() + */ + public void test_toByteArray() { + byte[] myByteArray, anotherByteArray; + myByteArray = new byte[] { 97, 33, 120, 124, 50, 2, 0, 0, 0, 12, 124, + 42 }; + anotherByteArray = new BigInteger(myByteArray).toByteArray(); + assertTrue("Incorrect byte array returned", + myByteArray.length == anotherByteArray.length); + for (int counter = myByteArray.length - 1; counter >= 0; counter--) { + assertTrue("Incorrect values in returned byte array", + myByteArray[counter] == anotherByteArray[counter]); + } + } + + /** + * @tests java.math.BigInteger#isProbablePrime(int) + */ + public void test_isProbablePrimeI() { + int fails = 0; + bi = new BigInteger(20, 20, rand); + if (!bi.isProbablePrime(17)) { + fails++; + } + bi = new BigInteger("4", 10); + if (bi.isProbablePrime(17)) { + fail("isProbablePrime failed for: " + bi); + } + bi = BigInteger.valueOf(17L * 13L); + if (bi.isProbablePrime(17)) { + fail("isProbablePrime failed for: " + bi); + } + for (long a = 2; a < 1000; a++) { + if (isPrime(a)) { + assertTrue("false negative on prime number <1000", BigInteger + .valueOf(a).isProbablePrime(5)); + } else if (BigInteger.valueOf(a).isProbablePrime(17)) { + System.out.println("isProbablePrime failed for: " + a); + fails++; + } + } + for (int a = 0; a < 1000; a++) { + bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply( + BigInteger.valueOf(rand.nextInt(1000000))); + if (bi.isProbablePrime(17)) { + System.out.println("isProbablePrime failed for: " + bi); + fails++; + } + } + for (int a = 0; a < 200; a++) { + bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand)); + if (bi.isProbablePrime(17)) { + System.out.println("isProbablePrime failed for: " + bi); + fails++; + } + } + assertTrue("Too many false positives - may indicate a problem", + fails <= 1); + } + + +// BEGIN android-added +// public void testModPowPerformance() { +// Random rnd = new Random(); +// for (int i = 0; i < 10; i++) { +// BigInteger a = new BigInteger(512, rnd); +// BigInteger m = new BigInteger(1024, rnd); +// BigInteger p = new BigInteger(256, rnd); +// BigInteger mp = a.modPow(p, m); +// System.out.println(mp); +// } +// } + +// shows factor 20 speed up (BIGNUM to Harmony Java): +// public void testNextProbablePrime() { +// Random rnd = new Random(); +// rnd.setSeed(0); +// for (int i = 1; i <= 32; i += 1) { +// BigInteger a = new BigInteger(i, rnd); +// System.out.println(a); +// BigInteger prime = a.nextProbablePrime(); +// System.out.print("Next Probable Prime is "); +// System.out.println(prime); +// } +// for (int i = 1; i <= 32; i += 4) { +// BigInteger a = new BigInteger(32 * i, rnd); +// System.out.println(a); +// BigInteger prime = a.nextProbablePrime(); +// System.out.print("Next Probable Prime is "); +// System.out.println(prime); +// } +// } + +// shows factor 20 speed up (BIGNUM to Harmony Java): +// shows that certainty 80 is "practically aquivalent" to certainty 100 +// public void testPrimeGenPerformance() { +// Random rnd = new Random(); +// rnd.setSeed(0); +// for (int i = 1; i <= 32; i +=8 ) { +// BigInteger a = new BigInteger(32 * i, 80, rnd); +// System.out.println(a); +// System.out.println("Now testing it again:"); +// if (a.isProbablePrime(100)) { +// System.out.println("************************ PASSED! **************************"); +// } else { +// System.out.println("************************ FAILED!!! **************************"); +// System.out.println("************************ FAILED!!! **************************"); +// System.out.println("************************ FAILED!!! **************************"); +// System.out.println("************************ FAILED!!! **************************"); +// System.out.println("************************ FAILED!!! **************************"); +// System.out.println("************************ FAILED!!! **************************"); +// } +// } +// } +// END android-added + + + /** + * @tests java.math.BigInteger#equals(java.lang.Object) + */ + public void test_equalsLjava_lang_Object() { + assertTrue("0=0", zero.equals(BigInteger.valueOf(0))); + assertTrue("-123=-123", BigInteger.valueOf(-123).equals( + BigInteger.valueOf(-123))); + assertTrue("0=1", !zero.equals(one)); + assertTrue("0=-1", !zero.equals(minusOne)); + assertTrue("1=-1", !one.equals(minusOne)); + assertTrue("bi3=bi3", bi3.equals(bi3)); + assertTrue("bi3=copy of bi3", bi3.equals(bi3.negate().negate())); + assertTrue("bi3=bi2", !bi3.equals(bi2)); + } + + /** + * @tests java.math.BigInteger#compareTo(java.math.BigInteger) + */ + public void test_compareToLjava_math_BigInteger() { + assertTrue("Smaller number returned >= 0", one.compareTo(two) < 0); + assertTrue("Larger number returned >= 0", two.compareTo(one) > 0); + assertTrue("Equal numbers did not return 0", one.compareTo(one) == 0); + assertTrue("Neg number messed things up", + two.negate().compareTo(one) < 0); + } + + /** + * @tests java.math.BigInteger#intValue() + */ + public void test_intValue() { + assertTrue("Incorrect intValue for 2**70", + twoToTheSeventy.intValue() == 0); + assertTrue("Incorrect intValue for 2", two.intValue() == 2); + } + + /** + * @tests java.math.BigInteger#longValue() + */ + public void test_longValue() { + assertTrue("Incorrect longValue for 2**70", + twoToTheSeventy.longValue() == 0); + assertTrue("Incorrect longValue for 2", two.longValue() == 2); + } + + /** + * @tests java.math.BigInteger#valueOf(long) + */ + public void test_valueOfJ() { + assertTrue("Incurred number returned for 2", BigInteger.valueOf(2L) + .equals(two)); + assertTrue("Incurred number returned for 200", BigInteger.valueOf(200L) + .equals(BigInteger.valueOf(139).add(BigInteger.valueOf(61)))); + } + + /** + * @tests java.math.BigInteger#add(java.math.BigInteger) + */ + public void test_addLjava_math_BigInteger() { + assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion) + .add(aZillion.negate()).equals(aZillion)); + assertTrue("0+0", zero.add(zero).equals(zero)); + assertTrue("0+1", zero.add(one).equals(one)); + assertTrue("1+0", one.add(zero).equals(one)); + assertTrue("1+1", one.add(one).equals(two)); + assertTrue("0+(-1)", zero.add(minusOne).equals(minusOne)); + assertTrue("(-1)+0", minusOne.add(zero).equals(minusOne)); + assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(minusTwo)); + assertTrue("1+(-1)", one.add(minusOne).equals(zero)); + assertTrue("(-1)+1", minusOne.add(one).equals(zero)); + + for (int i = 0; i < 200; i++) { + BigInteger midbit = zero.setBit(i); + assertTrue("add fails to carry on bit " + i, midbit.add(midbit) + .equals(zero.setBit(i + 1))); + } + BigInteger bi2p3 = bi2.add(bi3); + BigInteger bi3p2 = bi3.add(bi2); + assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2)); + + // add large positive + small positive + + // add large positive + small negative + + // add large negative + small positive + + // add large negative + small negative + } + + /** + * @tests java.math.BigInteger#negate() + */ + public void test_negate() { + assertTrue("Single negation of zero did not result in zero", zero + .negate().equals(zero)); + assertTrue("Single negation resulted in original nonzero number", + !aZillion.negate().equals(aZillion)); + assertTrue("Double negation did not result in original number", + aZillion.negate().negate().equals(aZillion)); + + assertTrue("0.neg", zero.negate().equals(zero)); + assertTrue("1.neg", one.negate().equals(minusOne)); + assertTrue("2.neg", two.negate().equals(minusTwo)); + assertTrue("-1.neg", minusOne.negate().equals(one)); + assertTrue("-2.neg", minusTwo.negate().equals(two)); + assertTrue("0x62EB40FEF85AA9EBL*2.neg", BigInteger.valueOf( + 0x62EB40FEF85AA9EBL * 2).negate().equals( + BigInteger.valueOf(-0x62EB40FEF85AA9EBL * 2))); + for (int i = 0; i < 200; i++) { + BigInteger midbit = zero.setBit(i); + BigInteger negate = midbit.negate(); + assertTrue("negate negate", negate.negate().equals(midbit)); + assertTrue("neg fails on bit " + i, midbit.negate().add(midbit) + .equals(zero)); + } + } + + /** + * @tests java.math.BigInteger#signum() + */ + public void test_signum() { + assertTrue("Wrong positive signum", two.signum() == 1); + assertTrue("Wrong zero signum", zero.signum() == 0); + assertTrue("Wrong neg zero signum", zero.negate().signum() == 0); + assertTrue("Wrong neg signum", two.negate().signum() == -1); + } + + /** + * @tests java.math.BigInteger#abs() + */ + public void test_abs() { + assertTrue("Invalid number returned for zillion", aZillion.negate() + .abs().equals(aZillion.abs())); + assertTrue("Invalid number returned for zero neg", zero.negate().abs() + .equals(zero)); + assertTrue("Invalid number returned for zero", zero.abs().equals(zero)); + assertTrue("Invalid number returned for two", two.negate().abs() + .equals(two)); + } + + /** + * @tests java.math.BigInteger#pow(int) + */ + public void test_powI() { + assertTrue("Incorrect exponent returned for 2**10", two.pow(10).equals( + twoToTheTen)); + assertTrue("Incorrect exponent returned for 2**70", two.pow(30) + .multiply(two.pow(40)).equals(twoToTheSeventy)); + assertTrue("Incorrect exponent returned for 10**50", ten.pow(50) + .equals(aZillion)); + } + + /** + * @tests java.math.BigInteger#modInverse(java.math.BigInteger) + */ + public void test_modInverseLjava_math_BigInteger() { + BigInteger a = zero, mod, inv; + for (int j = 3; j < 50; j++) { + mod = BigInteger.valueOf(j); + for (int i = -j + 1; i < j; i++) { + try { + a = BigInteger.valueOf(i); + inv = a.modInverse(mod); + assertTrue("bad inverse: " + a + " inv mod " + mod + + " equals " + inv, one.equals(a.multiply(inv).mod( + mod))); + assertTrue("inverse greater than modulo: " + a + + " inv mod " + mod + " equals " + inv, inv + .compareTo(mod) < 0); + assertTrue("inverse less than zero: " + a + " inv mod " + + mod + " equals " + inv, inv + .compareTo(BigInteger.ZERO) >= 0); + } catch (ArithmeticException e) { + assertTrue("should have found inverse for " + a + " mod " + + mod, !one.equals(a.gcd(mod))); + } + } + } + for (int j = 1; j < 10; j++) { + mod = bi2.add(BigInteger.valueOf(j)); + for (int i = 0; i < 20; i++) { + try { + a = bi3.add(BigInteger.valueOf(i)); + inv = a.modInverse(mod); + assertTrue("bad inverse: " + a + " inv mod " + mod + + " equals " + inv, one.equals(a.multiply(inv).mod( + mod))); + assertTrue("inverse greater than modulo: " + a + + " inv mod " + mod + " equals " + inv, inv + .compareTo(mod) < 0); + assertTrue("inverse less than zero: " + a + " inv mod " + + mod + " equals " + inv, inv + .compareTo(BigInteger.ZERO) >= 0); + } catch (ArithmeticException e) { + assertTrue("should have found inverse for " + a + " mod " + + mod, !one.equals(a.gcd(mod))); + } + } + } + } + + /** + * @tests java.math.BigInteger#shiftRight(int) + */ + public void test_shiftRightI() { + assertTrue("1 >> 0", BigInteger.valueOf(1).shiftRight(0).equals( + BigInteger.ONE)); + assertTrue("1 >> 1", BigInteger.valueOf(1).shiftRight(1).equals( + BigInteger.ZERO)); + assertTrue("1 >> 63", BigInteger.valueOf(1).shiftRight(63).equals( + BigInteger.ZERO)); + assertTrue("1 >> 64", BigInteger.valueOf(1).shiftRight(64).equals( + BigInteger.ZERO)); + assertTrue("1 >> 65", BigInteger.valueOf(1).shiftRight(65).equals( + BigInteger.ZERO)); + assertTrue("1 >> 1000", BigInteger.valueOf(1).shiftRight(1000).equals( + BigInteger.ZERO)); + assertTrue("-1 >> 0", BigInteger.valueOf(-1).shiftRight(0).equals( + minusOne)); + assertTrue("-1 >> 1", BigInteger.valueOf(-1).shiftRight(1).equals( + minusOne)); + assertTrue("-1 >> 63", BigInteger.valueOf(-1).shiftRight(63).equals( + minusOne)); + assertTrue("-1 >> 64", BigInteger.valueOf(-1).shiftRight(64).equals( + minusOne)); + assertTrue("-1 >> 65", BigInteger.valueOf(-1).shiftRight(65).equals( + minusOne)); + assertTrue("-1 >> 1000", BigInteger.valueOf(-1).shiftRight(1000) + .equals(minusOne)); + + BigInteger a = BigInteger.ONE; + BigInteger c = bi3; + BigInteger E = bi3.negate(); + BigInteger e = E; + for (int i = 0; i < 200; i++) { + BigInteger b = BigInteger.ZERO.setBit(i); + assertTrue("a==b", a.equals(b)); + a = a.shiftLeft(1); + assertTrue("a non-neg", a.signum() >= 0); + + BigInteger d = bi3.shiftRight(i); + assertTrue("c==d", c.equals(d)); + c = c.shiftRight(1); + assertTrue(">>1 == /2", d.divide(two).equals(c)); + assertTrue("c non-neg", c.signum() >= 0); + + BigInteger f = E.shiftRight(i); + assertTrue("e==f", e.equals(f)); + e = e.shiftRight(1); + assertTrue(">>1 == /2", f.subtract(one).divide(two).equals(e)); + assertTrue("e negative", e.signum() == -1); + + assertTrue("b >> i", b.shiftRight(i).equals(one)); + assertTrue("b >> i+1", b.shiftRight(i + 1).equals(zero)); + assertTrue("b >> i-1", b.shiftRight(i - 1).equals(two)); + } + } + + /** + * @tests java.math.BigInteger#shiftLeft(int) + */ + public void test_shiftLeftI() { + assertTrue("1 << 0", one.shiftLeft(0).equals(one)); + assertTrue("1 << 1", one.shiftLeft(1).equals(two)); + assertTrue("1 << 63", one.shiftLeft(63).equals( + new BigInteger("8000000000000000", 16))); + assertTrue("1 << 64", one.shiftLeft(64).equals( + new BigInteger("10000000000000000", 16))); + assertTrue("1 << 65", one.shiftLeft(65).equals( + new BigInteger("20000000000000000", 16))); + assertTrue("-1 << 0", minusOne.shiftLeft(0).equals(minusOne)); + assertTrue("-1 << 1", minusOne.shiftLeft(1).equals(minusTwo)); + assertTrue("-1 << 63", minusOne.shiftLeft(63).equals( + new BigInteger("-9223372036854775808"))); + assertTrue("-1 << 64", minusOne.shiftLeft(64).equals( + new BigInteger("-18446744073709551616"))); + assertTrue("-1 << 65", minusOne.shiftLeft(65).equals( + new BigInteger("-36893488147419103232"))); + + BigInteger a = bi3; + BigInteger c = minusOne; + for (int i = 0; i < 200; i++) { + BigInteger b = bi3.shiftLeft(i); + assertTrue("a==b", a.equals(b)); + assertTrue("a >> i == bi3", a.shiftRight(i).equals(bi3)); + a = a.shiftLeft(1); + assertTrue("<<1 == *2", b.multiply(two).equals(a)); + assertTrue("a non-neg", a.signum() >= 0); + assertTrue("a.bitCount==b.bitCount", a.bitCount() == b.bitCount()); + + BigInteger d = minusOne.shiftLeft(i); + assertTrue("c==d", c.equals(d)); + c = c.shiftLeft(1); + assertTrue("<<1 == *2 negative", d.multiply(two).equals(c)); + assertTrue("c negative", c.signum() == -1); + assertTrue("d >> i == minusOne", d.shiftRight(i).equals(minusOne)); + } + } + + /** + * @tests java.math.BigInteger#multiply(java.math.BigInteger) + */ + public void test_multiplyLjava_math_BigInteger() { + assertTrue("Incorrect sum--wanted three zillion", aZillion + .add(aZillion).add(aZillion).equals( + aZillion.multiply(new BigInteger("3", 10)))); + + assertTrue("0*0", zero.multiply(zero).equals(zero)); + assertTrue("0*1", zero.multiply(one).equals(zero)); + assertTrue("1*0", one.multiply(zero).equals(zero)); + assertTrue("1*1", one.multiply(one).equals(one)); + assertTrue("0*(-1)", zero.multiply(minusOne).equals(zero)); + assertTrue("(-1)*0", minusOne.multiply(zero).equals(zero)); + assertTrue("(-1)*(-1)", minusOne.multiply(minusOne).equals(one)); + assertTrue("1*(-1)", one.multiply(minusOne).equals(minusOne)); + assertTrue("(-1)*1", minusOne.multiply(one).equals(minusOne)); + + testAllMults(bi1, bi1, bi11); + testAllMults(bi2, bi2, bi22); + testAllMults(bi3, bi3, bi33); + testAllMults(bi1, bi2, bi12); + testAllMults(bi1, bi3, bi13); + testAllMults(bi2, bi3, bi23); + } + + /** + * @tests java.math.BigInteger#divide(java.math.BigInteger) + */ + public void test_divideLjava_math_BigInteger() { + testAllDivs(bi33, bi3); + testAllDivs(bi22, bi2); + testAllDivs(bi11, bi1); + testAllDivs(bi13, bi1); + testAllDivs(bi13, bi3); + testAllDivs(bi12, bi1); + testAllDivs(bi12, bi2); + testAllDivs(bi23, bi2); + testAllDivs(bi23, bi3); + testAllDivs(largePos, bi1); + testAllDivs(largePos, bi2); + testAllDivs(largePos, bi3); + testAllDivs(largeNeg, bi1); + testAllDivs(largeNeg, bi2); + testAllDivs(largeNeg, bi3); + testAllDivs(largeNeg, largePos); + testAllDivs(largePos, largeNeg); + testAllDivs(bi3, bi3); + testAllDivs(bi2, bi2); + testAllDivs(bi1, bi1); + testDivRanges(bi1); + testDivRanges(bi2); + testDivRanges(bi3); + testDivRanges(smallPos); + testDivRanges(largePos); + testDivRanges(new BigInteger("62EB40FEF85AA9EB", 16)); + testAllDivs(BigInteger.valueOf(0xCC0225953CL), BigInteger + .valueOf(0x1B937B765L)); + + try { + largePos.divide(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi1.divide(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi3.negate().divide(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + zero.divide(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigInteger#remainder(java.math.BigInteger) + */ + public void test_remainderLjava_math_BigInteger() { + try { + largePos.remainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi1.remainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi3.negate().remainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + zero.remainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigInteger#mod(java.math.BigInteger) + */ + public void test_modLjava_math_BigInteger() { + try { + largePos.mod(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi1.mod(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi3.negate().mod(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + zero.mod(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigInteger#divideAndRemainder(java.math.BigInteger) + */ + public void test_divideAndRemainderLjava_math_BigInteger() { + try { + largePos.divideAndRemainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi1.divideAndRemainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + bi3.negate().divideAndRemainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + + try { + zero.divideAndRemainder(zero); + fail("ArithmeticException expected"); + } catch (ArithmeticException e) { + } + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String) + */ + public void test_ConstructorLjava_lang_String() { + assertTrue("new(0)", new BigInteger("0").equals(BigInteger.valueOf(0))); + assertTrue("new(1)", new BigInteger("1").equals(BigInteger.valueOf(1))); + assertTrue("new(12345678901234)", new BigInteger("12345678901234") + .equals(BigInteger.valueOf(12345678901234L))); + assertTrue("new(-1)", new BigInteger("-1").equals(BigInteger + .valueOf(-1))); + assertTrue("new(-12345678901234)", new BigInteger("-12345678901234") + .equals(BigInteger.valueOf(-12345678901234L))); + } + + /** + * @tests java.math.BigInteger#BigInteger(java.lang.String, int) + */ + public void test_ConstructorLjava_lang_StringI() { + assertTrue("new(0,16)", new BigInteger("0", 16).equals(BigInteger + .valueOf(0))); + assertTrue("new(1,16)", new BigInteger("1", 16).equals(BigInteger + .valueOf(1))); + assertTrue("new(ABF345678901234,16)", new BigInteger("ABF345678901234", + 16).equals(BigInteger.valueOf(0xABF345678901234L))); + assertTrue("new(abf345678901234,16)", new BigInteger("abf345678901234", + 16).equals(BigInteger.valueOf(0xABF345678901234L))); + assertTrue("new(-1,16)", new BigInteger("-1", 16).equals(BigInteger + .valueOf(-1))); + assertTrue("new(-ABF345678901234,16)", new BigInteger( + "-ABF345678901234", 16).equals(BigInteger + .valueOf(-0xABF345678901234L))); + assertTrue("new(-abf345678901234,16)", new BigInteger( + "-abf345678901234", 16).equals(BigInteger + .valueOf(-0xABF345678901234L))); + assertTrue("new(-101010101,2)", new BigInteger("-101010101", 2) + .equals(BigInteger.valueOf(-341))); + } + + /** + * @tests java.math.BigInteger#toString() + */ + public void test_toString() { + assertTrue("0.toString", "0".equals(BigInteger.valueOf(0).toString())); + assertTrue("1.toString", "1".equals(BigInteger.valueOf(1).toString())); + assertTrue("12345678901234.toString", "12345678901234" + .equals(BigInteger.valueOf(12345678901234L).toString())); + assertTrue("-1.toString", "-1" + .equals(BigInteger.valueOf(-1).toString())); + assertTrue("-12345678901234.toString", "-12345678901234" + .equals(BigInteger.valueOf(-12345678901234L).toString())); + } + + /** + * @tests java.math.BigInteger#toString(int) + */ + public void test_toStringI() { + assertTrue("0.toString(16)", "0".equals(BigInteger.valueOf(0).toString( + 16))); + assertTrue("1.toString(16)", "1".equals(BigInteger.valueOf(1).toString( + 16))); + assertTrue("ABF345678901234.toString(16)", "abf345678901234" + .equals(BigInteger.valueOf(0xABF345678901234L).toString(16))); + assertTrue("-1.toString(16)", "-1".equals(BigInteger.valueOf(-1) + .toString(16))); + assertTrue("-ABF345678901234.toString(16)", "-abf345678901234" + .equals(BigInteger.valueOf(-0xABF345678901234L).toString(16))); + assertTrue("-101010101.toString(2)", "-101010101".equals(BigInteger + .valueOf(-341).toString(2))); + } + + /** + * @tests java.math.BigInteger#and(java.math.BigInteger) + */ + public void test_andLjava_math_BigInteger() { + for (BigInteger[] element : booleanPairs) { + BigInteger i1 = element[0], i2 = element[1]; + BigInteger res = i1.and(i2); + assertTrue("symmetry of and", res.equals(i2.and(i1))); + int len = Math.max(i1.bitLength(), i2.bitLength()) + 66; + for (int i = 0; i < len; i++) { + assertTrue("and", (i1.testBit(i) && i2.testBit(i)) == res + .testBit(i)); + } + } + } + + /** + * @tests java.math.BigInteger#or(java.math.BigInteger) + */ + public void test_orLjava_math_BigInteger() { + for (BigInteger[] element : booleanPairs) { + BigInteger i1 = element[0], i2 = element[1]; + BigInteger res = i1.or(i2); + assertTrue("symmetry of or", res.equals(i2.or(i1))); + int len = Math.max(i1.bitLength(), i2.bitLength()) + 66; + for (int i = 0; i < len; i++) { + assertTrue("or", (i1.testBit(i) || i2.testBit(i)) == res + .testBit(i)); + } + } + } + + /** + * @tests java.math.BigInteger#xor(java.math.BigInteger) + */ + public void test_xorLjava_math_BigInteger() { + for (BigInteger[] element : booleanPairs) { + BigInteger i1 = element[0], i2 = element[1]; + BigInteger res = i1.xor(i2); + assertTrue("symmetry of xor", res.equals(i2.xor(i1))); + int len = Math.max(i1.bitLength(), i2.bitLength()) + 66; + for (int i = 0; i < len; i++) { + assertTrue("xor", (i1.testBit(i) ^ i2.testBit(i)) == res + .testBit(i)); + } + } + } + + /** + * @tests java.math.BigInteger#not() + */ + public void test_not() { + for (BigInteger[] element : booleanPairs) { + BigInteger i1 = element[0]; + BigInteger res = i1.not(); + int len = i1.bitLength() + 66; + for (int i = 0; i < len; i++) { + assertTrue("not", !i1.testBit(i) == res.testBit(i)); + } + } + } + + /** + * @tests java.math.BigInteger#andNot(java.math.BigInteger) + */ + public void test_andNotLjava_math_BigInteger() { + for (BigInteger[] element : booleanPairs) { + BigInteger i1 = element[0], i2 = element[1]; + BigInteger res = i1.andNot(i2); + int len = Math.max(i1.bitLength(), i2.bitLength()) + 66; + for (int i = 0; i < len; i++) { + assertTrue("andNot", (i1.testBit(i) && !i2.testBit(i)) == res + .testBit(i)); + } + // asymmetrical + i1 = element[1]; + i2 = element[0]; + res = i1.andNot(i2); + for (int i = 0; i < len; i++) { + assertTrue("andNot reversed", + (i1.testBit(i) && !i2.testBit(i)) == res.testBit(i)); + } + } + } + + + public void testClone() { + // Regression test for HARMONY-1770 + MyBigInteger myBigInteger = new MyBigInteger("12345"); + myBigInteger = (MyBigInteger) myBigInteger.clone(); + } + + static class MyBigInteger extends BigInteger implements Cloneable { + public MyBigInteger(String val) { + super(val); + } + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + } + + @Override + protected void setUp() { + bi1 = new BigInteger("2436798324768978", 16); + bi2 = new BigInteger("4576829475724387584378543764555", 16); + bi3 = new BigInteger("43987298363278574365732645872643587624387563245", + 16); + + bi33 = new BigInteger( + "10730846694701319120609898625733976090865327544790136667944805934175543888691400559249041094474885347922769807001", + 10); + bi22 = new BigInteger( + "33301606932171509517158059487795669025817912852219962782230629632224456249", + 10); + bi11 = new BigInteger("6809003003832961306048761258711296064", 10); + bi23 = new BigInteger( + "597791300268191573513888045771594235932809890963138840086083595706565695943160293610527214057", + 10); + bi13 = new BigInteger( + "270307912162948508387666703213038600031041043966215279482940731158968434008", + 10); + bi12 = new BigInteger( + "15058244971895641717453176477697767050482947161656458456", 10); + + largePos = new BigInteger( + "834759814379857314986743298675687569845986736578576375675678998612743867438632986243982098437620983476924376", + 16); + smallPos = new BigInteger("48753269875973284765874598630960986276", 16); + largeNeg = new BigInteger( + "-878824397432651481891353247987891423768534321387864361143548364457698487264387568743568743265873246576467643756437657436587436", + 16); + smallNeg = new BigInteger("-567863254343798609857456273458769843", 16); + booleanPairs = new BigInteger[][] { { largePos, smallPos }, + { largePos, smallNeg }, { largeNeg, smallPos }, + { largeNeg, smallNeg } }; + } + + private void testDiv(BigInteger i1, BigInteger i2) { + BigInteger q = i1.divide(i2); + BigInteger r = i1.remainder(i2); + BigInteger[] temp = i1.divideAndRemainder(i2); + + assertTrue("divide and divideAndRemainder do not agree", q + .equals(temp[0])); + assertTrue("remainder and divideAndRemainder do not agree", r + .equals(temp[1])); + assertTrue("signum and equals(zero) do not agree on quotient", q + .signum() != 0 + || q.equals(zero)); + assertTrue("signum and equals(zero) do not agree on remainder", r + .signum() != 0 + || r.equals(zero)); + assertTrue("wrong sign on quotient", q.signum() == 0 + || q.signum() == i1.signum() * i2.signum()); + assertTrue("wrong sign on remainder", r.signum() == 0 + || r.signum() == i1.signum()); + assertTrue("remainder out of range", r.abs().compareTo(i2.abs()) < 0); + assertTrue("quotient too small", q.abs().add(one).multiply(i2.abs()) + .compareTo(i1.abs()) > 0); + assertTrue("quotient too large", q.abs().multiply(i2.abs()).compareTo( + i1.abs()) <= 0); + BigInteger p = q.multiply(i2); + BigInteger a = p.add(r); + assertTrue("(a/b)*b+(a%b) != a", a.equals(i1)); + try { + BigInteger mod = i1.mod(i2); + assertTrue("mod is negative", mod.signum() >= 0); + assertTrue("mod out of range", mod.abs().compareTo(i2.abs()) < 0); + assertTrue("positive remainder == mod", r.signum() < 0 + || r.equals(mod)); + assertTrue("negative remainder == mod - divisor", r.signum() >= 0 + || r.equals(mod.subtract(i2))); + } catch (ArithmeticException e) { + assertTrue("mod fails on negative divisor only", i2.signum() <= 0); + } + } + + private void testDivRanges(BigInteger i) { + BigInteger bound = i.multiply(two); + for (BigInteger j = bound.negate(); j.compareTo(bound) <= 0; j = j + .add(i)) { + BigInteger innerbound = j.add(two); + BigInteger k = j.subtract(two); + for (; k.compareTo(innerbound) <= 0; k = k.add(one)) { + testDiv(k, i); + } + } + } + + private boolean isPrime(long b) { + if (b == 2) { + return true; + } + // check for div by 2 + if ((b & 1L) == 0) { + return false; + } + long maxlen = ((long) Math.sqrt(b)) + 2; + for (long x = 3; x < maxlen; x += 2) { + if (b % x == 0) { + return false; + } + } + return true; + } + + private void testAllMults(BigInteger i1, BigInteger i2, BigInteger ans) { + assertTrue("i1*i2=ans", i1.multiply(i2).equals(ans)); + assertTrue("i2*i1=ans", i2.multiply(i1).equals(ans)); + assertTrue("-i1*i2=-ans", i1.negate().multiply(i2).equals(ans.negate())); + assertTrue("-i2*i1=-ans", i2.negate().multiply(i1).equals(ans.negate())); + assertTrue("i1*-i2=-ans", i1.multiply(i2.negate()).equals(ans.negate())); + assertTrue("i2*-i1=-ans", i2.multiply(i1.negate()).equals(ans.negate())); + assertTrue("-i1*-i2=ans", i1.negate().multiply(i2.negate()).equals(ans)); + assertTrue("-i2*-i1=ans", i2.negate().multiply(i1.negate()).equals(ans)); + } + + private void testAllDivs(BigInteger i1, BigInteger i2) { + testDiv(i1, i2); + testDiv(i1.negate(), i2); + testDiv(i1, i2.negate()); + testDiv(i1.negate(), i2.negate()); + } +} diff --git a/math/src/test/java/tests/math/AllTests.java b/math/src/test/java/tests/math/AllTests.java new file mode 100644 index 0000000..20664fd --- /dev/null +++ b/math/src/test/java/tests/math/AllTests.java @@ -0,0 +1,61 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.math; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Test suite that includes all tests for the Math project. + */ +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(AllTests.suite()); + } + + public static Test suite() { + TestSuite suite = new TestSuite("All Math test suites"); + + suite.addTest(tests.api.java.math.AllTests.suite()); + + suite.addTestSuite(org.apache.harmony.tests.java.math.BigDecimalArithmeticTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigDecimalCompareTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigDecimalConstructorsTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigDecimalConvertTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigDecimalScaleOperationsTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerAddTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerAndTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerCompareTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerConstructorsTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerConvertTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerDivideTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerHashCodeTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerModPowTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerMultiplyTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerNotTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerOperateBitsTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerOrTest.class); + // suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerProbablePrimeTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerSubtractTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerToStringTest.class); + suite.addTestSuite(org.apache.harmony.tests.java.math.BigIntegerXorTest.class); + // suite.addTestSuite(org.apache.harmony.tests.java.math.MathContextConstructorsTest.class); + // suite.addTestSuite(org.apache.harmony.tests.java.math.MathContextMethodsTest.class); + return suite; + } +} |