/* Generated from 'BigDecimal.nrx' 8 Sep 2000 11:10:50 [v2.00] */ | |
/* Options: Binary Comments Crossref Format Java Logo Strictargs Strictcase Trace2 Verbose3 */ | |
package com.ibm.icu.math; | |
import java.math.BigInteger; | |
/* ------------------------------------------------------------------ */ | |
/* BigDecimal -- Decimal arithmetic for Java */ | |
/* ------------------------------------------------------------------ */ | |
/* Copyright IBM Corporation, 1996-2011. All Rights Reserved. */ | |
/* */ | |
/* The BigDecimal class provides immutable arbitrary-precision */ | |
/* floating point (including integer) decimal numbers. */ | |
/* */ | |
/* As the numbers are decimal, there is an exact correspondence */ | |
/* between an instance of a BigDecimal object and its String */ | |
/* representation; the BigDecimal class provides direct conversions */ | |
/* to and from String and character array objects, and well as */ | |
/* conversions to and from the Java primitive types (which may not */ | |
/* be exact). */ | |
/* ------------------------------------------------------------------ */ | |
/* Notes: */ | |
/* */ | |
/* 1. A BigDecimal object is never changed in value once constructed; */ | |
/* this avoids the need for locking. Note in particular that the */ | |
/* mantissa array may be shared between many BigDecimal objects, */ | |
/* so that once exposed it must not be altered. */ | |
/* */ | |
/* 2. This class looks at MathContext class fields directly (for */ | |
/* performance). It must not and does not change them. */ | |
/* */ | |
/* 3. Exponent checking is delayed until finish(), as we know */ | |
/* intermediate calculations cannot cause 31-bit overflow. */ | |
/* [This assertion depends on MAX_DIGITS in MathContext.] */ | |
/* */ | |
/* 4. Comments for the public API now follow the javadoc conventions. */ | |
/* The NetRexx -comments option is used to pass these comments */ | |
/* through to the generated Java code (with -format, if desired). */ | |
/* */ | |
/* 5. System.arraycopy is faster than explicit loop as follows */ | |
/* Mean length 4: equal */ | |
/* Mean length 8: x2 */ | |
/* Mean length 16: x3 */ | |
/* Mean length 24: x4 */ | |
/* From prior experience, we expect mean length a little below 8, */ | |
/* but arraycopy is still the one to use, in general, until later */ | |
/* measurements suggest otherwise. */ | |
/* */ | |
/* 6. 'DMSRCN' referred to below is the original (1981) IBM S/370 */ | |
/* assembler code implementation of the algorithms below; it is */ | |
/* now called IXXRCN and is available with the OS/390 and VM/ESA */ | |
/* operating systems. */ | |
/* ------------------------------------------------------------------ */ | |
/* Change History: */ | |
/* 1997.09.02 Initial version (derived from netrexx.lang classes) */ | |
/* 1997.09.12 Add lostDigits checking */ | |
/* 1997.10.06 Change mantissa to a byte array */ | |
/* 1997.11.22 Rework power [did not prepare arguments, etc.] */ | |
/* 1997.12.13 multiply did not prepare arguments */ | |
/* 1997.12.14 add did not prepare and align arguments correctly */ | |
/* 1998.05.02 0.07 packaging changes suggested by Sun and Oracle */ | |
/* 1998.05.21 adjust remainder operator finalization */ | |
/* 1998.06.04 rework to pass MathContext to finish() and round() */ | |
/* 1998.06.06 change format to use round(); support rounding modes */ | |
/* 1998.06.25 rename to BigDecimal and begin merge */ | |
/* zero can now have trailing zeros (i.e., exp\=0) */ | |
/* 1998.06.28 new methods: movePointXxxx, scale, toBigInteger */ | |
/* unscaledValue, valueof */ | |
/* 1998.07.01 improve byteaddsub to allow array reuse, etc. */ | |
/* 1998.07.01 make null testing explicit to avoid JIT bug [Win32] */ | |
/* 1998.07.07 scaled division [divide(BigDecimal, int, int)] */ | |
/* 1998.07.08 setScale, faster equals */ | |
/* 1998.07.11 allow 1E6 (no sign) <sigh>; new double/float conversion */ | |
/* 1998.10.12 change package to com.ibm.icu.math */ | |
/* 1998.12.14 power operator no longer rounds RHS [to match ANSI] */ | |
/* add toBigDecimal() and BigDecimal(java.math.BigDecimal) */ | |
/* 1998.12.29 improve byteaddsub by using table lookup */ | |
/* 1999.02.04 lostdigits=0 behaviour rounds instead of digits+1 guard */ | |
/* 1999.02.05 cleaner code for BigDecimal(char[]) */ | |
/* 1999.02.06 add javadoc comments */ | |
/* 1999.02.11 format() changed from 7 to 2 method form */ | |
/* 1999.03.05 null pointer checking is no longer explicit */ | |
/* 1999.03.05 simplify; changes from discussion with J. Bloch: */ | |
/* null no longer permitted for MathContext; drop boolean, */ | |
/* byte, char, float, short constructor, deprecate double */ | |
/* constructor, no blanks in string constructor, add */ | |
/* offset and length version of char[] constructor; */ | |
/* add valueOf(double); drop booleanValue, charValue; */ | |
/* add ...Exact versions of remaining convertors */ | |
/* 1999.03.13 add toBigIntegerExact */ | |
/* 1999.03.13 1.00 release to IBM Centre for Java Technology */ | |
/* 1999.05.27 1.01 correct 0-0.2 bug under scaled arithmetic */ | |
/* 1999.06.29 1.02 constructors should not allow exponent > 9 digits */ | |
/* 1999.07.03 1.03 lost digits should not be checked if digits=0 */ | |
/* 1999.07.06 lost digits Exception message changed */ | |
/* 1999.07.10 1.04 more work on 0-0.2 (scaled arithmetic) */ | |
/* 1999.07.17 improve messages from pow method */ | |
/* 1999.08.08 performance tweaks */ | |
/* 1999.08.15 fastpath in multiply */ | |
/* 1999.11.05 1.05 fix problem in intValueExact [e.g., 5555555555] */ | |
/* 1999.12.22 1.06 remove multiply fastpath, and improve performance */ | |
/* 2000.01.01 copyright update [Y2K has arrived] */ | |
/* 2000.06.18 1.08 no longer deprecate BigDecimal(double) */ | |
/* ------------------------------------------------------------------ */ | |
/** | |
* The <code>BigDecimal</code> class implements immutable arbitrary-precision decimal numbers. The methods of the | |
* <code>BigDecimal</code> class provide operations for fixed and floating point arithmetic, comparison, format | |
* conversions, and hashing. | |
* <p> | |
* As the numbers are decimal, there is an exact correspondence between an instance of a <code>BigDecimal</code> object | |
* and its <code>String</code> representation; the <code>BigDecimal</code> class provides direct conversions to and from | |
* <code>String</code> and character array (<code>char[]</code>) objects, as well as conversions to and from the Java | |
* primitive types (which may not be exact) and <code>BigInteger</code>. | |
* <p> | |
* In the descriptions of constructors and methods in this documentation, the value of a <code>BigDecimal</code> number | |
* object is shown as the result of invoking the <code>toString()</code> method on the object. The internal | |
* representation of a decimal number is neither defined nor exposed, and is not permitted to affect the result of any | |
* operation. | |
* <p> | |
* The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also | |
* documented at <code>http://www2.hursley.ibm.com/decimal</code> <br> | |
* <i>[This URL will change.]</i> | |
* | |
* <h3>Operator methods</h3> | |
* <p> | |
* Operations on <code>BigDecimal</code> numbers are controlled by a {@link MathContext} object, which provides the | |
* context (precision and other information) for the operation. Methods that can take a <code>MathContext</code> | |
* parameter implement the standard arithmetic operators for <code>BigDecimal</code> objects and are known as | |
* <i>operator methods</i>. The default settings provided by the constant {@link MathContext#DEFAULT} (<code>digits=9, | |
* form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP</code>) perform general-purpose floating point | |
* arithmetic to nine digits of precision. The <code>MathContext</code> parameter must not be <code>null</code>. | |
* <p> | |
* Each operator method also has a version provided which does not take a <code>MathContext</code> parameter. For this | |
* version of each method, the context settings used are <code>digits=0, | |
* form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>; these settings perform fixed point arithmetic with | |
* unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2. | |
* <p> | |
* For monadic operators, only the optional <code>MathContext</code> parameter is present; the operation acts upon the | |
* current object. | |
* <p> | |
* For dyadic operators, a <code>BigDecimal</code> parameter is always present; it must not be <code>null</code>. The | |
* operation acts with the current object being the left-hand operand and the <code>BigDecimal</code> parameter being | |
* the right-hand operand. | |
* <p> | |
* For example, adding two <code>BigDecimal</code> objects referred to by the names <code>award</code> and | |
* <code>extra</code> could be written as any of: | |
* <p> | |
* <code> | |
* award.add(extra) | |
* <br>award.add(extra, MathContext.DEFAULT) | |
* <br>award.add(extra, acontext) | |
* </code> | |
* <p> | |
* (where <code>acontext</code> is a <code>MathContext</code> object), which would return a <code>BigDecimal</code> | |
* object whose value is the result of adding <code>award</code> and <code>extra</code> under the appropriate context | |
* settings. | |
* <p> | |
* When a <code>BigDecimal</code> operator method is used, a set of rules define what the result will be (and, by | |
* implication, how the result would be represented as a character string). These rules are defined in the BigDecimal | |
* arithmetic documentation (see the URL above), but in summary: | |
* <ul> | |
* <li>Results are normally calculated with up to some maximum number of significant digits. For example, if the | |
* <code>MathContext</code> parameter for an operation were <code>MathContext.DEFAULT</code> then the result would be | |
* rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667. <br> | |
* You can change the default of 9 significant digits by providing the method with a suitable <code>MathContext</code> | |
* object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled) | |
* arithmetic is indicated by using a <code>digits</code> setting of 0 (or omitting the <code>MathContext</code> | |
* parameter). <br> | |
* Similarly, you can change the algorithm used for rounding from the default "classic" algorithm. | |
* <li> | |
* In standard arithmetic (that is, when the <code>form</code> setting is not <code>PLAIN</code>), a zero result is | |
* always expressed as the single digit <code>'0'</code> (that is, with no sign, decimal point, or exponent part). | |
* <li> | |
* Except for the division and power operators in standard arithmetic, trailing zeros are preserved (this is in contrast | |
* to binary floating point operations and most electronic calculators, which lose the information about trailing zeros | |
* in the fractional part of results). <br> | |
* So, for example: | |
* <p> | |
* <code> | |
* new BigDecimal("2.40").add( new BigDecimal("2")) => "4.40" | |
* <br>new BigDecimal("2.40").subtract(new BigDecimal("2")) => "0.40" | |
* <br>new BigDecimal("2.40").multiply(new BigDecimal("2")) => "4.80" | |
* <br>new BigDecimal("2.40").divide( new BigDecimal("2"), def) => "1.2" | |
* </code> | |
* <p> | |
* where the value on the right of the <code>=></code> would be the result of the operation, expressed as a | |
* <code>String</code>, and <code>def</code> (in this and following examples) refers to <code>MathContext.DEFAULT</code> | |
* ). This preservation of trailing zeros is desirable for most calculations (including financial calculations). If | |
* necessary, trailing zeros may be easily removed using division by 1. | |
* <li> | |
* In standard arithmetic, exponential form is used for a result depending on its value and the current setting of | |
* <code>digits</code> (the default is 9 digits). If the number of places needed before the decimal point exceeds the | |
* <code>digits</code> setting, or the absolute value of the number is less than <code>0.000001</code>, then the number | |
* will be expressed in exponential notation; thus | |
* <p> | |
* <code> | |
* new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def) | |
* </code> | |
* <p> | |
* results in <code>1E+12</code> instead of <code>1000000000000</code>, and | |
* <p> | |
* <code> | |
* new BigDecimal("1").divide(new BigDecimal("3E+10"), def) | |
* </code> | |
* <p> | |
* results in <code>3.33333333E-11</code> instead of <code>0.0000000000333333333</code>. | |
* <p> | |
* The form of the exponential notation (scientific or engineering) is determined by the <code>form</code> setting. | |
* <eul> | |
* <p> | |
* The names of methods in this class follow the conventions established by <code>java.lang.Number</code>, | |
* <code>java.math.BigInteger</code>, and <code>java.math.BigDecimal</code> in Java 1.1 and Java 1.2. | |
* | |
* @see MathContext | |
* @author Mike Cowlishaw | |
* @stable ICU 2.0 | |
*/ | |
public class BigDecimal extends java.lang.Number implements java.io.Serializable, java.lang.Comparable<BigDecimal> { | |
// private static final java.lang.String $0="BigDecimal.nrx"; | |
/* ----- Constants ----- */ | |
/* properties constant public */// useful to others | |
/** | |
* The <code>BigDecimal</code> constant "0". | |
* | |
* @see #ONE | |
* @see #TEN | |
* @stable ICU 2.0 | |
*/ | |
public static final com.ibm.icu.math.BigDecimal ZERO = new com.ibm.icu.math.BigDecimal((long) 0); // use long as we | |
// want the int | |
// constructor | |
// .. to be able to use this, for speed | |
/** | |
* The <code>BigDecimal</code> constant "1". | |
* | |
* @see #TEN | |
* @see #ZERO | |
* @stable ICU 2.0 | |
*/ | |
public static final com.ibm.icu.math.BigDecimal ONE = new com.ibm.icu.math.BigDecimal((long) 1); // use long as we | |
// want the int | |
// constructor | |
// .. to be able to use this, for speed | |
/** | |
* The <code>BigDecimal</code> constant "10". | |
* | |
* @see #ONE | |
* @see #ZERO | |
* @stable ICU 2.0 | |
*/ | |
public static final com.ibm.icu.math.BigDecimal TEN = new com.ibm.icu.math.BigDecimal(10); | |
// the rounding modes (copied here for upwards compatibility) | |
/** | |
* Rounding mode to round to a more positive number. | |
* | |
* @see MathContext#ROUND_CEILING | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_CEILING = com.ibm.icu.math.MathContext.ROUND_CEILING; | |
/** | |
* Rounding mode to round towards zero. | |
* | |
* @see MathContext#ROUND_DOWN | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_DOWN = com.ibm.icu.math.MathContext.ROUND_DOWN; | |
/** | |
* Rounding mode to round to a more negative number. | |
* | |
* @see MathContext#ROUND_FLOOR | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_FLOOR = com.ibm.icu.math.MathContext.ROUND_FLOOR; | |
/** | |
* Rounding mode to round to nearest neighbor, where an equidistant value is rounded down. | |
* | |
* @see MathContext#ROUND_HALF_DOWN | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_HALF_DOWN = com.ibm.icu.math.MathContext.ROUND_HALF_DOWN; | |
/** | |
* Rounding mode to round to nearest neighbor, where an equidistant value is rounded to the nearest even neighbor. | |
* | |
* @see MathContext#ROUND_HALF_EVEN | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_HALF_EVEN = com.ibm.icu.math.MathContext.ROUND_HALF_EVEN; | |
/** | |
* Rounding mode to round to nearest neighbor, where an equidistant value is rounded up. | |
* | |
* @see MathContext#ROUND_HALF_UP | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_HALF_UP = com.ibm.icu.math.MathContext.ROUND_HALF_UP; | |
/** | |
* Rounding mode to assert that no rounding is necessary. | |
* | |
* @see MathContext#ROUND_UNNECESSARY | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_UNNECESSARY = com.ibm.icu.math.MathContext.ROUND_UNNECESSARY; | |
/** | |
* Rounding mode to round away from zero. | |
* | |
* @see MathContext#ROUND_UP | |
* @stable ICU 2.0 | |
*/ | |
public static final int ROUND_UP = com.ibm.icu.math.MathContext.ROUND_UP; | |
/* properties constant private */// locals | |
private static final byte ispos = 1; // ind: indicates positive (must be 1) | |
private static final byte iszero = 0; // ind: indicates zero (must be 0) | |
private static final byte isneg = -1; // ind: indicates negative (must be -1) | |
// [later could add NaN, +/- infinity, here] | |
private static final int MinExp = -999999999; // minimum exponent allowed | |
private static final int MaxExp = 999999999; // maximum exponent allowed | |
private static final int MinArg = -999999999; // minimum argument integer | |
private static final int MaxArg = 999999999; // maximum argument integer | |
private static final com.ibm.icu.math.MathContext plainMC = new com.ibm.icu.math.MathContext(0, | |
com.ibm.icu.math.MathContext.PLAIN); // context for plain unlimited math | |
/* properties constant private unused */// present but not referenced | |
// Serialization version | |
private static final long serialVersionUID = 8245355804974198832L; | |
// private static final java.lang.String | |
// copyright=" Copyright (c) IBM Corporation 1996, 2000. All rights reserved. "; | |
/* properties static private */ | |
// Precalculated constant arrays (used by byteaddsub) | |
private static byte bytecar[] = new byte[(90 + 99) + 1]; // carry/borrow array | |
private static byte bytedig[] = diginit(); // next digit array | |
/* ----- Instance properties [all private and immutable] ----- */ | |
/* properties private */ | |
/** | |
* The indicator. This may take the values: | |
* <ul> | |
* <li>ispos -- the number is positive <li>iszero -- the number is zero <li>isneg -- the number is negative | |
* </ul> | |
* | |
* @serial | |
*/ | |
private byte ind; // assumed undefined | |
// Note: some code below assumes IND = Sign [-1, 0, 1], at present. | |
// We only need two bits for this, but use a byte [also permits | |
// smooth future extension]. | |
/** | |
* The formatting style. This may take the values: | |
* <ul> | |
* <li>MathContext.PLAIN -- no exponent needed <li>MathContext.SCIENTIFIC -- scientific notation required <li> | |
* MathContext.ENGINEERING -- engineering notation required | |
* </ul> | |
* <p> | |
* This property is an optimization; it allows us to defer number layout until it is actually needed as a string, | |
* hence avoiding unnecessary formatting. | |
* | |
* @serial | |
*/ | |
private byte form = (byte) com.ibm.icu.math.MathContext.PLAIN; // assumed PLAIN | |
// We only need two bits for this, at present, but use a byte | |
// [again, to allow for smooth future extension] | |
/** | |
* The value of the mantissa. | |
* <p> | |
* Once constructed, this may become shared between several BigDecimal objects, so must not be altered. | |
* <p> | |
* For efficiency (speed), this is a byte array, with each byte taking a value of 0 -> 9. | |
* <p> | |
* If the first byte is 0 then the value of the number is zero (and mant.length=1, except when constructed from a | |
* plain number, for example, 0.000). | |
* | |
* @serial | |
*/ | |
private byte mant[]; // assumed null | |
/** | |
* The exponent. | |
* <p> | |
* For fixed point arithmetic, scale is <code>-exp</code>, and can apply to zero. | |
* | |
* Note that this property can have a value less than MinExp when the mantissa has more than one digit. | |
* | |
* @serial | |
*/ | |
private int exp; | |
// assumed 0 | |
/* ---------------------------------------------------------------- */ | |
/* Constructors */ | |
/* ---------------------------------------------------------------- */ | |
/** | |
* Constructs a <code>BigDecimal</code> object from a <code>java.math.BigDecimal</code>. | |
* <p> | |
* Constructs a <code>BigDecimal</code> as though the parameter had been represented as a <code>String</code> (using | |
* its <code>toString</code> method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used. | |
* The parameter must not be <code>null</code>. | |
* <p> | |
* <i>(Note: this constructor is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class. | |
* It would not be present in a <code>java.math</code> version.)</i> | |
* | |
* @param bd The <code>BigDecimal</code> to be translated. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(java.math.BigDecimal bd) { | |
this(bd.toString()); | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code>, with scale 0. | |
* <p> | |
* Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>, | |
* with a scale of zero. The value of the <code>BigDecimal</code> is identical to the value of the <code>BigInteger | |
* </code>. The parameter must not be <code>null</code>. | |
* <p> | |
* The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the | |
* <code>BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero. | |
* | |
* @param bi The <code>BigInteger</code> to be converted. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(java.math.BigInteger bi) { | |
this(bi.toString(10)); | |
return; | |
} | |
// exp remains 0 | |
/** | |
* Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code> and a scale. | |
* <p> | |
* Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>, | |
* scaled by the second parameter, which may not be negative. The value of the <code>BigDecimal</code> is the <code> | |
* BigInteger</code> divided by ten to the power of the scale. The <code>BigInteger</code> parameter must not be | |
* <code>null</code>. | |
* <p> | |
* The <code>BigDecimal</code> will contain only decimal digits, (with an embedded decimal point followed by <code> | |
* scale</code> decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the <code> | |
* BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero. | |
* | |
* @param bi The <code>BigInteger</code> to be converted. | |
* @param scale The <code>int</code> specifying the scale. | |
* @throws NumberFormatException If the scale is negative. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(java.math.BigInteger bi, int scale) { | |
this(bi.toString(10)); | |
if (scale < 0) | |
throw new java.lang.NumberFormatException("Negative scale:" + " " + scale); | |
exp = -scale; // exponent is -scale | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object from an array of characters. | |
* <p> | |
* Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character | |
* array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be | |
* <code>null</code>. | |
* <p> | |
* Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is | |
* already available in character array form. | |
* | |
* @param inchars The <code>char[]</code> array containing the number to be converted. | |
* @throws NumberFormatException If the parameter is not a valid number. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(char inchars[]) { | |
this(inchars, 0, inchars.length); | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object from an array of characters. | |
* <p> | |
* Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character | |
* array (or a subarray of that array) and the {@link #BigDecimal(java.lang.String)} constructor had then been used. | |
* The first parameter must not be <code>null</code>, and the subarray must be wholly contained within it. | |
* <p> | |
* Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is | |
* already available within a character array. | |
* | |
* @param inchars The <code>char[]</code> array containing the number to be converted. | |
* @param offset The <code>int</code> offset into the array of the start of the number to be converted. | |
* @param length The <code>int</code> length of the number. | |
* @throws NumberFormatException If the parameter is not a valid number for any reason. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(char inchars[], int offset, int length) { | |
super(); | |
boolean exotic; | |
boolean hadexp; | |
int d; | |
int dotoff; | |
int last; | |
int i = 0; | |
char si = 0; | |
boolean eneg = false; | |
int k = 0; | |
int elen = 0; | |
int j = 0; | |
char sj = 0; | |
int dvalue = 0; | |
int mag = 0; | |
// This is the primary constructor; all incoming strings end up | |
// here; it uses explicit (inline) parsing for speed and to avoid | |
// generating intermediate (temporary) objects of any kind. | |
// 1998.06.25: exponent form built only if E/e in string | |
// 1998.06.25: trailing zeros not removed for zero | |
// 1999.03.06: no embedded blanks; allow offset and length | |
if (length <= 0) | |
bad(inchars); // bad conversion (empty string) | |
// [bad offset will raise array bounds exception] | |
/* Handle and step past sign */ | |
ind = ispos; // assume positive | |
if (inchars[offset] == ('-')) { | |
length--; | |
if (length == 0) | |
bad(inchars); // nothing after sign | |
ind = isneg; | |
offset++; | |
} else if (inchars[offset] == ('+')) { | |
length--; | |
if (length == 0) | |
bad(inchars); // nothing after sign | |
offset++; | |
} | |
/* We're at the start of the number */ | |
exotic = false; // have extra digits | |
hadexp = false; // had explicit exponent | |
d = 0; // count of digits found | |
dotoff = -1; // offset where dot was found | |
last = -1; // last character of mantissa | |
{ | |
int $1 = length; | |
i = offset; | |
i: for (; $1 > 0; $1--, i++) { | |
si = inchars[i]; | |
if (si >= '0') // test for Arabic digit | |
if (si <= '9') { | |
last = i; | |
d++; // still in mantissa | |
continue i; | |
} | |
if (si == '.') { // record and ignore | |
if (dotoff >= 0) | |
bad(inchars); // two dots | |
dotoff = i - offset; // offset into mantissa | |
continue i; | |
} | |
if (si != 'e') | |
if (si != 'E') { // expect an extra digit | |
if ((!(Character.isDigit(si)))) | |
bad(inchars); // not a number | |
// defer the base 10 check until later to avoid extra method call | |
exotic = true; // will need conversion later | |
last = i; | |
d++; // still in mantissa | |
continue i; | |
} | |
/* Found 'e' or 'E' -- now process explicit exponent */ | |
// 1998.07.11: sign no longer required | |
if ((i - offset) > (length - 2)) | |
bad(inchars); // no room for even one digit | |
eneg = false; | |
if ((inchars[i + 1]) == ('-')) { | |
eneg = true; | |
k = i + 2; | |
} else if ((inchars[i + 1]) == ('+')) | |
k = i + 2; | |
else | |
k = i + 1; | |
// k is offset of first expected digit | |
elen = length - ((k - offset)); // possible number of digits | |
if ((elen == 0) | (elen > 9)) | |
bad(inchars); // 0 or more than 9 digits | |
{ | |
int $2 = elen; | |
j = k; | |
for (; $2 > 0; $2--, j++) { | |
sj = inchars[j]; | |
if (sj < '0') | |
bad(inchars); // always bad | |
if (sj > '9') { // maybe an exotic digit | |
if ((!(Character.isDigit(sj)))) | |
bad(inchars); // not a number | |
dvalue = Character.digit(sj, 10); // check base | |
if (dvalue < 0) | |
bad(inchars); // not base 10 | |
} else | |
dvalue = ((int) (sj)) - ((int) ('0')); | |
exp = (exp * 10) + dvalue; | |
} | |
}/* j */ | |
if (eneg) | |
exp = -exp; // was negative | |
hadexp = true; // remember we had one | |
break i; // we are done | |
} | |
}/* i */ | |
/* Here when all inspected */ | |
if (d == 0) | |
bad(inchars); // no mantissa digits | |
if (dotoff >= 0) | |
exp = (exp + dotoff) - d; // adjust exponent if had dot | |
/* strip leading zeros/dot (leave final if all 0's) */ | |
{ | |
int $3 = last - 1; | |
i = offset; | |
i: for (; i <= $3; i++) { | |
si = inchars[i]; | |
if (si == '0') { | |
offset++; | |
dotoff--; | |
d--; | |
} else if (si == '.') { | |
offset++; // step past dot | |
dotoff--; | |
} else if (si <= '9') | |
break i;/* non-0 */ | |
else {/* exotic */ | |
if ((Character.digit(si, 10)) != 0) | |
break i; // non-0 or bad | |
// is 0 .. strip like '0' | |
offset++; | |
dotoff--; | |
d--; | |
} | |
} | |
}/* i */ | |
/* Create the mantissa array */ | |
mant = new byte[d]; // we know the length | |
j = offset; // input offset | |
if (exotic) { | |
do { // slow: check for exotica | |
{ | |
int $4 = d; | |
i = 0; | |
for (; $4 > 0; $4--, i++) { | |
if (i == dotoff) | |
j++; // at dot | |
sj = inchars[j]; | |
if (sj <= '9') | |
mant[i] = (byte) (((int) (sj)) - ((int) ('0')));/* easy */ | |
else { | |
dvalue = Character.digit(sj, 10); | |
if (dvalue < 0) | |
bad(inchars); // not a number after all | |
mant[i] = (byte) dvalue; | |
} | |
j++; | |
} | |
}/* i */ | |
} while (false); | |
}/* exotica */ | |
else { | |
do { | |
{ | |
int $5 = d; | |
i = 0; | |
for (; $5 > 0; $5--, i++) { | |
if (i == dotoff) | |
j++; | |
mant[i] = (byte) (((int) (inchars[j])) - ((int) ('0'))); | |
j++; | |
} | |
}/* i */ | |
} while (false); | |
}/* simple */ | |
/* Looks good. Set the sign indicator and form, as needed. */ | |
// Trailing zeros are preserved | |
// The rule here for form is: | |
// If no E-notation, then request plain notation | |
// Otherwise act as though add(0,DEFAULT) and request scientific notation | |
// [form is already PLAIN] | |
if (mant[0] == 0) { | |
ind = iszero; // force to show zero | |
// negative exponent is significant (e.g., -3 for 0.000) if plain | |
if (exp > 0) | |
exp = 0; // positive exponent can be ignored | |
if (hadexp) { // zero becomes single digit from add | |
mant = ZERO.mant; | |
exp = 0; | |
} | |
} else { // non-zero | |
// [ind was set earlier] | |
// now determine form | |
if (hadexp) { | |
form = (byte) com.ibm.icu.math.MathContext.SCIENTIFIC; | |
// 1999.06.29 check for overflow | |
mag = (exp + mant.length) - 1; // true exponent in scientific notation | |
if ((mag < MinExp) | (mag > MaxExp)) | |
bad(inchars); | |
} | |
} | |
// say 'BD(c[]): mant[0] mantlen exp ind form:' mant[0] mant.length exp ind form | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object directly from a <code>double</code>. | |
* <p> | |
* Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary | |
* floating point parameter. | |
* <p> | |
* Note that this constructor it an exact conversion; it does not give the same result as converting <code>num | |
* </code> to a <code>String</code> using the <code>Double.toString()</code> method and then using the | |
* {@link #BigDecimal(java.lang.String)} constructor. To get that result, use the static {@link #valueOf(double)} | |
* method to construct a <code>BigDecimal</code> from a <code>double</code>. | |
* | |
* @param num The <code>double</code> to be converted. | |
* @throws NumberFormatException If the parameter is infinite or not a number. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(double num) { | |
// 1999.03.06: use exactly the old algorithm | |
// 2000.01.01: note that this constructor does give an exact result, | |
// so perhaps it should not be deprecated | |
// 2000.06.18: no longer deprecated | |
this((new java.math.BigDecimal(num)).toString()); | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object directly from a <code>int</code>. | |
* <p> | |
* Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 32-bit signed binary | |
* integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus | |
* sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero. | |
* | |
* @param num The <code>int</code> to be converted. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(int num) { | |
super(); | |
int mun; | |
int i = 0; | |
// We fastpath commoners | |
if (num <= 9) | |
if (num >= (-9)) { | |
do { | |
// very common single digit case | |
{/* select */ | |
if (num == 0) { | |
mant = ZERO.mant; | |
ind = iszero; | |
} else if (num == 1) { | |
mant = ONE.mant; | |
ind = ispos; | |
} else if (num == (-1)) { | |
mant = ONE.mant; | |
ind = isneg; | |
} else { | |
{ | |
mant = new byte[1]; | |
if (num > 0) { | |
mant[0] = (byte) num; | |
ind = ispos; | |
} else { // num<-1 | |
mant[0] = (byte) -num; | |
ind = isneg; | |
} | |
} | |
} | |
} | |
return; | |
} while (false); | |
}/* singledigit */ | |
/* We work on negative numbers so we handle the most negative number */ | |
if (num > 0) { | |
ind = ispos; | |
num = -num; | |
} else | |
ind = isneg;/* negative */// [0 case already handled] | |
// [it is quicker, here, to pre-calculate the length with | |
// one loop, then allocate exactly the right length of byte array, | |
// then re-fill it with another loop] | |
mun = num; // working copy | |
{ | |
i = 9; | |
i: for (;; i--) { | |
mun = mun / 10; | |
if (mun == 0) | |
break i; | |
} | |
}/* i */ | |
// i is the position of the leftmost digit placed | |
mant = new byte[10 - i]; | |
{ | |
i = (10 - i) - 1; | |
i: for (;; i--) { | |
mant[i] = (byte) -(((byte) (num % 10))); | |
num = num / 10; | |
if (num == 0) | |
break i; | |
} | |
}/* i */ | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object directly from a <code>long</code>. | |
* <p> | |
* Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary | |
* integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus | |
* sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero. | |
* | |
* @param num The <code>long</code> to be converted. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(long num) { | |
super(); | |
long mun; | |
int i = 0; | |
// Not really worth fastpathing commoners in this constructor [also, | |
// we use this to construct the static constants]. | |
// This is much faster than: this(String.valueOf(num).toCharArray()) | |
/* We work on negative num so we handle the most negative number */ | |
if (num > 0) { | |
ind = ispos; | |
num = -num; | |
} else if (num == 0) | |
ind = iszero; | |
else | |
ind = isneg;/* negative */ | |
mun = num; | |
{ | |
i = 18; | |
i: for (;; i--) { | |
mun = mun / 10; | |
if (mun == 0) | |
break i; | |
} | |
}/* i */ | |
// i is the position of the leftmost digit placed | |
mant = new byte[19 - i]; | |
{ | |
i = (19 - i) - 1; | |
i: for (;; i--) { | |
mant[i] = (byte) -(((byte) (num % 10))); | |
num = num / 10; | |
if (num == 0) | |
break i; | |
} | |
}/* i */ | |
return; | |
} | |
/** | |
* Constructs a <code>BigDecimal</code> object from a <code>String</code>. | |
* <p> | |
* Constructs a <code>BigDecimal</code> from the parameter, which must not be <code>null</code> and must represent a | |
* valid <i>number</i>, as described formally in the documentation referred to {@link BigDecimal above}. | |
* <p> | |
* In summary, numbers in <code>String</code> form must have at least one digit, may have a leading sign, may have a | |
* decimal point, and exponential notation may be used. They follow conventional syntax, and may not contain blanks. | |
* <p> | |
* Some valid strings from which a <code>BigDecimal</code> might be constructed are: | |
* | |
* <pre> | |
* | |
* "0" -- Zero "12" -- A whole number "-76" -- A signed whole number "12.70" -- Some decimal places "+0.003" -- Plus | |
* sign is allowed "17." -- The same as 17 ".5" -- The same as 0.5 "4E+9" -- Exponential notation "0.73e-7" -- | |
* Exponential notation | |
* | |
* </pre> | |
* <p> | |
* (Exponential notation means that the number includes an optional sign and a power of ten following an | |
* '</code>E</code>' that indicates how the decimal point will be shifted. Thus the <code>"4E+9"</code> above is | |
* just a short way of writing <code>4000000000</code>, and the <code>"0.73e-7"</code> is short for <code> | |
* 0.000000073</code>.) | |
* <p> | |
* The <code>BigDecimal</code> constructed from the String is in a standard form, with no blanks, as though the | |
* {@link #add(BigDecimal)} method had been used to add zero to the number with unlimited precision. If the string | |
* uses exponential notation (that is, includes an <code>e</code> or an <code>E</code>), then the <code>BigDecimal | |
* </code> number will be expressed in scientific notation (where the power of ten is adjusted so there is a single | |
* non-zero digit to the left of the decimal point); in this case if the number is zero then it will be expressed as | |
* the single digit 0, and if non-zero it will have an exponent unless that exponent would be 0. The exponent must | |
* fit in nine digits both before and after it is expressed in scientific notation. | |
* <p> | |
* Any digits in the parameter must be decimal; that is, <code>Character.digit(c, 10)</code> (where </code>c</code> | |
* is the character in question) would not return -1. | |
* | |
* @param string The <code>String</code> to be converted. | |
* @throws NumberFormatException If the parameter is not a valid number. | |
* @stable ICU 2.0 | |
*/ | |
public BigDecimal(java.lang.String string) { | |
this(string.toCharArray(), 0, string.length()); | |
return; | |
} | |
/* <sgml> Make a default BigDecimal object for local use. </sgml> */ | |
private BigDecimal() { | |
super(); | |
return; | |
} | |
/* ---------------------------------------------------------------- */ | |
/* Operator methods [methods which take a context parameter] */ | |
/* ---------------------------------------------------------------- */ | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>. | |
* <p> | |
* The same as {@link #abs(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will be <code>this.scale()</code> | |
* | |
* @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal abs() { | |
return this.abs(plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>. | |
* <p> | |
* If the current object is zero or positive, then the same result as invoking the {@link #plus(MathContext)} method | |
* with the same parameter is returned. Otherwise, the same result as invoking the {@link #negate(MathContext)} | |
* method with the same parameter is returned. | |
* | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal abs(com.ibm.icu.math.MathContext set) { | |
if (this.ind == isneg) | |
return this.negate(set); | |
return this.plus(set); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic. | |
* <p> | |
* The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the addition. | |
* @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs) { | |
return this.add(rhs, plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>this+rhs</code>. | |
* <p> | |
* Implements the addition (<b><code>+</code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the addition. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
com.ibm.icu.math.BigDecimal lhs; | |
int reqdig; | |
com.ibm.icu.math.BigDecimal res; | |
byte usel[]; | |
int usellen; | |
byte user[]; | |
int userlen; | |
int newlen = 0; | |
int tlen = 0; | |
int mult = 0; | |
byte t[] = null; | |
int ia = 0; | |
int ib = 0; | |
int ea = 0; | |
int eb = 0; | |
byte ca = 0; | |
byte cb = 0; | |
/* determine requested digits and form */ | |
if (set.lostDigits) | |
checkdigits(rhs, set.digits); | |
lhs = this; // name for clarity and proxy | |
/* Quick exit for add floating 0 */ | |
// plus() will optimize to return same object if possible | |
if (lhs.ind == 0) | |
if (set.form != com.ibm.icu.math.MathContext.PLAIN) | |
return rhs.plus(set); | |
if (rhs.ind == 0) | |
if (set.form != com.ibm.icu.math.MathContext.PLAIN) | |
return lhs.plus(set); | |
/* Prepare numbers (round, unless unlimited precision) */ | |
reqdig = set.digits; // local copy (heavily used) | |
if (reqdig > 0) { | |
if (lhs.mant.length > reqdig) | |
lhs = clone(lhs).round(set); | |
if (rhs.mant.length > reqdig) | |
rhs = clone(rhs).round(set); | |
// [we could reuse the new LHS for result in this case] | |
} | |
res = new com.ibm.icu.math.BigDecimal(); // build result here | |
/* | |
* Now see how much we have to pad or truncate lhs or rhs in order to align the numbers. If one number is much | |
* larger than the other, then the smaller cannot affect the answer [but we may still need to pad with up to | |
* DIGITS trailing zeros]. | |
*/ | |
// Note sign may be 0 if digits (reqdig) is 0 | |
// usel and user will be the byte arrays passed to the adder; we'll | |
// use them on all paths except quick exits | |
usel = lhs.mant; | |
usellen = lhs.mant.length; | |
user = rhs.mant; | |
userlen = rhs.mant.length; | |
{ | |
do {/* select */ | |
if (lhs.exp == rhs.exp) {/* no padding needed */ | |
// This is the most common, and fastest, path | |
res.exp = lhs.exp; | |
} else if (lhs.exp > rhs.exp) { // need to pad lhs and/or truncate rhs | |
newlen = (usellen + lhs.exp) - rhs.exp; | |
/* | |
* If, after pad, lhs would be longer than rhs by digits+1 or more (and digits>0) then rhs cannot | |
* affect answer, so we only need to pad up to a length of DIGITS+1. | |
*/ | |
if (newlen >= ((userlen + reqdig) + 1)) | |
if (reqdig > 0) { | |
// LHS is sufficient | |
res.mant = usel; | |
res.exp = lhs.exp; | |
res.ind = lhs.ind; | |
if (usellen < reqdig) { // need 0 padding | |
res.mant = extend(lhs.mant, reqdig); | |
res.exp = res.exp - ((reqdig - usellen)); | |
} | |
return res.finish(set, false); | |
} | |
// RHS may affect result | |
res.exp = rhs.exp; // expected final exponent | |
if (newlen > (reqdig + 1)) | |
if (reqdig > 0) { | |
// LHS will be max; RHS truncated | |
tlen = (newlen - reqdig) - 1; // truncation length | |
userlen = userlen - tlen; | |
res.exp = res.exp + tlen; | |
newlen = reqdig + 1; | |
} | |
if (newlen > usellen) | |
usellen = newlen; // need to pad LHS | |
} else { // need to pad rhs and/or truncate lhs | |
newlen = (userlen + rhs.exp) - lhs.exp; | |
if (newlen >= ((usellen + reqdig) + 1)) | |
if (reqdig > 0) { | |
// RHS is sufficient | |
res.mant = user; | |
res.exp = rhs.exp; | |
res.ind = rhs.ind; | |
if (userlen < reqdig) { // need 0 padding | |
res.mant = extend(rhs.mant, reqdig); | |
res.exp = res.exp - ((reqdig - userlen)); | |
} | |
return res.finish(set, false); | |
} | |
// LHS may affect result | |
res.exp = lhs.exp; // expected final exponent | |
if (newlen > (reqdig + 1)) | |
if (reqdig > 0) { | |
// RHS will be max; LHS truncated | |
tlen = (newlen - reqdig) - 1; // truncation length | |
usellen = usellen - tlen; | |
res.exp = res.exp + tlen; | |
newlen = reqdig + 1; | |
} | |
if (newlen > userlen) | |
userlen = newlen; // need to pad RHS | |
} | |
} while (false); | |
}/* padder */ | |
/* OK, we have aligned mantissas. Now add or subtract. */ | |
// 1998.06.27 Sign may now be 0 [e.g., 0.000] .. treat as positive | |
// 1999.05.27 Allow for 00 on lhs [is not larger than 2 on rhs] | |
// 1999.07.10 Allow for 00 on rhs [is not larger than 2 on rhs] | |
if (lhs.ind == iszero) | |
res.ind = ispos; | |
else | |
res.ind = lhs.ind; // likely sign, all paths | |
if (((lhs.ind == isneg) ? 1 : 0) == ((rhs.ind == isneg) ? 1 : 0)) // same sign, 0 non-negative | |
mult = 1; | |
else { | |
do { // different signs, so subtraction is needed | |
mult = -1; // will cause subtract | |
/* | |
* Before we can subtract we must determine which is the larger, as our add/subtract routine only | |
* handles non-negative results so we may need to swap the operands. | |
*/ | |
{ | |
do {/* select */ | |
if (rhs.ind == iszero) { | |
// original A bigger | |
} else if ((usellen < userlen) | (lhs.ind == iszero)) { // original B bigger | |
t = usel; | |
usel = user; | |
user = t; // swap | |
tlen = usellen; | |
usellen = userlen; | |
userlen = tlen; // .. | |
res.ind = (byte) -res.ind; // and set sign | |
} else if (usellen > userlen) { | |
// original A bigger | |
} else { | |
{/* logical lengths the same */// need compare | |
/* may still need to swap: compare the strings */ | |
ia = 0; | |
ib = 0; | |
ea = usel.length - 1; | |
eb = user.length - 1; | |
{ | |
compare: for (;;) { | |
if (ia <= ea) | |
ca = usel[ia]; | |
else { | |
if (ib > eb) {/* identical */ | |
if (set.form != com.ibm.icu.math.MathContext.PLAIN) | |
return ZERO; | |
// [if PLAIN we must do the subtract, in case of 0.000 results] | |
break compare; | |
} | |
ca = (byte) 0; | |
} | |
if (ib <= eb) | |
cb = user[ib]; | |
else | |
cb = (byte) 0; | |
if (ca != cb) { | |
if (ca < cb) {/* swap needed */ | |
t = usel; | |
usel = user; | |
user = t; // swap | |
tlen = usellen; | |
usellen = userlen; | |
userlen = tlen; // .. | |
res.ind = (byte) -res.ind; | |
} | |
break compare; | |
} | |
/* mantissas the same, so far */ | |
ia++; | |
ib++; | |
} | |
}/* compare */ | |
} // lengths the same | |
} | |
} while (false); | |
}/* swaptest */ | |
} while (false); | |
}/* signdiff */ | |
/* here, A is > B if subtracting */ | |
// add [A+B*1] or subtract [A+(B*-1)] | |
res.mant = byteaddsub(usel, usellen, user, userlen, mult, false); | |
// [reuse possible only after chop; accounting makes not worthwhile] | |
// Finish() rounds before stripping leading 0's, then sets form, etc. | |
return res.finish(set, false); | |
} | |
/** | |
* Compares this <code>BigDecimal</code> to another, using unlimited precision. | |
* <p> | |
* The same as {@link #compareTo(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, | |
* and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the comparison. | |
* @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to, | |
* or greater than <code>rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public int compareTo(com.ibm.icu.math.BigDecimal rhs) { | |
return this.compareTo(rhs, plainMC); | |
} | |
/** | |
* Compares this <code>BigDecimal</code> to another. | |
* <p> | |
* Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}), | |
* and returns a result of type <code>int</code>. | |
* <p> | |
* The result will be: | |
* <table cellpadding=2> | |
* <tr> | |
* <td align=right><b>-1</b></td> <td>if the current object is less than the first parameter</td> | |
* </tr> | |
* <tr> | |
* <td align=right><b>0</b></td> <td>if the current object is equal to the first parameter</td> | |
* </tr> | |
* <tr> | |
* <td align=right><b>1</b></td> <td>if the current object is greater than the first parameter.</td> | |
* </tr> | |
* </table> | |
* <p> | |
* A {@link #compareTo(BigDecimal)} method is also provided. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the comparison. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to, | |
* or greater than <code>rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public int compareTo(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
int thislength = 0; | |
int i = 0; | |
com.ibm.icu.math.BigDecimal newrhs; | |
// rhs=null will raise NullPointerException, as per Comparable interface | |
if (set.lostDigits) | |
checkdigits(rhs, set.digits); | |
// [add will recheck in slowpath cases .. but would report -rhs] | |
if ((this.ind == rhs.ind) & (this.exp == rhs.exp)) { | |
/* sign & exponent the same [very common] */ | |
thislength = this.mant.length; | |
if (thislength < rhs.mant.length) | |
return (byte) -this.ind; | |
if (thislength > rhs.mant.length) | |
return this.ind; | |
/* | |
* lengths are the same; we can do a straight mantissa compare unless maybe rounding [rounding is very | |
* unusual] | |
*/ | |
if ((thislength <= set.digits) | (set.digits == 0)) { | |
{ | |
int $6 = thislength; | |
i = 0; | |
for (; $6 > 0; $6--, i++) { | |
if (this.mant[i] < rhs.mant[i]) | |
return (byte) -this.ind; | |
if (this.mant[i] > rhs.mant[i]) | |
return this.ind; | |
} | |
}/* i */ | |
return 0; // identical | |
} | |
/* drop through for full comparison */ | |
} else { | |
/* More fastpaths possible */ | |
if (this.ind < rhs.ind) | |
return -1; | |
if (this.ind > rhs.ind) | |
return 1; | |
} | |
/* carry out a subtract to make the comparison */ | |
newrhs = clone(rhs); // safe copy | |
newrhs.ind = (byte) -newrhs.ind; // prepare to subtract | |
return this.add(newrhs, set).ind; // add, and return sign of result | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic. | |
* <p> | |
* The same as {@link #divide(BigDecimal, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* rounding mode is {@link MathContext#ROUND_HALF_UP}. | |
* | |
* The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if | |
* the latter were formatted without exponential notation. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the division. | |
* @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic. | |
* @throws ArithmeticException If <code>rhs</code> is zero. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs) { | |
return this.dodivide('D', rhs, plainMC, -1); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a | |
* rounding mode. | |
* <p> | |
* The same as {@link #divide(BigDecimal, int, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* second parameter is <code>this.scale()</code>, and the third is <code>round</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will therefore be the same as the scale of the current | |
* object, if the latter were formatted without exponential notation. | |
* <p> | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the division. | |
* @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class). | |
* @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and | |
* the specified rounding mode. | |
* @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>this.scale()</code> is insufficient to represent the result exactly. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int round) { | |
com.ibm.icu.math.MathContext set; | |
set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round, | |
// too] | |
return this.dodivide('D', rhs, set, -1); // take scale from LHS | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a | |
* given scale and rounding mode. | |
* <p> | |
* The same as {@link #divide(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, | |
* <code>new MathContext(0, MathContext.PLAIN, false, round)</code>, except that the length of the decimal part (the | |
* scale) to be used for the result is explicit rather than being taken from <code>this</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if | |
* the latter were formatted without exponential notation. | |
* <p> | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the division. | |
* @param scale The <code>int</code> scale to be used for the result. | |
* @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class). | |
* @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and | |
* the specified rounding mode. | |
* @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @throws ArithmeticException if <code>scale</code> is negative. | |
* @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>scale</code> is insufficient | |
* to represent the result exactly. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int scale, int round) { | |
com.ibm.icu.math.MathContext set; | |
if (scale < 0) | |
throw new java.lang.ArithmeticException("Negative scale:" + " " + scale); | |
set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round] | |
return this.dodivide('D', rhs, set, scale); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>this/rhs</code>. | |
* <p> | |
* Implements the division (<b><code>/</code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the division. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>this/rhs</code>. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
return this.dodivide('D', rhs, set, -1); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>. | |
* <p> | |
* The same as {@link #divideInteger(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs | |
* </code>, and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the integer division. | |
* @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs) { | |
// scale 0 to drop .000 when plain | |
return this.dodivide('I', rhs, plainMC, 0); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>. | |
* <p> | |
* Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class | |
* header}), and returns the result as a <code>BigDecimal</code> object. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the integer division. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @throws ArithmeticException if the result will not fit in the number of digits specified for the context. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
// scale 0 to drop .000 when plain | |
return this.dodivide('I', rhs, set, 0); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>. | |
* <p> | |
* The same as {@link #max(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the comparison. | |
* @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) { | |
return this.max(rhs, plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>. | |
* <p> | |
* Returns the larger of the current object and the first parameter. | |
* <p> | |
* If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>1 | |
* </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object | |
* (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the | |
* {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code> | |
* parameter) is returned. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the comparison. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
if ((this.compareTo(rhs, set)) >= 0) | |
return this.plus(set); | |
else | |
return rhs.plus(set); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>. | |
* <p> | |
* The same as {@link #min(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the comparison. | |
* @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) { | |
return this.min(rhs, plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>. | |
* <p> | |
* Returns the smaller of the current object and the first parameter. | |
* <p> | |
* If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>-1 | |
* </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object | |
* (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the | |
* {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code> | |
* parameter) is returned. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the comparison. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
if ((this.compareTo(rhs, set)) <= 0) | |
return this.plus(set); | |
else | |
return rhs.plus(set); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic. | |
* <p> | |
* The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will be the sum of the scales of the operands, if they | |
* were formatted without exponential notation. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication. | |
* @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs) { | |
return this.multiply(rhs, plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>this*rhs</code>. | |
* <p> | |
* Implements the multiplication (<b><code> </code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
com.ibm.icu.math.BigDecimal lhs; | |
int padding; | |
int reqdig; | |
byte multer[] = null; | |
byte multand[] = null; | |
int multandlen; | |
int acclen = 0; | |
com.ibm.icu.math.BigDecimal res; | |
byte acc[]; | |
int n = 0; | |
byte mult = 0; | |
if (set.lostDigits) | |
checkdigits(rhs, set.digits); | |
lhs = this; // name for clarity and proxy | |
/* Prepare numbers (truncate, unless unlimited precision) */ | |
padding = 0; // trailing 0's to add | |
reqdig = set.digits; // local copy | |
if (reqdig > 0) { | |
if (lhs.mant.length > reqdig) | |
lhs = clone(lhs).round(set); | |
if (rhs.mant.length > reqdig) | |
rhs = clone(rhs).round(set); | |
// [we could reuse the new LHS for result in this case] | |
} else {/* unlimited */ | |
// fixed point arithmetic will want every trailing 0; we add these | |
// after the calculation rather than before, for speed. | |
if (lhs.exp > 0) | |
padding = padding + lhs.exp; | |
if (rhs.exp > 0) | |
padding = padding + rhs.exp; | |
} | |
// For best speed, as in DMSRCN, we use the shorter number as the | |
// multiplier and the longer as the multiplicand. | |
// 1999.12.22: We used to special case when the result would fit in | |
// a long, but with Java 1.3 this gave no advantage. | |
if (lhs.mant.length < rhs.mant.length) { | |
multer = lhs.mant; | |
multand = rhs.mant; | |
} else { | |
multer = rhs.mant; | |
multand = lhs.mant; | |
} | |
/* Calculate how long result byte array will be */ | |
multandlen = (multer.length + multand.length) - 1; // effective length | |
// optimize for 75% of the cases where a carry is expected... | |
if ((multer[0] * multand[0]) > 9) | |
acclen = multandlen + 1; | |
else | |
acclen = multandlen; | |
/* Now the main long multiplication loop */ | |
res = new com.ibm.icu.math.BigDecimal(); // where we'll build result | |
acc = new byte[acclen]; // accumulator, all zeros | |
// 1998.07.01: calculate from left to right so that accumulator goes | |
// to likely final length on first addition; this avoids a one-digit | |
// extension (and object allocation) each time around the loop. | |
// Initial number therefore has virtual zeros added to right. | |
{ | |
int $7 = multer.length; | |
n = 0; | |
for (; $7 > 0; $7--, n++) { | |
mult = multer[n]; | |
if (mult != 0) { // [optimization] | |
// accumulate [accumulator is reusable array] | |
acc = byteaddsub(acc, acc.length, multand, multandlen, mult, true); | |
} | |
// divide multiplicand by 10 for next digit to right | |
multandlen--; // 'virtual length' | |
} | |
}/* n */ | |
res.ind = (byte) (lhs.ind * rhs.ind); // final sign | |
res.exp = (lhs.exp + rhs.exp) - padding; // final exponent | |
// [overflow is checked by finish] | |
/* add trailing zeros to the result, if necessary */ | |
if (padding == 0) | |
res.mant = acc; | |
else | |
res.mant = extend(acc, acc.length + padding); // add trailing 0s | |
return res.finish(set, false); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>-this</code>. | |
* <p> | |
* The same as {@link #negate(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code> | |
* . | |
* <p> | |
* The length of the decimal part (the scale) of the result will be be <code>this.scale()</code> | |
* | |
* | |
* @return A <code>BigDecimal</code> whose value is <code>-this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal negate() { | |
return this.negate(plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>-this</code>. | |
* <p> | |
* Implements the negation (Prefix <b><code>-</code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>-this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal negate(com.ibm.icu.math.MathContext set) { | |
com.ibm.icu.math.BigDecimal res; | |
// Originally called minus(), changed to matched Java precedents | |
// This simply clones, flips the sign, and possibly rounds | |
if (set.lostDigits) | |
checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits); | |
res = clone(this); // safe copy | |
res.ind = (byte) -res.ind; | |
return res.finish(set, false); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>+this</code>. Note that <code>this</code> is not | |
* necessarily a plain <code>BigDecimal</code>, but the result will always be. | |
* <p> | |
* The same as {@link #plus(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will be be <code>this.scale()</code> | |
* | |
* @return A <code>BigDecimal</code> whose value is <code>+this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal plus() { | |
return this.plus(plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>+this</code>. | |
* <p> | |
* Implements the plus (Prefix <b><code>+</code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* <p> | |
* This method is useful for rounding or otherwise applying a context to a decimal value. | |
* | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>+this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal plus(com.ibm.icu.math.MathContext set) { | |
// This clones and forces the result to the new settings | |
// May return same object | |
if (set.lostDigits) | |
checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits); | |
// Optimization: returns same object for some common cases | |
if (set.form == com.ibm.icu.math.MathContext.PLAIN) | |
if (this.form == com.ibm.icu.math.MathContext.PLAIN) { | |
if (this.mant.length <= set.digits) | |
return this; | |
if (set.digits == 0) | |
return this; | |
} | |
return clone(this).finish(set, false); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic. | |
* <p> | |
* The same as {@link #pow(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the | |
* context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* The parameter is the power to which the <code>this</code> will be raised; it must be in the range 0 through | |
* 999999999, and must have a decimal part of zero. Note that these restrictions may be removed in the future, so | |
* they should not be used as a test for a whole number. | |
* <p> | |
* In addition, the power must not be negative, as no <code>MathContext</code> is used and so the result would then | |
* always be 0. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power). | |
* @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic. | |
* @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs) { | |
return this.pow(rhs, plainMC); | |
} | |
// The name for this method is inherited from the precedent set by the | |
// BigInteger and Math classes. | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>this**rhs</code>. | |
* <p> | |
* Implements the power (<b><code> </code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* <p> | |
* The first parameter is the power to which the <code>this</code> will be raised; it must be in the range | |
* -999999999 through 999999999, and must have a decimal part of zero. Note that these restrictions may be removed | |
* in the future, so they should not be used as a test for a whole number. | |
* <p> | |
* If the <code>digits</code> setting of the <code>MathContext</code> parameter is 0, the power must be zero or | |
* positive. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power). | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>. | |
* @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
int n; | |
com.ibm.icu.math.BigDecimal lhs; | |
int reqdig; | |
int workdigits = 0; | |
int L = 0; | |
com.ibm.icu.math.MathContext workset; | |
com.ibm.icu.math.BigDecimal res; | |
boolean seenbit; | |
int i = 0; | |
if (set.lostDigits) | |
checkdigits(rhs, set.digits); | |
n = rhs.intcheck(MinArg, MaxArg); // check RHS by the rules | |
lhs = this; // clarified name | |
reqdig = set.digits; // local copy (heavily used) | |
if (reqdig == 0) { | |
if (rhs.ind == isneg) | |
throw new java.lang.ArithmeticException("Negative power:" + " " + rhs.toString()); | |
workdigits = 0; | |
} else {/* non-0 digits */ | |
if ((rhs.mant.length + rhs.exp) > reqdig) | |
throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString()); | |
/* Round the lhs to DIGITS if need be */ | |
if (lhs.mant.length > reqdig) | |
lhs = clone(lhs).round(set); | |
/* L for precision calculation [see ANSI X3.274-1996] */ | |
L = rhs.mant.length + rhs.exp; // length without decimal zeros/exp | |
workdigits = (reqdig + L) + 1; // calculate the working DIGITS | |
} | |
/* Create a copy of set for working settings */ | |
// Note: no need to check for lostDigits again. | |
// 1999.07.17 Note: this construction must follow RHS check | |
workset = new com.ibm.icu.math.MathContext(workdigits, set.form, false, set.roundingMode); | |
res = ONE; // accumulator | |
if (n == 0) | |
return res; // x**0 == 1 | |
if (n < 0) | |
n = -n; // [rhs.ind records the sign] | |
seenbit = false; // set once we've seen a 1-bit | |
{ | |
i = 1; | |
i: for (;; i++) { // for each bit [top bit ignored] | |
n = n + n; // shift left 1 bit | |
if (n < 0) { // top bit is set | |
seenbit = true; // OK, we're off | |
res = res.multiply(lhs, workset); // acc=acc*x | |
} | |
if (i == 31) | |
break i; // that was the last bit | |
if ((!seenbit)) | |
continue i; // we don't have to square 1 | |
res = res.multiply(res, workset); // acc=acc*acc [square] | |
} | |
}/* i */// 32 bits | |
if (rhs.ind < 0) // was a **-n [hence digits>0] | |
res = ONE.divide(res, workset); // .. so acc=1/acc | |
return res.finish(set, true); // round and strip [original digits] | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point | |
* arithmetic. | |
* <p> | |
* The same as {@link #remainder(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, | |
* and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* This is not the modulo operator -- the result may be negative. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation. | |
* @return A <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point | |
* arithmetic. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs) { | |
return this.dodivide('R', rhs, plainMC, -1); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>. | |
* <p> | |
* Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}), | |
* and returns the result as a <code>BigDecimal</code> object. | |
* <p> | |
* This is not the modulo operator -- the result may be negative. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is the remainder of <code>this+rhs</code>. | |
* @throws ArithmeticException if <code>rhs</code> is zero. | |
* @throws ArithmeticException if the integer part of the result will not fit in the number of digits specified for the context. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
return this.dodivide('R', rhs, set, -1); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic. | |
* <p> | |
* The same as {@link #subtract(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, | |
* and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. | |
* <p> | |
* The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction. | |
* @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs) { | |
return this.subtract(rhs, plainMC); | |
} | |
/** | |
* Returns a <code>BigDecimal</code> whose value is <code>this-rhs</code>. | |
* <p> | |
* Implements the subtraction (<b><code>-</code></b>) operator (as defined in the decimal documentation, see | |
* {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object. | |
* | |
* @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction. | |
* @param set The <code>MathContext</code> arithmetic settings. | |
* @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) { | |
com.ibm.icu.math.BigDecimal newrhs; | |
if (set.lostDigits) | |
checkdigits(rhs, set.digits); | |
// [add will recheck .. but would report -rhs] | |
/* carry out the subtraction */ | |
// we could fastpath -0, but it is too rare. | |
newrhs = clone(rhs); // safe copy | |
newrhs.ind = (byte) -newrhs.ind; // prepare to subtract | |
return this.add(newrhs, set); // arithmetic | |
} | |
/* ---------------------------------------------------------------- */ | |
/* Other methods */ | |
/* ---------------------------------------------------------------- */ | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>byte</code>. If the <code>BigDecimal</code> has a non-zero | |
* decimal part or is out of the possible range for a <code>byte</code> (8-bit signed integer) result then an <code> | |
* ArithmeticException</code> is thrown. | |
* | |
* @return A <code>byte</code> equal in value to <code>this</code>. | |
* @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>byte</code>. | |
* @stable ICU 2.0 | |
*/ | |
public byte byteValueExact() { | |
int num; | |
num = this.intValueExact(); // will check decimal part too | |
if ((num > 127) | (num < (-128))) | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString()); | |
return (byte) num; | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>double</code>. If the <code>BigDecimal</code> is out of the | |
* possible range for a <code>double</code> (64-bit signed floating point) result then an <code>ArithmeticException | |
* </code> is thrown. | |
* <p> | |
* The double produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and | |
* then converting it using the <code>Double(String)</code> constructor; this can result in values of <code> | |
* Double.NEGATIVE_INFINITY</code> or <code>Double.POSITIVE_INFINITY</code>. | |
* | |
* @return A <code>double</code> corresponding to <code>this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public double doubleValue() { | |
// We go via a String [as does BigDecimal in JDK 1.2] | |
// Next line could possibly raise NumberFormatException | |
return java.lang.Double.valueOf(this.toString()).doubleValue(); | |
} | |
/** | |
* Compares this <code>BigDecimal</code> with <code>rhs</code> for equality. | |
* <p> | |
* If the parameter is <code>null</code>, or is not an instance of the BigDecimal type, or is not exactly equal to | |
* the current <code>BigDecimal</code> object, then <i>false</i> is returned. Otherwise, <i>true</i> is returned. | |
* <p> | |
* "Exactly equal", here, means that the <code>String</code> representations of the <code>BigDecimal</code> numbers | |
* are identical (they have the same characters in the same sequence). | |
* <p> | |
* The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons. | |
* | |
* @param obj The <code>Object</code> for the right hand side of the comparison. | |
* @return A <code>boolean</code> whose value <i>true</i> if and only if the operands have identical string | |
* representations. | |
* @throws ClassCastException if <code>rhs</code> cannot be cast to a <code>BigDecimal</code> object. | |
* @stable ICU 2.0 | |
* @see #compareTo(BigDecimal) | |
* @see #compareTo(BigDecimal, MathContext) | |
*/ | |
public boolean equals(java.lang.Object obj) { | |
com.ibm.icu.math.BigDecimal rhs; | |
int i = 0; | |
char lca[] = null; | |
char rca[] = null; | |
// We are equal iff toString of both are exactly the same | |
if (obj == null) | |
return false; // not equal | |
if ((!(((obj instanceof com.ibm.icu.math.BigDecimal))))) | |
return false; // not a decimal | |
rhs = (com.ibm.icu.math.BigDecimal) obj; // cast; we know it will work | |
if (this.ind != rhs.ind) | |
return false; // different signs never match | |
if (((this.mant.length == rhs.mant.length) & (this.exp == rhs.exp)) & (this.form == rhs.form)) | |
{ // mantissas say all | |
// here with equal-length byte arrays to compare | |
{ | |
int $8 = this.mant.length; | |
i = 0; | |
for (; $8 > 0; $8--, i++) { | |
if (this.mant[i] != rhs.mant[i]) | |
return false; | |
} | |
}/* i */ | |
} else { // need proper layout | |
lca = this.layout(); // layout to character array | |
rca = rhs.layout(); | |
if (lca.length != rca.length) | |
return false; // mismatch | |
// here with equal-length character arrays to compare | |
{ | |
int $9 = lca.length; | |
i = 0; | |
for (; $9 > 0; $9--, i++) { | |
if (lca[i] != rca[i]) | |
return false; | |
} | |
}/* i */ | |
} | |
return true; // arrays have identical content | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>float</code>. If the <code>BigDecimal</code> is out of the | |
* possible range for a <code>float</code> (32-bit signed floating point) result then an <code>ArithmeticException | |
* </code> is thrown. | |
* <p> | |
* The float produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and | |
* then converting it using the <code>Float(String)</code> constructor; this can result in values of <code> | |
* Float.NEGATIVE_INFINITY</code> or <code>Float.POSITIVE_INFINITY</code>. | |
* | |
* @return A <code>float</code> corresponding to <code>this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public float floatValue() { | |
return java.lang.Float.valueOf(this.toString()).floatValue(); | |
} | |
/** | |
* Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters. | |
* <p> | |
* <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat | |
* </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a | |
* necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules | |
* for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class. | |
* </i> | |
* <p> | |
* The parameters, for both forms of the <code>format</code> method are all of type <code>int</code>. A value of -1 | |
* for any parameter indicates that the default action or value for that parameter should be used. | |
* <p> | |
* The parameters, <code>before</code> and <code>after</code>, specify the number of characters to be used for the | |
* integer part and decimal part of the result respectively. Exponential notation is not used. If either parameter | |
* is -1 (which indicates the default action), the number of characters used will be exactly as many as are needed | |
* for that part. | |
* <p> | |
* <code>before</code> must be a positive number; if it is larger than is needed to contain the integer part, that | |
* part is padded on the left with blanks to the requested length. If <code>before</code> is not large enough to | |
* contain the integer part of the number (including the sign, for negative numbers) an exception is thrown. | |
* <p> | |
* <code>after</code> must be a non-negative number; if it is not the same size as the decimal part of the number, | |
* the number will be rounded (or extended with zeros) to fit. Specifying 0 for <code>after</code> will cause the | |
* number to be rounded to an integer (that is, it will have no decimal part or decimal point). The rounding method | |
* will be the default, <code>MathContext.ROUND_HALF_UP</code>. | |
* <p> | |
* Other rounding methods, and the use of exponential notation, can be selected by using | |
* {@link #format(int,int,int,int,int,int)}. Using the two-parameter form of the method has exactly the same effect | |
* as using the six-parameter form with the final four parameters all being -1. | |
* | |
* @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as are needed'. | |
* @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as are needed'. | |
* @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified parameters | |
* @throws ArithmeticException if the number cannot be laid out as requested. | |
* @throws IllegalArgumentException if a parameter is out of range. | |
* @stable ICU 2.0 | |
* @see #toString | |
* @see #toCharArray | |
*/ | |
public java.lang.String format(int before, int after) { | |
return format(before, after, -1, -1, com.ibm.icu.math.MathContext.SCIENTIFIC, ROUND_HALF_UP); | |
} | |
/** | |
* Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters and | |
* allowing exponential notation. | |
* <p> | |
* <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat | |
* </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a | |
* necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules | |
* for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class. | |
* </i> | |
* <p> | |
* The parameters are all of type <code>int</code>. A value of -1 for any parameter indicates that the default | |
* action or value for that parameter should be used. | |
* <p> | |
* The first two parameters (<code>before</code> and <code>after</code>) specify the number of characters to be used | |
* for the integer part and decimal part of the result respectively, as defined for {@link #format(int,int)}. If | |
* either of these is -1 (which indicates the default action), the number of characters used will be exactly as many | |
* as are needed for that part. | |
* <p> | |
* The remaining parameters control the use of exponential notation and rounding. Three (<code>explaces</code>, | |
* <code>exdigits</code>, and <code>exform</code>) control the exponent part of the result. As before, the default | |
* action for any of these parameters may be selected by using the value -1. | |
* <p> | |
* <code>explaces</code> must be a positive number; it sets the number of places (digits after the sign of the | |
* exponent) to be used for any exponent part, the default (when <code>explaces</code> is -1) being to use as many | |
* as are needed. If <code>explaces</code> is not -1, space is always reserved for an exponent; if one is not needed | |
* (for example, if the exponent will be 0) then <code>explaces</code>+2 blanks are appended to the result. <!-- | |
* (This preserves vertical alignment of similarly formatted numbers in a monospace font.) --> If <code>explaces | |
* </code> is not -1 and is not large enough to contain the exponent, an exception is thrown. | |
* <p> | |
* <code>exdigits</code> sets the trigger point for use of exponential notation. If, before any rounding, the number | |
* of places needed before the decimal point exceeds <code>exdigits</code>, or if the absolute value of the result | |
* is less than <code>0.000001</code>, then exponential form will be used, provided that <code>exdigits</code> was | |
* specified. When <code>exdigits</code> is -1, exponential notation will never be used. If 0 is specified for | |
* <code>exdigits</code>, exponential notation is always used unless the exponent would be 0. | |
* <p> | |
* <code>exform</code> sets the form for exponential notation (if needed). It may be either | |
* {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}. If the latter, engineering, form is requested, | |
* up to three digits (plus sign, if negative) may be needed for the integer part of the result (<code>before</code> | |
* ). Otherwise, only one digit (plus sign, if negative) is needed. | |
* <p> | |
* Finally, the sixth argument, <code>exround</code>, selects the rounding algorithm to be used, and must be one of | |
* the values indicated by a public constant in the {@link MathContext} class whose name starts with <code>ROUND_ | |
* </code>. The default (<code>ROUND_HALF_UP</code>) may also be selected by using the value -1, as before. | |
* <p> | |
* The special value <code>MathContext.ROUND_UNNECESSARY</code> may be used to detect whether non-zero digits are | |
* discarded -- if <code>exround</code> has this value than if non-zero digits would be discarded (rounded) during | |
* formatting then an <code>ArithmeticException</code> is thrown. | |
* | |
* @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as | |
* are needed'. | |
* @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as | |
* are needed'. | |
* @param explaces The <code>int</code> specifying the number of places to be used for any exponent. Use -1 for 'as many | |
* as are needed'. | |
* @param exdigits The <code>int</code> specifying the trigger (digits before the decimal point) which if exceeded causes | |
* exponential notation to be used. Use 0 to force exponential notation. Use -1 to force plain notation | |
* (no exponential notation). | |
* @param exformint The <code>int</code> specifying the form of exponential notation to be used ( | |
* {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}). | |
* @param exround The <code>int</code> specifying the rounding mode to use. Use -1 for the default, | |
* {@link MathContext#ROUND_HALF_UP}. | |
* @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified | |
* parameters | |
* @throws ArithmeticException if the number cannot be laid out as requested. | |
* @throws IllegalArgumentException if a parameter is out of range. | |
* @see #toString | |
* @see #toCharArray | |
* @stable ICU 2.0 | |
*/ | |
public java.lang.String format(int before, int after, int explaces, int exdigits, int exformint, int exround) { | |
com.ibm.icu.math.BigDecimal num; | |
int mag = 0; | |
int thisafter = 0; | |
int lead = 0; | |
byte newmant[] = null; | |
int chop = 0; | |
int need = 0; | |
int oldexp = 0; | |
char a[]; | |
int p = 0; | |
char newa[] = null; | |
int i = 0; | |
int places = 0; | |
/* Check arguments */ | |
if ((before < (-1)) | (before == 0)) | |
badarg("format", 1, java.lang.String.valueOf(before)); | |
if (after < (-1)) | |
badarg("format", 2, java.lang.String.valueOf(after)); | |
if ((explaces < (-1)) | (explaces == 0)) | |
badarg("format", 3, java.lang.String.valueOf(explaces)); | |
if (exdigits < (-1)) | |
badarg("format", 4, java.lang.String.valueOf(explaces)); | |
{/* select */ | |
if (exformint == com.ibm.icu.math.MathContext.SCIENTIFIC) { | |
} else if (exformint == com.ibm.icu.math.MathContext.ENGINEERING) { | |
} else if (exformint == (-1)) | |
exformint = com.ibm.icu.math.MathContext.SCIENTIFIC; | |
// note PLAIN isn't allowed | |
else { | |
badarg("format", 5, java.lang.String.valueOf(exformint)); | |
} | |
} | |
// checking the rounding mode is done by trying to construct a | |
// MathContext object with that mode; it will fail if bad | |
if (exround != ROUND_HALF_UP) { | |
try { // if non-default... | |
if (exround == (-1)) | |
exround = ROUND_HALF_UP; | |
else | |
new com.ibm.icu.math.MathContext(9, com.ibm.icu.math.MathContext.SCIENTIFIC, false, exround); | |
} catch (java.lang.IllegalArgumentException $10) { | |
badarg("format", 6, java.lang.String.valueOf(exround)); | |
} | |
} | |
num = clone(this); // make private copy | |
/* | |
* Here: num is BigDecimal to format before is places before point [>0] after is places after point [>=0] | |
* explaces is exponent places [>0] exdigits is exponent digits [>=0] exformint is exponent form [one of two] | |
* exround is rounding mode [one of eight] 'before' through 'exdigits' are -1 if not specified | |
*/ | |
/* determine form */ | |
{ | |
do {/* select */ | |
if (exdigits == (-1)) | |
num.form = (byte) com.ibm.icu.math.MathContext.PLAIN; | |
else if (num.ind == iszero) | |
num.form = (byte) com.ibm.icu.math.MathContext.PLAIN; | |
else { | |
// determine whether triggers | |
mag = num.exp + num.mant.length; | |
if (mag > exdigits) | |
num.form = (byte) exformint; | |
else if (mag < (-5)) | |
num.form = (byte) exformint; | |
else | |
num.form = (byte) com.ibm.icu.math.MathContext.PLAIN; | |
} | |
} while (false); | |
}/* setform */ | |
/* | |
* If 'after' was specified then we may need to adjust the mantissa. This is a little tricky, as we must conform | |
* to the rules of exponential layout if necessary (e.g., we cannot end up with 10.0 if scientific). | |
*/ | |
if (after >= 0) { | |
setafter: for (;;) { | |
// calculate the current after-length | |
{/* select */ | |
if (num.form == com.ibm.icu.math.MathContext.PLAIN) | |
thisafter = -num.exp; // has decimal part | |
else if (num.form == com.ibm.icu.math.MathContext.SCIENTIFIC) | |
thisafter = num.mant.length - 1; | |
else { // engineering | |
lead = (((num.exp + num.mant.length) - 1)) % 3; // exponent to use | |
if (lead < 0) | |
lead = 3 + lead; // negative exponent case | |
lead++; // number of leading digits | |
if (lead >= num.mant.length) | |
thisafter = 0; | |
else | |
thisafter = num.mant.length - lead; | |
} | |
} | |
if (thisafter == after) | |
break setafter; // we're in luck | |
if (thisafter < after) { // need added trailing zeros | |
// [thisafter can be negative] | |
newmant = extend(num.mant, (num.mant.length + after) - thisafter); | |
num.mant = newmant; | |
num.exp = num.exp - ((after - thisafter)); // adjust exponent | |
if (num.exp < MinExp) | |
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + num.exp); | |
break setafter; | |
} | |
// We have too many digits after the decimal point; this could | |
// cause a carry, which could change the mantissa... | |
// Watch out for implied leading zeros in PLAIN case | |
chop = thisafter - after; // digits to lop [is >0] | |
if (chop > num.mant.length) { // all digits go, no chance of carry | |
// carry on with zero | |
num.mant = ZERO.mant; | |
num.ind = iszero; | |
num.exp = 0; | |
continue setafter; // recheck: we may need trailing zeros | |
} | |
// we have a digit to inspect from existing mantissa | |
// round the number as required | |
need = num.mant.length - chop; // digits to end up with [may be 0] | |
oldexp = num.exp; // save old exponent | |
num.round(need, exround); | |
// if the exponent grew by more than the digits we chopped, then | |
// we must have had a carry, so will need to recheck the layout | |
if ((num.exp - oldexp) == chop) | |
break setafter; // number did not have carry | |
// mantissa got extended .. so go around and check again | |
} | |
}/* setafter */ | |
a = num.layout(); // lay out, with exponent if required, etc. | |
/* Here we have laid-out number in 'a' */ | |
// now apply 'before' and 'explaces' as needed | |
if (before > 0) { | |
// look for '.' or 'E' | |
{ | |
int $11 = a.length; | |
p = 0; | |
p: for (; $11 > 0; $11--, p++) { | |
if (a[p] == '.') | |
break p; | |
if (a[p] == 'E') | |
break p; | |
} | |
}/* p */ | |
// p is now offset of '.', 'E', or character after end of array | |
// that is, the current length of before part | |
if (p > before) | |
badarg("format", 1, java.lang.String.valueOf(before)); // won't fit | |
if (p < before) { // need leading blanks | |
newa = new char[(a.length + before) - p]; | |
{ | |
int $12 = before - p; | |
i = 0; | |
for (; $12 > 0; $12--, i++) { | |
newa[i] = ' '; | |
} | |
}/* i */ | |
java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, i, a.length); | |
a = newa; | |
} | |
// [if p=before then it's just the right length] | |
} | |
if (explaces > 0) { | |
// look for 'E' [cannot be at offset 0] | |
{ | |
int $13 = a.length - 1; | |
p = a.length - 1; | |
p: for (; $13 > 0; $13--, p--) { | |
if (a[p] == 'E') | |
break p; | |
} | |
}/* p */ | |
// p is now offset of 'E', or 0 | |
if (p == 0) { // no E part; add trailing blanks | |
newa = new char[(a.length + explaces) + 2]; | |
java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, a.length); | |
{ | |
int $14 = explaces + 2; | |
i = a.length; | |
for (; $14 > 0; $14--, i++) { | |
newa[i] = ' '; | |
} | |
}/* i */ | |
a = newa; | |
} else {/* found E */// may need to insert zeros | |
places = (a.length - p) - 2; // number so far | |
if (places > explaces) | |
badarg("format", 3, java.lang.String.valueOf(explaces)); | |
if (places < explaces) { // need to insert zeros | |
newa = new char[(a.length + explaces) - places]; | |
java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, p + 2); // through E | |
// and sign | |
{ | |
int $15 = explaces - places; | |
i = p + 2; | |
for (; $15 > 0; $15--, i++) { | |
newa[i] = '0'; | |
} | |
}/* i */ | |
java.lang.System.arraycopy((java.lang.Object) a, p + 2, (java.lang.Object) newa, i, places); // remainder | |
// of | |
// exponent | |
a = newa; | |
} | |
// [if places=explaces then it's just the right length] | |
} | |
} | |
return new java.lang.String(a); | |
} | |
/** | |
* Returns the hashcode for this <code>BigDecimal</code>. This hashcode is suitable for use by the <code> | |
* java.util.Hashtable</code> class. | |
* <p> | |
* Note that two <code>BigDecimal</code> objects are only guaranteed to produce the same hashcode if they are | |
* exactly equal (that is, the <code>String</code> representations of the <code>BigDecimal</code> numbers are | |
* identical -- they have the same characters in the same sequence). | |
* | |
* @return An <code>int</code> that is the hashcode for <code>this</code>. | |
* @stable ICU 2.0 | |
*/ | |
public int hashCode() { | |
// Maybe calculate ourselves, later. If so, note that there can be | |
// more than one internal representation for a given toString() result. | |
return this.toString().hashCode(); | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero | |
* decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for an <code>int</code> | |
* (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be | |
* <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact} | |
* method. | |
* | |
* @return An <code>int</code> converted from <code>this</code>, truncated and decapitated if necessary. | |
* @stable ICU 2.0 | |
*/ | |
public int intValue() { | |
return toBigInteger().intValue(); | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero | |
* decimal part or is out of the possible range for an <code>int</code> (32-bit signed integer) result then an | |
* <code>ArithmeticException</code> is thrown. | |
* | |
* @return An <code>int</code> equal in value to <code>this</code>. | |
* @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in an <code>int</code>. | |
* @stable ICU 2.0 | |
*/ | |
public int intValueExact() { | |
int lodigit; | |
int useexp = 0; | |
int result; | |
int i = 0; | |
int topdig = 0; | |
// This does not use longValueExact() as the latter can be much | |
// slower. | |
// intcheck (from pow) relies on this to check decimal part | |
if (ind == iszero) | |
return 0; // easy, and quite common | |
/* test and drop any trailing decimal part */ | |
lodigit = mant.length - 1; | |
if (exp < 0) { | |
lodigit = lodigit + exp; // reduces by -(-exp) | |
/* all decimal places must be 0 */ | |
if ((!(allzero(mant, lodigit + 1)))) | |
throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString()); | |
if (lodigit < 0) | |
return 0; // -1<this<1 | |
useexp = 0; | |
} else {/* >=0 */ | |
if ((exp + lodigit) > 9) // early exit | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString()); | |
useexp = exp; | |
} | |
/* convert the mantissa to binary, inline for speed */ | |
result = 0; | |
{ | |
int $16 = lodigit + useexp; | |
i = 0; | |
for (; i <= $16; i++) { | |
result = result * 10; | |
if (i <= lodigit) | |
result = result + mant[i]; | |
} | |
}/* i */ | |
/* Now, if the risky length, check for overflow */ | |
if ((lodigit + useexp) == 9) { | |
// note we cannot just test for -ve result, as overflow can move a | |
// zero into the top bit [consider 5555555555] | |
topdig = result / 1000000000; // get top digit, preserving sign | |
if (topdig != mant[0]) { // digit must match and be positive | |
// except in the special case ... | |
if (result == java.lang.Integer.MIN_VALUE) // looks like the special | |
if (ind == isneg) // really was negative | |
if (mant[0] == 2) | |
return result; // really had top digit 2 | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString()); | |
} | |
} | |
/* Looks good */ | |
if (ind == ispos) | |
return result; | |
return -result; | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero | |
* decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for a <code>long</code> | |
* (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be | |
* <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact} | |
* method. | |
* | |
* @return A <code>long</code> converted from <code>this</code>, truncated and decapitated if necessary. | |
* @stable ICU 2.0 | |
*/ | |
public long longValue() { | |
return toBigInteger().longValue(); | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero | |
* decimal part or is out of the possible range for a <code>long</code> (64-bit signed integer) result then an | |
* <code>ArithmeticException</code> is thrown. | |
* | |
* @return A <code>long</code> equal in value to <code>this</code>. | |
* @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>long</code>. | |
* @stable ICU 2.0 | |
*/ | |
public long longValueExact() { | |
int lodigit; | |
int cstart = 0; | |
int useexp = 0; | |
long result; | |
int i = 0; | |
long topdig = 0; | |
// Identical to intValueExact except for result=long, and exp>=20 test | |
if (ind == 0) | |
return 0; // easy, and quite common | |
lodigit = mant.length - 1; // last included digit | |
if (exp < 0) { | |
lodigit = lodigit + exp; // -(-exp) | |
/* all decimal places must be 0 */ | |
if (lodigit < 0) | |
cstart = 0; | |
else | |
cstart = lodigit + 1; | |
if ((!(allzero(mant, cstart)))) | |
throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString()); | |
if (lodigit < 0) | |
return 0; // -1<this<1 | |
useexp = 0; | |
} else {/* >=0 */ | |
if ((exp + mant.length) > 18) // early exit | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString()); | |
useexp = exp; | |
} | |
/* convert the mantissa to binary, inline for speed */ | |
// note that we could safely use the 'test for wrap to negative' | |
// algorithm here, but instead we parallel the intValueExact | |
// algorithm for ease of checking and maintenance. | |
result = (long) 0; | |
{ | |
int $17 = lodigit + useexp; | |
i = 0; | |
for (; i <= $17; i++) { | |
result = result * 10; | |
if (i <= lodigit) | |
result = result + mant[i]; | |
} | |
}/* i */ | |
/* Now, if the risky length, check for overflow */ | |
if ((lodigit + useexp) == 18) { | |
topdig = result / 1000000000000000000L; // get top digit, preserving sign | |
if (topdig != mant[0]) { // digit must match and be positive | |
// except in the special case ... | |
if (result == java.lang.Long.MIN_VALUE) // looks like the special | |
if (ind == isneg) // really was negative | |
if (mant[0] == 9) | |
return result; // really had top digit 9 | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString()); | |
} | |
} | |
/* Looks good */ | |
if (ind == ispos) | |
return result; | |
return -result; | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the left by a specified number of | |
* positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is, | |
* if <code>n</code> is 0 or positive, the number returned is given by: | |
* <p> | |
* <code> this.multiply(TEN.pow(new BigDecimal(-n))) </code> | |
* <p> | |
* <code>n</code> may be negative, in which case the method returns the same result as <code>movePointRight(-n) | |
* </code>. | |
* | |
* @param n The <code>int</code> specifying the number of places to move the decimal point leftwards. | |
* @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code> | |
* places to the left. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal movePointLeft(int n) { | |
com.ibm.icu.math.BigDecimal res; | |
// very little point in optimizing for shift of 0 | |
res = clone(this); | |
res.exp = res.exp - n; | |
return res.finish(plainMC, false); // finish sets form and checks exponent | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the right by a specified number of | |
* positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is, | |
* if <code>n</code> is 0 or positive, the number returned is given by: | |
* <p> | |
* <code> this.multiply(TEN.pow(new BigDecimal(n))) </code> | |
* <p> | |
* <code>n</code> may be negative, in which case the method returns the same result as <code>movePointLeft(-n) | |
* </code>. | |
* | |
* @param n The <code>int</code> specifying the number of places to move the decimal point rightwards. | |
* @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code> | |
* places to the right. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal movePointRight(int n) { | |
com.ibm.icu.math.BigDecimal res; | |
res = clone(this); | |
res.exp = res.exp + n; | |
return res.finish(plainMC, false); | |
} | |
/** | |
* Returns the scale of this <code>BigDecimal</code>. Returns a non-negative <code>int</code> which is the scale of | |
* the number. The scale is the number of digits in the decimal part of the number if the number were formatted | |
* without exponential notation. | |
* | |
* @return An <code>int</code> whose value is the scale of this <code>BigDecimal</code>. | |
* @stable ICU 2.0 | |
*/ | |
public int scale() { | |
if (exp >= 0) | |
return 0; // scale can never be negative | |
return -exp; | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> with a given scale. | |
* <p> | |
* If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part | |
* (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary. | |
* <p> | |
* If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then | |
* trailing digits will be removed, and in this case an <code>ArithmeticException</code> is thrown if any discarded | |
* digits are non-zero. | |
* <p> | |
* The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is <code> | |
* MathContext.ROUND_UNNECESSARY</code>. | |
* | |
* @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>. | |
* @return A plain <code>BigDecimal</code> with the given scale. | |
* @throws ArithmeticException if <code>scale</code> is negative. | |
* @throws ArithmeticException if reducing scale would discard non-zero digits. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal setScale(int scale) { | |
return setScale(scale, ROUND_UNNECESSARY); | |
} | |
/** | |
* Returns a plain <code>BigDecimal</code> with a given scale. | |
* <p> | |
* If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part | |
* (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary. | |
* <p> | |
* If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then | |
* trailing digits will be removed, and the rounding mode given by the second parameter is used to determine if the | |
* remaining digits are affected by a carry. In this case, an <code>IllegalArgumentException</code> is thrown if | |
* <code>round</code> is not a valid rounding mode. | |
* <p> | |
* If <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, an <code>ArithmeticException</code> is | |
* thrown if any discarded digits are non-zero. | |
* | |
* @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>. | |
* @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class). | |
* @return A plain <code>BigDecimal</code> with the given scale. | |
* @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode. | |
* @throws ArithmeticException if <code>scale</code> is negative. | |
* @throws ArithmeticException if <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, and reducing scale would discard | |
* non-zero digits. | |
* @stable ICU 2.0 | |
*/ | |
public com.ibm.icu.math.BigDecimal setScale(int scale, int round) { | |
int ourscale; | |
com.ibm.icu.math.BigDecimal res; | |
int padding = 0; | |
int newlen = 0; | |
// at present this naughtily only checks the round value if it is | |
// needed (used), for speed | |
ourscale = this.scale(); | |
if (ourscale == scale) // already correct scale | |
if (this.form == com.ibm.icu.math.MathContext.PLAIN) // .. and form | |
return this; | |
res = clone(this); // need copy | |
if (ourscale <= scale) { // simply zero-padding/changing form | |
// if ourscale is 0 we may have lots of 0s to add | |
if (ourscale == 0) | |
padding = res.exp + scale; | |
else | |
padding = scale - ourscale; | |
res.mant = extend(res.mant, res.mant.length + padding); | |
res.exp = -scale; // as requested | |
} else {/* ourscale>scale: shortening, probably */ | |
if (scale < 0) | |
throw new java.lang.ArithmeticException("Negative scale:" + " " + scale); | |
// [round() will raise exception if invalid round] | |
newlen = res.mant.length - ((ourscale - scale)); // [<=0 is OK] | |
res = res.round(newlen, round); // round to required length | |
// This could have shifted left if round (say) 0.9->1[.0] | |
// Repair if so by adding a zero and reducing exponent | |
if (res.exp != -scale) { | |
res.mant = extend(res.mant, res.mant.length + 1); | |
res.exp = res.exp - 1; | |
} | |
} | |
res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // by definition | |
return res; | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>short</code>. If the <code>BigDecimal</code> has a non-zero | |
* decimal part or is out of the possible range for a <code>short</code> (16-bit signed integer) result then an | |
* <code>ArithmeticException</code> is thrown. | |
* | |
* @return A <code>short</code> equal in value to <code>this</code>. | |
* @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>short</code>. | |
* @stable ICU 2.0 | |
*/ | |
public short shortValueExact() { | |
int num; | |
num = this.intValueExact(); // will check decimal part too | |
if ((num > 32767) | (num < (-32768))) | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString()); | |
return (short) num; | |
} | |
/** | |
* Returns the sign of this <code>BigDecimal</code>, as an <code>int</code>. This returns the <i>signum</i> function | |
* value that represents the sign of this <code>BigDecimal</code>. That is, -1 if the <code>BigDecimal</code> is | |
* negative, 0 if it is numerically equal to zero, or 1 if it is positive. | |
* | |
* @return An <code>int</code> which is -1 if the <code>BigDecimal</code> is negative, 0 if it is numerically equal | |
* to zero, or 1 if it is positive. | |
* @stable ICU 2.0 | |
*/ | |
public int signum() { | |
return (int) this.ind; // [note this assumes values for ind.] | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>java.math.BigDecimal</code>. | |
* <p> | |
* This is an exact conversion; the result is the same as if the <code>BigDecimal</code> were formatted as a plain | |
* number without any rounding or exponent and then the <code>java.math.BigDecimal(java.lang.String)</code> | |
* constructor were used to construct the result. | |
* <p> | |
* <i>(Note: this method is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class. It | |
* would not be present in a <code>java.math</code> version.)</i> | |
* | |
* @return The <code>java.math.BigDecimal</code> equal in value to this <code>BigDecimal</code>. | |
* @stable ICU 2.0 | |
*/ | |
public java.math.BigDecimal toBigDecimal() { | |
return new java.math.BigDecimal(this.unscaledValue(), this.scale()); | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>. | |
* <p> | |
* Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use | |
* {@link #toBigIntegerExact()}. | |
* | |
* @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>. | |
* @stable ICU 2.0 | |
*/ | |
public java.math.BigInteger toBigInteger() { | |
com.ibm.icu.math.BigDecimal res = null; | |
int newlen = 0; | |
byte newmant[] = null; | |
{/* select */ | |
if ((exp >= 0) & (form == com.ibm.icu.math.MathContext.PLAIN)) | |
res = this; // can layout simply | |
else if (exp >= 0) { | |
res = clone(this); // safe copy | |
res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // .. and request PLAIN | |
} else { | |
{ // exp<0; scale to be truncated | |
// we could use divideInteger, but we may as well be quicker | |
if (-this.exp >= this.mant.length) | |
res = ZERO; // all blows away | |
else { | |
res = clone(this); // safe copy | |
newlen = res.mant.length + res.exp; | |
newmant = new byte[newlen]; // [shorter] | |
java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0, | |
newlen); | |
res.mant = newmant; | |
res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; | |
res.exp = 0; | |
} | |
} | |
} | |
} | |
return new BigInteger(new java.lang.String(res.layout())); | |
} | |
/** | |
* Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>. | |
* <p> | |
* An exception is thrown if the decimal part (if any) is non-zero. | |
* | |
* @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>. | |
* @throws ArithmeticException if <code>this</code> has a non-zero decimal part. | |
* @stable ICU 2.0 | |
*/ | |
public java.math.BigInteger toBigIntegerExact() { | |
/* test any trailing decimal part */ | |
if (exp < 0) { // possible decimal part | |
/* all decimal places must be 0; note exp<0 */ | |
if ((!(allzero(mant, mant.length + exp)))) | |
throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString()); | |
} | |
return toBigInteger(); | |
} | |
/** | |
* Returns the <code>BigDecimal</code> as a character array. The result of this method is the same as using the | |
* sequence <code>toString().toCharArray()</code>, but avoids creating the intermediate <code>String</code> and | |
* <code>char[]</code> objects. | |
* | |
* @return The <code>char[]</code> array corresponding to this <code>BigDecimal</code>. | |
* @stable ICU 2.0 | |
*/ | |
public char[] toCharArray() { | |
return layout(); | |
} | |
/** | |
* Returns the <code>BigDecimal</code> as a <code>String</code>. This returns a <code>String</code> that exactly | |
* represents this <code>BigDecimal</code>, as defined in the decimal documentation (see {@link BigDecimal class | |
* header}). | |
* <p> | |
* By definition, using the {@link #BigDecimal(String)} constructor on the result <code>String</code> will create a | |
* <code>BigDecimal</code> that is exactly equal to the original <code>BigDecimal</code>. | |
* | |
* @return The <code>String</code> exactly corresponding to this <code>BigDecimal</code>. | |
* @see #format(int, int) | |
* @see #format(int, int, int, int, int, int) | |
* @see #toCharArray() | |
* @stable ICU 2.0 | |
*/ | |
public java.lang.String toString() { | |
return new java.lang.String(layout()); | |
} | |
/** | |
* Returns the number as a <code>BigInteger</code> after removing the scale. That is, the number is expressed as a | |
* plain number, any decimal point is then removed (retaining the digits of any decimal part), and the result is | |
* then converted to a <code>BigInteger</code>. | |
* | |
* @return The <code>java.math.BigInteger</code> equal in value to this <code>BigDecimal</code> multiplied by ten to | |
* the power of <code>this.scale()</code>. | |
* @stable ICU 2.0 | |
*/ | |
public java.math.BigInteger unscaledValue() { | |
com.ibm.icu.math.BigDecimal res = null; | |
if (exp >= 0) | |
res = this; | |
else { | |
res = clone(this); // safe copy | |
res.exp = 0; // drop scale | |
} | |
return res.toBigInteger(); | |
} | |
/** | |
* Translates a <code>double</code> to a <code>BigDecimal</code>. | |
* <p> | |
* Returns a <code>BigDecimal</code> which is the decimal representation of the 64-bit signed binary floating point | |
* parameter. If the parameter is infinite, or is not a number (NaN), a <code>NumberFormatException</code> is | |
* thrown. | |
* <p> | |
* The number is constructed as though <code>num</code> had been converted to a <code>String</code> using the <code> | |
* Double.toString()</code> method and the {@link #BigDecimal(java.lang.String)} constructor had then been used. | |
* This is typically not an exact conversion. | |
* | |
* @param dub The <code>double</code> to be translated. | |
* @return The <code>BigDecimal</code> equal in value to <code>dub</code>. | |
* @throws NumberFormatException if the parameter is infinite or not a number. | |
* @stable ICU 2.0 | |
*/ | |
public static com.ibm.icu.math.BigDecimal valueOf(double dub) { | |
// Reminder: a zero double returns '0.0', so we cannot fastpath to | |
// use the constant ZERO. This might be important enough to justify | |
// a factory approach, a cache, or a few private constants, later. | |
return new com.ibm.icu.math.BigDecimal((new java.lang.Double(dub)).toString()); | |
} | |
/** | |
* Translates a <code>long</code> to a <code>BigDecimal</code>. That is, returns a plain <code>BigDecimal</code> | |
* whose value is equal to the given <code>long</code>. | |
* | |
* @param lint The <code>long</code> to be translated. | |
* @return The <code>BigDecimal</code> equal in value to <code>lint</code>. | |
* @stable ICU 2.0 | |
*/ | |
public static com.ibm.icu.math.BigDecimal valueOf(long lint) { | |
return valueOf(lint, 0); | |
} | |
/** | |
* Translates a <code>long</code> to a <code>BigDecimal</code> with a given scale. That is, returns a plain <code> | |
* BigDecimal</code> whose unscaled value is equal to the given <code>long</code>, adjusted by the second parameter, | |
* <code>scale</code>. | |
* <p> | |
* The result is given by: | |
* <p> | |
* <code> (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) </code> | |
* <p> | |
* A <code>NumberFormatException</code> is thrown if <code>scale</code> is negative. | |
* | |
* @param lint The <code>long</code> to be translated. | |
* @param scale The <code>int</code> scale to be applied. | |
* @return The <code>BigDecimal</code> equal in value to <code>lint</code>. | |
* @throws NumberFormatException if the scale is negative. | |
* @stable ICU 2.0 | |
*/ | |
public static com.ibm.icu.math.BigDecimal valueOf(long lint, int scale) { | |
com.ibm.icu.math.BigDecimal res = null; | |
{/* select */ | |
if (lint == 0) | |
res = ZERO; | |
else if (lint == 1) | |
res = ONE; | |
else if (lint == 10) | |
res = TEN; | |
else { | |
res = new com.ibm.icu.math.BigDecimal(lint); | |
} | |
} | |
if (scale == 0) | |
return res; | |
if (scale < 0) | |
throw new java.lang.NumberFormatException("Negative scale:" + " " + scale); | |
res = clone(res); // safe copy [do not mutate] | |
res.exp = -scale; // exponent is -scale | |
return res; | |
} | |
/* ---------------------------------------------------------------- */ | |
/* Private methods */ | |
/* ---------------------------------------------------------------- */ | |
/* | |
* <sgml> Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array). | |
* <p>The mantissa will either already have been rounded (following an operation) or will be of length appropriate | |
* (in the case of construction from an int, for example). <p>We must not alter the mantissa, here. <p>'form' | |
* describes whether we are to use exponential notation (and if so, which), or if we are to lay out as a plain/pure | |
* numeric. </sgml> | |
*/ | |
private char[] layout() { | |
char cmant[]; | |
int i = 0; | |
StringBuilder sb = null; | |
int euse = 0; | |
int sig = 0; | |
char csign = 0; | |
char rec[] = null; | |
int needsign; | |
int mag; | |
int len = 0; | |
cmant = new char[mant.length]; // copy byte[] to a char[] | |
{ | |
int $18 = mant.length; | |
i = 0; | |
for (; $18 > 0; $18--, i++) { | |
cmant[i] = (char) (mant[i] + ((int) ('0'))); | |
} | |
}/* i */ | |
if (form != com.ibm.icu.math.MathContext.PLAIN) {/* exponential notation needed */ | |
sb = new StringBuilder(cmant.length + 15); // -x.xxxE+999999999 | |
if (ind == isneg) | |
sb.append('-'); | |
euse = (exp + cmant.length) - 1; // exponent to use | |
/* setup sig=significant digits and copy to result */ | |
if (form == com.ibm.icu.math.MathContext.SCIENTIFIC) { // [default] | |
sb.append(cmant[0]); // significant character | |
if (cmant.length > 1) // have decimal part | |
sb.append('.').append(cmant, 1, cmant.length - 1); | |
} else { | |
do { | |
sig = euse % 3; // common | |
if (sig < 0) | |
sig = 3 + sig; // negative exponent | |
euse = euse - sig; | |
sig++; | |
if (sig >= cmant.length) { // zero padding may be needed | |
sb.append(cmant, 0, cmant.length); | |
{ | |
int $19 = sig - cmant.length; | |
for (; $19 > 0; $19--) { | |
sb.append('0'); | |
} | |
} | |
} else { // decimal point needed | |
sb.append(cmant, 0, sig).append('.').append(cmant, sig, cmant.length - sig); | |
} | |
} while (false); | |
}/* engineering */ | |
if (euse != 0) { | |
if (euse < 0) { | |
csign = '-'; | |
euse = -euse; | |
} else | |
csign = '+'; | |
sb.append('E').append(csign).append(euse); | |
} | |
rec = new char[sb.length()]; | |
int srcEnd = sb.length(); | |
if (0 != srcEnd) { | |
sb.getChars(0, srcEnd, rec, 0); | |
} | |
return rec; | |
} | |
/* Here for non-exponential (plain) notation */ | |
if (exp == 0) {/* easy */ | |
if (ind >= 0) | |
return cmant; // non-negative integer | |
rec = new char[cmant.length + 1]; | |
rec[0] = '-'; | |
java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, 1, cmant.length); | |
return rec; | |
} | |
/* Need a '.' and/or some zeros */ | |
needsign = (ind == isneg) ? 1 : 0; // space for sign? 0 or 1 | |
/* | |
* MAG is the position of the point in the mantissa (index of the character it follows) | |
*/ | |
mag = exp + cmant.length; | |
if (mag < 1) {/* 0.00xxxx form */ | |
len = (needsign + 2) - exp; // needsign+2+(-mag)+cmant.length | |
rec = new char[len]; | |
if (needsign != 0) | |
rec[0] = '-'; | |
rec[needsign] = '0'; | |
rec[needsign + 1] = '.'; | |
{ | |
int $20 = -mag; | |
i = needsign + 2; | |
for (; $20 > 0; $20--, i++) { // maybe none | |
rec[i] = '0'; | |
} | |
}/* i */ | |
java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, (needsign + 2) - mag, | |
cmant.length); | |
return rec; | |
} | |
if (mag > cmant.length) {/* xxxx0000 form */ | |
len = needsign + mag; | |
rec = new char[len]; | |
if (needsign != 0) | |
rec[0] = '-'; | |
java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, cmant.length); | |
{ | |
int $21 = mag - cmant.length; | |
i = needsign + cmant.length; | |
for (; $21 > 0; $21--, i++) { // never 0 | |
rec[i] = '0'; | |
} | |
}/* i */ | |
return rec; | |
} | |
/* decimal point is in the middle of the mantissa */ | |
len = (needsign + 1) + cmant.length; | |
rec = new char[len]; | |
if (needsign != 0) | |
rec[0] = '-'; | |
java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, mag); | |
rec[needsign + mag] = '.'; | |
java.lang.System.arraycopy((java.lang.Object) cmant, mag, (java.lang.Object) rec, (needsign + mag) + 1, | |
cmant.length - mag); | |
return rec; | |
} | |
/* | |
* <sgml> Checks a BigDecimal argument to ensure it's a true integer in a given range. <p>If OK, returns it as an | |
* int. </sgml> | |
*/ | |
// [currently only used by pow] | |
private int intcheck(int min, int max) { | |
int i; | |
i = this.intValueExact(); // [checks for non-0 decimal part] | |
// Use same message as though intValueExact failed due to size | |
if ((i < min) | (i > max)) | |
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + i); | |
return i; | |
} | |
/* <sgml> Carry out division operations. </sgml> */ | |
/* | |
* Arg1 is operation code: D=divide, I=integer divide, R=remainder Arg2 is the rhs. Arg3 is the context. Arg4 is | |
* explicit scale iff code='D' or 'I' (-1 if none). | |
* | |
* Underlying algorithm (complications for Remainder function and scaled division are omitted for clarity): | |
* | |
* Test for x/0 and then 0/x Exp =Exp1 - Exp2 Exp =Exp +len(var1) -len(var2) Sign=Sign1 Sign2 Pad accumulator (Var1) | |
* to double-length with 0's (pad1) Pad Var2 to same length as Var1 B2B=1st two digits of var2, +1 to allow for | |
* roundup have=0 Do until (have=digits+1 OR residue=0) if exp<0 then if integer divide/residue then leave | |
* this_digit=0 Do forever compare numbers if <0 then leave inner_loop if =0 then (- quick exit without subtract -) | |
* do this_digit=this_digit+1; output this_digit leave outer_loop; end Compare lengths of numbers (mantissae): If | |
* same then CA=first_digit_of_Var1 else CA=first_two_digits_of_Var1 mult=ca10/b2b -- Good and safe guess at divisor | |
* if mult=0 then mult=1 this_digit=this_digit+mult subtract end inner_loop if have\=0 | this_digit\=0 then do | |
* output this_digit have=have+1; end var2=var2/10 exp=exp-1 end outer_loop exp=exp+1 -- set the proper exponent if | |
* have=0 then generate answer=0 Return to FINISHED Result defined by MATHV1 | |
* | |
* For extended commentary, see DMSRCN. | |
*/ | |
private com.ibm.icu.math.BigDecimal dodivide(char code, com.ibm.icu.math.BigDecimal rhs, | |
com.ibm.icu.math.MathContext set, int scale) { | |
com.ibm.icu.math.BigDecimal lhs; | |
int reqdig; | |
int newexp; | |
com.ibm.icu.math.BigDecimal res; | |
int newlen; | |
byte var1[]; | |
int var1len; | |
byte var2[]; | |
int var2len; | |
int b2b; | |
int have; | |
int thisdigit = 0; | |
int i = 0; | |
byte v2 = 0; | |
int ba = 0; | |
int mult = 0; | |
int start = 0; | |
int padding = 0; | |
int d = 0; | |
byte newvar1[] = null; | |
byte lasthave = 0; | |
int actdig = 0; | |
byte newmant[] = null; | |
if (set.lostDigits) | |
checkdigits(rhs, set.digits); | |
lhs = this; // name for clarity | |
// [note we must have checked lostDigits before the following checks] | |
if (rhs.ind == 0) | |
throw new java.lang.ArithmeticException("Divide by 0"); // includes 0/0 | |
if (lhs.ind == 0) { // 0/x => 0 [possibly with .0s] | |
if (set.form != com.ibm.icu.math.MathContext.PLAIN) | |
return ZERO; | |
if (scale == (-1)) | |
return lhs; | |
return lhs.setScale(scale); | |
} | |
/* Prepare numbers according to BigDecimal rules */ | |
reqdig = set.digits; // local copy (heavily used) | |
if (reqdig > 0) { | |
if (lhs.mant.length > reqdig) | |
lhs = clone(lhs).round(set); | |
if (rhs.mant.length > reqdig) | |
rhs = clone(rhs).round(set); | |
} else {/* scaled divide */ | |
if (scale == (-1)) | |
scale = lhs.scale(); | |
// set reqdig to be at least large enough for the computation | |
reqdig = lhs.mant.length; // base length | |
// next line handles both positive lhs.exp and also scale mismatch | |
if (scale != -lhs.exp) | |
reqdig = (reqdig + scale) + lhs.exp; | |
reqdig = (reqdig - ((rhs.mant.length - 1))) - rhs.exp; // reduce by RHS effect | |
if (reqdig < lhs.mant.length) | |
reqdig = lhs.mant.length; // clamp | |
if (reqdig < rhs.mant.length) | |
reqdig = rhs.mant.length; // .. | |
} | |
/* precalculate exponent */ | |
newexp = ((lhs.exp - rhs.exp) + lhs.mant.length) - rhs.mant.length; | |
/* If new exponent -ve, then some quick exits are possible */ | |
if (newexp < 0) | |
if (code != 'D') { | |
if (code == 'I') | |
return ZERO; // easy - no integer part | |
/* Must be 'R'; remainder is [finished clone of] input value */ | |
return clone(lhs).finish(set, false); | |
} | |
/* We need slow division */ | |
res = new com.ibm.icu.math.BigDecimal(); // where we'll build result | |
res.ind = (byte) (lhs.ind * rhs.ind); // final sign (for D/I) | |
res.exp = newexp; // initial exponent (for D/I) | |
res.mant = new byte[reqdig + 1]; // where build the result | |
/* Now [virtually pad the mantissae with trailing zeros */ | |
// Also copy the LHS, which will be our working array | |
newlen = (reqdig + reqdig) + 1; | |
var1 = extend(lhs.mant, newlen); // always makes longer, so new safe array | |
var1len = newlen; // [remaining digits are 0] | |
var2 = rhs.mant; | |
var2len = newlen; | |
/* Calculate first two digits of rhs (var2), +1 for later estimations */ | |
b2b = (var2[0] * 10) + 1; | |
if (var2.length > 1) | |
b2b = b2b + var2[1]; | |
/* start the long-division loops */ | |
have = 0; | |
{ | |
outer: for (;;) { | |
thisdigit = 0; | |
/* find the next digit */ | |
{ | |
inner: for (;;) { | |
if (var1len < var2len) | |
break inner; // V1 too low | |
if (var1len == var2len) { // compare needed | |
{ | |
compare: do { // comparison | |
{ | |
int $22 = var1len; | |
i = 0; | |
for (; $22 > 0; $22--, i++) { | |
// var1len is always <= var1.length | |
if (i < var2.length) | |
v2 = var2[i]; | |
else | |
v2 = (byte) 0; | |
if (var1[i] < v2) | |
break inner; // V1 too low | |
if (var1[i] > v2) | |
break compare; // OK to subtract | |
} | |
}/* i */ | |
/* | |
* reach here if lhs and rhs are identical; subtraction will increase digit by one, | |
* and the residue will be 0 so we are done; leave the loop with residue set to 0 | |
* (in case code is 'R' or ROUND_UNNECESSARY or a ROUND_HALF_xxxx is being checked) | |
*/ | |
thisdigit++; | |
res.mant[have] = (byte) thisdigit; | |
have++; | |
var1[0] = (byte) 0; // residue to 0 [this is all we'll test] | |
// var1len=1 -- [optimized out] | |
break outer; | |
} while (false); | |
}/* compare */ | |
/* prepare for subtraction. Estimate BA (lengths the same) */ | |
ba = (int) var1[0]; // use only first digit | |
} // lengths the same | |
else {/* lhs longer than rhs */ | |
/* use first two digits for estimate */ | |
ba = var1[0] * 10; | |
if (var1len > 1) | |
ba = ba + var1[1]; | |
} | |
/* subtraction needed; V1>=V2 */ | |
mult = (ba * 10) / b2b; | |
if (mult == 0) | |
mult = 1; | |
thisdigit = thisdigit + mult; | |
// subtract; var1 reusable | |
var1 = byteaddsub(var1, var1len, var2, var2len, -mult, true); | |
if (var1[0] != 0) | |
continue inner; // maybe another subtract needed | |
/* | |
* V1 now probably has leading zeros, remove leading 0's and try again. (It could be longer than | |
* V2) | |
*/ | |
{ | |
int $23 = var1len - 2; | |
start = 0; | |
start: for (; start <= $23; start++) { | |
if (var1[start] != 0) | |
break start; | |
var1len--; | |
} | |
}/* start */ | |
if (start == 0) | |
continue inner; | |
// shift left | |
java.lang.System.arraycopy((java.lang.Object) var1, start, (java.lang.Object) var1, 0, var1len); | |
} | |
}/* inner */ | |
/* We have the next digit */ | |
if ((have != 0) | (thisdigit != 0)) { // put the digit we got | |
res.mant[have] = (byte) thisdigit; | |
have++; | |
if (have == (reqdig + 1)) | |
break outer; // we have all we need | |
if (var1[0] == 0) | |
break outer; // residue now 0 | |
} | |
/* can leave now if a scaled divide and exponent is small enough */ | |
if (scale >= 0) | |
if (-res.exp > scale) | |
break outer; | |
/* can leave now if not Divide and no integer part left */ | |
if (code != 'D') | |
if (res.exp <= 0) | |
break outer; | |
res.exp = res.exp - 1; // reduce the exponent | |
/* | |
* to get here, V1 is less than V2, so divide V2 by 10 and go for the next digit | |
*/ | |
var2len--; | |
} | |
}/* outer */ | |
/* here when we have finished dividing, for some reason */ | |
// have is the number of digits we collected in res.mant | |
if (have == 0) | |
have = 1; // res.mant[0] is 0; we always want a digit | |
if ((code == 'I') | (code == 'R')) {/* check for integer overflow needed */ | |
if ((have + res.exp) > reqdig) | |
throw new java.lang.ArithmeticException("Integer overflow"); | |
if (code == 'R') { | |
do { | |
/* We were doing Remainder -- return the residue */ | |
if (res.mant[0] == 0) // no integer part was found | |
return clone(lhs).finish(set, false); // .. so return lhs, canonical | |
if (var1[0] == 0) | |
return ZERO; // simple 0 residue | |
res.ind = lhs.ind; // sign is always as LHS | |
/* | |
* Calculate the exponent by subtracting the number of padding zeros we added and adding the | |
* original exponent | |
*/ | |
padding = ((reqdig + reqdig) + 1) - lhs.mant.length; | |
res.exp = (res.exp - padding) + lhs.exp; | |
/* | |
* strip insignificant padding zeros from residue, and create/copy the resulting mantissa if need be | |
*/ | |
d = var1len; | |
{ | |
i = d - 1; | |
i: for (; i >= 1; i--) { | |
if (!((res.exp < lhs.exp) & (res.exp < rhs.exp))) | |
break; | |
if (var1[i] != 0) | |
break i; | |
d--; | |
res.exp = res.exp + 1; | |
} | |
}/* i */ | |
if (d < var1.length) {/* need to reduce */ | |
newvar1 = new byte[d]; | |
java.lang.System.arraycopy((java.lang.Object) var1, 0, (java.lang.Object) newvar1, 0, d); // shorten | |
var1 = newvar1; | |
} | |
res.mant = var1; | |
return res.finish(set, false); | |
} while (false); | |
}/* remainder */ | |
} | |
else {/* 'D' -- no overflow check needed */ | |
// If there was a residue then bump the final digit (iff 0 or 5) | |
// so that the residue is visible for ROUND_UP, ROUND_HALF_xxx and | |
// ROUND_UNNECESSARY checks (etc.) later. | |
// [if we finished early, the residue will be 0] | |
if (var1[0] != 0) { // residue not 0 | |
lasthave = res.mant[have - 1]; | |
if (((lasthave % 5)) == 0) | |
res.mant[have - 1] = (byte) (lasthave + 1); | |
} | |
} | |
/* Here for Divide or Integer Divide */ | |
// handle scaled results first ['I' always scale 0, optional for 'D'] | |
if (scale >= 0) { | |
do { | |
// say 'scale have res.exp len' scale have res.exp res.mant.length | |
if (have != res.mant.length) | |
// already padded with 0's, so just adjust exponent | |
res.exp = res.exp - ((res.mant.length - have)); | |
// calculate number of digits we really want [may be 0] | |
actdig = res.mant.length - (-res.exp - scale); | |
res.round(actdig, set.roundingMode); // round to desired length | |
// This could have shifted left if round (say) 0.9->1[.0] | |
// Repair if so by adding a zero and reducing exponent | |
if (res.exp != -scale) { | |
res.mant = extend(res.mant, res.mant.length + 1); | |
res.exp = res.exp - 1; | |
} | |
return res.finish(set, true); // [strip if not PLAIN] | |
} while (false); | |
}/* scaled */ | |
// reach here only if a non-scaled | |
if (have == res.mant.length) { // got digits+1 digits | |
res.round(set); | |
have = reqdig; | |
} else {/* have<=reqdig */ | |
if (res.mant[0] == 0) | |
return ZERO; // fastpath | |
// make the mantissa truly just 'have' long | |
// [we could let finish do this, during strip, if we adjusted | |
// the exponent; however, truncation avoids the strip loop] | |
newmant = new byte[have]; // shorten | |
java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0, have); | |
res.mant = newmant; | |
} | |
return res.finish(set, true); | |
} | |
/* <sgml> Report a conversion exception. </sgml> */ | |
private void bad(char s[]) { | |
throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s)); | |
} | |
/* | |
* <sgml> Report a bad argument to a method. </sgml> Arg1 is method name Arg2 is argument position Arg3 is what was | |
* found | |
*/ | |
private void badarg(java.lang.String name, int pos, java.lang.String value) { | |
throw new java.lang.IllegalArgumentException("Bad argument" + " " + pos + " " + "to" + " " + name + ":" + " " | |
+ value); | |
} | |
/* | |
* <sgml> Extend byte array to given length, padding with 0s. If no extension is required then return the same | |
* array. </sgml> | |
* | |
* Arg1 is the source byte array Arg2 is the new length (longer) | |
*/ | |
private static final byte[] extend(byte inarr[], int newlen) { | |
byte newarr[]; | |
if (inarr.length == newlen) | |
return inarr; | |
newarr = new byte[newlen]; | |
java.lang.System.arraycopy((java.lang.Object) inarr, 0, (java.lang.Object) newarr, 0, inarr.length); | |
// 0 padding is carried out by the JVM on allocation initialization | |
return newarr; | |
} | |
/* | |
* <sgml> Add or subtract two >=0 integers in byte arrays <p>This routine performs the calculation: <pre> C=A+(BM) | |
* </pre> Where M is in the range -9 through +9 <p> If M<0 then A>=B must be true, so the result is always | |
* non-negative. | |
* | |
* Leading zeros are not removed after a subtraction. The result is either the same length as the longer of A and B, | |
* or 1 longer than that (if a carry occurred). | |
* | |
* A is not altered unless Arg6 is 1. B is never altered. | |
* | |
* Arg1 is A Arg2 is A length to use (if longer than A, pad with 0's) Arg3 is B Arg4 is B length to use (if longer | |
* than B, pad with 0's) Arg5 is M, the multiplier Arg6 is 1 if A can be used to build the result (if it fits) | |
* | |
* This routine is severely performance-critical;any change here must be measured (timed) to assure no performance | |
* degradation. | |
*/ | |
// 1996.02.20 -- enhanced version of DMSRCN algorithm (1981) | |
// 1997.10.05 -- changed to byte arrays (from char arrays) | |
// 1998.07.01 -- changed to allow destructive reuse of LHS | |
// 1998.07.01 -- changed to allow virtual lengths for the arrays | |
// 1998.12.29 -- use lookaside for digit/carry calculation | |
// 1999.08.07 -- avoid multiply when mult=1, and make db an int | |
// 1999.12.22 -- special case m=-1, also drop 0 special case | |
private static final byte[] byteaddsub(byte a[], int avlen, byte b[], int bvlen, int m, boolean reuse) { | |
int alength; | |
int blength; | |
int ap; | |
int bp; | |
int maxarr; | |
byte reb[]; | |
boolean quickm; | |
int digit; | |
int op = 0; | |
int dp90 = 0; | |
byte newarr[]; | |
int i = 0; | |
// We'll usually be right if we assume no carry | |
alength = a.length; // physical lengths | |
blength = b.length; // .. | |
ap = avlen - 1; // -> final (rightmost) digit | |
bp = bvlen - 1; // .. | |
maxarr = bp; | |
if (maxarr < ap) | |
maxarr = ap; | |
reb = (byte[]) null; // result byte array | |
if (reuse) | |
if ((maxarr + 1) == alength) | |
reb = a; // OK to reuse A | |
if (reb == null) | |
reb = new byte[maxarr + 1]; // need new array | |
quickm = false; // 1 if no multiply needed | |
if (m == 1) | |
quickm = true; // most common | |
else if (m == (-1)) | |
quickm = true; // also common | |
digit = 0; // digit, with carry or borrow | |
{ | |
op = maxarr; | |
op: for (; op >= 0; op--) { | |
if (ap >= 0) { | |
if (ap < alength) | |
digit = digit + a[ap]; // within A | |
ap--; | |
} | |
if (bp >= 0) { | |
if (bp < blength) { // within B | |
if (quickm) { | |
if (m > 0) | |
digit = digit + b[bp]; // most common | |
else | |
digit = digit - b[bp]; // also common | |
} else | |
digit = digit + (b[bp] * m); | |
} | |
bp--; | |
} | |
/* result so far (digit) could be -90 through 99 */ | |
if (digit < 10) | |
if (digit >= 0) { | |
do { // 0-9 | |
reb[op] = (byte) digit; | |
digit = 0; // no carry | |
continue op; | |
} while (false); | |
}/* quick */ | |
dp90 = digit + 90; | |
reb[op] = bytedig[dp90]; // this digit | |
digit = bytecar[dp90]; // carry or borrow | |
} | |
}/* op */ | |
if (digit == 0) | |
return reb; // no carry | |
// following line will become an Assert, later | |
// if digit<0 then signal ArithmeticException("internal.error ["digit"]") | |
/* We have carry -- need to make space for the extra digit */ | |
newarr = (byte[]) null; | |
if (reuse) | |
if ((maxarr + 2) == a.length) | |
newarr = a; // OK to reuse A | |
if (newarr == null) | |
newarr = new byte[maxarr + 2]; | |
newarr[0] = (byte) digit; // the carried digit .. | |
// .. and all the rest [use local loop for short numbers] | |
if (maxarr < 10) { | |
int $24 = maxarr + 1; | |
i = 0; | |
for (; $24 > 0; $24--, i++) { | |
newarr[i + 1] = reb[i]; | |
} | |
}/* i */ | |
else | |
java.lang.System.arraycopy((java.lang.Object) reb, 0, (java.lang.Object) newarr, 1, maxarr + 1); | |
return newarr; | |
} | |
/* | |
* <sgml> Initializer for digit array properties (lookaside). </sgml> Returns the digit array, and initializes the | |
* carry array. | |
*/ | |
private static final byte[] diginit() { | |
byte work[]; | |
int op = 0; | |
int digit = 0; | |
work = new byte[(90 + 99) + 1]; | |
{ | |
op = 0; | |
op: for (; op <= (90 + 99); op++) { | |
digit = op - 90; | |
if (digit >= 0) { | |
work[op] = (byte) (digit % 10); | |
bytecar[op] = (byte) (digit / 10); // calculate carry | |
continue op; | |
} | |
// borrowing... | |
digit = digit + 100; // yes, this is right [consider -50] | |
work[op] = (byte) (digit % 10); | |
bytecar[op] = (byte) ((digit / 10) - 10); // calculate borrow [NB: - after %] | |
} | |
}/* op */ | |
return work; | |
} | |
/* | |
* <sgml> Create a copy of BigDecimal object for local use. <p>This does NOT make a copy of the mantissa array. | |
* </sgml> Arg1 is the BigDecimal to clone (non-null) | |
*/ | |
private static final com.ibm.icu.math.BigDecimal clone(com.ibm.icu.math.BigDecimal dec) { | |
com.ibm.icu.math.BigDecimal copy; | |
copy = new com.ibm.icu.math.BigDecimal(); | |
copy.ind = dec.ind; | |
copy.exp = dec.exp; | |
copy.form = dec.form; | |
copy.mant = dec.mant; | |
return copy; | |
} | |
/* | |
* <sgml> Check one or two numbers for lost digits. </sgml> Arg1 is RHS (or null, if none) Arg2 is current DIGITS | |
* setting returns quietly or throws an exception | |
*/ | |
private void checkdigits(com.ibm.icu.math.BigDecimal rhs, int dig) { | |
if (dig == 0) | |
return; // don't check if digits=0 | |
// first check lhs... | |
if (this.mant.length > dig) | |
if ((!(allzero(this.mant, dig)))) | |
throw new java.lang.ArithmeticException("Too many digits:" + " " + this.toString()); | |
if (rhs == null) | |
return; // monadic | |
if (rhs.mant.length > dig) | |
if ((!(allzero(rhs.mant, dig)))) | |
throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString()); | |
} | |
/* | |
* <sgml> Round to specified digits, if necessary. </sgml> Arg1 is requested MathContext [with length and rounding | |
* mode] returns this, for convenience | |
*/ | |
private com.ibm.icu.math.BigDecimal round(com.ibm.icu.math.MathContext set) { | |
return round(set.digits, set.roundingMode); | |
} | |
/* | |
* <sgml> Round to specified digits, if necessary. Arg1 is requested length (digits to round to) [may be <=0 when | |
* called from format, dodivide, etc.] Arg2 is rounding mode returns this, for convenience | |
* | |
* ind and exp are adjusted, but not cleared for a mantissa of zero | |
* | |
* The length of the mantissa returned will be Arg1, except when Arg1 is 0, in which case the returned mantissa | |
* length will be 1. </sgml> | |
*/ | |
private com.ibm.icu.math.BigDecimal round(int len, int mode) { | |
int adjust; | |
int sign; | |
byte oldmant[]; | |
boolean reuse = false; | |
byte first = 0; | |
int increment; | |
byte newmant[] = null; | |
adjust = mant.length - len; | |
if (adjust <= 0) | |
return this; // nowt to do | |
exp = exp + adjust; // exponent of result | |
sign = (int) ind; // save [assumes -1, 0, 1] | |
oldmant = mant; // save | |
if (len > 0) { | |
// remove the unwanted digits | |
mant = new byte[len]; | |
java.lang.System.arraycopy((java.lang.Object) oldmant, 0, (java.lang.Object) mant, 0, len); | |
reuse = true; // can reuse mantissa | |
first = oldmant[len]; // first of discarded digits | |
} else {/* len<=0 */ | |
mant = ZERO.mant; | |
ind = iszero; | |
reuse = false; // cannot reuse mantissa | |
if (len == 0) | |
first = oldmant[0]; | |
else | |
first = (byte) 0; // [virtual digit] | |
} | |
// decide rounding adjustment depending on mode, sign, and discarded digits | |
increment = 0; // bumper | |
{ | |
do {/* select */ | |
if (mode == ROUND_HALF_UP) { // default first [most common] | |
if (first >= 5) | |
increment = sign; | |
} else if (mode == ROUND_UNNECESSARY) { // default for setScale() | |
// discarding any non-zero digits is an error | |
if ((!(allzero(oldmant, len)))) | |
throw new java.lang.ArithmeticException("Rounding necessary"); | |
} else if (mode == ROUND_HALF_DOWN) { // 0.5000 goes down | |
if (first > 5) | |
increment = sign; | |
else if (first == 5) | |
if ((!(allzero(oldmant, len + 1)))) | |
increment = sign; | |
} else if (mode == ROUND_HALF_EVEN) { // 0.5000 goes down if left digit even | |
if (first > 5) | |
increment = sign; | |
else if (first == 5) { | |
if ((!(allzero(oldmant, len + 1)))) | |
increment = sign; | |
else /* 0.5000 */ | |
if ((((mant[mant.length - 1]) % 2)) == 1) | |
increment = sign; | |
} | |
} else if (mode == ROUND_DOWN) { | |
// never increment | |
} else if (mode == ROUND_UP) { // increment if discarded non-zero | |
if ((!(allzero(oldmant, len)))) | |
increment = sign; | |
} else if (mode == ROUND_CEILING) { // more positive | |
if (sign > 0) | |
if ((!(allzero(oldmant, len)))) | |
increment = sign; | |
} else if (mode == ROUND_FLOOR) { // more negative | |
if (sign < 0) | |
if ((!(allzero(oldmant, len)))) | |
increment = sign; | |
} else { | |
throw new java.lang.IllegalArgumentException("Bad round value:" + " " + mode); | |
} | |
} while (false); | |
}/* modes */ | |
if (increment != 0) { | |
do { | |
if (ind == iszero) { | |
// we must not subtract from 0, but result is trivial anyway | |
mant = ONE.mant; | |
ind = (byte) increment; | |
} else { | |
// mantissa is non-0; we can safely add or subtract 1 | |
if (ind == isneg) | |
increment = -increment; | |
newmant = byteaddsub(mant, mant.length, ONE.mant, 1, increment, reuse); | |
if (newmant.length > mant.length) { // had a carry | |
// drop rightmost digit and raise exponent | |
exp++; | |
// mant is already the correct length | |
java.lang.System.arraycopy((java.lang.Object) newmant, 0, (java.lang.Object) mant, 0, | |
mant.length); | |
} else | |
mant = newmant; | |
} | |
} while (false); | |
}/* bump */ | |
// rounding can increase exponent significantly | |
if (exp > MaxExp) | |
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp); | |
return this; | |
} | |
/* | |
* <sgml> Test if rightmost digits are all 0. Arg1 is a mantissa array to test Arg2 is the offset of first digit to | |
* check [may be negative; if so, digits to left are 0's] returns 1 if all the digits starting at Arg2 are 0 | |
* | |
* Arg2 may be beyond array bounds, in which case 1 is returned </sgml> | |
*/ | |
private static final boolean allzero(byte array[], int start) { | |
int i = 0; | |
if (start < 0) | |
start = 0; | |
{ | |
int $25 = array.length - 1; | |
i = start; | |
for (; i <= $25; i++) { | |
if (array[i] != 0) | |
return false; | |
} | |
}/* i */ | |
return true; | |
} | |
/* | |
* <sgml> Carry out final checks and canonicalization <p> This finishes off the current number by: 1. Rounding if | |
* necessary (NB: length includes leading zeros) 2. Stripping trailing zeros (if requested and \PLAIN) 3. Stripping | |
* leading zeros (always) 4. Selecting exponential notation (if required) 5. Converting a zero result to just '0' | |
* (if \PLAIN) In practice, these operations overlap and share code. It always sets form. </sgml> Arg1 is requested | |
* MathContext (length to round to, trigger, and FORM) Arg2 is 1 if trailing insignificant zeros should be removed | |
* after round (for division, etc.), provided that set.form isn't PLAIN. returns this, for convenience | |
*/ | |
private com.ibm.icu.math.BigDecimal finish(com.ibm.icu.math.MathContext set, boolean strip) { | |
int d = 0; | |
int i = 0; | |
byte newmant[] = null; | |
int mag = 0; | |
int sig = 0; | |
/* Round if mantissa too long and digits requested */ | |
if (set.digits != 0) | |
if (this.mant.length > set.digits) | |
this.round(set); | |
/* | |
* If strip requested (and standard formatting), remove insignificant trailing zeros. | |
*/ | |
if (strip) | |
if (set.form != com.ibm.icu.math.MathContext.PLAIN) { | |
d = this.mant.length; | |
/* see if we need to drop any trailing zeros */ | |
{ | |
i = d - 1; | |
i: for (; i >= 1; i--) { | |
if (this.mant[i] != 0) | |
break i; | |
d--; | |
exp++; | |
} | |
}/* i */ | |
if (d < this.mant.length) {/* need to reduce */ | |
newmant = new byte[d]; | |
java.lang.System.arraycopy((java.lang.Object) this.mant, 0, (java.lang.Object) newmant, 0, d); | |
this.mant = newmant; | |
} | |
} | |
form = (byte) com.ibm.icu.math.MathContext.PLAIN; // preset | |
/* Now check for leading- and all- zeros in mantissa */ | |
{ | |
int $26 = this.mant.length; | |
i = 0; | |
for (; $26 > 0; $26--, i++) { | |
if (this.mant[i] != 0) { | |
// non-0 result; ind will be correct | |
// remove leading zeros [e.g., after subtract] | |
if (i > 0) { | |
do { | |
newmant = new byte[this.mant.length - i]; | |
java.lang.System.arraycopy((java.lang.Object) this.mant, i, (java.lang.Object) newmant, 0, | |
this.mant.length - i); | |
this.mant = newmant; | |
} while (false); | |
}/* delead */ | |
// now determine form if not PLAIN | |
mag = exp + mant.length; | |
if (mag > 0) { // most common path | |
if (mag > set.digits) | |
if (set.digits != 0) | |
form = (byte) set.form; | |
if ((mag - 1) <= MaxExp) | |
return this; // no overflow; quick return | |
} else if (mag < (-5)) | |
form = (byte) set.form; | |
/* check for overflow */ | |
mag--; | |
if ((mag < MinExp) | (mag > MaxExp)) { | |
overflow: do { | |
// possible reprieve if form is engineering | |
if (form == com.ibm.icu.math.MathContext.ENGINEERING) { | |
sig = mag % 3; // leftover | |
if (sig < 0) | |
sig = 3 + sig; // negative exponent | |
mag = mag - sig; // exponent to use | |
// 1999.06.29: second test here must be MaxExp | |
if (mag >= MinExp) | |
if (mag <= MaxExp) | |
break overflow; | |
} | |
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + mag); | |
} while (false); | |
}/* overflow */ | |
return this; | |
} | |
} | |
}/* i */ | |
// Drop through to here only if mantissa is all zeros | |
ind = iszero; | |
{/* select */ | |
if (set.form != com.ibm.icu.math.MathContext.PLAIN) | |
exp = 0; // standard result; go to '0' | |
else if (exp > 0) | |
exp = 0; // +ve exponent also goes to '0' | |
else { | |
// a plain number with -ve exponent; preserve and check exponent | |
if (exp < MinExp) | |
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp); | |
} | |
} | |
mant = ZERO.mant; // canonical mantissa | |
return this; | |
} | |
} |