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/04/20 06:13:47 UTC

svn commit: r395476 [1/3] - in /incubator/harmony/enhanced/classlib/trunk/modules/math/src: main/java/java/math/ test/java/org/apache/harmony/tests/java/math/ test/java/tests/api/java/math/

Author: mloenko
Date: Wed Apr 19 21:13:44 2006
New Revision: 395476

URL: http://svn.apache.org/viewcvs?rev=395476&view=rev
Log:
improvements from HARMONY-380:
extension of java.math with 1.5 methods

Added:
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/MathContext.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/RoundingMode.java
Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigInteger.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/BigDecimalCompareTest.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/BigDecimalConvertTest.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/BigIntegerAddTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.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/BigIntegerConvertTest.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/BigIntegerHashCodeTest.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/BigIntegerNotTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/tests/api/java/math/BigDecimalTest.java
    incubator/harmony/enhanced/classlib/trunk/modules/math/src/test/java/tests/api/java/math/BigIntegerTest.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java?rev=395476&r1=395475&r2=395476&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigDecimal.java Wed Apr 19 21:13:44 2006
@@ -15,7 +15,7 @@
  */
 /**
  * @author Elena Semukhina
- * @version $Revision: 1.11.2.3 $
+ * @version $Revision$
  */
 
 package java.math;
@@ -38,7 +38,8 @@
  * 
  * @see java.math.BigInteger
  */
-public class BigDecimal extends Number implements Comparable, Serializable {
+public class BigDecimal extends Number 
+                        implements Comparable<BigDecimal>, Serializable {
 
     /**
      * @com.intel.drl.spec_ref
@@ -46,12 +47,12 @@
     private static final long serialVersionUID = 6108874887143696463L; 
 
     /**
-     * @com.intel.drl.spec_ref
+     * The unscaled value of this BigDecimal
      */
     private BigInteger intVal;
 
     /**
-     * @com.intel.drl.spec_ref
+     * The scale of this BigDecimal
      */
     private int scale;
 
@@ -111,6 +112,23 @@
     public static final int ROUND_UP = 0;
     
     /**
+     * Controls overflow in the calculated preferred scale.
+     * If it overflows a 32-bit integer, return extreme Integer values.
+     * @param longScale the long preferred scale.
+     * @return int scale.
+     */
+    private int getPreferredScale(long longScale) {
+        if (longScale != (int) longScale) {
+            if (longScale < 0) {
+                return Integer.MIN_VALUE;
+            } else {
+                return Integer.MAX_VALUE;
+            }
+        }
+        return (int) longScale;
+    }
+
+    /**
      * Verifies if a value overflows a 32-bit integer.
      * @param longVal long value to be verified.
      * @param val the name of the value.
@@ -124,6 +142,13 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public static BigDecimal valueOf(double value) {
+        return new BigDecimal(Double.toString(value));
+    }
+
+    /**
      * Translate long value into a BigDecimal with scale of zero.
      * 
      * @return BigDecimal BigDecimal equivalence of a long value.
@@ -162,6 +187,125 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(BigInteger unscaledVal, int scale, MathContext mC) {
+        this(unscaledVal, scale);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(BigInteger value, MathContext mC) {
+        this(value);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(char[] input) {
+        this(input, 0, input.length);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(char[] in, int offset, int len) {
+        int endIndex = offset + len - 1;
+        if (offset < 0 || endIndex >= in.length) {
+            throw new NumberFormatException("the subarray exceeds the bounds" +
+                                            " of the array");
+        }
+        int count = 0; // the pointer to the current char
+        int dotPosition = -1; // the position of the decimal point
+        String unscaled;
+        String exponent;
+        char symbol = in[offset];
+        int startIndex = symbol == '+' ? offset + 1 : offset;
+        
+        // parse the significand
+        for (count = startIndex; count <= endIndex; count++) {
+            symbol = in[count];
+            if (symbol == '.') {
+                dotPosition = count;
+            }
+            if (symbol == 'e' || symbol == 'E') {
+                break;
+            }
+        }
+        if (dotPosition < 0) {
+            unscaled = new String(in, startIndex, count - startIndex);
+            scale = 0;
+        } else {
+            unscaled = new String(in, startIndex, dotPosition - startIndex) +
+                ((dotPosition == endIndex) 
+                 ? "" 
+                 : new String(in, dotPosition + 1, count - dotPosition - 1));
+            scale = count - dotPosition - 1;
+        }
+        intVal = new BigInteger(unscaled);
+        
+        // parse the exponent
+        if (count <= endIndex) {
+            if (++count > endIndex) {    // skip 'E'
+                throw new NumberFormatException("empty exponent");
+            }
+            symbol = in[count];
+            if ((symbol == '+' || symbol == '-') && count == endIndex) {
+                throw new NumberFormatException("empty exponent");
+            }
+            if (symbol == '+') {
+                count++;
+            }
+            exponent = new String(in, count, endIndex - count + 1);
+            int exp = 0;
+            try {
+                exp = Integer.parseInt(exponent);
+            } catch (NumberFormatException e) {
+                throw new NumberFormatException("exponent is not " +
+                                                "signed integer");
+            }
+            
+            // the value of the resulting scale must lie between 
+            // Integer.MIN_VALUE and Integer.MAX_VALUE inclusive
+            long longScale = (long) scale - (long) exp;
+            if (longScale != (int) longScale) {
+                throw new NumberFormatException("resulting scale out of range");
+            }
+            scale = (int) longScale;
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(char[] input, int offset, int len, MathContext mC) {
+        this(input, offset, len);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(char[] input, MathContext mC) {
+        this(input, 0, input.length, mC);
+    }
+
+    /**
      * Constructs a BigDecimal with a double value as an arugment.
      * 
      * @exception NumberFormatException
@@ -202,6 +346,56 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(double value, MathContext mC) {
+        this(value);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(int value) {
+        this(new Integer(value).toString());
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(int value, MathContext mC) {
+        this(value);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(long value) {
+        this(new Long(value).toString());
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(long value, MathContext mC) {
+        this(value);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
      * Constructs a BigDecimal from the string which can only
      * contain digits of 0-9, a decimal point and a negative sign.
      * 
@@ -268,6 +462,18 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal(String value, MathContext mC) {
+        this(value);
+        if (mC.precision != 0) {
+            BigDecimal rounded = this.round(mC);
+            this.intVal = rounded.intVal;
+            this.scale = rounded.scale;
+        }
+    }
+
+    /**
      * Answers the absolute value of this BigDecimal.
      * 
      * @return BigDecimal absolute value of the receiver.
@@ -277,6 +483,13 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal abs(MathContext mC) {
+        return round(mC).abs();
+    }
+
+    /**
      * Answers the sum of the receiver and argument.
      * 
      * @return BigDecimal The sum of adding two BigDecimal.
@@ -297,6 +510,52 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal add(BigDecimal value, MathContext mC) {
+        if (mC.precision == 0) {
+            return add(value);
+        }
+        int newScale = Math.max(this.scale, value.scale);
+        BigDecimal result = null;
+        boolean thisZero = this.intVal.signum() == 0;
+        boolean valueZero = value.intVal.signum() == 0;
+        if (thisZero || valueZero) {
+            if (thisZero && valueZero) {
+                return new BigDecimal(BigInteger.ZERO, newScale);
+            }
+            result = (thisZero) ? value.round(mC) : this.round(mC);
+            if (newScale == result.scale) {
+                return result;
+            }
+            if (newScale > result.scale) { 
+                // try to increase the result.scale 
+                // and stay in precision's limits
+                if (mC.precision - result.precision() >= 
+                    newScale - result.scale) {
+                    
+                    return result.setScale(newScale);
+                } else {
+                    return result.setScale(result.scale + mC.precision - 
+                                           result.precision()); 
+                }
+            } else { 
+                // try to decrease the result.scale by stripping possible zeros
+                return result.stripTrailingZeros(newScale);
+            }
+        } 
+        // both != 0
+        return round(add(value), mC);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public byte byteValueExact() {
+        return (byte)valueExact(3, "127", "-128");
+    }
+
+    /**
      * Compares the receiver BigDecimal and argument BigDecimal e.x 1.00 & 1.0
      * will return 0 in compareTo.
      * 
@@ -316,17 +575,46 @@
     }
 
     /**
-     * Compares an receiver to the argument Object.
-     * 
-     * @return int 0 - equal; 1 - this > object; -1 - this < object
-     * @exception ClassCastException
-     *                if the argument is not of type BigDecimal
+     * @com.intel.drl.spec_ref
      */
-    public int compareTo(Object object) {
-        if (object instanceof BigDecimal) {
-            return (this.compareTo((BigDecimal)object));
+    public BigDecimal divide(BigDecimal value) {
+        if (value.intVal.signum() == 0) {
+            throw new ArithmeticException("division by zero");
         }
-        throw new ClassCastException("BigDecimals are comparable only with other BigDecimals");
+        int newScale = getValidInt((long) this.scale - (long) value.scale, 
+                                   "preferred scale");
+        if (this.intVal.signum() == 0) {
+            return new BigDecimal(BigInteger.ZERO, newScale);
+        }
+        // Try to evaluate the precision of the terminating decimal expansion
+        // of the result.
+        // this / value = this * (1 / value).
+        // The precision of the result is not greater than the sum of 
+        // this.precision and the precision of (1 / value).
+        // It is known that the precision of (1 / 2 ^ n) is n digits. 
+        // We approximate the value.intVal by 2 ^ n 
+        // where n is the bit length of value.intVal.
+        // It is known that the number of bits for a radix digit is 
+        // log(radix) / log(2).
+        // The bit length can be approximated by precision * log(10) / log(2). 
+
+        int resultPrecision = getValidInt((long) this.precision() +
+            (long) Math.ceil(value.precision() * 3.321928094887362),
+            "result precision");
+        MathContext divisionMC = new MathContext(resultPrecision, 
+                                                 RoundingMode.UNNECESSARY);
+        BigDecimal result;
+        // if the exact result cannot be computed, throw the exception
+        try {
+            result = divide(value, divisionMC);
+        } catch (ArithmeticException e) {
+            throw new ArithmeticException("quotient does not have " + 
+                                          "a terminating decimal expansion");
+        }
+        if (newScale > result.scale) {
+            result = result.setScale(newScale);
+        }
+        return result;
     }
 
     /**
@@ -413,6 +701,161 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal divide(BigDecimal value, int scale, RoundingMode rm) {
+        return divide(value, scale, rm.bigDecimalRM);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal divide(BigDecimal value, MathContext mC) {
+        if (mC.precision == 0) {
+            return divide(value);
+        }
+        if (value.intVal.signum() == 0) {
+            throw new ArithmeticException("division by zero");
+        }
+        int newScale = getPreferredScale((long) this.scale - (long) value.scale);
+        if (this.intVal.signum() == 0) {
+            return new BigDecimal(BigInteger.ZERO, newScale);
+        }
+        long sDAdd = newScale > 0 ? newScale + 1L : 1L;
+        int pD = value.precision() - this.precision();
+        long pDAdd = pD > 0 ? pD + 1 : 1;
+        int divScale = getValidInt(mC.precision + 1 + pDAdd + sDAdd,
+                                   "intermediate division scale");
+        BigDecimal result = divide(value, divScale, 
+                                   mC.roundingMode.bigDecimalRM);
+        result = round(result, mC);
+        if (result.multiply(value).compareTo(this) == 0) { 
+             // exact result
+            result = result.stripTrailingZeros(newScale);
+        }
+        return result;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal divide(BigDecimal value, RoundingMode rm) {
+        return divide(value, rm.bigDecimalRM);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal[] divideAndRemainder(BigDecimal value) {
+        BigDecimal resultArray[] = new BigDecimal[2];
+        resultArray[0] = divideToIntegralValue(value);
+        resultArray[1] = subtract(resultArray[0].multiply(value));
+        return resultArray;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal[] divideAndRemainder(BigDecimal value, MathContext mC) {
+        if (mC.precision == 0) {
+            return divideAndRemainder(value);
+        }
+        BigDecimal resultArray[] = new BigDecimal[2];
+        resultArray[0] = divideToIntegralValue(value, mC);
+        resultArray[1] = subtract(resultArray[0].multiply(value));
+        return resultArray;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal divideToIntegralValue(BigDecimal value) {
+        if (value.intVal.signum() == 0) {
+            throw new ArithmeticException("division by zero");
+        }
+        int newScale = getPreferredScale((long) this.scale - (long)value.scale);
+        if (this.intVal.signum() == 0) {
+            return setScale(newScale);
+        }
+        if (value.abs().compareTo(this.abs()) > 0) {
+            // if the divisor > the dividend, return 0
+            return new BigDecimal(BigInteger.ZERO, newScale);
+        }
+        // below the divisor always <= the dividend
+        int dA = this.precision() - this.scale;
+        int dB = value.precision() - value.scale;
+        int divisionPrecision;
+        if (dA > 0 && dB > 0) { // there are integer parts in both numbers
+            // extra digits for rounding
+            divisionPrecision = dA - dB + (dA == dB ? 2 : 1);
+        } else if (dA > 0 && dB <= 0) {
+            // this has an integer part and value is a fraction
+            divisionPrecision = dA + Math.abs(dB) + 1;
+        } else { 
+            // both are fractions
+            divisionPrecision = Math.abs(dA) + Math.abs(dB) + 1;
+        }
+        // control overflow
+        if (divisionPrecision < 0) {
+            divisionPrecision = Integer.MAX_VALUE;
+        }
+        BigDecimal result = divide(value, new MathContext(divisionPrecision,
+                                                          RoundingMode.DOWN));
+        if (result.scale > 0) {
+            // round to an integer part
+            result = result.setScale(0, RoundingMode.DOWN);
+        } 
+        if (result.scale > newScale) {
+            result = result.stripTrailingZeros(newScale);
+        } else if (result.scale < newScale) {
+            result = result.setScale(newScale);
+        }
+        return result;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal divideToIntegralValue(BigDecimal value, MathContext mC) {
+        if (mC.precision == 0) {
+            return divideToIntegralValue(value);
+        }
+        if (value.intVal.signum() == 0) {
+            throw new ArithmeticException("division by zero");
+        }
+        int newScale = getPreferredScale((long) this.scale - (long)value.scale);
+        if (value.abs().compareTo(this.abs()) > 0) {
+            return new BigDecimal(BigInteger.ZERO, newScale);
+        }
+        BigDecimal result = divide(value, new MathContext(mC.precision,
+                                                          RoundingMode.DOWN));
+        if (result.scale > 0) {
+            // round to an integer part
+            result = result.setScale(0, RoundingMode.DOWN);
+        } else if (result.scale < 0) { // got an integer
+            BigDecimal remainder = this.subtract(result.multiply(value));
+            // compare the divisor and the remainder
+            if ((value.abs()).compareTo(remainder.abs()) == -1) {
+                throw new ArithmeticException(
+                    "integer part of the quotient needs more than " + 
+                    mC.precision + " digits");
+            }
+        }
+        // result.scale <= 0;
+        int dP = mC.precision - result.precision();
+        int dS = getValidInt((long) newScale - (long) result.scale,
+                             "temporary scale");
+        if (dS != 0 || dP != 0) {
+            if (dS < 0 || dP < 0) {
+                result = result.stripTrailingZeros(newScale);
+            } else {
+                result = result.setScale(result.scale + Math.min(dS, dP)); 
+            }
+        }
+        return result;
+    }
+
+    /**
      * Converts this BigDecimal to a double. If magnitude of the BigDecimal
      * value is larger than what can be represented by a double, either Infinity
      * or -Infinity is returned.
@@ -437,8 +880,8 @@
      */
     public boolean equals(Object object) {
         return (object instanceof BigDecimal &&
-            this.compareTo(object) == 0 && 
-            this.scale == ((BigDecimal)object).scale);
+                this.compareTo((BigDecimal)object) == 0 && 
+                this.scale == ((BigDecimal)object).scale);
     }
 
     /**
@@ -475,6 +918,13 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public int intValueExact() {
+        return (int) valueExact(10, "2147483647", "-2147483648");
+    }
+
+    /**
      * Converts this BigDecimal to a long.
      * 
      * @return long long representation of the receiver.
@@ -484,6 +934,13 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public long longValueExact() {
+        return valueExact(19, "9223372036854775807", "-9223372036854775808");
+    }
+
+    /**
      * Answers the max value between the receiver and this BigDecimal.
      * 
      * @return BigDecimal max BigDecimal.
@@ -544,6 +1001,17 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal multiply(BigDecimal value, MathContext mC) {
+        if (mC.precision != 0) {
+            return round(this.multiply(value), mC);
+        } else {
+            return this.multiply(value);
+        }
+    }
+
+    /**
      * Negates this BigDecimal value.
      * 
      * @return BigDecimal new BigDecimal with value negated.
@@ -553,6 +1021,136 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal negate(MathContext mC) {
+        return round(mC).negate();
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal plus() {
+        return this;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal plus(MathContext mc) {
+        return round(mc);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal pow(int exp) {
+        if (exp < 0 || exp > 999999999) {
+            throw new ArithmeticException("power is out of range");
+        }
+        if (intVal.signum() == 0 && exp == 0) {
+            return ONE;
+        }
+        // test if it fits an int 
+        int newScale = getValidInt((long) scale * exp, "result scale");
+        return new BigDecimal(this.intVal.pow(exp), newScale);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal pow(int exp, MathContext mC) {
+        if (mC.precision == 0) {
+            return pow(exp);
+        }
+        if (exp < -999999999 || exp > 999999999) {
+            throw new ArithmeticException("exponent out of range");
+        }
+        if (exp == 0) {
+            return ONE;
+        }
+        int expV = Math.abs(exp);
+        int expLen = new Integer(expV).toString().length();
+        if (expLen > mC.precision) {
+            throw new ArithmeticException("exponent is longer than " +
+                                          "MathContext precision");
+        }
+        MathContext multMC = new MathContext(mC.precision + expLen + 1,
+                                             mC.roundingMode);
+        BigDecimal result = ONE;
+        do {
+            result = this.multiply(result, multMC);
+        } while (--expV > 0);
+        if (exp < 0) {
+            result = ONE.divide(result, multMC);
+        }
+        return round(result, mC);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public int precision() {
+        if (intVal.equals(BigInteger.ZERO)) {
+            return 1;
+        }
+        return intVal.toString().length() - (intVal.signum() == -1 ? 1 : 0);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal remainder(BigDecimal value) {
+        return divideAndRemainder(value)[1];
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal remainder(BigDecimal value, MathContext mC) {
+        return divideAndRemainder(value, mC)[1];
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal round(MathContext mC) {
+        if (mC.precision == 0) {
+            return this;
+        }
+        return round(this, mC);
+    }
+
+    /**
+     * Rounds a BigDecimal according to required MathContext
+     * @param value the BigDecimal to be rounded
+     * @param mc the context to use
+     * @return the rounded value
+     */
+    private BigDecimal round(BigDecimal value, MathContext mC) {
+        int delta = mC.precision - value.precision();
+        if (delta >= 0) {
+            return value;
+        }
+        BigDecimal result = 
+            value.divide(new BigDecimal(BigInteger.TEN.pow(-delta), 0),
+                         value.scale, mC.roundingMode.bigDecimalRM);
+        result.scale += delta;
+        if (result.precision() != mC.precision) {
+            result = round(result, mC);
+        }
+        return result;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal scaleByPowerOfTen(int n) {
+        int intScale = getValidInt((long) this.scale - (long) n, "scale");
+        return new BigDecimal(this.intVal, intScale);
+    }
+
+    /**
      * Returns the scale of this BigDecimal.
      * 
      * @return int scale value.
@@ -594,6 +1192,53 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal setScale(int newScale, RoundingMode rm) {
+        return setScale(newScale, rm.bigDecimalRM);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public short shortValueExact() {
+        return (short)valueExact(5, "36767", "-36768");
+    }
+        
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal stripTrailingZeros() {
+        return stripTrailingZeros(Integer.MIN_VALUE);
+    }
+
+    /**
+     * Remove trailing zeros to make the scale closer to the required scale
+     * @param newScale the required scale
+     * @return this BigDecimal with reduced scale
+     */
+    private BigDecimal stripTrailingZeros(int newScale) {
+        if (intVal.testBit(0)) {
+            return this;
+        }
+        BigDecimal result = this;
+        StringBuffer strVal = new StringBuffer(intVal.toString());
+        int checkedChar = strVal.length();
+        while (--checkedChar > 0) {
+            if (strVal.charAt(checkedChar) != '0') {
+                break;
+            }
+            strVal.deleteCharAt(checkedChar);
+            result.scale--;
+            if (result.scale == newScale) {
+                break;
+            }
+        }
+        result.intVal = new BigInteger(strVal.toString());
+        return result;
+    }
+
+    /**
      * Answers the signum function of this instance.
      * 
      * @return int -1, 0, or 1 if the receiver is negative, zero, or positive.
@@ -623,6 +1268,16 @@
     }
 
     /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal subtract(BigDecimal value, MathContext mC) {
+        if (mC.precision == 0) {
+            return subtract(value);
+        }
+        return add(value.negate(), mC);
+    }
+
+    /**
      * Converts this to a BigInteger.
      * 
      * @return BigInteger BigDecimal equivalent of BigInteger.
@@ -640,6 +1295,87 @@
     /**
      * @com.intel.drl.spec_ref
      */
+    public BigInteger toBigIntegerExact() {
+        if (intVal.signum() == 0) {
+            return intVal;
+        }
+        String strVal = this.intVal.toString();
+        if (scale > 0) {
+            // check the fractional part
+            int checkedChar = strVal.length();
+            for (int i = 1; i <= scale; i++) {
+                if (strVal.charAt(--checkedChar) != '0') {
+                    throw new ArithmeticException("nonzero fractional part");
+                }
+            }
+        }
+        return toBigInteger();
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public String toEngineeringString() {
+        String intString = intVal.toString();
+        if (scale == 0) {
+            return intString;
+        }
+        boolean negNumber = intVal.signum() < 0;
+        int startPoint = negNumber ? 2 : 1;
+        int endPoint = intString.length();
+        int exponent = -scale + intString.length() - (negNumber ? 2 : 1);
+        StringBuffer result = new StringBuffer(intString);
+        if (scale > 0 && exponent >= -6) {
+            if (exponent >= 0) {
+                result.insert(exponent + (negNumber ? 2 : 1), '.');
+            } else {
+                char zeros[] = new char[-exponent + 1];
+                zeros[0] = '0';
+                zeros[1] = '.';
+                for (int i = 2; i < zeros.length; i++) {
+                    zeros[i] = '0';
+                }
+                result.insert(negNumber ? 1 : 0, zeros);
+            }
+        } else {
+            int delta = endPoint - startPoint;
+            int rem = exponent % 3;
+            if (rem != 0) { 
+                // adjust exponent so it is a multiple of three
+                if (intVal.signum() == 0) { 
+                    // zero value
+                    rem = rem < 0 ? -rem : 3 - rem;
+                    exponent += rem;
+                } else { 
+                    // nonzero value
+                    rem = rem < 0 ? rem + 3 : rem;
+                    exponent -= rem;
+                    startPoint += rem;
+                }
+                if (delta < 3) {
+                    for (int i = rem - delta; i > 0; i--) {
+                        result.insert(endPoint++, '0');
+                    }
+                }
+            } 
+            if (endPoint - startPoint >= 1) {
+                result.insert(startPoint, '.');
+                endPoint++;
+            }
+            if (exponent != 0) {
+                result.insert(endPoint, 'E');
+                if (exponent > 0) {
+                    result.insert(++endPoint, '+');
+                }
+                result.insert(++endPoint, Integer.toString(exponent));
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
     public String toPlainString() {
         String intString = intVal.toString();
         if (scale == 0) {
@@ -714,6 +1450,61 @@
             result.insert(++endPoint, Integer.toString(exponent));
         }
         return result.toString();
+    }
+
+    /**
+     * Calculates an exact value of a primitive type.
+     * @param charsPerMaxValue the number of characters in a type's 
+     * extreme value, e.g. 9 for an int.
+     * @param maxValue the type's maximal value
+     * @param minValue the type's minimal value
+     * @return the long value of this BigDecimal
+     */
+    private long valueExact(int charsPerMaxValue, String maxValue, 
+                            String minValue) {
+        int valueSign = intVal.signum();
+        if (valueSign == 0) {
+            return 0;
+        }
+        StringBuffer strVal = new StringBuffer(intVal.toString());
+        int startChar = valueSign == 1 ? 0 : 1;
+        if (scale > 0) {
+            // check the fractional part
+            int checkedChar = strVal.length() - 1;
+            for (int i = 1; i <= scale; i++) {
+                if (strVal.charAt(checkedChar) != '0') {
+                    throw new ArithmeticException("nonzero fractional part");
+                }
+                strVal.deleteCharAt(checkedChar);
+                checkedChar--;
+            }
+        } else {
+            for (int i = 1; i <= -scale; i++) {
+                strVal.append('0');
+            }
+        }
+        int delta = ((valueSign == 1) 
+                     ? charsPerMaxValue 
+                     : charsPerMaxValue + 1) - strVal.length();
+        if (delta < 0) {
+            throw new ArithmeticException("number does not fit in an int");
+        }
+        for (int i = 0; i < delta; i++) {
+            strVal.insert(startChar, '0');
+        }
+        String stringValue = strVal.toString();
+        if (valueSign == 1 && stringValue.compareTo(maxValue) > 0 ||
+            valueSign == -1 && stringValue.compareTo(minValue) > 0 ) { 
+            throw new ArithmeticException("number does not fit in an int");
+        }
+        return new Long(stringValue).longValue();
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public BigDecimal ulp() {
+        return new BigDecimal(BigInteger.ONE, scale);
     }
 
     /**

Modified: incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigInteger.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigInteger.java?rev=395476&r1=395475&r2=395476&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigInteger.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/BigInteger.java Wed Apr 19 21:13:44 2006
@@ -15,7 +15,7 @@
  */
 /**
  * @author Elena Semukhina
- * @version $Revision: 1.30.2.4 $
+ * @version $Revision$
  */
 
 package java.math;
@@ -31,12 +31,24 @@
  * contain values that cannot be changed. Thus, most operations on the
  * BigInteger objects yield new instances of BigInteger.
  */
-public class BigInteger extends Number implements Comparable, Serializable {
+public class BigInteger extends Number implements Comparable<BigInteger>, Serializable {
     private static final int EQUALS = 0;
     private static final int GREATER = 1;
     private static final int LESS = -1;
     private static final BigInteger NEG_ONE = new BigInteger (-1, 1);
 
+    // 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.
+    private static final int bigRadices[] = {
+            -2147483648, 1162261467, 1073741824, 1220703125, -2118184960,
+            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
+    };
+
     // the first 54 prime numbers were copied from the published sources,
     // e.g. http://en.wikipedia.org/wiki/List_of_prime_numbers#The_first_500_prime_numbers
     private static final int primes[] = {
@@ -808,23 +820,20 @@
             bigRadixDigitsLength++;
         }
         digits = new int[bigRadixDigitsLength];
-        
-        // calculate "big radix": exp(radix, charsPerInt)
+        // get the maximal power of radix that fits in int
+        int bigRadix = bigRadices[radix - 2];
 
-        int bigRadix = radix;
-        for (int n = 1; n < charsPerInt; n++) {
-            bigRadix *= radix;
-        }
-        
         // 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 substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars);
         int newDigit;
         for (int substrStart = startChar; substrStart < endChar; 
-                substrStart = substrEnd, substrEnd = substrStart + charsPerInt) {
-            int bigRadixDigit = Integer.parseInt(stringValue.substring(
-                    substrStart, substrEnd), radix);
+                substrStart = substrEnd, 
+                substrEnd = substrStart + charsPerInt) {
+            int bigRadixDigit = 
+                Integer.parseInt(stringValue.substring(substrStart, substrEnd),
+                                 radix);
             newDigit = multiplyByInt(digits, digitIndex, bigRadix);
             newDigit += addIntToArray(digits, digitIndex, bigRadixDigit);
             digits[digitIndex++] = newDigit;
@@ -1179,27 +1188,6 @@
     }
 
     /**
-     * Answers an integer indicating the relative positions of the receiver and
-     * the argument in the natural order of elements of the receiver's class.
-     * 
-     * @return int which should be <0 if the receiver should sort before the
-     *         argument, 0 if the receiver should sort in the same position as
-     *         the argument, and >0 if the receiver should sort after the
-     *         argument.
-     * @param obj
-     *            Object an object to compare the receiver to
-     * @exception ClassCastException
-     *                if the argument can not be converted into something
-     *                comparable with the receiver.
-     */
-    public int compareTo(Object obj) {
-        if (obj instanceof BigInteger) {
-            return (this.compareTo((BigInteger)obj));
-        }
-        throw new ClassCastException();
-    }
-
-    /**
      * Constructs randomly a big integer of the specified bit length.
      * @param numberBitLength the length in bits
      * @param rand source of random bits
@@ -2333,42 +2321,36 @@
         }
         double bitsForRadixDigit;
         if (radix == 10) {
-            bitsForRadixDigit = 3.321928094887362; // precomputed
+            bitsForRadixDigit = 3.3219280948873626;
         } else {
             bitsForRadixDigit = Math.log(radix) / Math.log(2);
         }
-        int resLengthInChars = (int)(abs().bitLength() / 
-                bitsForRadixDigit + (sign == -1 ? 1 : 0));
-        StringBuffer result = new StringBuffer(resLengthInChars);
-        int resDigit = -1;
-        if (radix == 16) {
-            for (int i = 0; i < numberLength; i++) {
-                for (int j = 0; j < 8; j++) {
-                    resDigit = digits[i] >> (4 * j) & 0xf;
-                    result.insert(0, Character.forDigit(resDigit, 16));
-                }
-            }
-        } else {
+        int resLengthInChars = (int)(abs().bitLength() / bitsForRadixDigit
+                               + ((sign == -1) ? 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 = getCharsPerInt(radix);
-            int bigRadix = 1;
             int i;
-            // compute the maximal power of radix that fits in int
-            for (i = 1; i < charsPerInt; i++) {
-                bigRadix *= radix;
-            }
+            // 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 String representation concatenating them in a StringBuffer
+                // to characters collecting them in the char array
                 resDigit = divideArrayByInt(temp, temp, tempLen, bigRadix);
-                String res = Integer.toString(resDigit, radix);
-                result.insert(0, res);
-                int delta = charsPerInt - res.length() - 1;
-                for (i = 0; i < delta; i++) {
-                    result.insert(0, '0');
-                }                
+                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--) {
                     ;
                 }
@@ -2377,14 +2359,22 @@
                     break;
                 }
             }
+        } else {
+            // radix == 16
+            for (int i = 0; i < numberLength; i++) {
+                for (int j = 0; j < 8 && currentChar > 0; j++) {
+                    resDigit = digits[i] >> (4 * j) & 0xf;
+                    result[--currentChar] = Character.forDigit(resDigit, 16);
+                }
+            }
         }
-        while (result.charAt(0) == '0') {
-            result.deleteCharAt(0);
+        while (result[currentChar] == '0') {
+            currentChar++;
         }
         if (sign == -1) {
-            result.insert(0, '-');
+            result[--currentChar] = '-';
         }
-        return result.toString();
+        return new String(result, currentChar, resLengthInChars - currentChar);
     }
 
     /**

Added: incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/MathContext.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/MathContext.java?rev=395476&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/MathContext.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/MathContext.java Wed Apr 19 21:13:44 2006
@@ -0,0 +1,179 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ * @version $Revision$
+ */
+
+package java.math;
+
+import java.io.IOException;
+import java.io.StreamCorruptedException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * @com.intel.drl.spec_ref
+ */
+public class MathContext implements Serializable {
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    private static final MathContext DECIMAL128 = 
+        new MathContext(34, RoundingMode.HALF_EVEN);
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    private static final MathContext DECIMAL32 = 
+        new MathContext(7, RoundingMode.HALF_EVEN);
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    private static final MathContext DECIMAL64 = 
+        new MathContext(16, RoundingMode.HALF_EVEN);
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    private static final MathContext UNLIMITED = 
+        new MathContext(0, RoundingMode.HALF_UP);
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    private static final long serialVersionUID = 5579720004786848255L; 
+
+    final int precision;
+    final RoundingMode roundingMode;
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public MathContext(int requiredPrecision) {
+        this(requiredPrecision, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public MathContext(int requiredPrecision, RoundingMode rm) {
+        if (rm == null) {
+            throw new NullPointerException("null roundingMode");
+        }
+        if (requiredPrecision < 0) {
+            throw new IllegalArgumentException("negative precision");
+        }
+        this.precision = requiredPrecision;
+        this.roundingMode = rm;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public MathContext(String value) {
+        if (!value.startsWith("precision=")) {
+            throw new IllegalArgumentException("the argument should start " +
+                                               "with \"precision=\"");
+        }
+        int spacePosition = value.indexOf(' ');
+        if (spacePosition == -1) {
+            throw new IllegalArgumentException("the argument's words should " +
+                                               "be separated by the space");
+        }
+        if (value.lastIndexOf(" ") != spacePosition) {
+            throw new IllegalArgumentException("there should be only one " +
+                                               "space symbol in the argument");
+        }
+        try {
+            precision = Integer.parseInt(value.substring(10, spacePosition));
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("bad precision value");
+        }
+        int shift = spacePosition + 1;
+        int valLen = value.length();
+        if (valLen - shift < 14) {
+            throw new IllegalArgumentException("bad roundingMode value");
+        }
+        if (!value.substring(shift, shift + 13).equals("roundingMode=")) {
+            throw new IllegalArgumentException
+                ("the second word in the argument should " +
+                 "be \"roundingMode=<rounding mode>\"");
+        }
+        shift += 13;
+        try {
+            roundingMode = RoundingMode.valueOf(value.substring(shift, valLen));
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException("bad roundingMode value");
+        }
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public boolean equals(Object obj) {
+        return (obj instanceof MathContext &&
+            this.precision == ((MathContext)obj).precision && 
+            this.roundingMode.equals(((MathContext)obj).roundingMode));
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public int getPrecision() {
+        return precision;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public RoundingMode getRoundingMode() {
+        return roundingMode;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public int hashCode() {
+        return precision * roundingMode.ordinal() + roundingMode.hashCode();
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    public String toString() {
+        return "precision=" + precision + " roundingMode=" + 
+               roundingMode.toString();
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    private void readObject(ObjectInputStream s)
+        throws IOException,
+        ClassNotFoundException {
+        s.defaultReadObject();
+        if (precision < 0) {
+            throw new StreamCorruptedException("bad precision value");
+        }
+        if (roundingMode == null) {
+            throw new StreamCorruptedException("null roundingMode");
+        }
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/RoundingMode.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/RoundingMode.java?rev=395476&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/RoundingMode.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/math/src/main/java/java/math/RoundingMode.java Wed Apr 19 21:13:44 2006
@@ -0,0 +1,99 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ * @version $Revision$
+ */
+
+package java.math;
+
+/**
+ * @com.intel.drl.spec_ref
+ */
+public enum RoundingMode {
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    UP(BigDecimal.ROUND_UP),
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    DOWN(BigDecimal.ROUND_DOWN),
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    CEILING(BigDecimal.ROUND_CEILING),
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    FLOOR(BigDecimal.ROUND_FLOOR),
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    HALF_UP(BigDecimal.ROUND_HALF_UP),
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
+    
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
+
+    protected final int bigDecimalRM;
+
+    RoundingMode(int rm) {
+        bigDecimalRM = rm;
+    }
+
+    /**
+     * @com.intel.drl.spec_ref
+     */
+    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:
+                throw new IllegalArgumentException("rounding mode out of range");
+        }
+    }
+}