All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.icu.math.BigDecimal Maven / Gradle / Ivy

Go to download

Vaadin is a web application framework for Rich Internet Applications (RIA). Vaadin enables easy development and maintenance of fast and secure rich web applications with a stunning look and feel and a wide browser support. It features a server-side architecture with the majority of the logic running on the server. Ajax technology is used at the browser-side to ensure a rich and interactive user experience.

There is a newer version: 1.2.0
Show newest version
/* 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) ; 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 BigDecimal class implements immutable arbitrary-precision decimal numbers. The methods of the
 * BigDecimal class provide operations for fixed and floating point arithmetic, comparison, format
 * conversions, and hashing.
 * 

* 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 (char[]) objects, as well as conversions to and from the Java * primitive types (which may not be exact) and BigInteger. *

* In the descriptions of constructors and methods in this documentation, the value of a BigDecimal number * object is shown as the result of invoking the toString() 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. *

* The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also * documented at http://www2.hursley.ibm.com/decimal
* [This URL will change.] * *

Operator methods

*

* Operations on BigDecimal numbers are controlled by a {@link MathContext} object, which provides the * context (precision and other information) for the operation. Methods that can take a MathContext * parameter implement the standard arithmetic operators for BigDecimal objects and are known as * operator methods. The default settings provided by the constant {@link MathContext#DEFAULT} (digits=9, * form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP) perform general-purpose floating point * arithmetic to nine digits of precision. The MathContext parameter must not be null. *

* Each operator method also has a version provided which does not take a MathContext parameter. For this * version of each method, the context settings used are digits=0, * form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP; these settings perform fixed point arithmetic with * unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2. *

* For monadic operators, only the optional MathContext parameter is present; the operation acts upon the * current object. *

* For dyadic operators, a BigDecimal parameter is always present; it must not be null. The * operation acts with the current object being the left-hand operand and the BigDecimal parameter being * the right-hand operand. *

* For example, adding two BigDecimal objects referred to by the names award and * extra could be written as any of: *

* * award.add(extra) *
award.add(extra, MathContext.DEFAULT) *
award.add(extra, acontext) *
*

* (where acontext is a MathContext object), which would return a BigDecimal * object whose value is the result of adding award and extra under the appropriate context * settings. *

* When a BigDecimal 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: *

    *
  • Results are normally calculated with up to some maximum number of significant digits. For example, if the * MathContext parameter for an operation were MathContext.DEFAULT then the result would be * rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667.
    * You can change the default of 9 significant digits by providing the method with a suitable MathContext * object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled) * arithmetic is indicated by using a digits setting of 0 (or omitting the MathContext * parameter).
    * Similarly, you can change the algorithm used for rounding from the default "classic" algorithm. *
  • * In standard arithmetic (that is, when the form setting is not PLAIN), a zero result is * always expressed as the single digit '0' (that is, with no sign, decimal point, or exponent part). *
  • * 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).
    * So, for example: *

    * * new BigDecimal("2.40").add( new BigDecimal("2")) => "4.40" *
    new BigDecimal("2.40").subtract(new BigDecimal("2")) => "0.40" *
    new BigDecimal("2.40").multiply(new BigDecimal("2")) => "4.80" *
    new BigDecimal("2.40").divide( new BigDecimal("2"), def) => "1.2" *
    *

    * where the value on the right of the => would be the result of the operation, expressed as a * String, and def (in this and following examples) refers to MathContext.DEFAULT * ). 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. *

  • * In standard arithmetic, exponential form is used for a result depending on its value and the current setting of * digits (the default is 9 digits). If the number of places needed before the decimal point exceeds the * digits setting, or the absolute value of the number is less than 0.000001, then the number * will be expressed in exponential notation; thus *

    * * new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def) * *

    * results in 1E+12 instead of 1000000000000, and *

    * * new BigDecimal("1").divide(new BigDecimal("3E+10"), def) * *

    * results in 3.33333333E-11 instead of 0.0000000000333333333. *

    * The form of the exponential notation (scientific or engineering) is determined by the form setting. * *

    * The names of methods in this class follow the conventions established by java.lang.Number, * java.math.BigInteger, and java.math.BigDecimal 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 { // private static final java.lang.String $0="BigDecimal.nrx"; /* ----- Constants ----- */ /* properties constant public */// useful to others /** * The BigDecimal 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 BigDecimal 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 BigDecimal 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: *

      *
    • ispos -- the number is positive
    • iszero -- the number is zero
    • isneg -- the number is negative *
    * * @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: *
      *
    • MathContext.PLAIN -- no exponent needed
    • MathContext.SCIENTIFIC -- scientific notation required
    • * MathContext.ENGINEERING -- engineering notation required *
    *

    * 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. *

    * Once constructed, this may become shared between several BigDecimal objects, so must not be altered. *

    * For efficiency (speed), this is a byte array, with each byte taking a value of 0 -> 9. *

    * 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. *

    * For fixed point arithmetic, scale is -exp, 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 BigDecimal object from a java.math.BigDecimal. *

    * Constructs a BigDecimal as though the parameter had been represented as a String (using * its toString method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used. * The parameter must not be null. *

    * (Note: this constructor is provided only in the com.ibm.icu.math version of the BigDecimal class. * It would not be present in a java.math version.) * * @param bd The BigDecimal to be translated. * @stable ICU 2.0 */ public BigDecimal(java.math.BigDecimal bd) { this(bd.toString()); return; } /** * Constructs a BigDecimal object from a BigInteger, with scale 0. *

    * Constructs a BigDecimal which is the exact decimal representation of the BigInteger, * with a scale of zero. The value of the BigDecimal is identical to the value of the BigInteger * . The parameter must not be null. *

    * The BigDecimal will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the * BigInteger is negative. A leading zero will be present only if the BigInteger is zero. * * @param bi The BigInteger to be converted. * @stable ICU 2.0 */ public BigDecimal(java.math.BigInteger bi) { this(bi.toString(10)); return; } // exp remains 0 /** * Constructs a BigDecimal object from a BigInteger and a scale. *

    * Constructs a BigDecimal which is the exact decimal representation of the BigInteger, * scaled by the second parameter, which may not be negative. The value of the BigDecimal is the * BigInteger divided by ten to the power of the scale. The BigInteger parameter must not be * null. *

    * The BigDecimal will contain only decimal digits, (with an embedded decimal point followed by * scale decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the * BigInteger is negative. A leading zero will be present only if the BigInteger is zero. * * @param bi The BigInteger to be converted. * @param scale The int 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 BigDecimal object from an array of characters. *

    * Constructs a BigDecimal as though a String had been constructed from the character * array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be * null. *

    * Using this constructor is faster than using the BigDecimal(String) constructor if the string is * already available in character array form. * * @param inchars The char[] 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 BigDecimal object from an array of characters. *

    * Constructs a BigDecimal as though a String 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 null, and the subarray must be wholly contained within it. *

    * Using this constructor is faster than using the BigDecimal(String) constructor if the string is * already available within a character array. * * @param inchars The char[] array containing the number to be converted. * @param offset The int offset into the array of the start of the number to be converted. * @param length The int 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 BigDecimal object directly from a double. *

    * Constructs a BigDecimal which is the exact decimal representation of the 64-bit signed binary * floating point parameter. *

    * Note that this constructor it an exact conversion; it does not give the same result as converting num * to a String using the Double.toString() 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 BigDecimal from a double. * * @param num The double 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 BigDecimal object directly from a int. *

    * Constructs a BigDecimal which is the exact decimal representation of the 32-bit signed binary * integer parameter. The BigDecimal 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 int 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 BigDecimal object directly from a long. *

    * Constructs a BigDecimal which is the exact decimal representation of the 64-bit signed binary * integer parameter. The BigDecimal 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 long 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 BigDecimal object from a String. *

    * Constructs a BigDecimal from the parameter, which must not be null and must represent a * valid number, as described formally in the documentation referred to {@link BigDecimal above}. *

    * In summary, numbers in String 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. *

    * Some valid strings from which a BigDecimal might be constructed are: * *

         * 
         * "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
         * 
         * 
    *

    * (Exponential notation means that the number includes an optional sign and a power of ten following an * 'E' that indicates how the decimal point will be shifted. Thus the "4E+9" above is * just a short way of writing 4000000000, and the "0.73e-7" is short for * 0.000000073.) *

    * The BigDecimal 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 e or an E), then the BigDecimal * 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. *

    * Any digits in the parameter must be decimal; that is, Character.digit(c, 10) (where c * is the character in question) would not return -1. * * @param string The String 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; } /* Make a default BigDecimal object for local use. */ private BigDecimal() { super(); return; } /* ---------------------------------------------------------------- */ /* Operator methods [methods which take a context parameter] */ /* ---------------------------------------------------------------- */ /** * Returns a plain BigDecimal whose value is the absolute value of this BigDecimal. *

    * The same as {@link #abs(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN). *

    * The length of the decimal part (the scale) of the result will be this.scale() * * @return A BigDecimal whose value is the absolute value of this BigDecimal. * @stable ICU 2.0 */ public com.ibm.icu.math.BigDecimal abs() { return this.abs(plainMC); } /** * Returns a BigDecimal whose value is the absolute value of this BigDecimal. *

    * 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 MathContext arithmetic settings. * @return A BigDecimal whose value is the absolute value of this BigDecimal. * @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 BigDecimal whose value is this+rhs, using fixed point arithmetic. *

    * The same as {@link #add(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the * context is new MathContext(0, MathContext.PLAIN). *

    * 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 BigDecimal for the right hand side of the addition. * @return A BigDecimal whose value is this+rhs, 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 BigDecimal whose value is this+rhs. *

    * Implements the addition (+) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. * * @param rhs The BigDecimal for the right hand side of the addition. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is this+rhs. * @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 BigDecimal to another, using unlimited precision. *

    * The same as {@link #compareTo(BigDecimal, MathContext)}, where the BigDecimal is rhs, * and the context is new MathContext(0, MathContext.PLAIN). * * @param rhs The BigDecimal for the right hand side of the comparison. * @return An int whose value is -1, 0, or 1 as this is numerically less than, equal to, * or greater than rhs. * @stable ICU 2.0 */ public int compareTo(com.ibm.icu.math.BigDecimal rhs) { return this.compareTo(rhs, plainMC); } /** * Compares this BigDecimal to another. *

    * Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}), * and returns a result of type int. *

    * The result will be: *

    * * * * * * * * * *
    -1 if the current object is less than the first parameter
    0 if the current object is equal to the first parameter
    1 if the current object is greater than the first parameter.
    *

    * A {@link #compareTo(BigDecimal)} method is also provided. * * @param rhs The BigDecimal for the right hand side of the comparison. * @param set The MathContext arithmetic settings. * @return An int whose value is -1, 0, or 1 as this is numerically less than, equal to, * or greater than rhs. * @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 BigDecimal whose value is this/rhs, using fixed point arithmetic. *

    * The same as {@link #divide(BigDecimal, int)}, where the BigDecimal is rhs, 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 BigDecimal for the right hand side of the division. * @return A plain BigDecimal whose value is this/rhs, using fixed point arithmetic. * @throws ArithmeticException If rhs 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 BigDecimal whose value is this/rhs, using fixed point arithmetic and a * rounding mode. *

    * The same as {@link #divide(BigDecimal, int, int)}, where the BigDecimal is rhs, and the * second parameter is this.scale(), and the third is round. *

    * 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. *

    * * @param rhs The BigDecimal for the right hand side of the division. * @param round The int rounding mode to be used for the division (see the {@link MathContext} class). * @return A plain BigDecimal whose value is this/rhs, using fixed point arithmetic and * the specified rounding mode. * @throws IllegalArgumentException if round is not a valid rounding mode. * @throws ArithmeticException if rhs is zero. * @throws ArithmeticException if round is {@link MathContext#ROUND_UNNECESSARY} and this.scale() 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 BigDecimal whose value is this/rhs, using fixed point arithmetic and a * given scale and rounding mode. *

    * The same as {@link #divide(BigDecimal, MathContext)}, where the BigDecimal is rhs, * new MathContext(0, MathContext.PLAIN, false, round), except that the length of the decimal part (the * scale) to be used for the result is explicit rather than being taken from this. *

    * 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 BigDecimal for the right hand side of the division. * @param scale The int scale to be used for the result. * @param round The int rounding mode to be used for the division (see the {@link MathContext} class). * @return A plain BigDecimal whose value is this/rhs, using fixed point arithmetic and * the specified rounding mode. * @throws IllegalArgumentException if round is not a valid rounding mode. * @throws ArithmeticException if rhs is zero. * @throws ArithmeticException if scale is negative. * @throws ArithmeticException if round is {@link MathContext#ROUND_UNNECESSARY} and scale 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 BigDecimal whose value is this/rhs. *

    * Implements the division (/) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. * * @param rhs The BigDecimal for the right hand side of the division. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is this/rhs. * @throws ArithmeticException if rhs 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 BigDecimal whose value is the integer part of this/rhs. *

    * The same as {@link #divideInteger(BigDecimal, MathContext)}, where the BigDecimal is rhs * , and the context is new MathContext(0, MathContext.PLAIN). * * @param rhs The BigDecimal for the right hand side of the integer division. * @return A BigDecimal whose value is the integer part of this/rhs. * @throws ArithmeticException if rhs 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 BigDecimal whose value is the integer part of this/rhs. *

    * Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class * header}), and returns the result as a BigDecimal object. * * @param rhs The BigDecimal for the right hand side of the integer division. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is the integer part of this/rhs. * @throws ArithmeticException if rhs 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 BigDecimal whose value is the maximum of this and rhs. *

    * The same as {@link #max(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the * context is new MathContext(0, MathContext.PLAIN). * * @param rhs The BigDecimal for the right hand side of the comparison. * @return A BigDecimal whose value is the maximum of this and rhs. * @stable ICU 2.0 */ public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) { return this.max(rhs, plainMC); } /** * Returns a BigDecimal whose value is the maximum of this and rhs. *

    * Returns the larger of the current object and the first parameter. *

    * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return 1 * or 0, then the result of calling the {@link #plus(MathContext)} method on the current object * (using the same MathContext parameter) is returned. Otherwise, the result of calling the * {@link #plus(MathContext)} method on the first parameter object (using the same MathContext * parameter) is returned. * * @param rhs The BigDecimal for the right hand side of the comparison. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is the maximum of this and rhs. * @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 BigDecimal whose value is the minimum of this and rhs. *

    * The same as {@link #min(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the * context is new MathContext(0, MathContext.PLAIN). * * @param rhs The BigDecimal for the right hand side of the comparison. * @return A BigDecimal whose value is the minimum of this and rhs. * @stable ICU 2.0 */ public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) { return this.min(rhs, plainMC); } /** * Returns a BigDecimal whose value is the minimum of this and rhs. *

    * Returns the smaller of the current object and the first parameter. *

    * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return -1 * or 0, then the result of calling the {@link #plus(MathContext)} method on the current object * (using the same MathContext parameter) is returned. Otherwise, the result of calling the * {@link #plus(MathContext)} method on the first parameter object (using the same MathContext * parameter) is returned. * * @param rhs The BigDecimal for the right hand side of the comparison. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is the minimum of this and rhs. * @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 BigDecimal whose value is this*rhs, using fixed point arithmetic. *

    * The same as {@link #add(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the * context is new MathContext(0, MathContext.PLAIN). *

    * 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 BigDecimal for the right hand side of the multiplication. * @return A BigDecimal whose value is this*rhs, 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 BigDecimal whose value is this*rhs. *

    * Implements the multiplication ( ) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. * * @param rhs The BigDecimal for the right hand side of the multiplication. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is this*rhs. * @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 BigDecimal whose value is -this. *

    * The same as {@link #negate(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN) * . *

    * The length of the decimal part (the scale) of the result will be be this.scale() * * * @return A BigDecimal whose value is -this. * @stable ICU 2.0 */ public com.ibm.icu.math.BigDecimal negate() { return this.negate(plainMC); } /** * Returns a BigDecimal whose value is -this. *

    * Implements the negation (Prefix -) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. * * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is -this. * @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 BigDecimal whose value is +this. Note that this is not * necessarily a plain BigDecimal, but the result will always be. *

    * The same as {@link #plus(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN). *

    * The length of the decimal part (the scale) of the result will be be this.scale() * * @return A BigDecimal whose value is +this. * @stable ICU 2.0 */ public com.ibm.icu.math.BigDecimal plus() { return this.plus(plainMC); } /** * Returns a BigDecimal whose value is +this. *

    * Implements the plus (Prefix +) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. *

    * This method is useful for rounding or otherwise applying a context to a decimal value. * * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is +this. * @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 BigDecimal whose value is this**rhs, using fixed point arithmetic. *

    * The same as {@link #pow(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the * context is new MathContext(0, MathContext.PLAIN). *

    * The parameter is the power to which the this 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. *

    * In addition, the power must not be negative, as no MathContext is used and so the result would then * always be 0. * * @param rhs The BigDecimal for the right hand side of the operation (the power). * @return A BigDecimal whose value is this**rhs, using fixed point arithmetic. * @throws ArithmeticException if rhs 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 BigDecimal whose value is this**rhs. *

    * Implements the power ( ) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. *

    * The first parameter is the power to which the this 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. *

    * If the digits setting of the MathContext parameter is 0, the power must be zero or * positive. * * @param rhs The BigDecimal for the right hand side of the operation (the power). * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is this**rhs. * @throws ArithmeticException if rhs 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 BigDecimal whose value is the remainder of this/rhs, using fixed point * arithmetic. *

    * The same as {@link #remainder(BigDecimal, MathContext)}, where the BigDecimal is rhs, * and the context is new MathContext(0, MathContext.PLAIN). *

    * This is not the modulo operator -- the result may be negative. * * @param rhs The BigDecimal for the right hand side of the remainder operation. * @return A BigDecimal whose value is the remainder of this/rhs, using fixed point * arithmetic. * @throws ArithmeticException if rhs 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 BigDecimal whose value is the remainder of this/rhs. *

    * Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}), * and returns the result as a BigDecimal object. *

    * This is not the modulo operator -- the result may be negative. * * @param rhs The BigDecimal for the right hand side of the remainder operation. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is the remainder of this+rhs. * @throws ArithmeticException if rhs 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 BigDecimal whose value is this-rhs, using fixed point arithmetic. *

    * The same as {@link #subtract(BigDecimal, MathContext)}, where the BigDecimal is rhs, * and the context is new MathContext(0, MathContext.PLAIN). *

    * 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 BigDecimal for the right hand side of the subtraction. * @return A BigDecimal whose value is this-rhs, 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 BigDecimal whose value is this-rhs. *

    * Implements the subtraction (-) operator (as defined in the decimal documentation, see * {@link BigDecimal class header}), and returns the result as a BigDecimal object. * * @param rhs The BigDecimal for the right hand side of the subtraction. * @param set The MathContext arithmetic settings. * @return A BigDecimal whose value is this-rhs. * @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 BigDecimal to a byte. If the BigDecimal has a non-zero * decimal part or is out of the possible range for a byte (8-bit signed integer) result then an * ArithmeticException is thrown. * * @return A byte equal in value to this. * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in a byte. * @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 BigDecimal to a double. If the BigDecimal is out of the * possible range for a double (64-bit signed floating point) result then an ArithmeticException * is thrown. *

    * The double produced is identical to result of expressing the BigDecimal as a String and * then converting it using the Double(String) constructor; this can result in values of * Double.NEGATIVE_INFINITY or Double.POSITIVE_INFINITY. * * @return A double corresponding to this. * @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 BigDecimal with rhs for equality. *

    * If the parameter is null, or is not an instance of the BigDecimal type, or is not exactly equal to * the current BigDecimal object, then false is returned. Otherwise, true is returned. *

    * "Exactly equal", here, means that the String representations of the BigDecimal numbers * are identical (they have the same characters in the same sequence). *

    * The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons. * * @param obj The Object for the right hand side of the comparison. * @return A boolean whose value true if and only if the operands have identical string * representations. * @throws ClassCastException if rhs cannot be cast to a BigDecimal 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 BigDecimal to a float. If the BigDecimal is out of the * possible range for a float (32-bit signed floating point) result then an ArithmeticException * is thrown. *

    * The float produced is identical to result of expressing the BigDecimal as a String and * then converting it using the Float(String) constructor; this can result in values of * Float.NEGATIVE_INFINITY or Float.POSITIVE_INFINITY. * * @return A float corresponding to this. * @stable ICU 2.0 */ public float floatValue() { return java.lang.Float.valueOf(this.toString()).floatValue(); } /** * Returns the String representation of this BigDecimal, modified by layout parameters. *

    * This method is provided as a primitive for use by more sophisticated classes, such as DecimalFormat * , 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. * *

    * The parameters, for both forms of the format method are all of type int. A value of -1 * for any parameter indicates that the default action or value for that parameter should be used. *

    * The parameters, before and after, 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. *

    * before 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 before is not large enough to * contain the integer part of the number (including the sign, for negative numbers) an exception is thrown. *

    * after 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 after 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, MathContext.ROUND_HALF_UP. *

    * 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 int specifying the number of places before the decimal point. Use -1 for 'as many as are needed'. * @param after The int specifying the number of places after the decimal point. Use -1 for 'as many as are needed'. * @return A String representing this BigDecimal, 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 String representation of this BigDecimal, modified by layout parameters and * allowing exponential notation. *

    * This method is provided as a primitive for use by more sophisticated classes, such as DecimalFormat * , 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. * *

    * The parameters are all of type int. A value of -1 for any parameter indicates that the default * action or value for that parameter should be used. *

    * The first two parameters (before and after) 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. *

    * The remaining parameters control the use of exponential notation and rounding. Three (explaces, * exdigits, and exform) 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. *

    * explaces 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 explaces is -1) being to use as many * as are needed. If explaces is not -1, space is always reserved for an exponent; if one is not needed * (for example, if the exponent will be 0) then explaces+2 blanks are appended to the result. If explaces * is not -1 and is not large enough to contain the exponent, an exception is thrown. *

    * exdigits sets the trigger point for use of exponential notation. If, before any rounding, the number * of places needed before the decimal point exceeds exdigits, or if the absolute value of the result * is less than 0.000001, then exponential form will be used, provided that exdigits was * specified. When exdigits is -1, exponential notation will never be used. If 0 is specified for * exdigits, exponential notation is always used unless the exponent would be 0. *

    * exform 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 (before * ). Otherwise, only one digit (plus sign, if negative) is needed. *

    * Finally, the sixth argument, exround, 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 ROUND_ * . The default (ROUND_HALF_UP) may also be selected by using the value -1, as before. *

    * The special value MathContext.ROUND_UNNECESSARY may be used to detect whether non-zero digits are * discarded -- if exround has this value than if non-zero digits would be discarded (rounded) during * formatting then an ArithmeticException is thrown. * * @param before The int specifying the number of places before the decimal point. Use -1 for 'as many as * are needed'. * @param after The int specifying the number of places after the decimal point. Use -1 for 'as many as * are needed'. * @param explaces The int specifying the number of places to be used for any exponent. Use -1 for 'as many * as are needed'. * @param exdigits The int 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 int specifying the form of exponential notation to be used ( * {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}). * @param exround The int specifying the rounding mode to use. Use -1 for the default, * {@link MathContext#ROUND_HALF_UP}. * @return A String representing this BigDecimal, 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 BigDecimal. This hashcode is suitable for use by the * java.util.Hashtable class. *

    * Note that two BigDecimal objects are only guaranteed to produce the same hashcode if they are * exactly equal (that is, the String representations of the BigDecimal numbers are * identical -- they have the same characters in the same sequence). * * @return An int that is the hashcode for this. * @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 BigDecimal to an int. If the BigDecimal has a non-zero * decimal part it is discarded. If the BigDecimal is out of the possible range for an int * (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be * decapitated.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact} * method. * * @return An int converted from this, truncated and decapitated if necessary. * @stable ICU 2.0 */ public int intValue() { return toBigInteger().intValue(); } /** * Converts this BigDecimal to an int. If the BigDecimal has a non-zero * decimal part or is out of the possible range for an int (32-bit signed integer) result then an * ArithmeticException is thrown. * * @return An int equal in value to this. * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in an int. * @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=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 BigDecimal to a long. If the BigDecimal has a non-zero * decimal part it is discarded. If the BigDecimal is out of the possible range for a long * (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be * decapitated.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact} * method. * * @return A long converted from this, truncated and decapitated if necessary. * @stable ICU 2.0 */ public long longValue() { return toBigInteger().longValue(); } /** * Converts this BigDecimal to a long. If the BigDecimal has a non-zero * decimal part or is out of the possible range for a long (64-bit signed integer) result then an * ArithmeticException is thrown. * * @return A long equal in value to this. * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in a long. * @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=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 BigDecimal whose decimal point has been moved to the left by a specified number of * positions. The parameter, n, specifies the number of positions to move the decimal point. That is, * if n is 0 or positive, the number returned is given by: *

    * this.multiply(TEN.pow(new BigDecimal(-n))) *

    * n may be negative, in which case the method returns the same result as movePointRight(-n) * . * * @param n The int specifying the number of places to move the decimal point leftwards. * @return A BigDecimal derived from this, with the decimal point moved n * 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 BigDecimal whose decimal point has been moved to the right by a specified number of * positions. The parameter, n, specifies the number of positions to move the decimal point. That is, * if n is 0 or positive, the number returned is given by: *

    * this.multiply(TEN.pow(new BigDecimal(n))) *

    * n may be negative, in which case the method returns the same result as movePointLeft(-n) * . * * @param n The int specifying the number of places to move the decimal point rightwards. * @return A BigDecimal derived from this, with the decimal point moved n * 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 BigDecimal. Returns a non-negative int 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 int whose value is the scale of this BigDecimal. * @stable ICU 2.0 */ public int scale() { if (exp >= 0) return 0; // scale can never be negative return -exp; } /** * Returns a plain BigDecimal with a given scale. *

    * 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 BigDecimal then trailing zeros will be added to the decimal part as necessary. *

    * If the given scale is less than the length of the decimal part (the scale) of this BigDecimal then * trailing digits will be removed, and in this case an ArithmeticException is thrown if any discarded * digits are non-zero. *

    * The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is * MathContext.ROUND_UNNECESSARY. * * @param scale The int specifying the scale of the resulting BigDecimal. * @return A plain BigDecimal with the given scale. * @throws ArithmeticException if scale 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 BigDecimal with a given scale. *

    * 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 BigDecimal then trailing zeros will be added to the decimal part as necessary. *

    * If the given scale is less than the length of the decimal part (the scale) of this BigDecimal 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 IllegalArgumentException is thrown if * round is not a valid rounding mode. *

    * If round is MathContext.ROUND_UNNECESSARY, an ArithmeticException is * thrown if any discarded digits are non-zero. * * @param scale The int specifying the scale of the resulting BigDecimal. * @param round The int rounding mode to be used for the division (see the {@link MathContext} class). * @return A plain BigDecimal with the given scale. * @throws IllegalArgumentException if round is not a valid rounding mode. * @throws ArithmeticException if scale is negative. * @throws ArithmeticException if round is MathContext.ROUND_UNNECESSARY, 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 BigDecimal to a short. If the BigDecimal has a non-zero * decimal part or is out of the possible range for a short (16-bit signed integer) result then an * ArithmeticException is thrown. * * @return A short equal in value to this. * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in a short. * @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 BigDecimal, as an int. This returns the signum function * value that represents the sign of this BigDecimal. That is, -1 if the BigDecimal is * negative, 0 if it is numerically equal to zero, or 1 if it is positive. * * @return An int which is -1 if the BigDecimal 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 BigDecimal to a java.math.BigDecimal. *

    * This is an exact conversion; the result is the same as if the BigDecimal were formatted as a plain * number without any rounding or exponent and then the java.math.BigDecimal(java.lang.String) * constructor were used to construct the result. *

    * (Note: this method is provided only in the com.ibm.icu.math version of the BigDecimal class. It * would not be present in a java.math version.) * * @return The java.math.BigDecimal equal in value to this BigDecimal. * @stable ICU 2.0 */ public java.math.BigDecimal toBigDecimal() { return new java.math.BigDecimal(this.unscaledValue(), this.scale()); } /** * Converts this BigDecimal to a java.math.BigInteger. *

    * Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use * {@link #toBigIntegerExact()}. * * @return The java.math.BigInteger equal in value to the integer part of this BigDecimal. * @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 BigDecimal to a java.math.BigInteger. *

    * An exception is thrown if the decimal part (if any) is non-zero. * * @return The java.math.BigInteger equal in value to the integer part of this BigDecimal. * @throws ArithmeticException if this 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 BigDecimal as a character array. The result of this method is the same as using the * sequence toString().toCharArray(), but avoids creating the intermediate String and * char[] objects. * * @return The char[] array corresponding to this BigDecimal. * @stable ICU 2.0 */ public char[] toCharArray() { return layout(); } /** * Returns the BigDecimal as a String. This returns a String that exactly * represents this BigDecimal, as defined in the decimal documentation (see {@link BigDecimal class * header}). *

    * By definition, using the {@link #BigDecimal(String)} constructor on the result String will create a * BigDecimal that is exactly equal to the original BigDecimal. * * @return The String exactly corresponding to this BigDecimal. * @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 BigInteger 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 BigInteger. * * @return The java.math.BigInteger equal in value to this BigDecimal multiplied by ten to * the power of this.scale(). * @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 double to a BigDecimal. *

    * Returns a BigDecimal 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 NumberFormatException is * thrown. *

    * The number is constructed as though num had been converted to a String using the * Double.toString() method and the {@link #BigDecimal(java.lang.String)} constructor had then been used. * This is typically not an exact conversion. * * @param dub The double to be translated. * @return The BigDecimal equal in value to dub. * @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 long to a BigDecimal. That is, returns a plain BigDecimal * whose value is equal to the given long. * * @param lint The long to be translated. * @return The BigDecimal equal in value to lint. * @stable ICU 2.0 */ public static com.ibm.icu.math.BigDecimal valueOf(long lint) { return valueOf(lint, 0); } /** * Translates a long to a BigDecimal with a given scale. That is, returns a plain * BigDecimal whose unscaled value is equal to the given long, adjusted by the second parameter, * scale. *

    * The result is given by: *

    * (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) *

    * A NumberFormatException is thrown if scale is negative. * * @param lint The long to be translated. * @param scale The int scale to be applied. * @return The BigDecimal equal in value to lint. * @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 */ /* ---------------------------------------------------------------- */ /* * Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array). *

    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).

    We must not alter the mantissa, here.

    '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. */ 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; } /* * Checks a BigDecimal argument to ensure it's a true integer in a given range.

    If OK, returns it as an * int. */ // [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; } /* Carry out division operations. */ /* * 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); } /* Report a conversion exception. */ private void bad(char s[]) { throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s)); } /* * Report a bad argument to a method. 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); } /* * Extend byte array to given length, padding with 0s. If no extension is required then return the same * array. * * 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; } /* * Add or subtract two >=0 integers in byte arrays

    This routine performs the calculation:

     C=A+(BM)
         * 
    Where M is in the range -9 through +9

    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; } /* * Initializer for digit array properties (lookaside). 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; } /* * Create a copy of BigDecimal object for local use.

    This does NOT make a copy of the mantissa array. * 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; } /* * Check one or two numbers for lost digits. 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()); } /* * Round to specified digits, if necessary. 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); } /* * 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. */ 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; } /* * 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 */ 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; } /* * Carry out final checks and canonicalization

    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. 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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy