You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ml...@apache.org on 2006/08/16 13:56:04 UTC
svn commit: r431881 [1/3] - in
/incubator/harmony/enhanced/classlib/trunk/modules:
luni/src/main/java/java/lang/ math/src/main/java/java/math/
math/src/main/resources/
math/src/test/java/org/apache/harmony/tests/java/math/ math2/
Author: mloenko
Date: Wed Aug 16 04:55:59 2006
New Revision: 431881
URL: http://svn.apache.org/viewvc?rev=431881&view=rev
Log:
integrated src.zip from HARMONY-935
[classlib][java.math] combination of math packages
The tests and new sources were adjusted to match each other
Had to add a method into luni module
Added:
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigInteger.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BitLevel.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/Conversion.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/Division.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/Elementary.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/Logical.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/MathContext.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/Multiplication.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/Primality.java (with props)
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/RoundingMode.java (with props)
Removed:
incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/resources/
incubator/harmony/enhanced/classlib/trunk/modules/math2/
Modified:
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java
incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java
Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java?rev=431881&r1=431880&r2=431881&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/Math.java Wed Aug 16 04:55:59 2006
@@ -191,6 +191,19 @@
*/
public static native double log(double d);
+ /**
+ * Answers the closest double approximation of the base 10 logarithm of the
+ * argument
+ *
+ * @param d
+ * the value to compute the log10 of
+ * @return the natural logarithm of the argument.
+ */
+ public static double log10(double d) {
+ //TODO: this is a stub to integrate HARMONY-935
+ return log(d)/log(10);
+ }
+
/**
* Answers the most positive (i.e. closest to positive infinity) of the two
* arguments.
Added: incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java?rev=431881&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java Wed Aug 16 04:55:59 2006
@@ -0,0 +1,1790 @@
+/*
+ * Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * 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 java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.io.StreamCorruptedException;
+
+/**
+ * @author Daniel Fridlender
+ * @author Matthias Gallé
+ * @author Mariano Heredia
+ * @author Miguel Vasquez
+ *
+ * @ar.org.fitc.spec_ref
+ */
+public class BigDecimal extends Number implements Comparable<BigDecimal>,
+ Serializable {
+
+ /* Static Fields */
+
+ /** @ar.org.fitc.spec_ref */
+ public static final BigDecimal ZERO = new BigDecimal(BigInteger.ZERO, 0);
+
+ /** @ar.org.fitc.spec_ref */
+ public static final BigDecimal ONE = new BigDecimal(BigInteger.ONE, 0);
+
+ /** @ar.org.fitc.spec_ref */
+ public static final BigDecimal TEN = new BigDecimal(BigInteger.TEN, 0);
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_UP = 0;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_DOWN = 1;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_CEILING = 2;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_FLOOR = 3;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_HALF_UP = 4;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_HALF_DOWN = 5;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_HALF_EVEN = 6;
+
+ /** @ar.org.fitc.spec_ref */
+ public static final int ROUND_UNNECESSARY = 7;
+
+ /* Private Fields */
+
+ /** @ar.org.fitc.spec_ref */
+ 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;
+
+ /**
+ * 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[] = new BigInteger[28];
+
+ /**
+ * 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[] = new BigInteger[19];
+
+ /**
+ * 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[11];
+
+ /**
+ * 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;
+ long fivePow = 1;
+
+ for (; i < ZERO_SCALED_BY.length; i++) {
+ BI_SCALED_BY_ZERO[i] = new BigDecimal(BigInteger.valueOf(i), 0);
+ ZERO_SCALED_BY[i] = new BigDecimal(BigInteger.ZERO, i);
+ FIVE_POW[i] = BigInteger.valueOf(fivePow);
+ TEN_POW[i] = BigInteger.valueOf(fivePow << i);
+ CH_ZEROS[i] = '0';
+ fivePow *= 5;
+ }
+ for (; i < TEN_POW.length; i++) {
+ FIVE_POW[i] = BigInteger.valueOf(fivePow);
+ TEN_POW[i] = BigInteger.valueOf(fivePow << i);
+ CH_ZEROS[i] = '0';
+ fivePow *= 5;
+ }
+ for (; i < FIVE_POW.length; i++) {
+ FIVE_POW[i] = BigInteger.valueOf(fivePow);
+ CH_ZEROS[i] = '0';
+ fivePow *= 5;
+ }
+ for (; i < CH_ZEROS.length; i++) {
+ CH_ZEROS[i] = '0';
+ }
+ }
+
+ /**
+ * The arbitrary precision integer (unscaled value) in the internal
+ * representation of <code>BigDecimal</code>.
+ */
+ private BigInteger unscaledValue;
+
+ /**
+ * 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 int precision = 0;
+
+ /* Constructors */
+
+ /** @ar.org.fitc.spec_ref */
+ 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
+ StringBuffer 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 StringBuffer(len);
+ // To skip a possible '+' symbol
+ if ((offset <= last) && (in[offset] == '+')) {
+ offset++;
+ begin++;
+ }
+ // Acumulating all digits until a possible decimal point
+ for (; (offset <= last) && (in[offset] != '.') && (in[offset] != 'e')
+ && (in[offset] != 'E'); offset++)
+ ;
+ unscaledBuffer.append(in, begin, offset - begin);
+ // A decimal point was found
+ if ((offset <= last) && (in[offset] == '.')) {
+ offset++;
+ // Acumulating all digits until a possible exponent
+ begin = offset;
+ for (; (offset <= last) && (in[offset] != 'e')
+ && (in[offset] != 'E'); offset++)
+ ;
+ scale = offset - begin;
+ 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 posible sign of scale
+ begin = offset;
+ if ((offset <= last) && (in[offset] == '+')) {
+ offset++;
+ if ((offset <= last) && (in[offset] != '-')) {
+ begin++;
+ }
+ }
+ // Acumulating all reminaining 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) {
+ throw new NumberFormatException("Scale out of range.");
+ }
+ }
+ // Parsing the unscaled value
+ unscaledValue = new BigInteger(unscaledBuffer.toString());
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(char[] in, int offset, int len, MathContext mc) {
+ this(in, offset, len);
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(char[] in) {
+ this(in, 0, in.length);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(char[] in, MathContext mc) {
+ this(in, 0, in.length);
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(String val) {
+ this(val.toCharArray(), 0, val.length());
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(String val, MathContext mc) {
+ this(val.toCharArray(), 0, val.length());
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(double val) {
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ throw new NumberFormatException("Infinite or NaN");
+ }
+ 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;
+ // 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
+ unscaledValue = BigInteger.valueOf(((bits >> 63) == 0) ? mantisa
+ : -mantisa);
+ if (scale < 0) {
+ unscaledValue = unscaledValue.shiftLeft(-scale);
+ scale = 0;
+ } else if (scale > 0) {
+ // m * 2^e = (m * 5^(-e)) * 10^e
+ unscaledValue = (scale < FIVE_POW.length) ? unscaledValue
+ .multiply(FIVE_POW[scale]) : unscaledValue
+ .multiply(FIVE_POW[1].pow(scale));
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(double val, MathContext mc) {
+ this(val);
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(BigInteger val) {
+ this(val, 0);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(BigInteger val, MathContext mc) {
+ this(val);
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(BigInteger unscaledVal, int scale) {
+ unscaledValue = unscaledVal;
+ this.scale = scale;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
+ this(unscaledVal, scale);
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(int val) {
+ this((long) val);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(int val, MathContext mc) {
+ this((long) val);
+ inplaceRound(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(long val) {
+ unscaledValue = BigInteger.valueOf(val);
+ scale = 0;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal(long val, MathContext mc) {
+ this(val);
+ inplaceRound(mc);
+ }
+
+ /* Public Methods */
+
+ /** @ar.org.fitc.spec_ref */
+ public static BigDecimal valueOf(long unscaledVal, int scale) {
+ if ((unscaledVal == 0) && (scale >= 0)
+ && (scale < ZERO_SCALED_BY.length)) {
+ return ZERO_SCALED_BY[scale];
+ }
+ if ((scale == 0) && (unscaledVal >= 0)
+ && (unscaledVal < BI_SCALED_BY_ZERO.length)) {
+ return BI_SCALED_BY_ZERO[(int) unscaledVal];
+ }
+ return new BigDecimal(BigInteger.valueOf(unscaledVal), scale);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public static BigDecimal valueOf(long val) {
+ return valueOf(val, 0);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public static BigDecimal valueOf(double val) {
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ throw new NumberFormatException("Infinity or NaN");
+ }
+ return new BigDecimal(Double.toString(val));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal add(BigDecimal augend) {
+ long diffScale = (long) this.scale - augend.scale;
+ // Fast return when some operand is zero
+ if (this.signum() == 0) {
+ if (diffScale <= 0) {
+ return augend;
+ }
+ if (augend.signum() == 0) {
+ return this;
+ }
+ } else if (augend.signum() == 0) {
+ if (diffScale >= 0) {
+ return this;
+ }
+ }
+ // Let be: this = [u1,s1] and augend = [u2,s2]
+ if (diffScale == 0) {
+ // case s1 == s2: [u1 + u2 , s1]
+ return new BigDecimal(this.unscaledValue.add(augend.unscaledValue),
+ this.scale);
+ } else if (diffScale > 0) {
+ // case s1 > s2 : [(u1 + u2) * 10 ^ (s1 - s2) , s1]
+ return new BigDecimal(this.unscaledValue.add(augend.unscaledValue
+ .multiply(powerOf10(diffScale))), this.scale);
+ } else {// case s2 > s1 : [(u2 + u1) * 10 ^ (s2 - s1) , s2]
+ return new BigDecimal(augend.unscaledValue.add(this.unscaledValue
+ .multiply(powerOf10(-diffScale))), augend.scale);
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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.signum() == 0) || (this.signum() == 0)
+ || (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 = larger.unscaledValue.multiply(BigInteger.TEN).add(
+ BigInteger.valueOf(largerSignum));
+ } else {
+ tempBI = larger.unscaledValue.subtract(BigInteger
+ .valueOf(largerSignum));
+ tempBI = tempBI.multiply(BigInteger.TEN).add(
+ BigInteger.valueOf(largerSignum * 9));
+ }
+ // Rounding the improved adding
+ larger = new BigDecimal(tempBI, larger.scale + 1);
+ return larger.round(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal subtract(BigDecimal subtrahend) {
+ long diffScale = (long) this.scale - subtrahend.scale;
+ // Fast return when some operand is zero
+ if (this.signum() == 0) {
+ if (diffScale <= 0) {
+ return subtrahend.negate();
+ }
+ if (subtrahend.signum() == 0) {
+ return this;
+ }
+ } else if (subtrahend.signum() == 0) {
+ if (diffScale >= 0) {
+ return this;
+ }
+ }
+ // Let be: this = [u1,s1] and subtrahend = [u2,s2] so:
+ if (diffScale == 0) {
+ // case s1 = s2 : [u1 - u2 , s1]
+ return new BigDecimal(this.unscaledValue
+ .subtract(subtrahend.unscaledValue), this.scale);
+ } else if (diffScale > 0) {
+ // case s1 > s2 : [ u1 - u2 * 10 ^ (s1 - s2) , s1 ]
+ return new BigDecimal(this.unscaledValue
+ .subtract(subtrahend.unscaledValue
+ .multiply(powerOf10(diffScale))), this.scale);
+ } else {// case s2 > s1 : [ u1 * 10 ^ (s2 - s1) - u2 , s2 ]
+ return new BigDecimal(this.unscaledValue.multiply(
+ powerOf10(-diffScale)).subtract(subtrahend.unscaledValue),
+ subtrahend.scale);
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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.signum() == 0) || (this.signum() == 0)
+ || (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 = this.unscaledValue.multiply(BigInteger.TEN).add(
+ BigInteger.valueOf(thisSignum));
+ } else {
+ tempBI = this.unscaledValue.subtract(BigInteger
+ .valueOf(thisSignum));
+ tempBI = tempBI.multiply(BigInteger.TEN).add(
+ BigInteger.valueOf(thisSignum * 9));
+ }
+ // Rounding the improved substracting
+ leftOperand = new BigDecimal(tempBI, this.scale + 1);
+ return leftOperand.round(mc);
+ }
+ }
+ // No optimization is done
+ return subtract(subtrahend).round(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal multiply(BigDecimal multiplicand) {
+ long newScale = (long) this.scale + multiplicand.scale;
+
+ if ((this.signum() == 0) || (multiplicand.signum() == 0)) {
+ return zeroScaledBy(newScale);
+ } else {
+ /* Let be: this = [u1,s1] and multiplicand = [u2,s2] so:
+ * this x multiplicand = [ s1 * s2 , s1 + s2 ] */
+ return new BigDecimal(this.unscaledValue
+ .multiply(multiplicand.unscaledValue), toIntScale(newScale));
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
+ BigDecimal result = multiply(multiplicand);
+
+ result.inplaceRound(mc);
+ return result;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
+ return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal divide(BigDecimal divisor, int scale,
+ RoundingMode roundingMode) {
+ // Let be: this = [u1,s1] and divisor = [u2,s2]
+ long diffScale = ((long) this.scale - divisor.scale) - (long) scale;
+ int sign = this.signum() * divisor.signum(); // sign of the result
+ int compRem; // 'compare to remainder'
+ BigInteger quotAndRem[] = { this.unscaledValue }; // quotient and remainder
+ BigInteger scaledDivisor = divisor.unscaledValue; // for scaling of 'u2'
+
+ if (roundingMode == null) {
+ throw new NullPointerException();
+ }
+ if (divisor.signum() == 0) {
+ throw new ArithmeticException("BigInteger divide by zero");
+ }
+ if (diffScale > 0) {
+ // Multiply 'u2' by: 10^((s1 - s2) - scale)
+ scaledDivisor = scaledDivisor.multiply(powerOf10(diffScale));
+ } else if (diffScale < 0) {
+ // Multiply 'u1' by: 10^(scale - (s1 - s2))
+ quotAndRem[0] = quotAndRem[0].multiply(powerOf10(-diffScale));
+ }
+ quotAndRem = quotAndRem[0].divideAndRemainder(scaledDivisor);
+ // If after division there is a remainder...
+ if (quotAndRem[1].signum() != 0) {
+ // Checking if: remainder * 2 >= scaledDivisor
+ compRem = quotAndRem[1].abs().shiftLeft(1).compareTo(
+ scaledDivisor.abs());
+ compRem = roundingBehavior(quotAndRem[0].testBit(0) ? 1 : 0, sign
+ * (5 + compRem), roundingMode);
+ if (compRem != 0) {
+ quotAndRem[0] = quotAndRem[0].add(BigInteger.valueOf(compRem));
+ }
+ }
+ // Constructing the result with the appropriate unscaled value
+ return new BigDecimal(quotAndRem[0], scale);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal divide(BigDecimal divisor, int roundingMode) {
+ return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
+ return divide(divisor, scale, roundingMode);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal divide(BigDecimal divisor) {
+ BigInteger p = this.unscaledValue;
+ BigInteger q = divisor.unscaledValue;
+ 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.signum() == 0) {
+ throw new ArithmeticException("BigInteger divide by zero");
+ }
+ 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)) {
+ throw new ArithmeticException("Non-terminating decimal expansion;"
+ + " no exact representable decimal result.");
+ }
+ // 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 >= FIVE_POW.length) ? p.multiply(FIVE_POW[1].pow(i))
+ : (i > 0) ? p.multiply(FIVE_POW[i]) : p.shiftLeft(i);
+ return new BigDecimal(p, newScale);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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 = (long) mc.getPrecision() + 2L
+ + (long) divisor.aproxPrecision() - (long) 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[] = { unscaledValue };
+ // In special cases it reduces the problem to call the dual method
+ if ((mc.getPrecision() == 0) || (this.signum() == 0)
+ || (divisor.signum() == 0)) {
+ return this.divide(divisor);
+ }
+ if (traillingZeros > 0) {
+ // To append trailing zeros at end of dividend
+ quotAndRem[0] = unscaledValue.multiply(powerOf10(traillingZeros));
+ newScale += traillingZeros;
+ }
+ quotAndRem = quotAndRem[0].divideAndRemainder(divisor.unscaledValue);
+ 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.unscaledValue);
+ // 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);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal divideToIntegralValue(BigDecimal divisor) {
+ BigInteger integralValue; // the integer of result
+ BigInteger powerOfTen; // some power of ten
+ BigInteger quotAndRem[] = { unscaledValue };
+ long newScale = (long) this.scale - divisor.scale;
+ long tempScale = 0;
+ int i = 1;
+ int lastPow = TEN_POW.length - 1;
+
+ if (divisor.signum() == 0) {
+ throw new ArithmeticException("BigInteger divide by zero");
+ }
+ if ((divisor.aproxPrecision() + newScale > this.aproxPrecision() + 1L)
+ || (this.signum() == 0)) {
+ /* If the divisor's integer part is greater than this's integer part,
+ * the result must be zero with the apropriate scale */
+ integralValue = BigInteger.ZERO;
+ } else if (newScale == 0) {
+ integralValue = unscaledValue.divide(divisor.unscaledValue);
+ } else if (newScale > 0) {
+ powerOfTen = powerOf10(newScale);
+ integralValue = unscaledValue.divide(divisor.unscaledValue
+ .multiply(powerOfTen));
+ integralValue = integralValue.multiply(powerOfTen);
+ } else {// (newScale < 0)
+ powerOfTen = powerOf10(-newScale);
+ integralValue = unscaledValue.multiply(powerOfTen).divide(
+ divisor.unscaledValue);
+ // To strip trailing zeros aproximating 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)));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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.signum() == 0)
+ || (divisor.signum() == 0)) {
+ 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.unscaledValue.divide(divisor.unscaledValue);
+ } else if (diffScale > 0) {
+ // CASE s1 >= s2: to calculate u1 / (u2 * 10^(s1-s2)
+ quotAndRem[0] = this.unscaledValue.divide(divisor.unscaledValue
+ .multiply(powerOf10(diffScale)));
+ // To chose 10^newScale to get a quotient with at least 'mc.precision()' digits
+ newScale = Math.min(diffScale, Math.max((long) mcPrecision
+ - quotPrecision + 1, 0));
+ // To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
+ quotAndRem[0] = quotAndRem[0].multiply(powerOf10(newScale));
+ } else {// CASE s2 > s1:
+ /* To calculate the minimus 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.unscaledValue.multiply(powerOf10(exp))
+ .divideAndRemainder(divisor.unscaledValue);
+ 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
+ - (long) divisor.precision();
+ if (compRemDiv == 0) {
+ // To calculate: (r * 10^exp2) / u2
+ quotAndRem[1] = quotAndRem[1].multiply(powerOf10(exp))
+ .divide(divisor.unscaledValue);
+ compRemDiv = Math.abs(quotAndRem[1].signum());
+ }
+ if (compRemDiv > 0) {
+ // The quotient won't fit in 'mc.precision()' digits
+ throw new ArithmeticException("Division impossible");
+ }
+ }
+ }
+ // 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) {
+ throw new ArithmeticException("Division impossible");
+ } else {
+ integralValue.unscaledValue = strippedBI;
+ integralValue.scale = toIntScale(newScale);
+ return integralValue;
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal remainder(BigDecimal divisor) {
+ return divideAndRemainder(divisor)[1];
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
+ return divideAndRemainder(divisor, mc)[1];
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal pow(int n) {
+ if (n == 0) {
+ return ONE;
+ }
+ if ((n < 0) || (n > 999999999)) {
+ throw new ArithmeticException("Invalid operation");
+ }
+ long newScale = scale * (long) n;
+ // Let be: this = [u,s] so: this^n = [u^n, s*n]
+ return ((signum() == 0) ? zeroScaledBy(newScale) : new BigDecimal(
+ unscaledValue.pow(n), toIntScale(newScale)));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ 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) || ((signum() == 0) && (n > 0))) {
+ return pow(n);
+ }
+ if ((m > 999999999) || ((mcPrecision == 0) && (n < 0))
+ || ((mcPrecision > 0) && (elength > mcPrecision))) {
+ throw new ArithmeticException("Invalid Operation");
+ }
+ 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;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal abs() {
+ return ((signum() < 0) ? negate() : this);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal abs(MathContext mc) {
+ return round(mc).abs();
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal negate() {
+ return new BigDecimal(unscaledValue.negate(), scale);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal negate(MathContext mc) {
+ return round(mc).negate();
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal plus() {
+ return this;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal plus(MathContext mc) {
+ return round(mc);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public int signum() {
+ return unscaledValue.signum();
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public int scale() {
+ return scale;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public int precision() {
+ // Checking if the precision already was calculated
+ if (precision > 0) {
+ return precision;
+ }
+ int bitLength = unscaledValue.bitLength();
+ int decimalDigits = 1; // the precision to be calculated
+ double doubleUnsc = 1; // unscaledValue in 'double'
+
+ if (bitLength < 1024) {
+ // To calculate the precision for small numbers
+ if (bitLength >= 64) {
+ doubleUnsc = unscaledValue.doubleValue();
+ } else if (bitLength >= 32) {
+ doubleUnsc = unscaledValue.longValue();
+ } else if (bitLength >= 1) {
+ doubleUnsc = unscaledValue.intValue();
+ }
+ decimalDigits += Math.log10(Math.abs(doubleUnsc));
+ } else {// (bitLength >= 1024)
+ /* To calculate the precision for large numbers
+ * Note that: 2 ^(bitlength() - 1) <= unscaledValue < 10 ^(precision()) */
+ decimalDigits += (bitLength - 1) * LOG10_2;
+ // If after division the number isn't zero, exists an aditional digit
+ if (unscaledValue.divide(powerOf10(decimalDigits)).signum() != 0) {
+ decimalDigits++;
+ }
+ }
+ precision = decimalDigits;
+ return precision;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigInteger unscaledValue() {
+ return unscaledValue;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal round(MathContext mc) {
+ BigDecimal thisBD = new BigDecimal(unscaledValue, scale);
+
+ thisBD.inplaceRound(mc);
+ return thisBD;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
+ long diffScale = newScale - (long) scale;
+
+ if (roundingMode == null) {
+ throw new NullPointerException();
+ }
+ // Let be: 'this' = [u,s]
+ return ((diffScale >= 0)
+ // return [u * 10^(s2 - s), newScale]
+ ? new BigDecimal(unscaledValue.multiply(powerOf10(diffScale)),
+ newScale)
+ // return [u,s] / [1,newScale] with the apropiate scale and rounding
+ : this.divide(BigDecimal.ONE, newScale, roundingMode));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal setScale(int newScale, int roundingMode) {
+ return setScale(newScale, RoundingMode.valueOf(roundingMode));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal setScale(int newScale) {
+ return setScale(newScale, RoundingMode.UNNECESSARY);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal movePointLeft(int n) {
+ long newScale = scale + (long) n;
+
+ if (signum() == 0) {
+ return zeroScaledBy(Math.max(newScale, 0));
+ } else {
+ /* When: 'n'== Integer.MIN_VALUE isn't possible to call to movePointRight(-n)
+ * since -Integer.MIN_VALUE == Integer.MIN_VALUE */
+ return ((newScale >= 0) ? new BigDecimal(unscaledValue,
+ toIntScale(newScale)) : new BigDecimal(unscaledValue
+ .multiply(powerOf10(-newScale)), 0));
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal movePointRight(int n) {
+ long newScale = scale - (long) n;
+
+ if (signum() == 0) {
+ return zeroScaledBy(Math.max(newScale, 0));
+ } else {
+ // Here we have the same observation that in the movePointLeft(int) method
+ return ((newScale >= 0) ? new BigDecimal(unscaledValue,
+ toIntScale(newScale)) : new BigDecimal(unscaledValue
+ .multiply(powerOf10(-newScale)), 0));
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal scaleByPowerOfTen(int n) {
+ long newScale = scale - (long) n;
+
+ return ((signum() == 0) ? zeroScaledBy(newScale) : new BigDecimal(
+ unscaledValue, toIntScale(newScale)));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal stripTrailingZeros() {
+ int i = 1; // 1 <= i <= 18
+ int lastPow = TEN_POW.length - 1;
+ long newScale = scale;
+ BigInteger strippedBI = unscaledValue;
+ BigInteger[] quotAndRem;
+
+ if (signum() == 0) {
+ return this;
+ }
+ // 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));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public int compareTo(BigDecimal val) {
+ int thisSign = signum();
+
+ if (thisSign > val.signum()) {
+ return 1;
+ } else if (thisSign < val.signum()) {
+ return -1;
+ } else {// thisSign == val.signum()
+ int diffPrecision = this.aproxPrecision() - val.aproxPrecision();
+ long diffScale = (long) this.scale - val.scale;
+
+ 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.unscaledValue;
+ BigInteger valUnscaled = val.unscaledValue;
+ // If any of both precision is bigger, append zeros to the shorter one
+ if (diffScale < 0) {
+ thisUnscaled = thisUnscaled.multiply(powerOf10(-diffScale));
+ } else if (diffScale > 0) {
+ valUnscaled = valUnscaled.multiply(powerOf10(diffScale));
+ }
+ return thisUnscaled.compareTo(valUnscaled);
+ }
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @Override
+ public boolean equals(Object x) {
+ return ((x instanceof BigDecimal) && (((BigDecimal) x).scale == scale) && (((BigDecimal) x).unscaledValue
+ .equals(unscaledValue)));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal min(BigDecimal val) {
+ return ((compareTo(val) <= 0) ? this : val);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal max(BigDecimal val) {
+ return ((compareTo(val) >= 0) ? this : val);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @Override
+ public int hashCode() {
+ /* Take the 24 trailing bits of BigInteger hashcode
+ * and the 8 trailing bits of scale. */
+ return ((unscaledValue.hashCode() << 24) | (0xFF & scale));
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @Override
+ public String toString() {
+ if (toStringImage != null) {
+ return toStringImage;
+ }
+ String intString = unscaledValue.toString();
+ if (scale == 0) {
+ return intString;
+ }
+ int begin = (unscaledValue.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.");
+ 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;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public String toEngineeringString() {
+ String intString = unscaledValue.toString();
+ if (scale == 0) {
+ return intString;
+ }
+ int begin = (unscaledValue.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.");
+ 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 (unscaledValue.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');
+ }
+ System.out.println("1");
+ }
+ }
+ 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();
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public String toPlainString() {
+ String intStr = unscaledValue.toString();
+ if ((scale == 0) || ((signum() == 0) && (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.");
+ // 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();
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigInteger toBigInteger() {
+ if ((scale == 0) || (signum() == 0)) {
+ return unscaledValue;
+ } else if (scale < 0) {
+ return unscaledValue.multiply(powerOf10(-(long) scale));
+ } else {// (scale > 0)
+ return unscaledValue.divide(powerOf10(scale));
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigInteger toBigIntegerExact() {
+ if ((scale == 0) || (signum() == 0)) {
+ return unscaledValue;
+ } else if (scale < 0) {
+ return unscaledValue.multiply(powerOf10(-(long) scale));
+ } else {// (scale > 0)
+ BigInteger[] integerAndFraction;
+ // An optimization before do a heavy division
+ if ((scale > aproxPrecision())
+ || (scale > unscaledValue.getLowestSetBit())) {
+ throw new ArithmeticException("Rounding necessary");
+ }
+ integerAndFraction = unscaledValue
+ .divideAndRemainder(powerOf10(scale));
+ if (integerAndFraction[1].signum() != 0) {
+ // It exists a non-zero fractional part
+ throw new ArithmeticException("Rounding necessary");
+ } else {
+ return integerAndFraction[0];
+ }
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @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());
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public long longValueExact() {
+ return valueExact(64);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @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());
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public int intValueExact() {
+ return (int) valueExact(32);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public short shortValueExact() {
+ return (short) valueExact(16);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public byte byteValueExact() {
+ return (byte) valueExact(8);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @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 = unscaledValue.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;
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ @Override
+ public double doubleValue() {
+ int sign = signum();
+ int exponent = 1076; // bias + 53
+ int lowestSetBit;
+ int discardedSize;
+ long powerOfTwo = unscaledValue.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 = unscaledValue.abs();
+ // Let be: this = [u,s], with s > 0
+ if (scale <= 0) {
+ // mantisa = abs(u) * 10^s
+ mantisa = mantisa.multiply(powerOf10(-scale));
+ } else {// (scale > 0)
+ BigInteger quotAndRem[];
+ BigInteger powerOfTen = 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);
+ } else {// -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);
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ public BigDecimal ulp() {
+ return new BigDecimal(BigInteger.ONE, 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();
+ int discardedPrecision = precision() - mcPrecision;
+ // If no rounding is necessary it returns inmediatly
+ if ((discardedPrecision <= 0) || (mcPrecision == 0)) {
+ return;
+ }
+ // When the number is small perform an efficient rounding
+ if (unscaledValue.bitLength() < 64) {
+ smallRound(mc, discardedPrecision);
+ return;
+ }
+ // Getting the interger part and the discarded fraction
+ BigInteger sizeOfFraction = powerOf10(discardedPrecision);
+ BigInteger[] integerAndFraction = unscaledValue
+ .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 inernal fields
+ scale = toIntScale(newScale);
+ unscaledValue = integerAndFraction[0];
+ precision = mcPrecision;
+ }
+
+ /**
+ * 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 = TEN_POW[discardedPrecision].longValue();
+ long newScale = (long) scale - discardedPrecision;
+ long unscaledVal = unscaledValue.longValue();
+ // Getting the interger 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 = ((new Long(Math.abs(fraction) << 1))
+ .compareTo(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 inernal fields
+ scale = toIntScale(newScale);
+ unscaledValue = BigInteger.valueOf(integer);
+ precision = mc.getPrecision();
+ }
+
+ /**
+ * 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 analized.
+ * @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) {
+ throw new ArithmeticException("Rounding necessary");
+ }
+ 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>unscaledValue</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();
+ } else {
+ throw new ArithmeticException("Rounding necessary");
+ }
+ }
+
+ /**
+ * If the precion already was calculated it returns that value, otherwise
+ * it calculates a very good aproximization efficiently . Note that this
+ * value will be <code>precision()</code> or <code>precision()-1</code>
+ * in the worst case.
+ * @return an aproximization of <code>precision()</code> value
+ */
+ private int aproxPrecision() {
+ return ((precision > 0) ? precision
+ : (int) ((unscaledValue.bitLength() - 1) * LOG10_2)) + 1;
+ }
+
+ /**
+ * 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</code>.
+ * @param exp the exponent of power of ten, it must be positive.
+ * @return a <code>BigInteger</code> with value <code>10^exp</code>.
+ */
+ private static BigInteger powerOf10(long exp) {
+ // PRE: exp >= 0
+ int intExp = (int) exp;
+ // "SMALL POWERS"
+ if (exp < TEN_POW.length) {
+ // The largest power that fit in 'long' type
+ return TEN_POW[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 FIVE_POW[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) */
+ long byteArraySize = 1 + (long) (exp / (8 * LOG10_2));
+
+ if (byteArraySize > Runtime.getRuntime().freeMemory()) {
+ throw new OutOfMemoryError("power of ten too big");
+ }
+ if (exp <= Integer.MAX_VALUE) {
+ // To calculate: 5^exp * 2^exp
+ return FIVE_POW[1].pow(intExp).shiftLeft(intExp);
+ } else {/* "HUGE POWERS"
+ * Probably this branch won't be executed
+ * since the power of ten is too big. */
+ // To calculate: 5^exp
+ BigInteger powerOfFive = FIVE_POW[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(FIVE_POW[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;
+ }
+ }
+
+ /**
+ * 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) {
+ throw new ArithmeticException("Overflow");
+ } else if (longScale > Integer.MAX_VALUE) {
+ throw new ArithmeticException("Underflow");
+ } else {
+ return (int) longScale;
+ }
+ }
+
+ /**
+ * It returns the value 0 with the most aproximated 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 >= 0) {
+ if (longScale < ZERO_SCALED_BY.length) {
+ return ZERO_SCALED_BY[(int) longScale];
+ } else {
+ return new BigDecimal(BigInteger.ZERO,
+ (longScale <= Integer.MAX_VALUE) ? (int) longScale
+ : Integer.MAX_VALUE);
+ }
+ } else {
+ return new BigDecimal(BigInteger.ZERO,
+ (longScale >= Integer.MIN_VALUE) ? (int) longScale
+ : Integer.MIN_VALUE);
+ }
+ }
+
+ /** @ar.org.fitc.spec_ref */
+ private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ in.defaultReadObject();
+ if (unscaledValue == null) {
+ throw new StreamCorruptedException("null unscaled value");
+ }
+ }
+
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java
------------------------------------------------------------------------------
svn:executable = *