| /* 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; |
| |
| import com.ibm.icu.lang.UCharacter; |
| |
| /* ------------------------------------------------------------------ */ |
| /* 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 ((!(UCharacter.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 ((!(UCharacter.isDigit(sj)))) |
| bad(inchars); // not a number |
| dvalue = UCharacter.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 ((UCharacter.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 = UCharacter.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)) != 0) |
| 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; |
| } |
| } |