Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 1269 invoked from network); 20 Mar 2006 16:33:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 20 Mar 2006 16:33:08 -0000 Received: (qmail 84464 invoked by uid 500); 20 Mar 2006 16:33:07 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 84318 invoked by uid 500); 20 Mar 2006 16:33:06 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 84297 invoked by uid 99); 20 Mar 2006 16:33:06 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 20 Mar 2006 08:33:06 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Mon, 20 Mar 2006 08:32:56 -0800 Received: (qmail 977 invoked by uid 65534); 20 Mar 2006 16:32:35 -0000 Message-ID: <20060320163235.976.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r387239 [7/21] - in /incubator/harmony/enhanced/classlib/trunk/modules/regex-beans-math: ./ Harmony/ doc/ doc/images/ make/ src/ src/common/ src/common/javasrc/ src/common/javasrc/java/ src/common/javasrc/java/applet/ src/common/javasrc/jav... Date: Mon, 20 Mar 2006 16:31:33 -0000 To: harmony-commits@incubator.apache.org From: geirm@apache.org X-Mailer: svnmailer-1.0.7 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: incubator/harmony/enhanced/classlib/trunk/modules/regex-beans-math/src/common/javasrc/java/math/BigDecimal.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/regex-beans-math/src/common/javasrc/java/math/BigDecimal.java?rev=387239&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/regex-beans-math/src/common/javasrc/java/math/BigDecimal.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/regex-beans-math/src/common/javasrc/java/math/BigDecimal.java Mon Mar 20 08:31:09 2006 @@ -0,0 +1,629 @@ +/* + * Copyright 2005 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: 1.11.2.3 $ + */ + +package java.math; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.StreamCorruptedException; +import java.io.Serializable; + +/** + * @com.intel.drl.spec_ref + */ +public class BigDecimal extends Number implements Comparable, Serializable { + + /** + * @com.intel.drl.spec_ref + */ + private static final long serialVersionUID = 6108874887143696463L; + + /** + * @com.intel.drl.spec_ref + */ + private BigInteger intVal; + + /** + * @com.intel.drl.spec_ref + */ + private int scale; + + /** + * @com.intel.drl.spec_ref + */ + public static final BigDecimal ONE = new BigDecimal(BigInteger.ONE, 0); + + /** + * @com.intel.drl.spec_ref + */ + public static final BigDecimal TEN = new BigDecimal(BigInteger.TEN, 0); + + /** + * @com.intel.drl.spec_ref + */ + public static final BigDecimal ZERO = new BigDecimal(BigInteger.ZERO, 0); + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_CEILING = 2; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_DOWN = 1; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_FLOOR = 3; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_HALF_DOWN = 5; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_HALF_EVEN = 6; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_HALF_UP = 4; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_UNNECESSARY = 7; + + /** + * @com.intel.drl.spec_ref + */ + public static final int ROUND_UP = 0; + + /** + * Verifies if a value overflows a 32-bit integer. + * @param longVal long value to be verified. + * @param val the name of the value. + * @return int longVal. + */ + private static int getValidInt(long longVal, String val) { + if (longVal != (int)longVal) { + throw new ArithmeticException(val + " outside the range of a 32-bit integer"); + } + return (int)longVal; + } + + /** + * @com.intel.drl.spec_ref + */ + public static BigDecimal valueOf(long value) { + return valueOf(value, 0); + } + + /** + * @com.intel.drl.spec_ref + */ + public static BigDecimal valueOf(long unscaledValue, int scale) { + return new BigDecimal(BigInteger.valueOf(unscaledValue), scale); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal(BigInteger value) { + intVal = value; + scale = 0; + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal(BigInteger unScaledValue, int scale) { + intVal = unScaledValue; + this.scale = scale; + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal(double value) { + if (value != value) { + throw new NumberFormatException ("argument is NaN"); + } + if (Double.isInfinite(value)) { + throw new NumberFormatException ("argument is infinite"); + } + long longValue = Double.doubleToLongBits(value); + long significand = longValue & 0x000fffffffffffffL; // mantissa + scale = ((int)(longValue >> 52)) & 0x7ff; // exponent + if (scale == 0) { + scale = 1; // to be calculated correctly in the next operation + } else { + significand |= 0x0010000000000000L; + } + scale -= 1075; + // if the scale is negative, strip tailing zeros + // to ensure that the scale is the smallest + while ((significand & 1) == 0 && scale < 0) { + significand >>= 1; + scale++; + } + intVal = BigInteger.valueOf((longValue & 0x8000000000000000L) == 0 ? + significand : -significand); + if (scale > 0) { + intVal = intVal.shiftLeft(scale); + scale = 0; + } else { + // m * 2 ^ e = m * (10 / 5) ^ e = (m * 5 ^ (-e)) * 10 ^ e + intVal = intVal.multiply(BigInteger.valueOf(5L).pow(-scale)); + scale = -scale; + } + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal(String value) { + int count; // the significand's length + int dotPlace = -1; + int strLen = value.length(); + String unscaled; + String exponent; + char symbol = value.charAt(0); + int startPoint = symbol == '+' ? 1 : 0; + + // parse the significand + for (count = 0; count < strLen; count++) { + symbol = value.charAt(count); + if (symbol == '.') { + dotPlace = count; + } + if (symbol == 'e' || symbol == 'E') { + break; + } + } + if (dotPlace == -1) { + unscaled = value.substring(startPoint, count); + scale = 0; + } else { + unscaled = value.substring(startPoint, dotPlace) + + value.substring(dotPlace + 1, count); + scale = count - dotPlace - 1; + } + intVal = new BigInteger(unscaled); + + // parse the exponent + if (count < strLen) { + if (++count == strLen) { // skip 'E' + throw new NumberFormatException("empty exponent"); + } + symbol = value.charAt(count); + if ((symbol == '+' || symbol == '-') && count == strLen - 1) { + throw new NumberFormatException("empty exponent"); + } + if (symbol == '+') { + count++; + } + exponent = value.substring(count, strLen); + 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 abs() { + return new BigDecimal(intVal.abs(), this.scale); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal add(BigDecimal value) { + if (scale == value.scale) { + return new BigDecimal(intVal.add(value.intVal), scale); + } + boolean thisScaleIsLess = this.scale < value.scale; + int newScale = thisScaleIsLess ? value.scale : this.scale; + if (thisScaleIsLess) { + return new BigDecimal(this.intVal.multiply + (BigInteger.TEN.pow(value.scale - this.scale)).add(value.intVal), newScale); + } else { + return new BigDecimal(value.intVal.multiply + (BigInteger.TEN.pow(this.scale - value.scale)).add(this.intVal), newScale); + } + } + + /** + * @com.intel.drl.spec_ref + */ + public int compareTo(BigDecimal value) { + if (this.scale == value.scale) { + return this.intVal.compareTo(value.intVal); + } + if (this.scale < value.scale) { + return this.intVal.multiply(BigInteger.TEN.pow(value.scale - this.scale)). + compareTo(value.intVal); + } else { + return this.intVal.compareTo(value.intVal.multiply + (BigInteger.TEN.pow(this.scale - value.scale))); + } + } + + /** + * @com.intel.drl.spec_ref + */ + public int compareTo(Object object) { + if (object instanceof BigDecimal) { + return (this.compareTo((BigDecimal)object)); + } + throw new ClassCastException("BigDecimals are comparable only with other BigDecimals"); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal divide(BigDecimal value, int roundingMode) { + return divide(value, this.scale, roundingMode); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal divide(BigDecimal value, int quotientScale, int roundingMode) { + if (roundingMode > 7 || roundingMode < 0) { + throw new IllegalArgumentException("invalid rounding mode"); + } + if (value.intVal.signum() == 0) { + throw new ArithmeticException("division by zero"); + } + int exponent = quotientScale - this.scale + value.scale; + // If exponent > 0, the dividend should be multiplied by 10**exponent. + // If exponent < 0, the divisor should be multiplied by 10**(-exponent). + BigInteger dividend = this.intVal; + BigInteger divisor = value.intVal; + if (exponent < 0) { + divisor = divisor.multiply(BigInteger.TEN.pow(-exponent)); + } else if (exponent > 0) { + dividend = dividend.multiply(BigInteger.TEN.pow(exponent)); + } + BigInteger res[] = dividend.divideAndRemainder(divisor); + BigInteger quotient = res[0]; + if (res[1].signum() != 0) { + if (roundingMode == ROUND_UNNECESSARY) { + throw new ArithmeticException + ("rounding mode is ROUND_UNNECESSARY but the result is not exact"); + } + boolean negativeQuotient = intVal.signum() != divisor.signum(); + boolean negativeRemainder = res[1].signum() == -1; + boolean negativeDivisor = divisor.signum() == -1; + if (roundingMode == ROUND_FLOOR) { + roundingMode = negativeQuotient ? ROUND_UP : ROUND_DOWN; + } else if (roundingMode == ROUND_CEILING) { + roundingMode = negativeQuotient ? ROUND_DOWN : ROUND_UP; + } else { + if (negativeDivisor) { + divisor = divisor.abs(); + } + if (negativeRemainder) { + res[1] = res[1].abs(); + } + // distance == -1 if the quotient is NOT the nearest neighbor to the exact result; + // distance == 0 if the exact result is equidistant from the neighbors; + // distance == +1 if the quotient is the nearest neighbor to the exact result. + int distance = divisor.subtract(res[1]).compareTo(res[1]); + if (roundingMode == ROUND_HALF_DOWN) { + roundingMode = distance >= 0 ? ROUND_DOWN : ROUND_UP; + } else if (roundingMode == ROUND_HALF_UP) { + roundingMode = distance > 0 ? ROUND_DOWN : ROUND_UP; + } else if (roundingMode == ROUND_HALF_EVEN) { + if (distance > 0) { + roundingMode = ROUND_DOWN; + } else if (distance < 0) { + roundingMode = ROUND_UP; + } else if (!quotient.testBit(0)) { + roundingMode = ROUND_DOWN; + } else { + roundingMode = ROUND_UP; + } + } + } + if (roundingMode == ROUND_UP) { + quotient = quotient.add(BigInteger.valueOf(negativeQuotient ? -1 : 1)); + } + } + return new BigDecimal(quotient, quotientScale); + } + + /** + * @com.intel.drl.spec_ref + */ + public double doubleValue() { + return Double.valueOf(toString()).doubleValue(); + } + + /** + * @com.intel.drl.spec_ref + */ + public boolean equals(Object object) { + return (object instanceof BigDecimal && + this.compareTo(object) == 0 && + this.scale == ((BigDecimal)object).scale); + } + + /** + * @com.intel.drl.spec_ref + */ + public float floatValue() { + return Float.valueOf(toString()).floatValue(); + } + + /** + * @com.intel.drl.spec_ref + */ + public int hashCode() { + return intVal.intValue() + scale; + } + + /** + * @com.intel.drl.spec_ref + */ + public int intValue() { + return toBigInteger().intValue(); + } + + /** + * @com.intel.drl.spec_ref + */ + public long longValue() { + return toBigInteger().longValue(); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal max(BigDecimal value) { + return (this.compareTo(value) >= 0 ? this : value); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal min(BigDecimal value) { + return (this.compareTo(value) <= 0 ? this : value); + } + + /** + * Moves the decimal point shift digits + * @param shift shift distance + */ + private BigDecimal movePoint(int shift) { + int newScale = getValidInt((long)scale + (long)shift, "scale"); + if (newScale > 0) { + return new BigDecimal(intVal, newScale); + } + return new BigDecimal(this.intVal.multiply(BigInteger.TEN.pow(-newScale)), 0); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal movePointLeft(int shift) { + return movePoint(shift); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal movePointRight(int shift) { + return movePoint(-shift); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal multiply(BigDecimal value) { + return new BigDecimal(this.intVal.multiply(value.intVal), + this.scale + value.scale); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal negate() { + return new BigDecimal(intVal.negate(), scale); + } + + /** + * @com.intel.drl.spec_ref + */ + public int scale() { + return scale; + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal setScale(int newScale) { + return setScale(newScale, ROUND_UNNECESSARY); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal setScale(int newScale, int roundingMode) { + int delta = this.scale - newScale; + if (delta == 0) { + return this; + } + if (delta > 0) { + return divide(new BigDecimal(BigInteger.TEN.pow(delta), delta), newScale, roundingMode); + } else { + return new BigDecimal(intVal.multiply(BigInteger.TEN.pow(-delta)), newScale); + } + } + + /** + * @com.intel.drl.spec_ref + */ + public int signum() { + return intVal.signum(); + } + + /** + * @com.intel.drl.spec_ref + */ + public BigDecimal subtract(BigDecimal value) { + if (scale == value.scale) { + return new BigDecimal(intVal.subtract(value.intVal), scale); + } + boolean thisScaleIsLess = this.scale < value.scale; + int newScale = thisScaleIsLess ? value.scale : this.scale; + if (thisScaleIsLess) { + return new BigDecimal(this.intVal.multiply(BigInteger.TEN.pow(value.scale - this.scale)). + subtract(value.intVal), newScale); + } else { + return new BigDecimal(this.intVal. + subtract(value.intVal.multiply(BigInteger.TEN.pow(this.scale - value.scale))), newScale); + } + } + + /** + * @com.intel.drl.spec_ref + */ + public BigInteger toBigInteger() { + if (scale == 0) { + return intVal; + } + if (scale > 0) { + return intVal.divide(BigInteger.TEN.pow(scale)); + } + return intVal.multiply(BigInteger.TEN.pow(-scale)); + } + + /** + * @com.intel.drl.spec_ref + */ + public String toPlainString() { + String intString = intVal.toString(); + if (scale == 0) { + return intString; + } + boolean negNumber = intVal.signum() < 0; + int startPoint = negNumber ? 2 : 1; + int endPoint = intString.length(); + int dotPosition = -scale + intString.length() - (negNumber ? 2 : 1); + StringBuffer result = new StringBuffer(intString); + char zeros[]; + if (scale > 0) { + if (dotPosition >= 0) { + result.insert(dotPosition + (negNumber ? 2 : 1), '.'); + } else { + zeros = new char[-dotPosition + 1]; + zeros[0] = '0'; + zeros[1] = '.'; + for (int i = 2; i < zeros.length; i++) { + zeros[i] = '0'; + } + result.insert(negNumber ? 1 : 0, zeros); + } + } else { + zeros = new char[-scale]; + for (int i = 0; i < zeros.length; i++) { + zeros[i] = '0'; + } + result.insert(endPoint, zeros); + } + return result.toString(); + } + + /** + * @com.intel.drl.spec_ref + */ + public String toString() { + 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(); + result.append(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 { + if (endPoint - startPoint >= 1) { + result.insert(startPoint, '.'); + endPoint++; + } + 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 BigInteger unscaledValue() { + return intVal; + } + + /** + * @com.intel.drl.spec_ref + */ + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + if (intVal == null) { + throw new StreamCorruptedException("null unscaled value"); + } + } +} \ No newline at end of file