//##header
/* 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-2005.  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                                                     */
 /* ---------------------------------------------------------------- */
 
//#ifndef FOUNDATION
 /**
  * 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;}
//#ENDIF

 /**
  * 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
//#ifndef FOUNDATION
  this((new java.math.BigDecimal(num)).toString());
//#else
//##    this(String.valueOf(num));
//#endif
  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.]
  }

//#ifndef FOUNDATION
 /**
  * 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());
  }
//#ENDIF

 /**
  * 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());
  }

 /* <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;
  }
 }
