// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/* 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-2016.  All Rights Reserved.       */
/*                                                                    */
/* The BigDecimal class provides immutable arbitrary-precision        */
/* floating point (including integer) decimal numbers.                */
/*                                                                    */
/* As the numbers are decimal, there is an exact correspondence       */
/* between an instance of a BigDecimal object and its String          */
/* representation; the BigDecimal class provides direct conversions   */
/* to and from String and character array objects, and well as        */
/* conversions to and from the Java primitive types (which may not    */
/* be exact).                                                         */
/* ------------------------------------------------------------------ */
/* Notes:                                                             */
/*                                                                    */
/* 1. A BigDecimal object is never changed in value once constructed; */
/*    this avoids the need for locking.  Note in particular that the  */
/*    mantissa array may be shared between many BigDecimal objects,   */
/*    so that once exposed it must not be altered.                    */
/*                                                                    */
/* 2. This class looks at MathContext class fields directly (for      */
/*    performance).  It must not and does not change them.            */
/*                                                                    */
/* 3. Exponent checking is delayed until finish(), as we know         */
/*    intermediate calculations cannot cause 31-bit overflow.         */
/*    [This assertion depends on MAX_DIGITS in MathContext.]          */
/*                                                                    */
/* 4. Comments for the public API now follow the javadoc conventions. */
/*    The NetRexx -comments option is used to pass these comments     */
/*    through to the generated Java code (with -format, if desired).  */
/*                                                                    */
/* 5. System.arraycopy is faster than explicit loop as follows        */
/*      Mean length 4:  equal                                         */
/*      Mean length 8:  x2                                            */
/*      Mean length 16: x3                                            */
/*      Mean length 24: x4                                            */
/*    From prior experience, we expect mean length a little below 8,  */
/*    but arraycopy is still the one to use, in general, until later  */
/*    measurements suggest otherwise.                                 */
/*                                                                    */
/* 6. 'DMSRCN' referred to below is the original (1981) IBM S/370     */
/*    assembler code implementation of the algorithms below; it is    */
/*    now called IXXRCN and is available with the OS/390 and VM/ESA   */
/*    operating systems.                                              */
/* ------------------------------------------------------------------ */
/* Change History:                                                    */
/* 1997.09.02 Initial version (derived from netrexx.lang classes)     */
/* 1997.09.12 Add lostDigits checking                                 */
/* 1997.10.06 Change mantissa to a byte array                         */
/* 1997.11.22 Rework power [did not prepare arguments, etc.]          */
/* 1997.12.13 multiply did not prepare arguments                      */
/* 1997.12.14 add did not prepare and align arguments correctly       */
/* 1998.05.02 0.07 packaging changes suggested by Sun and Oracle      */
/* 1998.05.21 adjust remainder operator finalization                  */
/* 1998.06.04 rework to pass MathContext to finish() and round()      */
/* 1998.06.06 change format to use round(); support rounding modes    */
/* 1998.06.25 rename to BigDecimal and begin merge                    */
/*            zero can now have trailing zeros (i.e., exp\=0)         */
/* 1998.06.28 new methods: movePointXxxx, scale, toBigInteger         */
/*                         unscaledValue, valueof                     */
/* 1998.07.01 improve byteaddsub to allow array reuse, etc.           */
/* 1998.07.01 make null testing explicit to avoid JIT bug [Win32]     */
/* 1998.07.07 scaled division  [divide(BigDecimal, int, int)]         */
/* 1998.07.08 setScale, faster equals                                 */
/* 1998.07.11 allow 1E6 (no sign) <sigh>; new double/float conversion */
/* 1998.10.12 change package to com.ibm.icu.math                          */
/* 1998.12.14 power operator no longer rounds RHS [to match ANSI]     */
/*            add toBigDecimal() and BigDecimal(java.math.BigDecimal) */
/* 1998.12.29 improve byteaddsub by using table lookup                */
/* 1999.02.04 lostdigits=0 behaviour rounds instead of digits+1 guard */
/* 1999.02.05 cleaner code for BigDecimal(char[])                     */
/* 1999.02.06 add javadoc comments                                    */
/* 1999.02.11 format() changed from 7 to 2 method form                */
/* 1999.03.05 null pointer checking is no longer explicit             */
/* 1999.03.05 simplify; changes from discussion with J. Bloch:        */
/*            null no longer permitted for MathContext; drop boolean, */
/*            byte, char, float, short constructor, deprecate double  */
/*            constructor, no blanks in string constructor, add       */
/*            offset and length version of char[] constructor;        */
/*            add valueOf(double); drop booleanValue, charValue;      */
/*            add ...Exact versions of remaining convertors           */
/* 1999.03.13 add toBigIntegerExact                                   */
/* 1999.03.13 1.00 release to IBM Centre for Java Technology          */
/* 1999.05.27 1.01 correct 0-0.2 bug under scaled arithmetic          */
/* 1999.06.29 1.02 constructors should not allow exponent > 9 digits  */
/* 1999.07.03 1.03 lost digits should not be checked if digits=0      */
/* 1999.07.06      lost digits Exception message changed              */
/* 1999.07.10 1.04 more work on 0-0.2 (scaled arithmetic)             */
/* 1999.07.17      improve messages from pow method                   */
/* 1999.08.08      performance tweaks                                 */
/* 1999.08.15      fastpath in multiply                               */
/* 1999.11.05 1.05 fix problem in intValueExact [e.g., 5555555555]    */
/* 1999.12.22 1.06 remove multiply fastpath, and improve performance  */
/* 2000.01.01      copyright update [Y2K has arrived]                 */
/* 2000.06.18 1.08 no longer deprecate BigDecimal(double)             */
/* ------------------------------------------------------------------ */

/**
 * The <code>BigDecimal</code> class implements immutable arbitrary-precision decimal numbers. The methods of the
 * <code>BigDecimal</code> class provide operations for fixed and floating point arithmetic, comparison, format
 * conversions, and hashing.
 * <p>
 * As the numbers are decimal, there is an exact correspondence between an instance of a <code>BigDecimal</code> object
 * and its <code>String</code> representation; the <code>BigDecimal</code> class provides direct conversions to and from
 * <code>String</code> and character array (<code>char[]</code>) objects, as well as conversions to and from the Java
 * primitive types (which may not be exact) and <code>BigInteger</code>.
 * <p>
 * In the descriptions of constructors and methods in this documentation, the value of a <code>BigDecimal</code> number
 * object is shown as the result of invoking the <code>toString()</code> method on the object. The internal
 * representation of a decimal number is neither defined nor exposed, and is not permitted to affect the result of any
 * operation.
 * <p>
 * The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also
 * documented at <code>http://www2.hursley.ibm.com/decimal</code> <br>
 * <i>[This URL will change.]</i>
 * 
 * <h3>Operator methods</h3>
 * <p>
 * Operations on <code>BigDecimal</code> numbers are controlled by a {@link MathContext} object, which provides the
 * context (precision and other information) for the operation. Methods that can take a <code>MathContext</code>
 * parameter implement the standard arithmetic operators for <code>BigDecimal</code> objects and are known as
 * <i>operator methods</i>. The default settings provided by the constant {@link MathContext#DEFAULT} (<code>digits=9,
 * form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP</code>) perform general-purpose floating point
 * arithmetic to nine digits of precision. The <code>MathContext</code> parameter must not be <code>null</code>.
 * <p>
 * Each operator method also has a version provided which does not take a <code>MathContext</code> parameter. For this
 * version of each method, the context settings used are <code>digits=0,
 * form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>; these settings perform fixed point arithmetic with
 * unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2.
 * <p>
 * For monadic operators, only the optional <code>MathContext</code> parameter is present; the operation acts upon the
 * current object.
 * <p>
 * For dyadic operators, a <code>BigDecimal</code> parameter is always present; it must not be <code>null</code>. The
 * operation acts with the current object being the left-hand operand and the <code>BigDecimal</code> parameter being
 * the right-hand operand.
 * <p>
 * For example, adding two <code>BigDecimal</code> objects referred to by the names <code>award</code> and
 * <code>extra</code> could be written as any of:
 * <p>
 * <code>
 *     award.add(extra)
 * <br>award.add(extra, MathContext.DEFAULT)
 * <br>award.add(extra, acontext)
 * </code>
 * <p>
 * (where <code>acontext</code> is a <code>MathContext</code> object), which would return a <code>BigDecimal</code>
 * object whose value is the result of adding <code>award</code> and <code>extra</code> under the appropriate context
 * settings.
 * <p>
 * When a <code>BigDecimal</code> operator method is used, a set of rules define what the result will be (and, by
 * implication, how the result would be represented as a character string). These rules are defined in the BigDecimal
 * arithmetic documentation (see the URL above), but in summary:
 * <ul>
 * <li>Results are normally calculated with up to some maximum number of significant digits. For example, if the
 * <code>MathContext</code> parameter for an operation were <code>MathContext.DEFAULT</code> then the result would be
 * rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667. <br>
 * You can change the default of 9 significant digits by providing the method with a suitable <code>MathContext</code>
 * object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled)
 * arithmetic is indicated by using a <code>digits</code> setting of 0 (or omitting the <code>MathContext</code>
 * parameter). <br>
 * Similarly, you can change the algorithm used for rounding from the default "classic" algorithm.
 * <li>
 * In standard arithmetic (that is, when the <code>form</code> setting is not <code>PLAIN</code>), a zero result is
 * always expressed as the single digit <code>'0'</code> (that is, with no sign, decimal point, or exponent part).
 * <li>
 * Except for the division and power operators in standard arithmetic, trailing zeros are preserved (this is in contrast
 * to binary floating point operations and most electronic calculators, which lose the information about trailing zeros
 * in the fractional part of results). <br>
 * So, for example:
 * <p>
 * <code>
 *     new BigDecimal("2.40").add(     new BigDecimal("2"))      =&gt; "4.40"
 * <br>new BigDecimal("2.40").subtract(new BigDecimal("2"))      =&gt; "0.40"
 * <br>new BigDecimal("2.40").multiply(new BigDecimal("2"))      =&gt; "4.80"
 * <br>new BigDecimal("2.40").divide(  new BigDecimal("2"), def) =&gt; "1.2"
 * </code>
 * <p>
 * where the value on the right of the <code>=&gt;</code> would be the result of the operation, expressed as a
 * <code>String</code>, and <code>def</code> (in this and following examples) refers to <code>MathContext.DEFAULT</code>
 * ). This preservation of trailing zeros is desirable for most calculations (including financial calculations). If
 * necessary, trailing zeros may be easily removed using division by 1.
 * <li>
 * In standard arithmetic, exponential form is used for a result depending on its value and the current setting of
 * <code>digits</code> (the default is 9 digits). If the number of places needed before the decimal point exceeds the
 * <code>digits</code> setting, or the absolute value of the number is less than <code>0.000001</code>, then the number
 * will be expressed in exponential notation; thus
 * <p>
 * <code>
 *   new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def)
 * </code>
 * <p>
 * results in <code>1E+12</code> instead of <code>1000000000000</code>, and
 * <p>
 * <code>
 *   new BigDecimal("1").divide(new BigDecimal("3E+10"), def)
 * </code>
 * <p>
 * results in <code>3.33333333E-11</code> instead of <code>0.0000000000333333333</code>.
 * <p>
 * The form of the exponential notation (scientific or engineering) is determined by the <code>form</code> setting.
 * </ul>
 * <p>
 * The names of methods in this class follow the conventions established by <code>java.lang.Number</code>,
 * <code>java.math.BigInteger</code>, and <code>java.math.BigDecimal</code> in Java 1.1 and Java 1.2.
 * 
 * @see MathContext
 * @author Mike Cowlishaw
 * @stable ICU 2.0
 */

public class BigDecimal extends java.lang.Number implements java.io.Serializable, java.lang.Comparable<BigDecimal> {
    // private static final java.lang.String $0="BigDecimal.nrx";

    /* ----- Constants ----- */
    /* properties constant public */// useful to others
    /**
     * The <code>BigDecimal</code> constant "0".
     * 
     * @see #ONE
     * @see #TEN
     * @stable ICU 2.0
     */
    public static final com.ibm.icu.math.BigDecimal ZERO = new com.ibm.icu.math.BigDecimal((long) 0); // use long as we
                                                                                                      // want the int
                                                                                                      // constructor
    // .. to be able to use this, for speed

    /**
     * The <code>BigDecimal</code> constant "1".
     * 
     * @see #TEN
     * @see #ZERO
     * @stable ICU 2.0
     */
    public static final com.ibm.icu.math.BigDecimal ONE = new com.ibm.icu.math.BigDecimal((long) 1); // use long as we
                                                                                                     // want the int
                                                                                                     // constructor
    // .. to be able to use this, for speed

    /**
     * The <code>BigDecimal</code> constant "10".
     * 
     * @see #ONE
     * @see #ZERO
     * @stable ICU 2.0
     */
    public static final com.ibm.icu.math.BigDecimal TEN = new com.ibm.icu.math.BigDecimal(10);

    // the rounding modes (copied here for upwards compatibility)
    /**
     * Rounding mode to round to a more positive number.
     * 
     * @see MathContext#ROUND_CEILING
     * @stable ICU 2.0
     */
    public static final int ROUND_CEILING = com.ibm.icu.math.MathContext.ROUND_CEILING;

    /**
     * Rounding mode to round towards zero.
     * 
     * @see MathContext#ROUND_DOWN
     * @stable ICU 2.0
     */
    public static final int ROUND_DOWN = com.ibm.icu.math.MathContext.ROUND_DOWN;

    /**
     * Rounding mode to round to a more negative number.
     * 
     * @see MathContext#ROUND_FLOOR
     * @stable ICU 2.0
     */
    public static final int ROUND_FLOOR = com.ibm.icu.math.MathContext.ROUND_FLOOR;

    /**
     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded down.
     * 
     * @see MathContext#ROUND_HALF_DOWN
     * @stable ICU 2.0
     */
    public static final int ROUND_HALF_DOWN = com.ibm.icu.math.MathContext.ROUND_HALF_DOWN;

    /**
     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded to the nearest even neighbor.
     * 
     * @see MathContext#ROUND_HALF_EVEN
     * @stable ICU 2.0
     */
    public static final int ROUND_HALF_EVEN = com.ibm.icu.math.MathContext.ROUND_HALF_EVEN;

    /**
     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded up.
     * 
     * @see MathContext#ROUND_HALF_UP
     * @stable ICU 2.0
     */
    public static final int ROUND_HALF_UP = com.ibm.icu.math.MathContext.ROUND_HALF_UP;

    /**
     * Rounding mode to assert that no rounding is necessary.
     * 
     * @see MathContext#ROUND_UNNECESSARY
     * @stable ICU 2.0
     */
    public static final int ROUND_UNNECESSARY = com.ibm.icu.math.MathContext.ROUND_UNNECESSARY;

    /**
     * Rounding mode to round away from zero.
     * 
     * @see MathContext#ROUND_UP
     * @stable ICU 2.0
     */
    public static final int ROUND_UP = com.ibm.icu.math.MathContext.ROUND_UP;

    /* properties constant private */// locals
    private static final byte ispos = 1; // ind: indicates positive (must be 1)
    private static final byte iszero = 0; // ind: indicates zero (must be 0)
    private static final byte isneg = -1; // ind: indicates negative (must be -1)
    // [later could add NaN, +/- infinity, here]

    private static final int MinExp = -999999999; // minimum exponent allowed
    private static final int MaxExp = 999999999; // maximum exponent allowed
    private static final int MinArg = -999999999; // minimum argument integer
    private static final int MaxArg = 999999999; // maximum argument integer

    private static final com.ibm.icu.math.MathContext plainMC = new com.ibm.icu.math.MathContext(0,
            com.ibm.icu.math.MathContext.PLAIN); // context for plain unlimited math

    /* properties constant private unused */// present but not referenced
    // Serialization version
    private static final long serialVersionUID = 8245355804974198832L;

    // private static final java.lang.String
    // copyright=" Copyright (c) IBM Corporation 1996, 2000.  All rights reserved. ";

    /* properties static private */
    // Precalculated constant arrays (used by byteaddsub)
    private static byte bytecar[] = new byte[(90 + 99) + 1]; // carry/borrow array
    private static byte bytedig[] = diginit(); // next digit array

    /* ----- Instance properties [all private and immutable] ----- */
    /* properties private */

    /**
     * The indicator. This may take the values:
     * <ul>
     * <li>ispos -- the number is positive <li>iszero -- the number is zero <li>isneg -- the number is negative
     * </ul>
     * 
     * @serial
     */
    private byte ind; // assumed undefined
    // Note: some code below assumes IND = Sign [-1, 0, 1], at present.
    // We only need two bits for this, but use a byte [also permits
    // smooth future extension].

    /**
     * The formatting style. This may take the values:
     * <ul>
     * <li>MathContext.PLAIN -- no exponent needed <li>MathContext.SCIENTIFIC -- scientific notation required <li>
     * MathContext.ENGINEERING -- engineering notation required
     * </ul>
     * <p>
     * This property is an optimization; it allows us to defer number layout until it is actually needed as a string,
     * hence avoiding unnecessary formatting.
     * 
     * @serial
     */
    private byte form = (byte) com.ibm.icu.math.MathContext.PLAIN; // assumed PLAIN
    // We only need two bits for this, at present, but use a byte
    // [again, to allow for smooth future extension]

    /**
     * The value of the mantissa.
     * <p>
     * Once constructed, this may become shared between several BigDecimal objects, so must not be altered.
     * <p>
     * For efficiency (speed), this is a byte array, with each byte taking a value of 0 -&gt; 9.
     * <p>
     * If the first byte is 0 then the value of the number is zero (and mant.length=1, except when constructed from a
     * plain number, for example, 0.000).
     * 
     * @serial
     */
    private byte mant[]; // assumed null

    /**
     * The exponent.
     * <p>
     * For fixed point arithmetic, scale is <code>-exp</code>, and can apply to zero.
     * 
     * Note that this property can have a value less than MinExp when the mantissa has more than one digit.
     * 
     * @serial
     */
    private int exp;

    // assumed 0

    /* ---------------------------------------------------------------- */
    /* Constructors */
    /* ---------------------------------------------------------------- */

    /**
     * Constructs a <code>BigDecimal</code> object from a <code>java.math.BigDecimal</code>.
     * <p>
     * Constructs a <code>BigDecimal</code> as though the parameter had been represented as a <code>String</code> (using
     * its <code>toString</code> method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
     * The parameter must not be <code>null</code>.
     * <p>
     * <i>(Note: this constructor is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class.
     * It would not be present in a <code>java.math</code> version.)</i>
     * 
     * @param bd The <code>BigDecimal</code> to be translated.
     * @stable ICU 2.0
     */

    public BigDecimal(java.math.BigDecimal bd) {
        this(bd.toString());
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code>, with scale 0.
     * <p>
     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>,
     * with a scale of zero. The value of the <code>BigDecimal</code> is identical to the value of the <code>BigInteger
     * </code>. The parameter must not be <code>null</code>.
     * <p>
     * The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the
     * <code>BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero.
     * 
     * @param bi The <code>BigInteger</code> to be converted.
     * @stable ICU 2.0
     */

    public BigDecimal(java.math.BigInteger bi) {
        this(bi.toString(10));
        return;
    }

    // exp remains 0

    /**
     * Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code> and a scale.
     * <p>
     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>,
     * scaled by the second parameter, which may not be negative. The value of the <code>BigDecimal</code> is the <code>
     * BigInteger</code> divided by ten to the power of the scale. The <code>BigInteger</code> parameter must not be
     * <code>null</code>.
     * <p>
     * The <code>BigDecimal</code> will contain only decimal digits, (with an embedded decimal point followed by <code>
     * scale</code> decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the <code>
     * BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero.
     * 
     * @param bi The <code>BigInteger</code> to be converted.
     * @param scale The <code>int</code> specifying the scale.
     * @throws NumberFormatException If the scale is negative.
     * @stable ICU 2.0
     */

    public BigDecimal(java.math.BigInteger bi, int scale) {
        this(bi.toString(10));
        if (scale < 0)
            throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
        exp = -scale; // exponent is -scale
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object from an array of characters.
     * <p>
     * Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character
     * array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be
     * <code>null</code>.
     * <p>
     * Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is
     * already available in character array form.
     * 
     * @param inchars The <code>char[]</code> array containing the number to be converted.
     * @throws NumberFormatException If the parameter is not a valid number.
     * @stable ICU 2.0
     */

    public BigDecimal(char inchars[]) {
        this(inchars, 0, inchars.length);
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object from an array of characters.
     * <p>
     * Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character
     * array (or a subarray of that array) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
     * The first parameter must not be <code>null</code>, and the subarray must be wholly contained within it.
     * <p>
     * Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is
     * already available within a character array.
     * 
     * @param inchars The <code>char[]</code> array containing the number to be converted.
     * @param offset The <code>int</code> offset into the array of the start of the number to be converted.
     * @param length The <code>int</code> length of the number.
     * @throws NumberFormatException If the parameter is not a valid number for any reason.
     * @stable ICU 2.0
     */

    public BigDecimal(char inchars[], int offset, int length) {
        super();
        boolean exotic;
        boolean hadexp;
        int d;
        int dotoff;
        int last;
        int i = 0;
        char si = 0;
        boolean eneg = false;
        int k = 0;
        int elen = 0;
        int j = 0;
        char sj = 0;
        int dvalue = 0;
        int mag = 0;
        // This is the primary constructor; all incoming strings end up
        // here; it uses explicit (inline) parsing for speed and to avoid
        // generating intermediate (temporary) objects of any kind.
        // 1998.06.25: exponent form built only if E/e in string
        // 1998.06.25: trailing zeros not removed for zero
        // 1999.03.06: no embedded blanks; allow offset and length
        if (length <= 0)
            bad(inchars); // bad conversion (empty string)
        // [bad offset will raise array bounds exception]

        /* Handle and step past sign */
        ind = ispos; // assume positive
        if (inchars[offset] == ('-')) {
            length--;
            if (length == 0)
                bad(inchars); // nothing after sign
            ind = isneg;
            offset++;
        } else if (inchars[offset] == ('+')) {
            length--;
            if (length == 0)
                bad(inchars); // nothing after sign
            offset++;
        }

        /* We're at the start of the number */
        exotic = false; // have extra digits
        hadexp = false; // had explicit exponent
        d = 0; // count of digits found
        dotoff = -1; // offset where dot was found
        last = -1; // last character of mantissa
        {
            int $1 = length;
            i = offset;
            i: for (; $1 > 0; $1--, i++) {
                si = inchars[i];
                if (si >= '0') // test for Arabic digit
                    if (si <= '9') {
                        last = i;
                        d++; // still in mantissa
                        continue i;
                    }
                if (si == '.') { // record and ignore
                    if (dotoff >= 0)
                        bad(inchars); // two dots
                    dotoff = i - offset; // offset into mantissa
                    continue i;
                }
                if (si != 'e')
                    if (si != 'E') { // expect an extra digit
                        if ((!(UCharacter.isDigit(si))))
                            bad(inchars); // not a number
                        // defer the base 10 check until later to avoid extra method call
                        exotic = true; // will need conversion later
                        last = i;
                        d++; // still in mantissa
                        continue i;
                    }
                /* Found 'e' or 'E' -- now process explicit exponent */
                // 1998.07.11: sign no longer required
                if ((i - offset) > (length - 2))
                    bad(inchars); // no room for even one digit
                eneg = false;
                if ((inchars[i + 1]) == ('-')) {
                    eneg = true;
                    k = i + 2;
                } else if ((inchars[i + 1]) == ('+'))
                    k = i + 2;
                else
                    k = i + 1;
                // k is offset of first expected digit
                elen = length - ((k - offset)); // possible number of digits
                if ((elen == 0) | (elen > 9))
                    bad(inchars); // 0 or more than 9 digits
                {
                    int $2 = elen;
                    j = k;
                    for (; $2 > 0; $2--, j++) {
                        sj = inchars[j];
                        if (sj < '0')
                            bad(inchars); // always bad
                        if (sj > '9') { // maybe an exotic digit
                            if ((!(UCharacter.isDigit(sj))))
                                bad(inchars); // not a number
                            dvalue = UCharacter.digit(sj, 10); // check base
                            if (dvalue < 0)
                                bad(inchars); // not base 10
                        } else
                            dvalue = ((int) (sj)) - ((int) ('0'));
                        exp = (exp * 10) + dvalue;
                    }
                }/* j */
                if (eneg)
                    exp = -exp; // was negative
                hadexp = true; // remember we had one
                break i; // we are done
            }
        }/* i */

        /* Here when all inspected */
        if (d == 0)
            bad(inchars); // no mantissa digits
        if (dotoff >= 0)
            exp = (exp + dotoff) - d; // adjust exponent if had dot

        /* strip leading zeros/dot (leave final if all 0's) */
        {
            int $3 = last - 1;
            i = offset;
            i: for (; i <= $3; i++) {
                si = inchars[i];
                if (si == '0') {
                    offset++;
                    dotoff--;
                    d--;
                } else if (si == '.') {
                    offset++; // step past dot
                    dotoff--;
                } else if (si <= '9')
                    break i;/* non-0 */
                else {/* exotic */
                    if ((UCharacter.digit(si, 10)) != 0)
                        break i; // non-0 or bad
                    // is 0 .. strip like '0'
                    offset++;
                    dotoff--;
                    d--;
                }
            }
        }/* i */

        /* Create the mantissa array */
        mant = new byte[d]; // we know the length
        j = offset; // input offset
        if (exotic) {
            do { // slow: check for exotica
                {
                    int $4 = d;
                    i = 0;
                    for (; $4 > 0; $4--, i++) {
                        if (i == dotoff)
                            j++; // at dot
                        sj = inchars[j];
                        if (sj <= '9')
                            mant[i] = (byte) (((int) (sj)) - ((int) ('0')));/* easy */
                        else {
                            dvalue = UCharacter.digit(sj, 10);
                            if (dvalue < 0)
                                bad(inchars); // not a number after all
                            mant[i] = (byte) dvalue;
                        }
                        j++;
                    }
                }/* i */
            } while (false);
        }/* exotica */
        else {
            do {
                {
                    int $5 = d;
                    i = 0;
                    for (; $5 > 0; $5--, i++) {
                        if (i == dotoff)
                            j++;
                        mant[i] = (byte) (((int) (inchars[j])) - ((int) ('0')));
                        j++;
                    }
                }/* i */
            } while (false);
        }/* simple */

        /* Looks good. Set the sign indicator and form, as needed. */
        // Trailing zeros are preserved
        // The rule here for form is:
        // If no E-notation, then request plain notation
        // Otherwise act as though add(0,DEFAULT) and request scientific notation
        // [form is already PLAIN]
        if (mant[0] == 0) {
            ind = iszero; // force to show zero
            // negative exponent is significant (e.g., -3 for 0.000) if plain
            if (exp > 0)
                exp = 0; // positive exponent can be ignored
            if (hadexp) { // zero becomes single digit from add
                mant = ZERO.mant;
                exp = 0;
            }
        } else { // non-zero
            // [ind was set earlier]
            // now determine form
            if (hadexp) {
                form = (byte) com.ibm.icu.math.MathContext.SCIENTIFIC;
                // 1999.06.29 check for overflow
                mag = (exp + mant.length) - 1; // true exponent in scientific notation
                if ((mag < MinExp) | (mag > MaxExp))
                    bad(inchars);
            }
        }
        // say 'BD(c[]): mant[0] mantlen exp ind form:' mant[0] mant.length exp ind form
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object directly from a <code>double</code>.
     * <p>
     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary
     * floating point parameter.
     * <p>
     * Note that this constructor it an exact conversion; it does not give the same result as converting <code>num
     * </code> to a <code>String</code> using the <code>Double.toString()</code> method and then using the
     * {@link #BigDecimal(java.lang.String)} constructor. To get that result, use the static {@link #valueOf(double)}
     * method to construct a <code>BigDecimal</code> from a <code>double</code>.
     * 
     * @param num The <code>double</code> to be converted.
     * @throws NumberFormatException If the parameter is infinite or not a number.
     * @stable ICU 2.0
     */

    public BigDecimal(double num) {
        // 1999.03.06: use exactly the old algorithm
        // 2000.01.01: note that this constructor does give an exact result,
        // so perhaps it should not be deprecated
        // 2000.06.18: no longer deprecated
        this((new java.math.BigDecimal(num)).toString());
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object directly from a <code>int</code>.
     * <p>
     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 32-bit signed binary
     * integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus
     * sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
     * 
     * @param num The <code>int</code> to be converted.
     * @stable ICU 2.0
     */

    public BigDecimal(int num) {
        super();
        int mun;
        int i = 0;
        // We fastpath commoners
        if (num <= 9)
            if (num >= (-9)) {
                do {
                    // very common single digit case
                    {/* select */
                        if (num == 0) {
                            mant = ZERO.mant;
                            ind = iszero;
                        } else if (num == 1) {
                            mant = ONE.mant;
                            ind = ispos;
                        } else if (num == (-1)) {
                            mant = ONE.mant;
                            ind = isneg;
                        } else {
                            {
                                mant = new byte[1];
                                if (num > 0) {
                                    mant[0] = (byte) num;
                                    ind = ispos;
                                } else { // num<-1
                                    mant[0] = (byte) -num;
                                    ind = isneg;
                                }
                            }
                        }
                    }
                    return;
                } while (false);
            }/* singledigit */

        /* We work on negative numbers so we handle the most negative number */
        if (num > 0) {
            ind = ispos;
            num = -num;
        } else
            ind = isneg;/* negative */// [0 case already handled]
        // [it is quicker, here, to pre-calculate the length with
        // one loop, then allocate exactly the right length of byte array,
        // then re-fill it with another loop]
        mun = num; // working copy
        {
            i = 9;
            i: for (;; i--) {
                mun = mun / 10;
                if (mun == 0)
                    break i;
            }
        }/* i */
        // i is the position of the leftmost digit placed
        mant = new byte[10 - i];
        {
            i = (10 - i) - 1;
            i: for (;; i--) {
                mant[i] = (byte) -(((byte) (num % 10)));
                num = num / 10;
                if (num == 0)
                    break i;
            }
        }/* i */
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object directly from a <code>long</code>.
     * <p>
     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary
     * integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus
     * sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
     * 
     * @param num The <code>long</code> to be converted.
     * @stable ICU 2.0
     */

    public BigDecimal(long num) {
        super();
        long mun;
        int i = 0;
        // Not really worth fastpathing commoners in this constructor [also,
        // we use this to construct the static constants].
        // This is much faster than: this(String.valueOf(num).toCharArray())
        /* We work on negative num so we handle the most negative number */
        if (num > 0) {
            ind = ispos;
            num = -num;
        } else if (num == 0)
            ind = iszero;
        else
            ind = isneg;/* negative */
        mun = num;
        {
            i = 18;
            i: for (;; i--) {
                mun = mun / 10;
                if (mun == 0)
                    break i;
            }
        }/* i */
        // i is the position of the leftmost digit placed
        mant = new byte[19 - i];
        {
            i = (19 - i) - 1;
            i: for (;; i--) {
                mant[i] = (byte) -(((byte) (num % 10)));
                num = num / 10;
                if (num == 0)
                    break i;
            }
        }/* i */
        return;
    }

    /**
     * Constructs a <code>BigDecimal</code> object from a <code>String</code>.
     * <p>
     * Constructs a <code>BigDecimal</code> from the parameter, which must not be <code>null</code> and must represent a
     * valid <i>number</i>, as described formally in the documentation referred to {@link BigDecimal above}.
     * <p>
     * In summary, numbers in <code>String</code> form must have at least one digit, may have a leading sign, may have a
     * decimal point, and exponential notation may be used. They follow conventional syntax, and may not contain blanks.
     * <p>
     * Some valid strings from which a <code>BigDecimal</code> might be constructed are:
     * 
     * <pre>
     * 
     * "0" -- Zero "12" -- A whole number "-76" -- A signed whole number "12.70" -- Some decimal places "+0.003" -- Plus
     * sign is allowed "17." -- The same as 17 ".5" -- The same as 0.5 "4E+9" -- Exponential notation "0.73e-7" --
     * Exponential notation
     * 
     * </pre>
     * <p>
     * (Exponential notation means that the number includes an optional sign and a power of ten following an
     * '<code>E</code>' that indicates how the decimal point will be shifted. Thus the <code>"4E+9"</code> above is
     * just a short way of writing <code>4000000000</code>, and the <code>"0.73e-7"</code> is short for <code>
     * 0.000000073</code>.)
     * <p>
     * The <code>BigDecimal</code> constructed from the String is in a standard form, with no blanks, as though the
     * {@link #add(BigDecimal)} method had been used to add zero to the number with unlimited precision. If the string
     * uses exponential notation (that is, includes an <code>e</code> or an <code>E</code>), then the <code>BigDecimal
     * </code> number will be expressed in scientific notation (where the power of ten is adjusted so there is a single
     * non-zero digit to the left of the decimal point); in this case if the number is zero then it will be expressed as
     * the single digit 0, and if non-zero it will have an exponent unless that exponent would be 0. The exponent must
     * fit in nine digits both before and after it is expressed in scientific notation.
     * <p>
     * Any digits in the parameter must be decimal; that is, <code>Character.digit(c, 10)</code> (where <code>c</code>
     * is the character in question) would not return -1.
     * 
     * @param string The <code>String</code> to be converted.
     * @throws NumberFormatException If the parameter is not a valid number.
     * @stable ICU 2.0
     */

    public BigDecimal(java.lang.String string) {
        this(string.toCharArray(), 0, string.length());
        return;
    }

    /* <sgml> Make a default BigDecimal object for local use. </sgml> */

    private BigDecimal() {
        super();
        return;
    }

    /* ---------------------------------------------------------------- */
    /* Operator methods [methods which take a context parameter] */
    /* ---------------------------------------------------------------- */

    /**
     * Returns a plain <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
     * <p>
     * The same as {@link #abs(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will be <code>this.scale()</code>
     * 
     * @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal abs() {
        return this.abs(plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
     * <p>
     * If the current object is zero or positive, then the same result as invoking the {@link #plus(MathContext)} method
     * with the same parameter is returned. Otherwise, the same result as invoking the {@link #negate(MathContext)}
     * method with the same parameter is returned.
     * 
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal abs(com.ibm.icu.math.MathContext set) {
        if (this.ind == isneg)
            return this.negate(set);
        return this.plus(set);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic.
     * <p>
     * The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the addition.
     * @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs) {
        return this.add(rhs, plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>this+rhs</code>.
     * <p>
     * Implements the addition (<b><code>+</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the addition.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        com.ibm.icu.math.BigDecimal lhs;
        int reqdig;
        com.ibm.icu.math.BigDecimal res;
        byte usel[];
        int usellen;
        byte user[];
        int userlen;
        int newlen = 0;
        int tlen = 0;
        int mult = 0;
        byte t[] = null;
        int ia = 0;
        int ib = 0;
        int ea = 0;
        int eb = 0;
        byte ca = 0;
        byte cb = 0;
        /* determine requested digits and form */
        if (set.lostDigits)
            checkdigits(rhs, set.digits);
        lhs = this; // name for clarity and proxy

        /* Quick exit for add floating 0 */
        // plus() will optimize to return same object if possible
        if (lhs.ind == 0)
            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
                return rhs.plus(set);
        if (rhs.ind == 0)
            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
                return lhs.plus(set);

        /* Prepare numbers (round, unless unlimited precision) */
        reqdig = set.digits; // local copy (heavily used)
        if (reqdig > 0) {
            if (lhs.mant.length > reqdig)
                lhs = clone(lhs).round(set);
            if (rhs.mant.length > reqdig)
                rhs = clone(rhs).round(set);
            // [we could reuse the new LHS for result in this case]
        }

        res = new com.ibm.icu.math.BigDecimal(); // build result here

        /*
         * Now see how much we have to pad or truncate lhs or rhs in order to align the numbers. If one number is much
         * larger than the other, then the smaller cannot affect the answer [but we may still need to pad with up to
         * DIGITS trailing zeros].
         */
        // Note sign may be 0 if digits (reqdig) is 0
        // usel and user will be the byte arrays passed to the adder; we'll
        // use them on all paths except quick exits
        usel = lhs.mant;
        usellen = lhs.mant.length;
        user = rhs.mant;
        userlen = rhs.mant.length;
        {
            do {/* select */
                if (lhs.exp == rhs.exp) {/* no padding needed */
                    // This is the most common, and fastest, path
                    res.exp = lhs.exp;
                } else if (lhs.exp > rhs.exp) { // need to pad lhs and/or truncate rhs
                    newlen = (usellen + lhs.exp) - rhs.exp;
                    /*
                     * If, after pad, lhs would be longer than rhs by digits+1 or more (and digits>0) then rhs cannot
                     * affect answer, so we only need to pad up to a length of DIGITS+1.
                     */
                    if (newlen >= ((userlen + reqdig) + 1))
                        if (reqdig > 0) {
                            // LHS is sufficient
                            res.mant = usel;
                            res.exp = lhs.exp;
                            res.ind = lhs.ind;
                            if (usellen < reqdig) { // need 0 padding
                                res.mant = extend(lhs.mant, reqdig);
                                res.exp = res.exp - ((reqdig - usellen));
                            }
                            return res.finish(set, false);
                        }
                    // RHS may affect result
                    res.exp = rhs.exp; // expected final exponent
                    if (newlen > (reqdig + 1))
                        if (reqdig > 0) {
                            // LHS will be max; RHS truncated
                            tlen = (newlen - reqdig) - 1; // truncation length
                            userlen = userlen - tlen;
                            res.exp = res.exp + tlen;
                            newlen = reqdig + 1;
                        }
                    if (newlen > usellen)
                        usellen = newlen; // need to pad LHS
                } else { // need to pad rhs and/or truncate lhs
                    newlen = (userlen + rhs.exp) - lhs.exp;
                    if (newlen >= ((usellen + reqdig) + 1))
                        if (reqdig > 0) {
                            // RHS is sufficient
                            res.mant = user;
                            res.exp = rhs.exp;
                            res.ind = rhs.ind;
                            if (userlen < reqdig) { // need 0 padding
                                res.mant = extend(rhs.mant, reqdig);
                                res.exp = res.exp - ((reqdig - userlen));
                            }
                            return res.finish(set, false);
                        }
                    // LHS may affect result
                    res.exp = lhs.exp; // expected final exponent
                    if (newlen > (reqdig + 1))
                        if (reqdig > 0) {
                            // RHS will be max; LHS truncated
                            tlen = (newlen - reqdig) - 1; // truncation length
                            usellen = usellen - tlen;
                            res.exp = res.exp + tlen;
                            newlen = reqdig + 1;
                        }
                    if (newlen > userlen)
                        userlen = newlen; // need to pad RHS
                }
            } while (false);
        }/* padder */

        /* OK, we have aligned mantissas. Now add or subtract. */
        // 1998.06.27 Sign may now be 0 [e.g., 0.000] .. treat as positive
        // 1999.05.27 Allow for 00 on lhs [is not larger than 2 on rhs]
        // 1999.07.10 Allow for 00 on rhs [is not larger than 2 on rhs]
        if (lhs.ind == iszero)
            res.ind = ispos;
        else
            res.ind = lhs.ind; // likely sign, all paths
        if (((lhs.ind == isneg) ? 1 : 0) == ((rhs.ind == isneg) ? 1 : 0)) // same sign, 0 non-negative
            mult = 1;
        else {
            do { // different signs, so subtraction is needed
                mult = -1; // will cause subtract
                /*
                 * Before we can subtract we must determine which is the larger, as our add/subtract routine only
                 * handles non-negative results so we may need to swap the operands.
                 */
                {
                    do {/* select */
                        if (rhs.ind == iszero) {
                            // original A bigger
                        } else if ((usellen < userlen) | (lhs.ind == iszero)) { // original B bigger
                            t = usel;
                            usel = user;
                            user = t; // swap
                            tlen = usellen;
                            usellen = userlen;
                            userlen = tlen; // ..
                            res.ind = (byte) -res.ind; // and set sign
                        } else if (usellen > userlen) {
                            // original A bigger
                        } else {
                            {/* logical lengths the same */// need compare
                                /* may still need to swap: compare the strings */
                                ia = 0;
                                ib = 0;
                                ea = usel.length - 1;
                                eb = user.length - 1;
                                {
                                    compare: for (;;) {
                                        if (ia <= ea)
                                            ca = usel[ia];
                                        else {
                                            if (ib > eb) {/* identical */
                                                if (set.form != com.ibm.icu.math.MathContext.PLAIN)
                                                    return ZERO;
                                                // [if PLAIN we must do the subtract, in case of 0.000 results]
                                                break compare;
                                            }
                                            ca = (byte) 0;
                                        }
                                        if (ib <= eb)
                                            cb = user[ib];
                                        else
                                            cb = (byte) 0;
                                        if (ca != cb) {
                                            if (ca < cb) {/* swap needed */
                                                t = usel;
                                                usel = user;
                                                user = t; // swap
                                                tlen = usellen;
                                                usellen = userlen;
                                                userlen = tlen; // ..
                                                res.ind = (byte) -res.ind;
                                            }
                                            break compare;
                                        }
                                        /* mantissas the same, so far */
                                        ia++;
                                        ib++;
                                    }
                                }/* compare */
                            } // lengths the same
                        }
                    } while (false);
                }/* swaptest */
            } while (false);
        }/* signdiff */

        /* here, A is > B if subtracting */
        // add [A+B*1] or subtract [A+(B*-1)]
        res.mant = byteaddsub(usel, usellen, user, userlen, mult, false);
        // [reuse possible only after chop; accounting makes not worthwhile]

        // Finish() rounds before stripping leading 0's, then sets form, etc.
        return res.finish(set, false);
    }

    /**
     * Compares this <code>BigDecimal</code> to another, using unlimited precision.
     * <p>
     * The same as {@link #compareTo(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
     * @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to,
     *         or greater than <code>rhs</code>.
     * @stable ICU 2.0
     */

    public int compareTo(com.ibm.icu.math.BigDecimal rhs) {
        return this.compareTo(rhs, plainMC);
    }

    /**
     * Compares this <code>BigDecimal</code> to another.
     * <p>
     * Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}),
     * and returns a result of type <code>int</code>.
     * <p>
     * The result will be:
     * <table cellpadding=2>
     * <tr>
     * <td align=right><b>-1</b></td> <td>if the current object is less than the first parameter</td>
     * </tr>
     * <tr>
     * <td align=right><b>0</b></td> <td>if the current object is equal to the first parameter</td>
     * </tr>
     * <tr>
     * <td align=right><b>1</b></td> <td>if the current object is greater than the first parameter.</td>
     * </tr>
     * </table>
     * <p>
     * A {@link #compareTo(BigDecimal)} method is also provided.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to,
     *         or greater than <code>rhs</code>.
     * @stable ICU 2.0
     */

    public int compareTo(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        int thislength = 0;
        int i = 0;
        com.ibm.icu.math.BigDecimal newrhs;
        // rhs=null will raise NullPointerException, as per Comparable interface
        if (set.lostDigits)
            checkdigits(rhs, set.digits);
        // [add will recheck in slowpath cases .. but would report -rhs]
        if ((this.ind == rhs.ind) & (this.exp == rhs.exp)) {
            /* sign & exponent the same [very common] */
            thislength = this.mant.length;
            if (thislength < rhs.mant.length)
                return (byte) -this.ind;
            if (thislength > rhs.mant.length)
                return this.ind;
            /*
             * lengths are the same; we can do a straight mantissa compare unless maybe rounding [rounding is very
             * unusual]
             */
            if ((thislength <= set.digits) | (set.digits == 0)) {
                {
                    int $6 = thislength;
                    i = 0;
                    for (; $6 > 0; $6--, i++) {
                        if (this.mant[i] < rhs.mant[i])
                            return (byte) -this.ind;
                        if (this.mant[i] > rhs.mant[i])
                            return this.ind;
                    }
                }/* i */
                return 0; // identical
            }
            /* drop through for full comparison */
        } else {
            /* More fastpaths possible */
            if (this.ind < rhs.ind)
                return -1;
            if (this.ind > rhs.ind)
                return 1;
        }
        /* carry out a subtract to make the comparison */
        newrhs = clone(rhs); // safe copy
        newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
        return this.add(newrhs, set).ind; // add, and return sign of result
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic.
     * <p>
     * The same as {@link #divide(BigDecimal, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * rounding mode is {@link MathContext#ROUND_HALF_UP}.
     * 
     * The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
     * the latter were formatted without exponential notation.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic.
     * @throws ArithmeticException If <code>rhs</code> is zero.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs) {
        return this.dodivide('D', rhs, plainMC, -1);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a
     * rounding mode.
     * <p>
     * The same as {@link #divide(BigDecimal, int, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * second parameter is <code>this.scale()</code>, and the third is <code>round</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will therefore be the same as the scale of the current
     * object, if the latter were formatted without exponential notation.
     * <p>
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and
     *         the specified rounding mode.
     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>this.scale()</code> is insufficient to represent the result exactly.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int round) {
        com.ibm.icu.math.MathContext set;
        set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round,
                                                                                                     // too]
        return this.dodivide('D', rhs, set, -1); // take scale from LHS
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a
     * given scale and rounding mode.
     * <p>
     * The same as {@link #divide(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
     * <code>new MathContext(0, MathContext.PLAIN, false, round)</code>, except that the length of the decimal part (the
     * scale) to be used for the result is explicit rather than being taken from <code>this</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
     * the latter were formatted without exponential notation.
     * <p>
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
     * @param scale The <code>int</code> scale to be used for the result.
     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and
     *         the specified rounding mode.
     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @throws ArithmeticException if <code>scale</code> is negative.
     * @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>scale</code> is insufficient
     *             to represent the result exactly.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int scale, int round) {
        com.ibm.icu.math.MathContext set;
        if (scale < 0)
            throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
        set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round]
        return this.dodivide('D', rhs, set, scale);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>this/rhs</code>.
     * <p>
     * Implements the division (<b><code>/</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>this/rhs</code>.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        return this.dodivide('D', rhs, set, -1);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
     * <p>
     * The same as {@link #divideInteger(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs
     * </code>, and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the integer division.
     * @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs) {
        // scale 0 to drop .000 when plain
        return this.dodivide('I', rhs, plainMC, 0);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
     * <p>
     * Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class
     * header}), and returns the result as a <code>BigDecimal</code> object.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the integer division.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @throws ArithmeticException if the result will not fit in the number of digits specified for the context.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        // scale 0 to drop .000 when plain
        return this.dodivide('I', rhs, set, 0);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
     * <p>
     * The same as {@link #max(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
     * @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) {
        return this.max(rhs, plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
     * <p>
     * Returns the larger of the current object and the first parameter.
     * <p>
     * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>1
     * </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object
     * (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the
     * {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code>
     * parameter) is returned.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        if ((this.compareTo(rhs, set)) >= 0)
            return this.plus(set);
        else
            return rhs.plus(set);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
     * <p>
     * The same as {@link #min(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
     * @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) {
        return this.min(rhs, plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
     * <p>
     * Returns the smaller of the current object and the first parameter.
     * <p>
     * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>-1
     * </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object
     * (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the
     * {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code>
     * parameter) is returned.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        if ((this.compareTo(rhs, set)) <= 0)
            return this.plus(set);
        else
            return rhs.plus(set);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic.
     * <p>
     * The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will be the sum of the scales of the operands, if they
     * were formatted without exponential notation.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication.
     * @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs) {
        return this.multiply(rhs, plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>this*rhs</code>.
     * <p>
     * Implements the multiplication (<b><code>&#42;</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        com.ibm.icu.math.BigDecimal lhs;
        int padding;
        int reqdig;
        byte multer[] = null;
        byte multand[] = null;
        int multandlen;
        int acclen = 0;
        com.ibm.icu.math.BigDecimal res;
        byte acc[];
        int n = 0;
        byte mult = 0;
        if (set.lostDigits)
            checkdigits(rhs, set.digits);
        lhs = this; // name for clarity and proxy

        /* Prepare numbers (truncate, unless unlimited precision) */
        padding = 0; // trailing 0's to add
        reqdig = set.digits; // local copy
        if (reqdig > 0) {
            if (lhs.mant.length > reqdig)
                lhs = clone(lhs).round(set);
            if (rhs.mant.length > reqdig)
                rhs = clone(rhs).round(set);
            // [we could reuse the new LHS for result in this case]
        } else {/* unlimited */
            // fixed point arithmetic will want every trailing 0; we add these
            // after the calculation rather than before, for speed.
            if (lhs.exp > 0)
                padding = padding + lhs.exp;
            if (rhs.exp > 0)
                padding = padding + rhs.exp;
        }

        // For best speed, as in DMSRCN, we use the shorter number as the
        // multiplier and the longer as the multiplicand.
        // 1999.12.22: We used to special case when the result would fit in
        // a long, but with Java 1.3 this gave no advantage.
        if (lhs.mant.length < rhs.mant.length) {
            multer = lhs.mant;
            multand = rhs.mant;
        } else {
            multer = rhs.mant;
            multand = lhs.mant;
        }

        /* Calculate how long result byte array will be */
        multandlen = (multer.length + multand.length) - 1; // effective length
        // optimize for 75% of the cases where a carry is expected...
        if ((multer[0] * multand[0]) > 9)
            acclen = multandlen + 1;
        else
            acclen = multandlen;

        /* Now the main long multiplication loop */
        res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
        acc = new byte[acclen]; // accumulator, all zeros
        // 1998.07.01: calculate from left to right so that accumulator goes
        // to likely final length on first addition; this avoids a one-digit
        // extension (and object allocation) each time around the loop.
        // Initial number therefore has virtual zeros added to right.
        {
            int $7 = multer.length;
            n = 0;
            for (; $7 > 0; $7--, n++) {
                mult = multer[n];
                if (mult != 0) { // [optimization]
                    // accumulate [accumulator is reusable array]
                    acc = byteaddsub(acc, acc.length, multand, multandlen, mult, true);
                }
                // divide multiplicand by 10 for next digit to right
                multandlen--; // 'virtual length'
            }
        }/* n */

        res.ind = (byte) (lhs.ind * rhs.ind); // final sign
        res.exp = (lhs.exp + rhs.exp) - padding; // final exponent
        // [overflow is checked by finish]

        /* add trailing zeros to the result, if necessary */
        if (padding == 0)
            res.mant = acc;
        else
            res.mant = extend(acc, acc.length + padding); // add trailing 0s
        return res.finish(set, false);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>-this</code>.
     * <p>
     * The same as {@link #negate(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>
     * .
     * <p>
     * The length of the decimal part (the scale) of the result will be be <code>this.scale()</code>
     * 
     * 
     * @return A <code>BigDecimal</code> whose value is <code>-this</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal negate() {
        return this.negate(plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>-this</code>.
     * <p>
     * Implements the negation (Prefix <b><code>-</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * 
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>-this</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal negate(com.ibm.icu.math.MathContext set) {
        com.ibm.icu.math.BigDecimal res;
        // Originally called minus(), changed to matched Java precedents
        // This simply clones, flips the sign, and possibly rounds
        if (set.lostDigits)
            checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
        res = clone(this); // safe copy
        res.ind = (byte) -res.ind;
        return res.finish(set, false);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>+this</code>. Note that <code>this</code> is not
     * necessarily a plain <code>BigDecimal</code>, but the result will always be.
     * <p>
     * The same as {@link #plus(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will be be <code>this.scale()</code>
     * 
     * @return A <code>BigDecimal</code> whose value is <code>+this</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal plus() {
        return this.plus(plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>+this</code>.
     * <p>
     * Implements the plus (Prefix <b><code>+</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * <p>
     * This method is useful for rounding or otherwise applying a context to a decimal value.
     * 
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>+this</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal plus(com.ibm.icu.math.MathContext set) {
        // This clones and forces the result to the new settings
        // May return same object
        if (set.lostDigits)
            checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
        // Optimization: returns same object for some common cases
        if (set.form == com.ibm.icu.math.MathContext.PLAIN)
            if (this.form == com.ibm.icu.math.MathContext.PLAIN) {
                if (this.mant.length <= set.digits)
                    return this;
                if (set.digits == 0)
                    return this;
            }
        return clone(this).finish(set, false);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic.
     * <p>
     * The same as {@link #pow(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * The parameter is the power to which the <code>this</code> will be raised; it must be in the range 0 through
     * 999999999, and must have a decimal part of zero. Note that these restrictions may be removed in the future, so
     * they should not be used as a test for a whole number.
     * <p>
     * In addition, the power must not be negative, as no <code>MathContext</code> is used and so the result would then
     * always be 0.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power).
     * @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic.
     * @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs) {
        return this.pow(rhs, plainMC);
    }

    // The name for this method is inherited from the precedent set by the
    // BigInteger and Math classes.

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>this**rhs</code>.
     * <p>
     * Implements the power (<b><code>^</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * <p>
     * The first parameter is the power to which the <code>this</code> will be raised; it must be in the range
     * -999999999 through 999999999, and must have a decimal part of zero. Note that these restrictions may be removed
     * in the future, so they should not be used as a test for a whole number.
     * <p>
     * If the <code>digits</code> setting of the <code>MathContext</code> parameter is 0, the power must be zero or
     * positive.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power).
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>.
     * @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        int n;
        com.ibm.icu.math.BigDecimal lhs;
        int reqdig;
        int workdigits = 0;
        int L = 0;
        com.ibm.icu.math.MathContext workset;
        com.ibm.icu.math.BigDecimal res;
        boolean seenbit;
        int i = 0;
        if (set.lostDigits)
            checkdigits(rhs, set.digits);
        n = rhs.intcheck(MinArg, MaxArg); // check RHS by the rules
        lhs = this; // clarified name

        reqdig = set.digits; // local copy (heavily used)
        if (reqdig == 0) {
            if (rhs.ind == isneg)
                throw new java.lang.ArithmeticException("Negative power:" + " " + rhs.toString());
            workdigits = 0;
        } else {/* non-0 digits */
            if ((rhs.mant.length + rhs.exp) > reqdig)
                throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());

            /* Round the lhs to DIGITS if need be */
            if (lhs.mant.length > reqdig)
                lhs = clone(lhs).round(set);

            /* L for precision calculation [see ANSI X3.274-1996] */
            L = rhs.mant.length + rhs.exp; // length without decimal zeros/exp
            workdigits = (reqdig + L) + 1; // calculate the working DIGITS
        }

        /* Create a copy of set for working settings */
        // Note: no need to check for lostDigits again.
        // 1999.07.17 Note: this construction must follow RHS check
        workset = new com.ibm.icu.math.MathContext(workdigits, set.form, false, set.roundingMode);

        res = ONE; // accumulator
        if (n == 0)
            return res; // x**0 == 1
        if (n < 0)
            n = -n; // [rhs.ind records the sign]
        seenbit = false; // set once we've seen a 1-bit
        {
            i = 1;
            i: for (;; i++) { // for each bit [top bit ignored]
                n = n + n; // shift left 1 bit
                if (n < 0) { // top bit is set
                    seenbit = true; // OK, we're off
                    res = res.multiply(lhs, workset); // acc=acc*x
                }
                if (i == 31)
                    break i; // that was the last bit
                if ((!seenbit))
                    continue i; // we don't have to square 1
                res = res.multiply(res, workset); // acc=acc*acc [square]
            }
        }/* i */// 32 bits
        if (rhs.ind < 0) // was a **-n [hence digits>0]
            res = ONE.divide(res, workset); // .. so acc=1/acc
        return res.finish(set, true); // round and strip [original digits]
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point
     * arithmetic.
     * <p>
     * The same as {@link #remainder(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * This is not the modulo operator -- the result may be negative.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation.
     * @return A <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point
     *         arithmetic.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs) {
        return this.dodivide('R', rhs, plainMC, -1);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>.
     * <p>
     * Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}),
     * and returns the result as a <code>BigDecimal</code> object.
     * <p>
     * This is not the modulo operator -- the result may be negative.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is the remainder of <code>this+rhs</code>.
     * @throws ArithmeticException if <code>rhs</code> is zero.
     * @throws ArithmeticException  if the integer part of the result will not fit in the number of digits specified for the context.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        return this.dodivide('R', rhs, set, -1);
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic.
     * <p>
     * The same as {@link #subtract(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
     * <p>
     * The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction.
     * @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs) {
        return this.subtract(rhs, plainMC);
    }

    /**
     * Returns a <code>BigDecimal</code> whose value is <code>this-rhs</code>.
     * <p>
     * Implements the subtraction (<b><code>-</code></b>) operator (as defined in the decimal documentation, see
     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
     * 
     * @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction.
     * @param set The <code>MathContext</code> arithmetic settings.
     * @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
        com.ibm.icu.math.BigDecimal newrhs;
        if (set.lostDigits)
            checkdigits(rhs, set.digits);
        // [add will recheck .. but would report -rhs]
        /* carry out the subtraction */
        // we could fastpath -0, but it is too rare.
        newrhs = clone(rhs); // safe copy
        newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
        return this.add(newrhs, set); // arithmetic
    }

    /* ---------------------------------------------------------------- */
    /* Other methods */
    /* ---------------------------------------------------------------- */

    /**
     * Converts this <code>BigDecimal</code> to a <code>byte</code>. If the <code>BigDecimal</code> has a non-zero
     * decimal part or is out of the possible range for a <code>byte</code> (8-bit signed integer) result then an <code>
     * ArithmeticException</code> is thrown.
     * 
     * @return A <code>byte</code> equal in value to <code>this</code>.
     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>byte</code>.
     * @stable ICU 2.0
     */

    public byte byteValueExact() {
        int num;
        num = this.intValueExact(); // will check decimal part too
        if ((num > 127) | (num < (-128)))
            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
        return (byte) num;
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>double</code>. If the <code>BigDecimal</code> is out of the
     * possible range for a <code>double</code> (64-bit signed floating point) result then an <code>ArithmeticException
     * </code> is thrown.
     * <p>
     * The double produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and
     * then converting it using the <code>Double(String)</code> constructor; this can result in values of <code>
     * Double.NEGATIVE_INFINITY</code> or <code>Double.POSITIVE_INFINITY</code>.
     * 
     * @return A <code>double</code> corresponding to <code>this</code>.
     * @stable ICU 2.0
     */

    public double doubleValue() {
        // We go via a String [as does BigDecimal in JDK 1.2]
        // Next line could possibly raise NumberFormatException
        return java.lang.Double.valueOf(this.toString()).doubleValue();
    }

    /**
     * Compares this <code>BigDecimal</code> with <code>rhs</code> for equality.
     * <p>
     * If the parameter is <code>null</code>, or is not an instance of the BigDecimal type, or is not exactly equal to
     * the current <code>BigDecimal</code> object, then <i>false</i> is returned. Otherwise, <i>true</i> is returned.
     * <p>
     * "Exactly equal", here, means that the <code>String</code> representations of the <code>BigDecimal</code> numbers
     * are identical (they have the same characters in the same sequence).
     * <p>
     * The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons.
     * 
     * @param obj The <code>Object</code> for the right hand side of the comparison.
     * @return A <code>boolean</code> whose value <i>true</i> if and only if the operands have identical string
     *         representations.
     * @throws ClassCastException if <code>rhs</code> cannot be cast to a <code>BigDecimal</code> object.
     * @stable ICU 2.0
     * @see #compareTo(BigDecimal)
     * @see #compareTo(BigDecimal, MathContext)
     */

    public boolean equals(java.lang.Object obj) {
        com.ibm.icu.math.BigDecimal rhs;
        int i = 0;
        char lca[] = null;
        char rca[] = null;
        // We are equal iff toString of both are exactly the same
        if (obj == null)
            return false; // not equal
        if ((!(((obj instanceof com.ibm.icu.math.BigDecimal)))))
            return false; // not a decimal
        rhs = (com.ibm.icu.math.BigDecimal) obj; // cast; we know it will work
        if (this.ind != rhs.ind)
            return false; // different signs never match
        if (((this.mant.length == rhs.mant.length) & (this.exp == rhs.exp)) & (this.form == rhs.form))

        { // mantissas say all
            // here with equal-length byte arrays to compare
            {
                int $8 = this.mant.length;
                i = 0;
                for (; $8 > 0; $8--, i++) {
                    if (this.mant[i] != rhs.mant[i])
                        return false;
                }
            }/* i */
        } else { // need proper layout
            lca = this.layout(); // layout to character array
            rca = rhs.layout();
            if (lca.length != rca.length)
                return false; // mismatch
            // here with equal-length character arrays to compare
            {
                int $9 = lca.length;
                i = 0;
                for (; $9 > 0; $9--, i++) {
                    if (lca[i] != rca[i])
                        return false;
                }
            }/* i */
        }
        return true; // arrays have identical content
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>float</code>. If the <code>BigDecimal</code> is out of the
     * possible range for a <code>float</code> (32-bit signed floating point) result then an <code>ArithmeticException
     * </code> is thrown.
     * <p>
     * The float produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and
     * then converting it using the <code>Float(String)</code> constructor; this can result in values of <code>
     * Float.NEGATIVE_INFINITY</code> or <code>Float.POSITIVE_INFINITY</code>.
     * 
     * @return A <code>float</code> corresponding to <code>this</code>.
     * @stable ICU 2.0
     */

    public float floatValue() {
        return java.lang.Float.valueOf(this.toString()).floatValue();
    }

    /**
     * Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters.
     * <p>
     * <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat
     * </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
     * necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
     * for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
     * </i>
     * <p>
     * The parameters, for both forms of the <code>format</code> method are all of type <code>int</code>. A value of -1
     * for any parameter indicates that the default action or value for that parameter should be used.
     * <p>
     * The parameters, <code>before</code> and <code>after</code>, specify the number of characters to be used for the
     * integer part and decimal part of the result respectively. Exponential notation is not used. If either parameter
     * is -1 (which indicates the default action), the number of characters used will be exactly as many as are needed
     * for that part.
     * <p>
     * <code>before</code> must be a positive number; if it is larger than is needed to contain the integer part, that
     * part is padded on the left with blanks to the requested length. If <code>before</code> is not large enough to
     * contain the integer part of the number (including the sign, for negative numbers) an exception is thrown.
     * <p>
     * <code>after</code> must be a non-negative number; if it is not the same size as the decimal part of the number,
     * the number will be rounded (or extended with zeros) to fit. Specifying 0 for <code>after</code> will cause the
     * number to be rounded to an integer (that is, it will have no decimal part or decimal point). The rounding method
     * will be the default, <code>MathContext.ROUND_HALF_UP</code>.
     * <p>
     * Other rounding methods, and the use of exponential notation, can be selected by using
     * {@link #format(int,int,int,int,int,int)}. Using the two-parameter form of the method has exactly the same effect
     * as using the six-parameter form with the final four parameters all being -1.
     * 
     * @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as are needed'.
     * @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as are needed'.
     * @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified parameters
     * @throws ArithmeticException if the number cannot be laid out as requested.
     * @throws IllegalArgumentException if a parameter is out of range.
     * @stable ICU 2.0
     * @see #toString
     * @see #toCharArray
     */

    public java.lang.String format(int before, int after) {
        return format(before, after, -1, -1, com.ibm.icu.math.MathContext.SCIENTIFIC, ROUND_HALF_UP);
    }

    /**
     * Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters and
     * allowing exponential notation.
     * <p>
     * <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat
     * </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
     * necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
     * for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
     * </i>
     * <p>
     * The parameters are all of type <code>int</code>. A value of -1 for any parameter indicates that the default
     * action or value for that parameter should be used.
     * <p>
     * The first two parameters (<code>before</code> and <code>after</code>) specify the number of characters to be used
     * for the integer part and decimal part of the result respectively, as defined for {@link #format(int,int)}. If
     * either of these is -1 (which indicates the default action), the number of characters used will be exactly as many
     * as are needed for that part.
     * <p>
     * The remaining parameters control the use of exponential notation and rounding. Three (<code>explaces</code>,
     * <code>exdigits</code>, and <code>exform</code>) control the exponent part of the result. As before, the default
     * action for any of these parameters may be selected by using the value -1.
     * <p>
     * <code>explaces</code> must be a positive number; it sets the number of places (digits after the sign of the
     * exponent) to be used for any exponent part, the default (when <code>explaces</code> is -1) being to use as many
     * as are needed. If <code>explaces</code> is not -1, space is always reserved for an exponent; if one is not needed
     * (for example, if the exponent will be 0) then <code>explaces</code>+2 blanks are appended to the result.
     * (This preserves vertical alignment of similarly formatted numbers in a monospace font.) If <code>explaces
     * </code> is not -1 and is not large enough to contain the exponent, an exception is thrown.
     * <p>
     * <code>exdigits</code> sets the trigger point for use of exponential notation. If, before any rounding, the number
     * of places needed before the decimal point exceeds <code>exdigits</code>, or if the absolute value of the result
     * is less than <code>0.000001</code>, then exponential form will be used, provided that <code>exdigits</code> was
     * specified. When <code>exdigits</code> is -1, exponential notation will never be used. If 0 is specified for
     * <code>exdigits</code>, exponential notation is always used unless the exponent would be 0.
     * <p>
     * <code>exform</code> sets the form for exponential notation (if needed). It may be either
     * {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}. If the latter, engineering, form is requested,
     * up to three digits (plus sign, if negative) may be needed for the integer part of the result (<code>before</code>
     * ). Otherwise, only one digit (plus sign, if negative) is needed.
     * <p>
     * Finally, the sixth argument, <code>exround</code>, selects the rounding algorithm to be used, and must be one of
     * the values indicated by a public constant in the {@link MathContext} class whose name starts with <code>ROUND_
     * </code>. The default (<code>ROUND_HALF_UP</code>) may also be selected by using the value -1, as before.
     * <p>
     * The special value <code>MathContext.ROUND_UNNECESSARY</code> may be used to detect whether non-zero digits are
     * discarded -- if <code>exround</code> has this value than if non-zero digits would be discarded (rounded) during
     * formatting then an <code>ArithmeticException</code> is thrown.
     * 
     * @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as
     *            are needed'.
     * @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as
     *            are needed'.
     * @param explaces The <code>int</code> specifying the number of places to be used for any exponent. Use -1 for 'as many
     *            as are needed'.
     * @param exdigits The <code>int</code> specifying the trigger (digits before the decimal point) which if exceeded causes
     *            exponential notation to be used. Use 0 to force exponential notation. Use -1 to force plain notation
     *            (no exponential notation).
     * @param exformint The <code>int</code> specifying the form of exponential notation to be used (
     *            {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}).
     * @param exround The <code>int</code> specifying the rounding mode to use. Use -1 for the default,
     *            {@link MathContext#ROUND_HALF_UP}.
     * @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified
     *         parameters
     * @throws ArithmeticException if the number cannot be laid out as requested.
     * @throws IllegalArgumentException if a parameter is out of range.
     * @see #toString
     * @see #toCharArray
     * @stable ICU 2.0
     */

    public java.lang.String format(int before, int after, int explaces, int exdigits, int exformint, int exround) {
        com.ibm.icu.math.BigDecimal num;
        int mag = 0;
        int thisafter = 0;
        int lead = 0;
        byte newmant[] = null;
        int chop = 0;
        int need = 0;
        int oldexp = 0;
        char a[];
        int p = 0;
        char newa[] = null;
        int i = 0;
        int places = 0;

        /* Check arguments */
        if ((before < (-1)) | (before == 0))
            badarg("format", 1, java.lang.String.valueOf(before));
        if (after < (-1))
            badarg("format", 2, java.lang.String.valueOf(after));
        if ((explaces < (-1)) | (explaces == 0))
            badarg("format", 3, java.lang.String.valueOf(explaces));
        if (exdigits < (-1))
            badarg("format", 4, java.lang.String.valueOf(explaces));
        {/* select */
            if (exformint == com.ibm.icu.math.MathContext.SCIENTIFIC) {
            } else if (exformint == com.ibm.icu.math.MathContext.ENGINEERING) {
            } else if (exformint == (-1))
                exformint = com.ibm.icu.math.MathContext.SCIENTIFIC;
            // note PLAIN isn't allowed
            else {
                badarg("format", 5, java.lang.String.valueOf(exformint));
            }
        }
        // checking the rounding mode is done by trying to construct a
        // MathContext object with that mode; it will fail if bad
        if (exround != ROUND_HALF_UP) {
            try { // if non-default...
                if (exround == (-1))
                    exround = ROUND_HALF_UP;
                else
                    new com.ibm.icu.math.MathContext(9, com.ibm.icu.math.MathContext.SCIENTIFIC, false, exround);
            } catch (java.lang.IllegalArgumentException $10) {
                badarg("format", 6, java.lang.String.valueOf(exround));
            }
        }

        num = clone(this); // make private copy

        /*
         * Here: num is BigDecimal to format before is places before point [>0] after is places after point [>=0]
         * explaces is exponent places [>0] exdigits is exponent digits [>=0] exformint is exponent form [one of two]
         * exround is rounding mode [one of eight] 'before' through 'exdigits' are -1 if not specified
         */

        /* determine form */
        {
            do {/* select */
                if (exdigits == (-1))
                    num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
                else if (num.ind == iszero)
                    num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
                else {
                    // determine whether triggers
                    mag = num.exp + num.mant.length;
                    if (mag > exdigits)
                        num.form = (byte) exformint;
                    else if (mag < (-5))
                        num.form = (byte) exformint;
                    else
                        num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
                }
            } while (false);
        }/* setform */

        /*
         * If 'after' was specified then we may need to adjust the mantissa. This is a little tricky, as we must conform
         * to the rules of exponential layout if necessary (e.g., we cannot end up with 10.0 if scientific).
         */
        if (after >= 0) {
            setafter: for (;;) {
                // calculate the current after-length
                {/* select */
                    if (num.form == com.ibm.icu.math.MathContext.PLAIN)
                        thisafter = -num.exp; // has decimal part
                    else if (num.form == com.ibm.icu.math.MathContext.SCIENTIFIC)
                        thisafter = num.mant.length - 1;
                    else { // engineering
                        lead = (((num.exp + num.mant.length) - 1)) % 3; // exponent to use
                        if (lead < 0)
                            lead = 3 + lead; // negative exponent case
                        lead++; // number of leading digits
                        if (lead >= num.mant.length)
                            thisafter = 0;
                        else
                            thisafter = num.mant.length - lead;
                    }
                }
                if (thisafter == after)
                    break setafter; // we're in luck
                if (thisafter < after) { // need added trailing zeros
                    // [thisafter can be negative]
                    newmant = extend(num.mant, (num.mant.length + after) - thisafter);
                    num.mant = newmant;
                    num.exp = num.exp - ((after - thisafter)); // adjust exponent
                    if (num.exp < MinExp)
                        throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + num.exp);
                    break setafter;
                }
                // We have too many digits after the decimal point; this could
                // cause a carry, which could change the mantissa...
                // Watch out for implied leading zeros in PLAIN case
                chop = thisafter - after; // digits to lop [is >0]
                if (chop > num.mant.length) { // all digits go, no chance of carry
                    // carry on with zero
                    num.mant = ZERO.mant;
                    num.ind = iszero;
                    num.exp = 0;
                    continue setafter; // recheck: we may need trailing zeros
                }
                // we have a digit to inspect from existing mantissa
                // round the number as required
                need = num.mant.length - chop; // digits to end up with [may be 0]
                oldexp = num.exp; // save old exponent
                num.round(need, exround);
                // if the exponent grew by more than the digits we chopped, then
                // we must have had a carry, so will need to recheck the layout
                if ((num.exp - oldexp) == chop)
                    break setafter; // number did not have carry
                // mantissa got extended .. so go around and check again
            }
        }/* setafter */

        a = num.layout(); // lay out, with exponent if required, etc.

        /* Here we have laid-out number in 'a' */
        // now apply 'before' and 'explaces' as needed
        if (before > 0) {
            // look for '.' or 'E'
            {
                int $11 = a.length;
                p = 0;
                p: for (; $11 > 0; $11--, p++) {
                    if (a[p] == '.')
                        break p;
                    if (a[p] == 'E')
                        break p;
                }
            }/* p */
            // p is now offset of '.', 'E', or character after end of array
            // that is, the current length of before part
            if (p > before)
                badarg("format", 1, java.lang.String.valueOf(before)); // won't fit
            if (p < before) { // need leading blanks
                newa = new char[(a.length + before) - p];
                {
                    int $12 = before - p;
                    i = 0;
                    for (; $12 > 0; $12--, i++) {
                        newa[i] = ' ';
                    }
                }/* i */
                java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, i, a.length);
                a = newa;
            }
            // [if p=before then it's just the right length]
        }

        if (explaces > 0) {
            // look for 'E' [cannot be at offset 0]
            {
                int $13 = a.length - 1;
                p = a.length - 1;
                p: for (; $13 > 0; $13--, p--) {
                    if (a[p] == 'E')
                        break p;
                }
            }/* p */
            // p is now offset of 'E', or 0
            if (p == 0) { // no E part; add trailing blanks
                newa = new char[(a.length + explaces) + 2];
                java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, a.length);
                {
                    int $14 = explaces + 2;
                    i = a.length;
                    for (; $14 > 0; $14--, i++) {
                        newa[i] = ' ';
                    }
                }/* i */
                a = newa;
            } else {/* found E */// may need to insert zeros
                places = (a.length - p) - 2; // number so far
                if (places > explaces)
                    badarg("format", 3, java.lang.String.valueOf(explaces));
                if (places < explaces) { // need to insert zeros
                    newa = new char[(a.length + explaces) - places];
                    java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, p + 2); // through E
                                                                                                            // and sign
                    {
                        int $15 = explaces - places;
                        i = p + 2;
                        for (; $15 > 0; $15--, i++) {
                            newa[i] = '0';
                        }
                    }/* i */
                    java.lang.System.arraycopy((java.lang.Object) a, p + 2, (java.lang.Object) newa, i, places); // remainder
                                                                                                                 // of
                                                                                                                 // exponent
                    a = newa;
                }
                // [if places=explaces then it's just the right length]
            }
        }
        return new java.lang.String(a);
    }

    /**
     * Returns the hashcode for this <code>BigDecimal</code>. This hashcode is suitable for use by the <code>
     * java.util.Hashtable</code> class.
     * <p>
     * Note that two <code>BigDecimal</code> objects are only guaranteed to produce the same hashcode if they are
     * exactly equal (that is, the <code>String</code> representations of the <code>BigDecimal</code> numbers are
     * identical -- they have the same characters in the same sequence).
     * 
     * @return An <code>int</code> that is the hashcode for <code>this</code>.
     * @stable ICU 2.0
     */

    public int hashCode() {
        // Maybe calculate ourselves, later. If so, note that there can be
        // more than one internal representation for a given toString() result.
        return this.toString().hashCode();
    }

    /**
     * Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero
     * decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for an <code>int</code>
     * (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be
     * <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact}
     * method.
     * 
     * @return An <code>int</code> converted from <code>this</code>, truncated and decapitated if necessary.
     * @stable ICU 2.0
     */

    public int intValue() {
        return toBigInteger().intValue();
    }

    /**
     * Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero
     * decimal part or is out of the possible range for an <code>int</code> (32-bit signed integer) result then an
     * <code>ArithmeticException</code> is thrown.
     * 
     * @return An <code>int</code> equal in value to <code>this</code>.
     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in an <code>int</code>.
     * @stable ICU 2.0
     */

    public int intValueExact() {
        int lodigit;
        int useexp = 0;
        int result;
        int i = 0;
        int topdig = 0;
        // This does not use longValueExact() as the latter can be much
        // slower.
        // intcheck (from pow) relies on this to check decimal part
        if (ind == iszero)
            return 0; // easy, and quite common
        /* test and drop any trailing decimal part */
        lodigit = mant.length - 1;
        if (exp < 0) {
            lodigit = lodigit + exp; // reduces by -(-exp)
            /* all decimal places must be 0 */
            if ((!(allzero(mant, lodigit + 1))))
                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
            if (lodigit < 0)
                return 0; // -1<this<1
            useexp = 0;
        } else {/* >=0 */
            if ((exp + lodigit) > 9) // early exit
                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
            useexp = exp;
        }
        /* convert the mantissa to binary, inline for speed */
        result = 0;
        {
            int $16 = lodigit + useexp;
            i = 0;
            for (; i <= $16; i++) {
                result = result * 10;
                if (i <= lodigit)
                    result = result + mant[i];
            }
        }/* i */

        /* Now, if the risky length, check for overflow */
        if ((lodigit + useexp) == 9) {
            // note we cannot just test for -ve result, as overflow can move a
            // zero into the top bit [consider 5555555555]
            topdig = result / 1000000000; // get top digit, preserving sign
            if (topdig != mant[0]) { // digit must match and be positive
                // except in the special case ...
                if (result == java.lang.Integer.MIN_VALUE) // looks like the special
                    if (ind == isneg) // really was negative
                        if (mant[0] == 2)
                            return result; // really had top digit 2
                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
            }
        }

        /* Looks good */
        if (ind == ispos)
            return result;
        return -result;
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero
     * decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for a <code>long</code>
     * (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be
     * <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact}
     * method.
     * 
     * @return A <code>long</code> converted from <code>this</code>, truncated and decapitated if necessary.
     * @stable ICU 2.0
     */

    public long longValue() {
        return toBigInteger().longValue();
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero
     * decimal part or is out of the possible range for a <code>long</code> (64-bit signed integer) result then an
     * <code>ArithmeticException</code> is thrown.
     * 
     * @return A <code>long</code> equal in value to <code>this</code>.
     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>long</code>.
     * @stable ICU 2.0
     */

    public long longValueExact() {
        int lodigit;
        int cstart = 0;
        int useexp = 0;
        long result;
        int i = 0;
        long topdig = 0;
        // Identical to intValueExact except for result=long, and exp>=20 test
        if (ind == 0)
            return 0; // easy, and quite common
        lodigit = mant.length - 1; // last included digit
        if (exp < 0) {
            lodigit = lodigit + exp; // -(-exp)
            /* all decimal places must be 0 */
            if (lodigit < 0)
                cstart = 0;
            else
                cstart = lodigit + 1;
            if ((!(allzero(mant, cstart))))
                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
            if (lodigit < 0)
                return 0; // -1<this<1
            useexp = 0;
        } else {/* >=0 */
            if ((exp + mant.length) > 18) // early exit
                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
            useexp = exp;
        }

        /* convert the mantissa to binary, inline for speed */
        // note that we could safely use the 'test for wrap to negative'
        // algorithm here, but instead we parallel the intValueExact
        // algorithm for ease of checking and maintenance.
        result = (long) 0;
        {
            int $17 = lodigit + useexp;
            i = 0;
            for (; i <= $17; i++) {
                result = result * 10;
                if (i <= lodigit)
                    result = result + mant[i];
            }
        }/* i */

        /* Now, if the risky length, check for overflow */
        if ((lodigit + useexp) == 18) {
            topdig = result / 1000000000000000000L; // get top digit, preserving sign
            if (topdig != mant[0]) { // digit must match and be positive
                // except in the special case ...
                if (result == java.lang.Long.MIN_VALUE) // looks like the special
                    if (ind == isneg) // really was negative
                        if (mant[0] == 9)
                            return result; // really had top digit 9
                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
            }
        }

        /* Looks good */
        if (ind == ispos)
            return result;
        return -result;
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the left by a specified number of
     * positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is,
     * if <code>n</code> is 0 or positive, the number returned is given by:
     * <p>
     * <code> this.multiply(TEN.pow(new BigDecimal(-n))) </code>
     * <p>
     * <code>n</code> may be negative, in which case the method returns the same result as <code>movePointRight(-n)
     * </code>.
     * 
     * @param n The <code>int</code> specifying the number of places to move the decimal point leftwards.
     * @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code>
     *         places to the left.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal movePointLeft(int n) {
        com.ibm.icu.math.BigDecimal res;
        // very little point in optimizing for shift of 0
        res = clone(this);
        res.exp = res.exp - n;
        return res.finish(plainMC, false); // finish sets form and checks exponent
    }

    /**
     * Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the right by a specified number of
     * positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is,
     * if <code>n</code> is 0 or positive, the number returned is given by:
     * <p>
     * <code> this.multiply(TEN.pow(new BigDecimal(n))) </code>
     * <p>
     * <code>n</code> may be negative, in which case the method returns the same result as <code>movePointLeft(-n)
     * </code>.
     * 
     * @param n The <code>int</code> specifying the number of places to move the decimal point rightwards.
     * @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code>
     *         places to the right.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal movePointRight(int n) {
        com.ibm.icu.math.BigDecimal res;
        res = clone(this);
        res.exp = res.exp + n;
        return res.finish(plainMC, false);
    }

    /**
     * Returns the scale of this <code>BigDecimal</code>. Returns a non-negative <code>int</code> which is the scale of
     * the number. The scale is the number of digits in the decimal part of the number if the number were formatted
     * without exponential notation.
     * 
     * @return An <code>int</code> whose value is the scale of this <code>BigDecimal</code>.
     * @stable ICU 2.0
     */

    public int scale() {
        if (exp >= 0)
            return 0; // scale can never be negative
        return -exp;
    }

    /**
     * Returns a plain <code>BigDecimal</code> with a given scale.
     * <p>
     * If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
     * (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary.
     * <p>
     * If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then
     * trailing digits will be removed, and in this case an <code>ArithmeticException</code> is thrown if any discarded
     * digits are non-zero.
     * <p>
     * The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is <code>
     * MathContext.ROUND_UNNECESSARY</code>.
     * 
     * @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>.
     * @return A plain <code>BigDecimal</code> with the given scale.
     * @throws ArithmeticException if <code>scale</code> is negative.
     * @throws ArithmeticException if reducing scale would discard non-zero digits.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal setScale(int scale) {
        return setScale(scale, ROUND_UNNECESSARY);
    }

    /**
     * Returns a plain <code>BigDecimal</code> with a given scale.
     * <p>
     * If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
     * (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary.
     * <p>
     * If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then
     * trailing digits will be removed, and the rounding mode given by the second parameter is used to determine if the
     * remaining digits are affected by a carry. In this case, an <code>IllegalArgumentException</code> is thrown if
     * <code>round</code> is not a valid rounding mode.
     * <p>
     * If <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, an <code>ArithmeticException</code> is
     * thrown if any discarded digits are non-zero.
     * 
     * @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>.
     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
     * @return A plain <code>BigDecimal</code> with the given scale.
     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
     * @throws ArithmeticException if <code>scale</code> is negative.
     * @throws ArithmeticException if <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, and reducing scale would discard
     *             non-zero digits.
     * @stable ICU 2.0
     */

    public com.ibm.icu.math.BigDecimal setScale(int scale, int round) {
        int ourscale;
        com.ibm.icu.math.BigDecimal res;
        int padding = 0;
        int newlen = 0;
        // at present this naughtily only checks the round value if it is
        // needed (used), for speed
        ourscale = this.scale();
        if (ourscale == scale) // already correct scale
            if (this.form == com.ibm.icu.math.MathContext.PLAIN) // .. and form
                return this;
        res = clone(this); // need copy
        if (ourscale <= scale) { // simply zero-padding/changing form
            // if ourscale is 0 we may have lots of 0s to add
            if (ourscale == 0)
                padding = res.exp + scale;
            else
                padding = scale - ourscale;
            res.mant = extend(res.mant, res.mant.length + padding);
            res.exp = -scale; // as requested
        } else {/* ourscale>scale: shortening, probably */
            if (scale < 0)
                throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
            // [round() will raise exception if invalid round]
            newlen = res.mant.length - ((ourscale - scale)); // [<=0 is OK]
            res = res.round(newlen, round); // round to required length
            // This could have shifted left if round (say) 0.9->1[.0]
            // Repair if so by adding a zero and reducing exponent
            if (res.exp != -scale) {
                res.mant = extend(res.mant, res.mant.length + 1);
                res.exp = res.exp - 1;
            }
        }
        res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // by definition
        return res;
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>short</code>. If the <code>BigDecimal</code> has a non-zero
     * decimal part or is out of the possible range for a <code>short</code> (16-bit signed integer) result then an
     * <code>ArithmeticException</code> is thrown.
     * 
     * @return A <code>short</code> equal in value to <code>this</code>.
     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>short</code>.
     * @stable ICU 2.0
     */

    public short shortValueExact() {
        int num;
        num = this.intValueExact(); // will check decimal part too
        if ((num > 32767) | (num < (-32768)))
            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
        return (short) num;
    }

    /**
     * Returns the sign of this <code>BigDecimal</code>, as an <code>int</code>. This returns the <i>signum</i> function
     * value that represents the sign of this <code>BigDecimal</code>. That is, -1 if the <code>BigDecimal</code> is
     * negative, 0 if it is numerically equal to zero, or 1 if it is positive.
     * 
     * @return An <code>int</code> which is -1 if the <code>BigDecimal</code> is negative, 0 if it is numerically equal
     *         to zero, or 1 if it is positive.
     * @stable ICU 2.0
     */

    public int signum() {
        return (int) this.ind; // [note this assumes values for ind.]
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>java.math.BigDecimal</code>.
     * <p>
     * This is an exact conversion; the result is the same as if the <code>BigDecimal</code> were formatted as a plain
     * number without any rounding or exponent and then the <code>java.math.BigDecimal(java.lang.String)</code>
     * constructor were used to construct the result.
     * <p>
     * <i>(Note: this method is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class. It
     * would not be present in a <code>java.math</code> version.)</i>
     * 
     * @return The <code>java.math.BigDecimal</code> equal in value to this <code>BigDecimal</code>.
     * @stable ICU 2.0
     */

    public java.math.BigDecimal toBigDecimal() {
        return new java.math.BigDecimal(this.unscaledValue(), this.scale());
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>.
     * <p>
     * Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use
     * {@link #toBigIntegerExact()}.
     * 
     * @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>.
     * @stable ICU 2.0
     */

    public java.math.BigInteger toBigInteger() {
        com.ibm.icu.math.BigDecimal res = null;
        int newlen = 0;
        byte newmant[] = null;
        {/* select */
            if ((exp >= 0) & (form == com.ibm.icu.math.MathContext.PLAIN))
                res = this; // can layout simply
            else if (exp >= 0) {
                res = clone(this); // safe copy
                res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // .. and request PLAIN
            } else {
                { // exp<0; scale to be truncated
                    // we could use divideInteger, but we may as well be quicker
                    if (-this.exp >= this.mant.length)
                        res = ZERO; // all blows away
                    else {
                        res = clone(this); // safe copy
                        newlen = res.mant.length + res.exp;
                        newmant = new byte[newlen]; // [shorter]
                        java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0,
                                newlen);
                        res.mant = newmant;
                        res.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
                        res.exp = 0;
                    }
                }
            }
        }
        return new BigInteger(new java.lang.String(res.layout()));
    }

    /**
     * Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>.
     * <p>
     * An exception is thrown if the decimal part (if any) is non-zero.
     * 
     * @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>.
     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part.
     * @stable ICU 2.0
     */

    public java.math.BigInteger toBigIntegerExact() {
        /* test any trailing decimal part */
        if (exp < 0) { // possible decimal part
            /* all decimal places must be 0; note exp<0 */
            if ((!(allzero(mant, mant.length + exp))))
                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
        }
        return toBigInteger();
    }

    /**
     * Returns the <code>BigDecimal</code> as a character array. The result of this method is the same as using the
     * sequence <code>toString().toCharArray()</code>, but avoids creating the intermediate <code>String</code> and
     * <code>char[]</code> objects.
     * 
     * @return The <code>char[]</code> array corresponding to this <code>BigDecimal</code>.
     * @stable ICU 2.0
     */

    public char[] toCharArray() {
        return layout();
    }

    /**
     * Returns the <code>BigDecimal</code> as a <code>String</code>. This returns a <code>String</code> that exactly
     * represents this <code>BigDecimal</code>, as defined in the decimal documentation (see {@link BigDecimal class
     * header}).
     * <p>
     * By definition, using the {@link #BigDecimal(String)} constructor on the result <code>String</code> will create a
     * <code>BigDecimal</code> that is exactly equal to the original <code>BigDecimal</code>.
     * 
     * @return The <code>String</code> exactly corresponding to this <code>BigDecimal</code>.
     * @see #format(int, int)
     * @see #format(int, int, int, int, int, int)
     * @see #toCharArray()
     * @stable ICU 2.0
     */

    public java.lang.String toString() {
        return new java.lang.String(layout());
    }

    /**
     * Returns the number as a <code>BigInteger</code> after removing the scale. That is, the number is expressed as a
     * plain number, any decimal point is then removed (retaining the digits of any decimal part), and the result is
     * then converted to a <code>BigInteger</code>.
     * 
     * @return The <code>java.math.BigInteger</code> equal in value to this <code>BigDecimal</code> multiplied by ten to
     *         the power of <code>this.scale()</code>.
     * @stable ICU 2.0
     */

    public java.math.BigInteger unscaledValue() {
        com.ibm.icu.math.BigDecimal res = null;
        if (exp >= 0)
            res = this;
        else {
            res = clone(this); // safe copy
            res.exp = 0; // drop scale
        }
        return res.toBigInteger();
    }

    /**
     * Translates a <code>double</code> to a <code>BigDecimal</code>.
     * <p>
     * Returns a <code>BigDecimal</code> which is the decimal representation of the 64-bit signed binary floating point
     * parameter. If the parameter is infinite, or is not a number (NaN), a <code>NumberFormatException</code> is
     * thrown.
     * <p>
     * The number is constructed as though <code>num</code> had been converted to a <code>String</code> using the <code>
     * Double.toString()</code> method and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
     * This is typically not an exact conversion.
     * 
     * @param dub The <code>double</code> to be translated.
     * @return The <code>BigDecimal</code> equal in value to <code>dub</code>.
     * @throws NumberFormatException if the parameter is infinite or not a number.
     * @stable ICU 2.0
     */

    public static com.ibm.icu.math.BigDecimal valueOf(double dub) {
        // Reminder: a zero double returns '0.0', so we cannot fastpath to
        // use the constant ZERO. This might be important enough to justify
        // a factory approach, a cache, or a few private constants, later.
        return new com.ibm.icu.math.BigDecimal((new java.lang.Double(dub)).toString());
    }

    /**
     * Translates a <code>long</code> to a <code>BigDecimal</code>. That is, returns a plain <code>BigDecimal</code>
     * whose value is equal to the given <code>long</code>.
     * 
     * @param lint The <code>long</code> to be translated.
     * @return The <code>BigDecimal</code> equal in value to <code>lint</code>.
     * @stable ICU 2.0
     */

    public static com.ibm.icu.math.BigDecimal valueOf(long lint) {
        return valueOf(lint, 0);
    }

    /**
     * Translates a <code>long</code> to a <code>BigDecimal</code> with a given scale. That is, returns a plain <code>
     * BigDecimal</code> whose unscaled value is equal to the given <code>long</code>, adjusted by the second parameter,
     * <code>scale</code>.
     * <p>
     * The result is given by:
     * <p>
     * <code> (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) </code>
     * <p>
     * A <code>NumberFormatException</code> is thrown if <code>scale</code> is negative.
     * 
     * @param lint The <code>long</code> to be translated.
     * @param scale The <code>int</code> scale to be applied.
     * @return The <code>BigDecimal</code> equal in value to <code>lint</code>.
     * @throws NumberFormatException if the scale is negative.
     * @stable ICU 2.0
     */

    public static com.ibm.icu.math.BigDecimal valueOf(long lint, int scale) {
        com.ibm.icu.math.BigDecimal res = null;
        {/* select */
            if (lint == 0)
                res = ZERO;
            else if (lint == 1)
                res = ONE;
            else if (lint == 10)
                res = TEN;
            else {
                res = new com.ibm.icu.math.BigDecimal(lint);
            }
        }
        if (scale == 0)
            return res;
        if (scale < 0)
            throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
        res = clone(res); // safe copy [do not mutate]
        res.exp = -scale; // exponent is -scale
        return res;
    }

    /* ---------------------------------------------------------------- */
    /* Private methods */
    /* ---------------------------------------------------------------- */

    /*
     * <sgml> Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array).
     * <p>The mantissa will either already have been rounded (following an operation) or will be of length appropriate
     * (in the case of construction from an int, for example). <p>We must not alter the mantissa, here. <p>'form'
     * describes whether we are to use exponential notation (and if so, which), or if we are to lay out as a plain/pure
     * numeric. </sgml>
     */

    private char[] layout() {
        char cmant[];
        int i = 0;
        StringBuilder sb = null;
        int euse = 0;
        int sig = 0;
        char csign = 0;
        char rec[] = null;
        int needsign;
        int mag;
        int len = 0;
        cmant = new char[mant.length]; // copy byte[] to a char[]
        {
            int $18 = mant.length;
            i = 0;
            for (; $18 > 0; $18--, i++) {
                cmant[i] = (char) (mant[i] + ((int) ('0')));
            }
        }/* i */

        if (form != com.ibm.icu.math.MathContext.PLAIN) {/* exponential notation needed */
            sb = new StringBuilder(cmant.length + 15); // -x.xxxE+999999999
            if (ind == isneg)
                sb.append('-');
            euse = (exp + cmant.length) - 1; // exponent to use
            /* setup sig=significant digits and copy to result */
            if (form == com.ibm.icu.math.MathContext.SCIENTIFIC) { // [default]
                sb.append(cmant[0]); // significant character
                if (cmant.length > 1) // have decimal part
                    sb.append('.').append(cmant, 1, cmant.length - 1);
            } else {
                do {
                    sig = euse % 3; // common
                    if (sig < 0)
                        sig = 3 + sig; // negative exponent
                    euse = euse - sig;
                    sig++;
                    if (sig >= cmant.length) { // zero padding may be needed
                        sb.append(cmant, 0, cmant.length);
                        {
                            int $19 = sig - cmant.length;
                            for (; $19 > 0; $19--) {
                                sb.append('0');
                            }
                        }
                    } else { // decimal point needed
                        sb.append(cmant, 0, sig).append('.').append(cmant, sig, cmant.length - sig);
                    }
                } while (false);
            }/* engineering */
            if (euse != 0) {
                if (euse < 0) {
                    csign = '-';
                    euse = -euse;
                } else
                    csign = '+';
                sb.append('E').append(csign).append(euse);
            }
            rec = new char[sb.length()];
            int srcEnd = sb.length();
            if (0 != srcEnd) {
                sb.getChars(0, srcEnd, rec, 0);
            }
            return rec;
        }

        /* Here for non-exponential (plain) notation */
        if (exp == 0) {/* easy */
            if (ind >= 0)
                return cmant; // non-negative integer
            rec = new char[cmant.length + 1];
            rec[0] = '-';
            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, 1, cmant.length);
            return rec;
        }

        /* Need a '.' and/or some zeros */
        needsign = (ind == isneg) ? 1 : 0; // space for sign? 0 or 1

        /*
         * MAG is the position of the point in the mantissa (index of the character it follows)
         */
        mag = exp + cmant.length;

        if (mag < 1) {/* 0.00xxxx form */
            len = (needsign + 2) - exp; // needsign+2+(-mag)+cmant.length
            rec = new char[len];
            if (needsign != 0)
                rec[0] = '-';
            rec[needsign] = '0';
            rec[needsign + 1] = '.';
            {
                int $20 = -mag;
                i = needsign + 2;
                for (; $20 > 0; $20--, i++) { // maybe none
                    rec[i] = '0';
                }
            }/* i */
            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, (needsign + 2) - mag,
                    cmant.length);
            return rec;
        }

        if (mag > cmant.length) {/* xxxx0000 form */
            len = needsign + mag;
            rec = new char[len];
            if (needsign != 0)
                rec[0] = '-';
            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, cmant.length);
            {
                int $21 = mag - cmant.length;
                i = needsign + cmant.length;
                for (; $21 > 0; $21--, i++) { // never 0
                    rec[i] = '0';
                }
            }/* i */
            return rec;
        }

        /* decimal point is in the middle of the mantissa */
        len = (needsign + 1) + cmant.length;
        rec = new char[len];
        if (needsign != 0)
            rec[0] = '-';
        java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, mag);
        rec[needsign + mag] = '.';
        java.lang.System.arraycopy((java.lang.Object) cmant, mag, (java.lang.Object) rec, (needsign + mag) + 1,
                cmant.length - mag);
        return rec;
    }

    /*
     * <sgml> Checks a BigDecimal argument to ensure it's a true integer in a given range. <p>If OK, returns it as an
     * int. </sgml>
     */
    // [currently only used by pow]
    private int intcheck(int min, int max) {
        int i;
        i = this.intValueExact(); // [checks for non-0 decimal part]
        // Use same message as though intValueExact failed due to size
        if ((i < min) | (i > max))
            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + i);
        return i;
    }

    /* <sgml> Carry out division operations. </sgml> */
    /*
     * Arg1 is operation code: D=divide, I=integer divide, R=remainder Arg2 is the rhs. Arg3 is the context. Arg4 is
     * explicit scale iff code='D' or 'I' (-1 if none).
     * 
     * Underlying algorithm (complications for Remainder function and scaled division are omitted for clarity):
     * 
     * Test for x/0 and then 0/x Exp =Exp1 - Exp2 Exp =Exp +len(var1) -len(var2) Sign=Sign1 Sign2 Pad accumulator (Var1)
     * to double-length with 0's (pad1) Pad Var2 to same length as Var1 B2B=1st two digits of var2, +1 to allow for
     * roundup have=0 Do until (have=digits+1 OR residue=0) if exp<0 then if integer divide/residue then leave
     * this_digit=0 Do forever compare numbers if <0 then leave inner_loop if =0 then (- quick exit without subtract -)
     * do this_digit=this_digit+1; output this_digit leave outer_loop; end Compare lengths of numbers (mantissae): If
     * same then CA=first_digit_of_Var1 else CA=first_two_digits_of_Var1 mult=ca10/b2b -- Good and safe guess at divisor
     * if mult=0 then mult=1 this_digit=this_digit+mult subtract end inner_loop if have\=0 | this_digit\=0 then do
     * output this_digit have=have+1; end var2=var2/10 exp=exp-1 end outer_loop exp=exp+1 -- set the proper exponent if
     * have=0 then generate answer=0 Return to FINISHED Result defined by MATHV1
     * 
     * For extended commentary, see DMSRCN.
     */

    private com.ibm.icu.math.BigDecimal dodivide(char code, com.ibm.icu.math.BigDecimal rhs,
            com.ibm.icu.math.MathContext set, int scale) {
        com.ibm.icu.math.BigDecimal lhs;
        int reqdig;
        int newexp;
        com.ibm.icu.math.BigDecimal res;
        int newlen;
        byte var1[];
        int var1len;
        byte var2[];
        int var2len;
        int b2b;
        int have;
        int thisdigit = 0;
        int i = 0;
        byte v2 = 0;
        int ba = 0;
        int mult = 0;
        int start = 0;
        int padding = 0;
        int d = 0;
        byte newvar1[] = null;
        byte lasthave = 0;
        int actdig = 0;
        byte newmant[] = null;

        if (set.lostDigits)
            checkdigits(rhs, set.digits);
        lhs = this; // name for clarity

        // [note we must have checked lostDigits before the following checks]
        if (rhs.ind == 0)
            throw new java.lang.ArithmeticException("Divide by 0"); // includes 0/0
        if (lhs.ind == 0) { // 0/x => 0 [possibly with .0s]
            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
                return ZERO;
            if (scale == (-1))
                return lhs;
            return lhs.setScale(scale);
        }

        /* Prepare numbers according to BigDecimal rules */
        reqdig = set.digits; // local copy (heavily used)
        if (reqdig > 0) {
            if (lhs.mant.length > reqdig)
                lhs = clone(lhs).round(set);
            if (rhs.mant.length > reqdig)
                rhs = clone(rhs).round(set);
        } else {/* scaled divide */
            if (scale == (-1))
                scale = lhs.scale();
            // set reqdig to be at least large enough for the computation
            reqdig = lhs.mant.length; // base length
            // next line handles both positive lhs.exp and also scale mismatch
            if (scale != -lhs.exp)
                reqdig = (reqdig + scale) + lhs.exp;
            reqdig = (reqdig - ((rhs.mant.length - 1))) - rhs.exp; // reduce by RHS effect
            if (reqdig < lhs.mant.length)
                reqdig = lhs.mant.length; // clamp
            if (reqdig < rhs.mant.length)
                reqdig = rhs.mant.length; // ..
        }

        /* precalculate exponent */
        newexp = ((lhs.exp - rhs.exp) + lhs.mant.length) - rhs.mant.length;
        /* If new exponent -ve, then some quick exits are possible */
        if (newexp < 0)
            if (code != 'D') {
                if (code == 'I')
                    return ZERO; // easy - no integer part
                /* Must be 'R'; remainder is [finished clone of] input value */
                return clone(lhs).finish(set, false);
            }

        /* We need slow division */
        res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
        res.ind = (byte) (lhs.ind * rhs.ind); // final sign (for D/I)
        res.exp = newexp; // initial exponent (for D/I)
        res.mant = new byte[reqdig + 1]; // where build the result

        /* Now [virtually pad the mantissae with trailing zeros */
        // Also copy the LHS, which will be our working array
        newlen = (reqdig + reqdig) + 1;
        var1 = extend(lhs.mant, newlen); // always makes longer, so new safe array
        var1len = newlen; // [remaining digits are 0]

        var2 = rhs.mant;
        var2len = newlen;

        /* Calculate first two digits of rhs (var2), +1 for later estimations */
        b2b = (var2[0] * 10) + 1;
        if (var2.length > 1)
            b2b = b2b + var2[1];

        /* start the long-division loops */
        have = 0;
        {
            outer: for (;;) {
                thisdigit = 0;
                /* find the next digit */
                {
                    inner: for (;;) {
                        if (var1len < var2len)
                            break inner; // V1 too low
                        if (var1len == var2len) { // compare needed
                            {
                                compare: do { // comparison
                                    {
                                        int $22 = var1len;
                                        i = 0;
                                        for (; $22 > 0; $22--, i++) {
                                            // var1len is always <= var1.length
                                            if (i < var2.length)
                                                v2 = var2[i];
                                            else
                                                v2 = (byte) 0;
                                            if (var1[i] < v2)
                                                break inner; // V1 too low
                                            if (var1[i] > v2)
                                                break compare; // OK to subtract
                                        }
                                    }/* i */
                                    /*
                                     * reach here if lhs and rhs are identical; subtraction will increase digit by one,
                                     * and the residue will be 0 so we are done; leave the loop with residue set to 0
                                     * (in case code is 'R' or ROUND_UNNECESSARY or a ROUND_HALF_xxxx is being checked)
                                     */
                                    thisdigit++;
                                    res.mant[have] = (byte) thisdigit;
                                    have++;
                                    var1[0] = (byte) 0; // residue to 0 [this is all we'll test]
                                    // var1len=1 -- [optimized out]
                                    break outer;
                                } while (false);
                            }/* compare */
                            /* prepare for subtraction. Estimate BA (lengths the same) */
                            ba = (int) var1[0]; // use only first digit
                        } // lengths the same
                        else {/* lhs longer than rhs */
                            /* use first two digits for estimate */
                            ba = var1[0] * 10;
                            if (var1len > 1)
                                ba = ba + var1[1];
                        }
                        /* subtraction needed; V1>=V2 */
                        mult = (ba * 10) / b2b;
                        if (mult == 0)
                            mult = 1;
                        thisdigit = thisdigit + mult;
                        // subtract; var1 reusable
                        var1 = byteaddsub(var1, var1len, var2, var2len, -mult, true);
                        if (var1[0] != 0)
                            continue inner; // maybe another subtract needed
                        /*
                         * V1 now probably has leading zeros, remove leading 0's and try again. (It could be longer than
                         * V2)
                         */
                        {
                            int $23 = var1len - 2;
                            start = 0;
                            start: for (; start <= $23; start++) {
                                if (var1[start] != 0)
                                    break start;
                                var1len--;
                            }
                        }/* start */
                        if (start == 0)
                            continue inner;
                        // shift left
                        java.lang.System.arraycopy((java.lang.Object) var1, start, (java.lang.Object) var1, 0, var1len);
                    }
                }/* inner */

                /* We have the next digit */
                if ((have != 0) | (thisdigit != 0)) { // put the digit we got
                    res.mant[have] = (byte) thisdigit;
                    have++;
                    if (have == (reqdig + 1))
                        break outer; // we have all we need
                    if (var1[0] == 0)
                        break outer; // residue now 0
                }
                /* can leave now if a scaled divide and exponent is small enough */
                if (scale >= 0)
                    if (-res.exp > scale)
                        break outer;
                /* can leave now if not Divide and no integer part left */
                if (code != 'D')
                    if (res.exp <= 0)
                        break outer;
                res.exp = res.exp - 1; // reduce the exponent
                /*
                 * to get here, V1 is less than V2, so divide V2 by 10 and go for the next digit
                 */
                var2len--;
            }
        }/* outer */

        /* here when we have finished dividing, for some reason */
        // have is the number of digits we collected in res.mant
        if (have == 0)
            have = 1; // res.mant[0] is 0; we always want a digit

        if ((code == 'I') | (code == 'R')) {/* check for integer overflow needed */
            if ((have + res.exp) > reqdig)
                throw new java.lang.ArithmeticException("Integer overflow");

            if (code == 'R') {
                do {
                    /* We were doing Remainder -- return the residue */
                    if (res.mant[0] == 0) // no integer part was found
                        return clone(lhs).finish(set, false); // .. so return lhs, canonical
                    if (var1[0] == 0)
                        return ZERO; // simple 0 residue
                    res.ind = lhs.ind; // sign is always as LHS
                    /*
                     * Calculate the exponent by subtracting the number of padding zeros we added and adding the
                     * original exponent
                     */
                    padding = ((reqdig + reqdig) + 1) - lhs.mant.length;
                    res.exp = (res.exp - padding) + lhs.exp;

                    /*
                     * strip insignificant padding zeros from residue, and create/copy the resulting mantissa if need be
                     */
                    d = var1len;
                    {
                        i = d - 1;
                        i: for (; i >= 1; i--) {
                            if (!((res.exp < lhs.exp) & (res.exp < rhs.exp)))
                                break;
                            if (var1[i] != 0)
                                break i;
                            d--;
                            res.exp = res.exp + 1;
                        }
                    }/* i */
                    if (d < var1.length) {/* need to reduce */
                        newvar1 = new byte[d];
                        java.lang.System.arraycopy((java.lang.Object) var1, 0, (java.lang.Object) newvar1, 0, d); // shorten
                        var1 = newvar1;
                    }
                    res.mant = var1;
                    return res.finish(set, false);
                } while (false);
            }/* remainder */
        }

        else {/* 'D' -- no overflow check needed */
            // If there was a residue then bump the final digit (iff 0 or 5)
            // so that the residue is visible for ROUND_UP, ROUND_HALF_xxx and
            // ROUND_UNNECESSARY checks (etc.) later.
            // [if we finished early, the residue will be 0]
            if (var1[0] != 0) { // residue not 0
                lasthave = res.mant[have - 1];
                if (((lasthave % 5)) == 0)
                    res.mant[have - 1] = (byte) (lasthave + 1);
            }
        }

        /* Here for Divide or Integer Divide */
        // handle scaled results first ['I' always scale 0, optional for 'D']
        if (scale >= 0) {
            do {
                // say 'scale have res.exp len' scale have res.exp res.mant.length
                if (have != res.mant.length)
                    // already padded with 0's, so just adjust exponent
                    res.exp = res.exp - ((res.mant.length - have));
                // calculate number of digits we really want [may be 0]
                actdig = res.mant.length - (-res.exp - scale);
                res.round(actdig, set.roundingMode); // round to desired length
                // This could have shifted left if round (say) 0.9->1[.0]
                // Repair if so by adding a zero and reducing exponent
                if (res.exp != -scale) {
                    res.mant = extend(res.mant, res.mant.length + 1);
                    res.exp = res.exp - 1;
                }
                return res.finish(set, true); // [strip if not PLAIN]
            } while (false);
        }/* scaled */

        // reach here only if a non-scaled
        if (have == res.mant.length) { // got digits+1 digits
            res.round(set);
            have = reqdig;
        } else {/* have<=reqdig */
            if (res.mant[0] == 0)
                return ZERO; // fastpath
            // make the mantissa truly just 'have' long
            // [we could let finish do this, during strip, if we adjusted
            // the exponent; however, truncation avoids the strip loop]
            newmant = new byte[have]; // shorten
            java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0, have);
            res.mant = newmant;
        }
        return res.finish(set, true);
    }

    /* <sgml> Report a conversion exception. </sgml> */

    private void bad(char s[]) {
        throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s));
    }

    /*
     * <sgml> Report a bad argument to a method. </sgml> Arg1 is method name Arg2 is argument position Arg3 is what was
     * found
     */

    private void badarg(java.lang.String name, int pos, java.lang.String value) {
        throw new java.lang.IllegalArgumentException("Bad argument" + " " + pos + " " + "to" + " " + name + ":" + " "
                + value);
    }

    /*
     * <sgml> Extend byte array to given length, padding with 0s. If no extension is required then return the same
     * array. </sgml>
     * 
     * Arg1 is the source byte array Arg2 is the new length (longer)
     */

    private static final byte[] extend(byte inarr[], int newlen) {
        byte newarr[];
        if (inarr.length == newlen)
            return inarr;
        newarr = new byte[newlen];
        java.lang.System.arraycopy((java.lang.Object) inarr, 0, (java.lang.Object) newarr, 0, inarr.length);
        // 0 padding is carried out by the JVM on allocation initialization
        return newarr;
    }

    /*
     * <sgml> Add or subtract two >=0 integers in byte arrays <p>This routine performs the calculation: <pre> C=A+(BM)
     * </pre> Where M is in the range -9 through +9 <p> If M<0 then A>=B must be true, so the result is always
     * non-negative.
     * 
     * Leading zeros are not removed after a subtraction. The result is either the same length as the longer of A and B,
     * or 1 longer than that (if a carry occurred).
     * 
     * A is not altered unless Arg6 is 1. B is never altered.
     * 
     * Arg1 is A Arg2 is A length to use (if longer than A, pad with 0's) Arg3 is B Arg4 is B length to use (if longer
     * than B, pad with 0's) Arg5 is M, the multiplier Arg6 is 1 if A can be used to build the result (if it fits)
     * 
     * This routine is severely performance-critical;any change here must be measured (timed) to assure no performance
     * degradation.
     */
    // 1996.02.20 -- enhanced version of DMSRCN algorithm (1981)
    // 1997.10.05 -- changed to byte arrays (from char arrays)
    // 1998.07.01 -- changed to allow destructive reuse of LHS
    // 1998.07.01 -- changed to allow virtual lengths for the arrays
    // 1998.12.29 -- use lookaside for digit/carry calculation
    // 1999.08.07 -- avoid multiply when mult=1, and make db an int
    // 1999.12.22 -- special case m=-1, also drop 0 special case
    private static final byte[] byteaddsub(byte a[], int avlen, byte b[], int bvlen, int m, boolean reuse) {
        int alength;
        int blength;
        int ap;
        int bp;
        int maxarr;
        byte reb[];
        boolean quickm;
        int digit;
        int op = 0;
        int dp90 = 0;
        byte newarr[];
        int i = 0;

        // We'll usually be right if we assume no carry
        alength = a.length; // physical lengths
        blength = b.length; // ..
        ap = avlen - 1; // -> final (rightmost) digit
        bp = bvlen - 1; // ..
        maxarr = bp;
        if (maxarr < ap)
            maxarr = ap;
        reb = (byte[]) null; // result byte array
        if (reuse)
            if ((maxarr + 1) == alength)
                reb = a; // OK to reuse A
        if (reb == null)
            reb = new byte[maxarr + 1]; // need new array

        quickm = false; // 1 if no multiply needed
        if (m == 1)
            quickm = true; // most common
        else if (m == (-1))
            quickm = true; // also common

        digit = 0; // digit, with carry or borrow
        {
            op = maxarr;
            op: for (; op >= 0; op--) {
                if (ap >= 0) {
                    if (ap < alength)
                        digit = digit + a[ap]; // within A
                    ap--;
                }
                if (bp >= 0) {
                    if (bp < blength) { // within B
                        if (quickm) {
                            if (m > 0)
                                digit = digit + b[bp]; // most common
                            else
                                digit = digit - b[bp]; // also common
                        } else
                            digit = digit + (b[bp] * m);
                    }
                    bp--;
                }
                /* result so far (digit) could be -90 through 99 */
                if (digit < 10)
                    if (digit >= 0) {
                        do { // 0-9
                            reb[op] = (byte) digit;
                            digit = 0; // no carry
                            continue op;
                        } while (false);
                    }/* quick */
                dp90 = digit + 90;
                reb[op] = bytedig[dp90]; // this digit
                digit = bytecar[dp90]; // carry or borrow
            }
        }/* op */

        if (digit == 0)
            return reb; // no carry
        // following line will become an Assert, later
        // if digit<0 then signal ArithmeticException("internal.error ["digit"]")

        /* We have carry -- need to make space for the extra digit */
        newarr = (byte[]) null;
        if (reuse)
            if ((maxarr + 2) == a.length)
                newarr = a; // OK to reuse A
        if (newarr == null)
            newarr = new byte[maxarr + 2];
        newarr[0] = (byte) digit; // the carried digit ..
        // .. and all the rest [use local loop for short numbers]
        if (maxarr < 10) {
            int $24 = maxarr + 1;
            i = 0;
            for (; $24 > 0; $24--, i++) {
                newarr[i + 1] = reb[i];
            }
        }/* i */
        else
            java.lang.System.arraycopy((java.lang.Object) reb, 0, (java.lang.Object) newarr, 1, maxarr + 1);
        return newarr;
    }

    /*
     * <sgml> Initializer for digit array properties (lookaside). </sgml> Returns the digit array, and initializes the
     * carry array.
     */

    private static final byte[] diginit() {
        byte work[];
        int op = 0;
        int digit = 0;
        work = new byte[(90 + 99) + 1];
        {
            op = 0;
            op: for (; op <= (90 + 99); op++) {
                digit = op - 90;
                if (digit >= 0) {
                    work[op] = (byte) (digit % 10);
                    bytecar[op] = (byte) (digit / 10); // calculate carry
                    continue op;
                }
                // borrowing...
                digit = digit + 100; // yes, this is right [consider -50]
                work[op] = (byte) (digit % 10);
                bytecar[op] = (byte) ((digit / 10) - 10); // calculate borrow [NB: - after %]
            }
        }/* op */
        return work;
    }

    /*
     * <sgml> Create a copy of BigDecimal object for local use. <p>This does NOT make a copy of the mantissa array.
     * </sgml> Arg1 is the BigDecimal to clone (non-null)
     */

    private static final com.ibm.icu.math.BigDecimal clone(com.ibm.icu.math.BigDecimal dec) {
        com.ibm.icu.math.BigDecimal copy;
        copy = new com.ibm.icu.math.BigDecimal();
        copy.ind = dec.ind;
        copy.exp = dec.exp;
        copy.form = dec.form;
        copy.mant = dec.mant;
        return copy;
    }

    /*
     * <sgml> Check one or two numbers for lost digits. </sgml> Arg1 is RHS (or null, if none) Arg2 is current DIGITS
     * setting returns quietly or throws an exception
     */

    private void checkdigits(com.ibm.icu.math.BigDecimal rhs, int dig) {
        if (dig == 0)
            return; // don't check if digits=0
        // first check lhs...
        if (this.mant.length > dig)
            if ((!(allzero(this.mant, dig))))
                throw new java.lang.ArithmeticException("Too many digits:" + " " + this.toString());
        if (rhs == null)
            return; // monadic
        if (rhs.mant.length > dig)
            if ((!(allzero(rhs.mant, dig))))
                throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
    }

    /*
     * <sgml> Round to specified digits, if necessary. </sgml> Arg1 is requested MathContext [with length and rounding
     * mode] returns this, for convenience
     */

    private com.ibm.icu.math.BigDecimal round(com.ibm.icu.math.MathContext set) {
        return round(set.digits, set.roundingMode);
    }

    /*
     * <sgml> Round to specified digits, if necessary. Arg1 is requested length (digits to round to) [may be <=0 when
     * called from format, dodivide, etc.] Arg2 is rounding mode returns this, for convenience
     * 
     * ind and exp are adjusted, but not cleared for a mantissa of zero
     * 
     * The length of the mantissa returned will be Arg1, except when Arg1 is 0, in which case the returned mantissa
     * length will be 1. </sgml>
     */

    private com.ibm.icu.math.BigDecimal round(int len, int mode) {
        int adjust;
        int sign;
        byte oldmant[];
        boolean reuse = false;
        byte first = 0;
        int increment;
        byte newmant[] = null;
        adjust = mant.length - len;
        if (adjust <= 0)
            return this; // nowt to do

        exp = exp + adjust; // exponent of result
        sign = (int) ind; // save [assumes -1, 0, 1]
        oldmant = mant; // save
        if (len > 0) {
            // remove the unwanted digits
            mant = new byte[len];
            java.lang.System.arraycopy((java.lang.Object) oldmant, 0, (java.lang.Object) mant, 0, len);
            reuse = true; // can reuse mantissa
            first = oldmant[len]; // first of discarded digits
        } else {/* len<=0 */
            mant = ZERO.mant;
            ind = iszero;
            reuse = false; // cannot reuse mantissa
            if (len == 0)
                first = oldmant[0];
            else
                first = (byte) 0; // [virtual digit]
        }

        // decide rounding adjustment depending on mode, sign, and discarded digits
        increment = 0; // bumper
        {
            do {/* select */
                if (mode == ROUND_HALF_UP) { // default first [most common]
                    if (first >= 5)
                        increment = sign;
                } else if (mode == ROUND_UNNECESSARY) { // default for setScale()
                    // discarding any non-zero digits is an error
                    if ((!(allzero(oldmant, len))))
                        throw new java.lang.ArithmeticException("Rounding necessary");
                } else if (mode == ROUND_HALF_DOWN) { // 0.5000 goes down
                    if (first > 5)
                        increment = sign;
                    else if (first == 5)
                        if ((!(allzero(oldmant, len + 1))))
                            increment = sign;
                } else if (mode == ROUND_HALF_EVEN) { // 0.5000 goes down if left digit even
                    if (first > 5)
                        increment = sign;
                    else if (first == 5) {
                        if ((!(allzero(oldmant, len + 1))))
                            increment = sign;
                        else /* 0.5000 */
                        if ((((mant[mant.length - 1]) % 2)) != 0)
                            increment = sign;
                    }
                } else if (mode == ROUND_DOWN) {
                    // never increment
                } else if (mode == ROUND_UP) { // increment if discarded non-zero
                    if ((!(allzero(oldmant, len))))
                        increment = sign;
                } else if (mode == ROUND_CEILING) { // more positive
                    if (sign > 0)
                        if ((!(allzero(oldmant, len))))
                            increment = sign;
                } else if (mode == ROUND_FLOOR) { // more negative
                    if (sign < 0)
                        if ((!(allzero(oldmant, len))))
                            increment = sign;
                } else {
                    throw new java.lang.IllegalArgumentException("Bad round value:" + " " + mode);
                }
            } while (false);
        }/* modes */

        if (increment != 0) {
            do {
                if (ind == iszero) {
                    // we must not subtract from 0, but result is trivial anyway
                    mant = ONE.mant;
                    ind = (byte) increment;
                } else {
                    // mantissa is non-0; we can safely add or subtract 1
                    if (ind == isneg)
                        increment = -increment;
                    newmant = byteaddsub(mant, mant.length, ONE.mant, 1, increment, reuse);
                    if (newmant.length > mant.length) { // had a carry
                        // drop rightmost digit and raise exponent
                        exp++;
                        // mant is already the correct length
                        java.lang.System.arraycopy((java.lang.Object) newmant, 0, (java.lang.Object) mant, 0,
                                mant.length);
                    } else
                        mant = newmant;
                }
            } while (false);
        }/* bump */
        // rounding can increase exponent significantly
        if (exp > MaxExp)
            throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
        return this;
    }

    /*
     * <sgml> Test if rightmost digits are all 0. Arg1 is a mantissa array to test Arg2 is the offset of first digit to
     * check [may be negative; if so, digits to left are 0's] returns 1 if all the digits starting at Arg2 are 0
     * 
     * Arg2 may be beyond array bounds, in which case 1 is returned </sgml>
     */

    private static final boolean allzero(byte array[], int start) {
        int i = 0;
        if (start < 0)
            start = 0;
        {
            int $25 = array.length - 1;
            i = start;
            for (; i <= $25; i++) {
                if (array[i] != 0)
                    return false;
            }
        }/* i */
        return true;
    }

    /*
     * <sgml> Carry out final checks and canonicalization <p> This finishes off the current number by: 1. Rounding if
     * necessary (NB: length includes leading zeros) 2. Stripping trailing zeros (if requested and \PLAIN) 3. Stripping
     * leading zeros (always) 4. Selecting exponential notation (if required) 5. Converting a zero result to just '0'
     * (if \PLAIN) In practice, these operations overlap and share code. It always sets form. </sgml> Arg1 is requested
     * MathContext (length to round to, trigger, and FORM) Arg2 is 1 if trailing insignificant zeros should be removed
     * after round (for division, etc.), provided that set.form isn't PLAIN. returns this, for convenience
     */

    private com.ibm.icu.math.BigDecimal finish(com.ibm.icu.math.MathContext set, boolean strip) {
        int d = 0;
        int i = 0;
        byte newmant[] = null;
        int mag = 0;
        int sig = 0;
        /* Round if mantissa too long and digits requested */
        if (set.digits != 0)
            if (this.mant.length > set.digits)
                this.round(set);

        /*
         * If strip requested (and standard formatting), remove insignificant trailing zeros.
         */
        if (strip)
            if (set.form != com.ibm.icu.math.MathContext.PLAIN) {
                d = this.mant.length;
                /* see if we need to drop any trailing zeros */
                {
                    i = d - 1;
                    i: for (; i >= 1; i--) {
                        if (this.mant[i] != 0)
                            break i;
                        d--;
                        exp++;
                    }
                }/* i */
                if (d < this.mant.length) {/* need to reduce */
                    newmant = new byte[d];
                    java.lang.System.arraycopy((java.lang.Object) this.mant, 0, (java.lang.Object) newmant, 0, d);
                    this.mant = newmant;
                }
            }

        form = (byte) com.ibm.icu.math.MathContext.PLAIN; // preset

        /* Now check for leading- and all- zeros in mantissa */
        {
            int $26 = this.mant.length;
            i = 0;
            for (; $26 > 0; $26--, i++) {
                if (this.mant[i] != 0) {
                    // non-0 result; ind will be correct
                    // remove leading zeros [e.g., after subtract]
                    if (i > 0) {
                        do {
                            newmant = new byte[this.mant.length - i];
                            java.lang.System.arraycopy((java.lang.Object) this.mant, i, (java.lang.Object) newmant, 0,
                                    this.mant.length - i);
                            this.mant = newmant;
                        } while (false);
                    }/* delead */
                    // now determine form if not PLAIN
                    mag = exp + mant.length;
                    if (mag > 0) { // most common path
                        if (mag > set.digits)
                            if (set.digits != 0)
                                form = (byte) set.form;
                        if ((mag - 1) <= MaxExp)
                            return this; // no overflow; quick return
                    } else if (mag < (-5))
                        form = (byte) set.form;
                    /* check for overflow */
                    mag--;
                    if ((mag < MinExp) | (mag > MaxExp)) {
                        overflow: do {
                            // possible reprieve if form is engineering
                            if (form == com.ibm.icu.math.MathContext.ENGINEERING) {
                                sig = mag % 3; // leftover
                                if (sig < 0)
                                    sig = 3 + sig; // negative exponent
                                mag = mag - sig; // exponent to use
                                // 1999.06.29: second test here must be MaxExp
                                if (mag >= MinExp)
                                    if (mag <= MaxExp)
                                        break overflow;
                            }
                            throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + mag);
                        } while (false);
                    }/* overflow */
                    return this;
                }
            }
        }/* i */

        // Drop through to here only if mantissa is all zeros
        ind = iszero;
        {/* select */
            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
                exp = 0; // standard result; go to '0'
            else if (exp > 0)
                exp = 0; // +ve exponent also goes to '0'
            else {
                // a plain number with -ve exponent; preserve and check exponent
                if (exp < MinExp)
                    throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
            }
        }
        mant = ZERO.mant; // canonical mantissa
        return this;
    }
}
