/* 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.impl.Utility;

/* ------------------------------------------------------------------ */
/* BigDecimal -- Decimal arithmetic for Java                          */
/* ------------------------------------------------------------------ */
/* Copyright IBM Corporation, 1996-2003.  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.
 * <eul>
 * <p>
 * The names of methods in this class follow the conventions established
 * by <code>java.lang.Number</code>, <code>java.math.BigInteger</code>,
 * and <code>java.math.BigDecimal</code> in Java 1.1 and Java 1.2.
 *
 * @see     MathContext
 * @author  Mike Cowlishaw
 * @stable ICU 2.0
 */

public class BigDecimal extends java.lang.Number implements java.io.Serializable,java.lang.Comparable{
 private static final java.lang.String $0="BigDecimal.nrx";
 
 
 
 /* ----- Constants ----- */
 /* properties constant public */ // useful to others
 /**
  * The <code>BigDecimal</code> constant "0".
  *
  * @see #ONE
  * @see #TEN
  * @stable ICU 2.0
  */
 public static final com.ibm.icu.math.BigDecimal ZERO=new com.ibm.icu.math.BigDecimal((long)0); // use long as we want the int constructor
 // .. to be able to use this, for speed
 
 /**
  * The <code>BigDecimal</code> constant "1".
  *
  * @see #TEN
  * @see #ZERO
  * @stable ICU 2.0
  */
 public static final com.ibm.icu.math.BigDecimal ONE=new com.ibm.icu.math.BigDecimal((long)1); // use long as we want the int constructor
 // .. to be able to use this, for speed
 
 /**
  * The <code>BigDecimal</code> constant "10".
  *
  * @see #ONE
  * @see #ZERO
  * @stable ICU 2.0
  */
 public static final com.ibm.icu.math.BigDecimal TEN=new com.ibm.icu.math.BigDecimal(10);
 
 // the rounding modes (copied here for upwards compatibility)
 /**
  * Rounding mode to round to a more positive number.
  * @see MathContext#ROUND_CEILING
  * @stable ICU 2.0
  */
 public static final int ROUND_CEILING=com.ibm.icu.math.MathContext.ROUND_CEILING;
 
 /**
  * Rounding mode to round towards zero.
  * @see MathContext#ROUND_DOWN
  * @stable ICU 2.0
  */
 public static final int ROUND_DOWN=com.ibm.icu.math.MathContext.ROUND_DOWN;
 
 /**
  * Rounding mode to round to a more negative number.
  * @see MathContext#ROUND_FLOOR
  * @stable ICU 2.0
  */
 public static final int ROUND_FLOOR=com.ibm.icu.math.MathContext.ROUND_FLOOR;
 
 /**
  * Rounding mode to round to nearest neighbor, where an equidistant
  * value is rounded down.
  * @see MathContext#ROUND_HALF_DOWN
  * @stable ICU 2.0
  */
 public static final int ROUND_HALF_DOWN=com.ibm.icu.math.MathContext.ROUND_HALF_DOWN;
 
 /**
  * Rounding mode to round to nearest neighbor, where an equidistant
  * value is rounded to the nearest even neighbor.
  * @see MathContext#ROUND_HALF_EVEN
  * @stable ICU 2.0
  */
 public static final int ROUND_HALF_EVEN=com.ibm.icu.math.MathContext.ROUND_HALF_EVEN;
 
 /**
  * Rounding mode to round to nearest neighbor, where an equidistant
  * value is rounded up.
  * @see MathContext#ROUND_HALF_UP
  * @stable ICU 2.0
  */
 public static final int ROUND_HALF_UP=com.ibm.icu.math.MathContext.ROUND_HALF_UP;
 
 /**
  * Rounding mode to assert that no rounding is necessary.
  * @see MathContext#ROUND_UNNECESSARY
  * @stable ICU 2.0
  */
 public static final int ROUND_UNNECESSARY=com.ibm.icu.math.MathContext.ROUND_UNNECESSARY;
 
 /**
  * Rounding mode to round away from zero.
  * @see MathContext#ROUND_UP
  * @stable ICU 2.0
  */
 public static final int ROUND_UP=com.ibm.icu.math.MathContext.ROUND_UP;
 
 /* properties constant private */ // locals
 private static final byte ispos=1; // ind: indicates positive (must be 1)
 private static final byte iszero=0; // ind: indicates zero     (must be 0)
 private static final byte isneg=-1; // ind: indicates negative (must be -1)
 // [later could add NaN, +/- infinity, here]
 
 private static final int MinExp=-999999999; // minimum exponent allowed
 private static final int MaxExp=999999999; // maximum exponent allowed
 private static final int MinArg=-999999999; // minimum argument integer
 private static final int MaxArg=999999999; // maximum argument integer
 
 private static final com.ibm.icu.math.MathContext plainMC=new com.ibm.icu.math.MathContext(0,com.ibm.icu.math.MathContext.PLAIN); // context for plain unlimited math
 
 /* properties constant private unused */ // present but not referenced
 
 // Serialization version
 private static final long serialVersionUID=8245355804974198832L;
 
 private static final java.lang.String copyright=" Copyright (c) IBM Corporation 1996, 2000.  All rights reserved. ";
 
 /* properties static private */
 // Precalculated constant arrays (used by byteaddsub)
 private static byte bytecar[]=new byte[(90+99)+1]; // carry/borrow array
 private static byte bytedig[]=diginit(); // next digit array
 
 /* ----- Instance properties [all private and immutable] ----- */
 /* properties private */
 
 /**
  * The indicator. This may take the values:
  * <ul>
  * <li>ispos  -- the number is positive
  * <li>iszero -- the number is zero
  * <li>isneg  -- the number is negative
  * </ul>
  *
  * @serial
  */
 private byte ind; // assumed undefined
 // Note: some code below assumes IND = Sign [-1, 0, 1], at present.
 // We only need two bits for this, but use a byte [also permits
 // smooth future extension].
 
 /**
  * The formatting style. This may take the values:
  * <ul>
  * <li>MathContext.PLAIN        -- no exponent needed
  * <li>MathContext.SCIENTIFIC   -- scientific notation required
  * <li>MathContext.ENGINEERING  -- engineering notation required
  * </ul>
  * <p>
  * This property is an optimization; it allows us to defer number
  * layout until it is actually needed as a string, hence avoiding
  * unnecessary formatting.
  *
  * @serial
  */
 private byte form=(byte)com.ibm.icu.math.MathContext.PLAIN; // assumed PLAIN
 // We only need two bits for this, at present, but use a byte
 // [again, to allow for smooth future extension]
 
 /**
  * The value of the mantissa.
  * <p>
  * Once constructed, this may become shared between several BigDecimal
  * objects, so must not be altered.
  * <p>
  * For efficiency (speed), this is a byte array, with each byte
  * taking a value of 0 -> 9.
  * <p>
  * If the first byte is 0 then the value of the number is zero (and
  * mant.length=1, except when constructed from a plain number, for
  * example, 0.000).
  *
  * @serial
  */
 private byte mant[]; // assumed null
 
 /**
  * The exponent.
  * <p>
  * For fixed point arithmetic, scale is <code>-exp</code>, and can
  * apply to zero.
  *
  * Note that this property can have a value less than MinExp when
  * the mantissa has more than one digit.
  *
  * @serial
  */
 private int exp;
 // assumed 0
 
 /* ---------------------------------------------------------------- */
 /* Constructors                                                     */
 /* ---------------------------------------------------------------- */
 
 /**
  * Constructs a <code>BigDecimal</code> object from a
  * <code>java.math.BigDecimal</code>.
  * <p>
  * Constructs a <code>BigDecimal</code> as though the parameter had
  * been represented as a <code>String</code> (using its
  * <code>toString</code> method) and the
  * {@link #BigDecimal(java.lang.String)} constructor had then been
  * used.
  * The parameter must not be <code>null</code>.
  * <p>
  * <i>(Note: this constructor is provided only in the
  * <code>com.ibm.icu.math</code> version of the BigDecimal class.
  * It would not be present in a <code>java.math</code> version.)</i>
  *
  * @param bd The <code>BigDecimal</code> to be translated.
  * @stable ICU 2.0
  */
 
 public BigDecimal(java.math.BigDecimal bd){
  this(bd.toString());
  return;}

 /**
  * Constructs a <code>BigDecimal</code> object from a
  * <code>BigInteger</code>, with scale 0.
  * <p>
  * Constructs a <code>BigDecimal</code> which is the exact decimal
  * representation of the <code>BigInteger</code>, with a scale of
  * zero.
  * The value of the <code>BigDecimal</code> is identical to the value
  * of the <code>BigInteger</code>.
  * The parameter must not be <code>null</code>.
  * <p>
  * The <code>BigDecimal</code> will contain only decimal digits,
  * prefixed with a leading minus sign (hyphen) if the
  * <code>BigInteger</code> is negative.  A leading zero will be
  * present only if the <code>BigInteger</code> is zero.
  *
  * @param bi The <code>BigInteger</code> to be converted.
  * @stable ICU 2.0
  */
 
 public BigDecimal(java.math.BigInteger bi){
  this(bi.toString(10));
  return;}
 // exp remains 0
 
 /**
  * Constructs a <code>BigDecimal</code> object from a
  * <code>BigInteger</code> and a scale.
  * <p>
  * Constructs a <code>BigDecimal</code> which is the exact decimal
  * representation of the <code>BigInteger</code>, scaled by the
  * second parameter, which may not be negative.
  * The value of the <code>BigDecimal</code> is the
  * <code>BigInteger</code> divided by ten to the power of the scale.
  * The <code>BigInteger</code> parameter must not be
  * <code>null</code>.
  * <p>
  * The <code>BigDecimal</code> will contain only decimal digits, (with
  * an embedded decimal point followed by <code>scale</code> decimal
  * digits if the scale is positive), prefixed with a leading minus
  * sign (hyphen) if the <code>BigInteger</code> is negative.  A
  * leading zero will be present only if the <code>BigInteger</code> is
  * zero.
  *
  * @param  bi    The <code>BigInteger</code> to be converted.
  * @param  scale The <code>int</code> specifying the scale.
  * @throws NumberFormatException if the scale is negative.
  * @stable ICU 2.0
  */
 
 public BigDecimal(java.math.BigInteger bi,int scale){
  this(bi.toString(10));
  if (scale<0) 
   throw new java.lang.NumberFormatException("Negative scale:"+" "+scale);
  exp=(int)-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 ((!(java.lang.Character.isDigit(si)))) 
       bad(inchars); // not a number
      // defer the base 10 check until later to avoid extra method call
      exotic=true; // will need conversion later
      last=i;
      d++; // still in mantissa
      continue i;
     }
   /* Found 'e' or 'E' -- now process explicit exponent */
   // 1998.07.11: sign no longer required
   if ((i-offset)>(length-2)) 
    bad(inchars); // no room for even one digit
   eneg=false;
   if ((inchars[i+1])==('-')) 
    {
     eneg=true;
     k=i+2;
    }
   else 
    if ((inchars[i+1])==('+')) 
     k=i+2;
    else 
     k=i+1;
   // k is offset of first expected digit
   elen=length-((k-offset)); // possible number of digits
   if ((elen==0)|(elen>9)) 
    bad(inchars); // 0 or more than 9 digits
   {int $2=elen;j=k;j:for(;$2>0;$2--,j++){
    sj=inchars[j];
    if (sj<'0') 
     bad(inchars); // always bad
    if (sj>'9') 
     { // maybe an exotic digit
      if ((!(java.lang.Character.isDigit(sj)))) 
       bad(inchars); // not a number
      dvalue=java.lang.Character.digit(sj,10); // check base
      if (dvalue<0) 
       bad(inchars); // not base 10
     }
    else 
     dvalue=((int)(sj))-((int)('0'));
    exp=(exp*10)+dvalue;
    }
   }/*j*/
   if (eneg) 
    exp=(int)-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 ((java.lang.Character.digit(si,10))!=0) 
        break i; // non-0 or bad
       // is 0 .. strip like '0'
       offset++;
       dotoff--;
       d--;
      }
   }
  }/*i*/
  
  /* Create the mantissa array */
  mant=new byte[d]; // we know the length
  j=offset; // input offset
  if (exotic) 
   {exotica:do{ // slow: check for exotica
    {int $4=d;i=0;i: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=java.lang.Character.digit(sj,10);
       if (dvalue<0) 
        bad(inchars); // not a number after all
       mant[i]=(byte)dvalue;
      }
     j++;
     }
    }/*i*/
   }while(false);}/*exotica*/
  else 
   {simple:do{
    {int $5=d;i=0;i: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)) 
    {singledigit: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)((int)-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=(int)-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=(long)-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;
  {padder: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 
   {signdiff: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. */
    {swaptest: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>.
  * @see    #compareTo(Object)
  * @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(Object)} 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>.
  * @see    #compareTo(Object)
  * @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;i:for(;$6>0;$6--,i++){
       if (this.mant[i]<rhs.mant[i]) 
        return (byte)-this.ind;
       if (this.mant[i]>rhs.mant[i]) 
        return this.ind;
       }
      }/*i*/
      return 0; // identical
     }
   /* drop through for full comparison */
   }
  else 
   {
    /* More fastpaths possible */
    if (this.ind<rhs.ind) 
     return -1;
    if (this.ind>rhs.ind) 
     return 1;
   }
  /* carry out a subtract to make the comparison */
  newrhs=clone(rhs); // safe copy
  newrhs.ind=(byte)-newrhs.ind; // prepare to subtract
  return this.add(newrhs,set).ind; // add, and return sign of result
  }

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

 /**
  * Returns a plain <code>BigDecimal</code> whose value is
  * <code>this/rhs</code>, using fixed point arithmetic and a
  * rounding mode.
  * <p>
  * The same as {@link #divide(BigDecimal, int, int)},
  * where the <code>BigDecimal</code> is <code>rhs</code>,
  * and the second parameter is <code>this.scale()</code>, and
  * the third is <code>round</code>.
  * <p>
  * The length of the decimal part (the scale) of the result will
  * therefore be the same as the scale of the current object, if the
  * latter were formatted without exponential notation.
  * <p>
  * @param  rhs   The <code>BigDecimal</code> for the right hand side of
  *               the division.
  * @param  round The <code>int</code> rounding mode to be used for
  *               the division (see the {@link MathContext} class).
  * @return       A plain <code>BigDecimal</code> whose value is
  *               <code>this/rhs</code>, using fixed point arithmetic
  *               and the specified rounding mode.
  * @throws IllegalArgumentException if <code>round</code> is not a
  *               valid rounding mode.
  * @throws ArithmeticException if <code>rhs</code> is zero.
  * @throws ArithmeticException if <code>round</code> is {@link
  *               MathContext#ROUND_UNNECESSARY} and
  *               <code>this.scale()</code> is insufficient to
  *               represent the result exactly.
  * @stable ICU 2.0
  */
 
 public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs,int round){
  com.ibm.icu.math.MathContext set;
  set=new com.ibm.icu.math.MathContext(0,com.ibm.icu.math.MathContext.PLAIN,false,round); // [checks round, too]
  return this.dodivide('D',rhs,set,-1); // take scale from LHS
  }

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

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

 /**
  * Returns a plain <code>BigDecimal</code> whose value is the integer
  * part of <code>this/rhs</code>.
  * <p>
  * The same as {@link #divideInteger(BigDecimal, MathContext)},
  * where the <code>BigDecimal</code> is <code>rhs</code>,
  * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
  *
  * @param  rhs The <code>BigDecimal</code> for the right hand side of
  *             the integer division.
  * @return     A <code>BigDecimal</code> whose value is the integer
  *             part of <code>this/rhs</code>.
  * @throws ArithmeticException if <code>rhs</code> is zero.
  * @stable ICU 2.0
  */
 
 public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs){
  // scale 0 to drop .000 when plain
  return this.dodivide('I',rhs,plainMC,0);
  }

 /**
  * Returns a <code>BigDecimal</code> whose value is the integer
  * part of <code>this/rhs</code>.
  * <p>
  * Implements the integer division operator
  * (as defined in the decimal documentation, see {@link BigDecimal
  * class header}),
  * and returns the result as a <code>BigDecimal</code> object.
  *
  * @param  rhs The <code>BigDecimal</code> for the right hand side of
  *             the integer division.
  * @param  set The <code>MathContext</code> arithmetic settings.
  * @return     A <code>BigDecimal</code> whose value is the integer
  *             part of <code>this/rhs</code>.
  * @throws ArithmeticException if <code>rhs</code> is zero.
  * @throws ArithmeticException if the result will not fit in the
  *             number of digits specified for the context.
  * @stable ICU 2.0
  */
 
 public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs,com.ibm.icu.math.MathContext set){
  // scale 0 to drop .000 when plain
  return this.dodivide('I',rhs,set,0);
  }

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

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

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

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

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

 /**
  * Returns a <code>BigDecimal</code> whose value is <code>this*rhs</code>.
  * <p>
  * Implements the multiplication (<b><code>*</code></b>) operator
  * (as defined in the decimal documentation, see {@link BigDecimal
  * class header}),
  * and returns the result as a <code>BigDecimal</code> object.
  *
  * @param  rhs The <code>BigDecimal</code> for the right hand side of
  *             the multiplication.
  * @param  set The <code>MathContext</code> arithmetic settings.
  * @return     A <code>BigDecimal</code> whose value is
  *             <code>this*rhs</code>.
  * @stable ICU 2.0
  */
 
 public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs,com.ibm.icu.math.MathContext set){
  com.ibm.icu.math.BigDecimal lhs;
  int padding;
  int reqdig;
  byte multer[]=null;
  byte multand[]=null;
  int multandlen;
  int acclen=0;
  com.ibm.icu.math.BigDecimal res;
  byte acc[];
  int n=0;
  byte mult=0;
  if (set.lostDigits) 
   checkdigits(rhs,set.digits);
  lhs=this; // name for clarity and proxy
  
  /* Prepare numbers (truncate, unless unlimited precision) */
  padding=0; // trailing 0's to add
  reqdig=set.digits; // local copy
  if (reqdig>0) 
   {
    if (lhs.mant.length>reqdig) 
     lhs=clone(lhs).round(set);
    if (rhs.mant.length>reqdig) 
     rhs=clone(rhs).round(set);
   // [we could reuse the new LHS for result in this case]
   }
  else 
   {/* unlimited */
    // fixed point arithmetic will want every trailing 0; we add these
    // after the calculation rather than before, for speed.
    if (lhs.exp>0) 
     padding=padding+lhs.exp;
    if (rhs.exp>0) 
     padding=padding+rhs.exp;
   }
  
  // For best speed, as in DMSRCN, we use the shorter number as the
  // multiplier and the longer as the multiplicand.
  // 1999.12.22: We used to special case when the result would fit in
  //             a long, but with Java 1.3 this gave no advantage.
  if (lhs.mant.length<rhs.mant.length) 
   {
    multer=lhs.mant;
    multand=rhs.mant;
   }
  else 
   {
    multer=rhs.mant;
    multand=lhs.mant;
   }
  
  /* Calculate how long result byte array will be */
  multandlen=(multer.length+multand.length)-1; // effective length
  // optimize for 75% of the cases where a carry is expected...
  if ((multer[0]*multand[0])>9) 
   acclen=multandlen+1;
  else 
   acclen=multandlen;
  
  /* Now the main long multiplication loop */
  res=new com.ibm.icu.math.BigDecimal(); // where we'll build result
  acc=new byte[acclen]; // accumulator, all zeros
  // 1998.07.01: calculate from left to right so that accumulator goes
  // to likely final length on first addition; this avoids a one-digit
  // extension (and object allocation) each time around the loop.
  // Initial number therefore has virtual zeros added to right.
  {int $7=multer.length;n=0;n: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=(int)-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;
  }

 /**
  * Compares this <code>BigDecimal</code> with the value of the parameter.
  * <p>
  * If the parameter is <code>null</code>, or is not an instance of the
  * <code>BigDecimal</code> type, an exception is thrown.
  * Otherwise, the parameter is cast to type <code>BigDecimal</code>
  * and the result of the {@link #compareTo(BigDecimal)} method,
  * using the cast parameter, is returned.
  * <p>
  * The {@link #compareTo(BigDecimal, MathContext)} method should be
  * used when a <code>MathContext</code> is needed for the comparison.
  *
  * @param  rhsobj The <code>Object</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>.
  * @throws ClassCastException if <code>rhs</code> cannot be cast to
  *                 a <code>BigDecimal</code> object.
  * @see    #compareTo(BigDecimal)
  * @stable ICU 2.0
  */
 
 public int compareTo(java.lang.Object rhsobj){
  // the cast in the next line will raise ClassCastException if necessary
  return compareTo((com.ibm.icu.math.BigDecimal)rhsobj,plainMC);
  }

 /**
  * 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(Object)
  * @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;i: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;i: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 */
  {setform: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=(int)-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;i: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;i: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;i: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;i: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 (int)-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;i: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 (long)-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 (int)-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=(int)-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!=((int)-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 (((int)-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=(int)-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;
  java.lang.StringBuffer 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;i: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 java.lang.StringBuffer(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 
     {engineering: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=(int)-euse;
       }
      else 
       csign='+';
      sb.append('E').append(csign).append(euse);
     }
    rec=new char[sb.length()];
    Utility.getChars(sb, 0,sb.length(),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=(int)((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=(int)-mag;i=needsign+2;i: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;i: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=ca*10/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!=((int)-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;i: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,(int)-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 (((int)-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') 
     {remainder: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) 
   {scaled: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-((((int)-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!=((int)-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+(B*M)
    </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) 
     {quick: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;i: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());
  return;
  }

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