/* java.math.BigDecimal -- Arbitrary precision decimals.
   Copyright (C) 1999, 2000, 2001, 2003, 2005, 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.math;

import gnu.java.lang.CPStringBuilder;

public class BigDecimal extends Number implements Comparable<BigDecimal>
{
  private BigInteger intVal;
  private int scale;
  private int precision = 0;
  private static final long serialVersionUID = 6108874887143696463L;

  /**
   * The constant zero as a BigDecimal with scale zero.
   * @since 1.5
   */
  public static final BigDecimal ZERO =
    new BigDecimal (BigInteger.ZERO, 0);

  /**
   * The constant one as a BigDecimal with scale zero.
   * @since 1.5
   */
  public static final BigDecimal ONE =
    new BigDecimal (BigInteger.ONE, 0);

  /**
   * The constant ten as a BigDecimal with scale zero.
   * @since 1.5
   */
  public static final BigDecimal TEN =
    new BigDecimal (BigInteger.TEN, 0);

  public static final int ROUND_UP = 0;
  public static final int ROUND_DOWN = 1;
  public static final int ROUND_CEILING = 2;
  public static final int ROUND_FLOOR = 3;
  public static final int ROUND_HALF_UP = 4;
  public static final int ROUND_HALF_DOWN = 5;
  public static final int ROUND_HALF_EVEN = 6;
  public static final int ROUND_UNNECESSARY = 7;

  /**
   * Constructs a new BigDecimal whose unscaled value is val and whose
   * scale is zero.
   * @param val the value of the new BigDecimal
   * @since 1.5
   */
  public BigDecimal (int val)
  {
    this.intVal = BigInteger.valueOf(val);
    this.scale = 0;
  }

  /**
   * Constructs a BigDecimal using the BigDecimal(int) constructor and then
   * rounds according to the MathContext.
   * @param val the value for the initial (unrounded) BigDecimal
   * @param mc the MathContext specifying the rounding
   * @throws ArithmeticException if the result is inexact but the rounding type
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal (int val, MathContext mc)
  {
    this (val);
    if (mc.getPrecision() != 0)
      {
        BigDecimal result = this.round(mc);
        this.intVal = result.intVal;
        this.scale = result.scale;
        this.precision = result.precision;
      }
  }

  /**
   * Constructs a new BigDecimal whose unscaled value is val and whose
   * scale is zero.
   * @param val the value of the new BigDecimal
   */
  public BigDecimal (long val)
  {
    this.intVal = BigInteger.valueOf(val);
    this.scale = 0;
  }

  /**
   * Constructs a BigDecimal from the long in the same way as BigDecimal(long)
   * and then rounds according to the MathContext.
   * @param val the long from which we create the initial BigDecimal
   * @param mc the MathContext that specifies the rounding behaviour
   * @throws ArithmeticException if the result is inexact but the rounding type
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal (long val, MathContext mc)
  {
    this(val);
    if (mc.getPrecision() != 0)
      {
        BigDecimal result = this.round(mc);
        this.intVal = result.intVal;
        this.scale = result.scale;
        this.precision = result.precision;
      }
  }

  /**
   * Constructs a BigDecimal whose value is given by num rounded according to
   * mc.  Since num is already a BigInteger, the rounding refers only to the
   * precision setting in mc, if mc.getPrecision() returns an int lower than
   * the number of digits in num, then rounding is necessary.
   * @param num the unscaledValue, before rounding
   * @param mc the MathContext that specifies the precision
   * @throws ArithmeticException if the result is inexact but the rounding type
   * is RoundingMode.UNNECESSARY
   * * @since 1.5
   */
  public BigDecimal (BigInteger num, MathContext mc)
  {
    this (num, 0);
    if (mc.getPrecision() != 0)
      {
        BigDecimal result = this.round(mc);
        this.intVal = result.intVal;
        this.scale = result.scale;
        this.precision = result.precision;
      }
  }

  /**
   * Constructs a BigDecimal from the String val according to the same
   * rules as the BigDecimal(String) constructor and then rounds
   * according to the MathContext mc.
   * @param val the String from which we construct the initial BigDecimal
   * @param mc the MathContext that specifies the rounding
   * @throws ArithmeticException if the result is inexact but the rounding type
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal (String val, MathContext mc)
  {
    this (val);
    if (mc.getPrecision() != 0)
      {
        BigDecimal result = this.round(mc);
        this.intVal = result.intVal;
        this.scale = result.scale;
        this.precision = result.precision;
      }
  }

  /**
   * Constructs a BigDecimal whose unscaled value is num and whose
   * scale is zero.
   * @param num the value of the new BigDecimal
   */
  public BigDecimal (BigInteger num)
  {
    this (num, 0);
  }

  /**
   * Constructs a BigDecimal whose unscaled value is num and whose
   * scale is scale.
   * @param num
   * @param scale
   */
  public BigDecimal (BigInteger num, int scale)
  {
    this.intVal = num;
    this.scale = scale;
  }

  /**
   * Constructs a BigDecimal using the BigDecimal(BigInteger, int)
   * constructor and then rounds according to the MathContext.
   * @param num the unscaled value of the unrounded BigDecimal
   * @param scale the scale of the unrounded BigDecimal
   * @param mc the MathContext specifying the rounding
   * @throws ArithmeticException if the result is inexact but the rounding type
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal (BigInteger num, int scale, MathContext mc)
  {
    this (num, scale);
    if (mc.getPrecision() != 0)
      {
        BigDecimal result = this.round(mc);
        this.intVal = result.intVal;
        this.scale = result.scale;
        this.precision = result.precision;
      }
  }

  /**
   * Constructs a BigDecimal in the same way as BigDecimal(double) and then
   * rounds according to the MathContext.
   * @param num the double from which the initial BigDecimal is created
   * @param mc the MathContext that specifies the rounding behaviour
   * @throws ArithmeticException if the result is inexact but the rounding type
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal (double num, MathContext mc)
  {
    this (num);
    if (mc.getPrecision() != 0)
      {
        BigDecimal result = this.round(mc);
        this.intVal = result.intVal;
        this.scale = result.scale;
        this.precision = result.precision;
      }
  }

  public BigDecimal (double num) throws NumberFormatException
  {
    if (Double.isInfinite (num) || Double.isNaN (num))
      throw new NumberFormatException ("invalid argument: " + num);
    // Note we can't convert NUM to a String and then use the
    // String-based constructor.  The BigDecimal documentation makes
    // it clear that the two constructors work differently.

    final int mantissaBits = 52;
    final int exponentBits = 11;
    final long mantMask = (1L << mantissaBits) - 1;
    final long expMask = (1L << exponentBits) - 1;

    long bits = Double.doubleToLongBits (num);
    long mantissa = bits & mantMask;
    long exponent = (bits >>> mantissaBits) & expMask;
    boolean denormal = exponent == 0;

    // Correct the exponent for the bias.
    exponent -= denormal ? 1022 : 1023;

    // Now correct the exponent to account for the bits to the right
    // of the decimal.
    exponent -= mantissaBits;
    // Ordinary numbers have an implied leading `1' bit.
    if (! denormal)
      mantissa |= (1L << mantissaBits);

    // Shave off factors of 10.
    while (exponent < 0 && (mantissa & 1) == 0)
      {
        ++exponent;
        mantissa >>= 1;
      }

    intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa);
    if (exponent < 0)
      {
        // We have MANTISSA * 2 ^ (EXPONENT).
        // Since (1/2)^N == 5^N * 10^-N we can easily convert this
        // into a power of 10.
        scale = (int) (- exponent);
        BigInteger mult = BigInteger.valueOf (5).pow (scale);
        intVal = intVal.multiply (mult);
      }
    else
      {
        intVal = intVal.shiftLeft ((int) exponent);
        scale = 0;
      }
  }

  /**
   * Constructs a BigDecimal from the char subarray and rounding
   * according to the MathContext.
   * @param in the char array
   * @param offset the start of the subarray
   * @param len the length of the subarray
   * @param mc the MathContext for rounding
   * @throws NumberFormatException if the char subarray is not a valid
   * BigDecimal representation
   * @throws ArithmeticException if the result is inexact but the rounding
   * mode is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal(char[] in, int offset, int len, MathContext mc)
  {
    this(in, offset, len);
    // If mc has precision other than zero then we must round.
    if (mc.getPrecision() != 0)
      {
        BigDecimal temp = this.round(mc);
        this.intVal = temp.intVal;
        this.scale = temp.scale;
        this.precision = temp.precision;
      }
  }

  /**
   * Constructs a BigDecimal from the char array and rounding according
   * to the MathContext.
   * @param in the char array
   * @param mc the MathContext
   * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal
   * representation
   * @throws ArithmeticException if the result is inexact but the rounding mode
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal(char[] in, MathContext mc)
  {
    this(in, 0, in.length);
    // If mc has precision other than zero then we must round.
    if (mc.getPrecision() != 0)
      {
        BigDecimal temp = this.round(mc);
        this.intVal = temp.intVal;
        this.scale = temp.scale;
        this.precision = temp.precision;
      }
  }

  /**
   * Constructs a BigDecimal from the given char array, accepting the same
   * sequence of characters as the BigDecimal(String) constructor.
   * @param in the char array
   * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal
   * representation
   * @since 1.5
   */
  public BigDecimal(char[] in)
  {
    this(in, 0, in.length);
  }

  /**
   * Constructs a BigDecimal from a char subarray, accepting the same sequence
   * of characters as the BigDecimal(String) constructor.
   * @param in the char array
   * @param offset the start of the subarray
   * @param len the length of the subarray
   * @throws NumberFormatException if <code>in</code> is not a valid
   * BigDecimal representation.
   * @since 1.5
   */
  public BigDecimal(char[] in, int offset, int len)
  {
    //  start is the index into the char array where the significand starts
    int start = offset;
    //  end is one greater than the index of the last character used
    int end = offset + len;
    //  point is the index into the char array where the exponent starts
    //  (or, if there is no exponent, this is equal to end)
    int point = offset;
    //  dot is the index into the char array where the decimal point is
    //  found, or -1 if there is no decimal point
    int dot = -1;

    //  The following examples show what these variables mean.  Note that
    //  point and dot don't yet have the correct values, they will be
    //  properly assigned in a loop later on in this method.
    //
    //  Example 1
    //
    //         +  1  0  2  .  4  6  9
    //  __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
    //
    //  offset = 2, len = 8, start = 3, dot = 6, point = end = 10
    //
    //  Example 2
    //
    //         +  2  3  4  .  6  1  3  E  -  1
    //  __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
    //
    //  offset = 2, len = 11, start = 3, dot = 6, point = 10, end = 13
    //
    //  Example 3
    //
    //         -  1  2  3  4  5  e  7
    //  __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
    //
    //  offset = 2, len = 8, start = 3, dot = -1, point = 8, end = 10

    //  Determine the sign of the number.
    boolean negative = false;
    if (in[offset] == '+')
      {
        ++start;
        ++point;
      }
    else if (in[offset] == '-')
      {
        ++start;
        ++point;
        negative = true;
      }

    //  Check each character looking for the decimal point and the
    //  start of the exponent.
    while (point < end)
      {
        char c = in[point];
        if (c == '.')
          {
            // If dot != -1 then we've seen more than one decimal point.
            if (dot != -1)
              throw new NumberFormatException("multiple `.'s in number");
            dot = point;
          }
        // Break when we reach the start of the exponent.
        else if (c == 'e' || c == 'E')
          break;
        // Throw an exception if the character was not a decimal or an
        // exponent and is not a digit.
        else if (!Character.isDigit(c))
          throw new NumberFormatException("unrecognized character at " + point
                                          + ": " + c);
        ++point;
      }

    // val is a StringBuilder from which we'll create a BigInteger
    // which will be the unscaled value for this BigDecimal
    CPStringBuilder val = new CPStringBuilder(point - start - 1);
    if (dot != -1)
      {
        // If there was a decimal we must combine the two parts that
        // contain only digits and we must set the scale properly.
        val.append(in, start, dot - start);
        val.append(in, dot + 1, point - dot - 1);
        scale = point - 1 - dot;
      }
    else
      {
        // If there was no decimal then the unscaled value is just the number
        // formed from all the digits and the scale is zero.
        val.append(in, start, point - start);
        scale = 0;
      }
    if (val.length() == 0)
      throw new NumberFormatException("no digits seen");

    // Prepend a negative sign if necessary.
    if (negative)
      val.insert(0, '-');
    intVal = new BigInteger(val.toString());

    // Now parse exponent.
    // If point < end that means we broke out of the previous loop when we
    // saw an 'e' or an 'E'.
    if (point < end)
      {
        point++;
        // Ignore a '+' sign.
        if (in[point] == '+')
          point++;

        // Throw an exception if there were no digits found after the 'e'
        // or 'E'.
        if (point >= end)
          throw new NumberFormatException("no exponent following e or E");

        try
          {
            // Adjust the scale according to the exponent.
            // Remember that the value of a BigDecimal is
            // unscaledValue x Math.pow(10, -scale)
            scale -= Integer.parseInt(new String(in, point, end - point));
          }
        catch (NumberFormatException ex)
          {
            throw new NumberFormatException("malformed exponent");
          }
      }
  }

  public BigDecimal (String num) throws NumberFormatException
  {
    int len = num.length();
    int start = 0, point = 0;
    int dot = -1;
    boolean negative = false;
    if (num.charAt(0) == '+')
      {
        ++start;
        ++point;
      }
    else if (num.charAt(0) == '-')
      {
        ++start;
        ++point;
        negative = true;
      }

    while (point < len)
      {
        char c = num.charAt (point);
        if (c == '.')
          {
            if (dot >= 0)
              throw new NumberFormatException ("multiple `.'s in number");
            dot = point;
          }
        else if (c == 'e' || c == 'E')
          break;
        else if (Character.digit (c, 10) < 0)
          throw new NumberFormatException ("unrecognized character: " + c);
        ++point;
      }

    String val;
    if (dot >= 0)
      {
        val = num.substring (start, dot) + num.substring (dot + 1, point);
        scale = point - 1 - dot;
      }
    else
      {
        val = num.substring (start, point);
        scale = 0;
      }
    if (val.length () == 0)
      throw new NumberFormatException ("no digits seen");

    if (negative)
      val = "-" + val;
    intVal = new BigInteger (val);

    // Now parse exponent.
    if (point < len)
      {
        point++;
        if (num.charAt(point) == '+')
          point++;

        if (point >= len )
          throw new NumberFormatException ("no exponent following e or E");

        try
          {
        scale -= Integer.parseInt (num.substring (point));
          }
        catch (NumberFormatException ex)
          {
            throw new NumberFormatException ("malformed exponent");
          }
      }
  }

  public static BigDecimal valueOf (long val)
  {
    return valueOf (val, 0);
  }

  public static BigDecimal valueOf (long val, int scale)
    throws NumberFormatException
  {
    if ((scale == 0) && ((int)val == val))
      switch ((int) val)
        {
        case 0:
          return ZERO;
        case 1:
          return ONE;
        }

    return new BigDecimal (BigInteger.valueOf (val), scale);
  }

  public BigDecimal add (BigDecimal val)
  {
    // For addition, need to line up decimals.  Note that the movePointRight
    // method cannot be used for this as it might return a BigDecimal with
    // scale == 0 instead of the scale we need.
    BigInteger op1 = intVal;
    BigInteger op2 = val.intVal;
    if (scale < val.scale)
      op1 = op1.multiply (BigInteger.TEN.pow (val.scale - scale));
    else if (scale > val.scale)
      op2 = op2.multiply (BigInteger.TEN.pow (scale - val.scale));

    return new BigDecimal (op1.add (op2), Math.max (scale, val.scale));
  }

  /**
   * Returns a BigDecimal whose value is found first by calling the
   * method add(val) and then by rounding according to the MathContext mc.
   * @param val the augend
   * @param mc the MathContext for rounding
   * @throws ArithmeticException if the value is inexact but the rounding is
   * RoundingMode.UNNECESSARY
   * @return <code>this</code> + <code>val</code>, rounded if need be
   * @since 1.5
   */
  public BigDecimal add (BigDecimal val, MathContext mc)
  {
    return add(val).round(mc);
  }

  public BigDecimal subtract (BigDecimal val)
  {
    return this.add(val.negate());
  }

  /**
   * Returns a BigDecimal whose value is found first by calling the
   * method subtract(val) and then by rounding according to the MathContext mc.
   * @param val the subtrahend
   * @param mc the MathContext for rounding
   * @throws ArithmeticException if the value is inexact but the rounding is
   * RoundingMode.UNNECESSARY
   * @return <code>this</code> - <code>val</code>, rounded if need be
   * @since 1.5
   */
  public BigDecimal subtract (BigDecimal val, MathContext mc)
  {
    return subtract(val).round(mc);
  }

  public BigDecimal multiply (BigDecimal val)
  {
    return new BigDecimal (intVal.multiply (val.intVal), scale + val.scale);
  }

  /**
   * Returns a BigDecimal whose value is (this x val) before it is rounded
   * according to the MathContext mc.
   * @param val the multiplicand
   * @param mc the MathContext for rounding
   * @return a new BigDecimal with value approximately (this x val)
   * @throws ArithmeticException if the value is inexact but the rounding mode
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal multiply (BigDecimal val, MathContext mc)
  {
    return multiply(val).round(mc);
  }

  public BigDecimal divide (BigDecimal val, int roundingMode)
    throws ArithmeticException, IllegalArgumentException
  {
    return divide (val, scale, roundingMode);
  }

  /**
   * Returns a BigDecimal whose value is (this / val), with the specified scale
   * and rounding according to the RoundingMode
   * @param val the divisor
   * @param scale the scale of the BigDecimal returned
   * @param roundingMode the rounding mode to use
   * @return a BigDecimal whose value is approximately (this / val)
   * @throws ArithmeticException if divisor is zero or the rounding mode is
   * UNNECESSARY but the specified scale cannot represent the value exactly
   * @since 1.5
   */
  public BigDecimal divide(BigDecimal val,
                           int scale, RoundingMode roundingMode)
  {
    return divide (val, scale, roundingMode.ordinal());
  }

  /**
   * Returns a BigDecimal whose value is (this / val) rounded according to the
   * RoundingMode
   * @param val the divisor
   * @param roundingMode the rounding mode to use
   * @return a BigDecimal whose value is approximately (this / val)
   * @throws ArithmeticException if divisor is zero or the rounding mode is
   * UNNECESSARY but the specified scale cannot represent the value exactly
   */
  public BigDecimal divide (BigDecimal val, RoundingMode roundingMode)
  {
    return divide (val, scale, roundingMode.ordinal());
  }

  public BigDecimal divide(BigDecimal val, int newScale, int roundingMode)
    throws ArithmeticException, IllegalArgumentException
  {
    if (roundingMode < 0 || roundingMode > 7)
      throw
        new IllegalArgumentException("illegal rounding mode: " + roundingMode);

    if (intVal.signum () == 0)  // handle special case of 0.0/0.0
      return newScale == 0 ? ZERO : new BigDecimal (ZERO.intVal, newScale);

    // Ensure that pow gets a non-negative value.
    BigInteger valIntVal = val.intVal;
    int power = newScale - (scale - val.scale);
    if (power < 0)
      {
        // Effectively increase the scale of val to avoid an
        // ArithmeticException for a negative power.
        valIntVal = valIntVal.multiply (BigInteger.TEN.pow (-power));
        power = 0;
      }

    BigInteger dividend = intVal.multiply (BigInteger.TEN.pow (power));

    BigInteger parts[] = dividend.divideAndRemainder (valIntVal);

    BigInteger unrounded = parts[0];
    if (parts[1].signum () == 0) // no remainder, no rounding necessary
      return new BigDecimal (unrounded, newScale);

    if (roundingMode == ROUND_UNNECESSARY)
      throw new ArithmeticException ("Rounding necessary");

    int sign = intVal.signum () * valIntVal.signum ();

    if (roundingMode == ROUND_CEILING)
      roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN;
    else if (roundingMode == ROUND_FLOOR)
      roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN;
    else
      {
        // half is -1 if remainder*2 < positive intValue (*power), 0 if equal,
        // 1 if >. This implies that the remainder to round is less than,
        // equal to, or greater than half way to the next digit.
        BigInteger posRemainder
          = parts[1].signum () < 0 ? parts[1].negate() : parts[1];
        valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal;
        int half = posRemainder.shiftLeft(1).compareTo(valIntVal);

        switch(roundingMode)
          {
          case ROUND_HALF_UP:
            roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP;
            break;
          case ROUND_HALF_DOWN:
            roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN;
            break;
          case ROUND_HALF_EVEN:
            if (half < 0)
              roundingMode = ROUND_DOWN;
            else if (half > 0)
              roundingMode = ROUND_UP;
            else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP
              roundingMode = ROUND_UP;
            else                           // even, ROUND_HALF_DOWN
              roundingMode = ROUND_DOWN;
            break;
          }
      }

    if (roundingMode == ROUND_UP)
      unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1));

    // roundingMode == ROUND_DOWN
    return new BigDecimal (unrounded, newScale);
  }

  /**
   * Performs division, if the resulting quotient requires rounding
   * (has a nonterminating decimal expansion),
   * an ArithmeticException is thrown.
   * #see divide(BigDecimal, int, int)
   * @since 1.5
   */
  public BigDecimal divide(BigDecimal divisor)
    throws ArithmeticException, IllegalArgumentException
  {
    return divide(divisor, scale, ROUND_UNNECESSARY);
  }

  /**
   * Returns a BigDecimal whose value is the remainder in the quotient
   * this / val.  This is obtained by
   * subtract(divideToIntegralValue(val).multiply(val)).
   * @param val the divisor
   * @return a BigDecimal whose value is the remainder
   * @throws ArithmeticException if val == 0
   * @since 1.5
   */
  public BigDecimal remainder(BigDecimal val)
  {
    return subtract(divideToIntegralValue(val).multiply(val));
  }

  /**
   * Returns a BigDecimal array, the first element of which is the integer part
   * of this / val, and the second element of which is the remainder of
   * that quotient.
   * @param val the divisor
   * @return the above described BigDecimal array
   * @throws ArithmeticException if val == 0
   * @since 1.5
   */
  public BigDecimal[] divideAndRemainder(BigDecimal val)
  {
    BigDecimal[] result = new BigDecimal[2];
    result[0] = divideToIntegralValue(val);
    result[1] = subtract(result[0].multiply(val));
    return result;
  }

  /**
   * Returns a BigDecimal whose value is the integer part of the quotient
   * this / val.  The preferred scale is this.scale - val.scale.
   * @param val the divisor
   * @return a BigDecimal whose value is the integer part of this / val.
   * @throws ArithmeticException if val == 0
   * @since 1.5
   */
  public BigDecimal divideToIntegralValue(BigDecimal val)
  {
    return divide(val, ROUND_DOWN).floor().setScale(scale - val.scale, ROUND_DOWN);
  }

  /**
   * Mutates this BigDecimal into one with no fractional part, whose value is
   * equal to the largest integer that is <= to this BigDecimal.  Note that
   * since this method is private it is okay to mutate this BigDecimal.
   * @return the BigDecimal obtained through the floor operation on this
   * BigDecimal.
   */
  private BigDecimal floor()
  {
    if (scale <= 0)
      return this;
    String intValStr = intVal.toString();
    intValStr = intValStr.substring(0, intValStr.length() - scale);
    intVal = new BigInteger(intValStr).multiply(BigInteger.TEN.pow(scale));
    return this;
  }

  public int compareTo (BigDecimal val)
  {
    if (scale == val.scale)
      return intVal.compareTo (val.intVal);

    BigInteger thisParts[] =
      intVal.divideAndRemainder (BigInteger.TEN.pow (scale));
    BigInteger valParts[] =
      val.intVal.divideAndRemainder (BigInteger.TEN.pow (val.scale));

    int compare;
    if ((compare = thisParts[0].compareTo (valParts[0])) != 0)
      return compare;

    // quotients are the same, so compare remainders

    // Add some trailing zeros to the remainder with the smallest scale
    if (scale < val.scale)
      thisParts[1] = thisParts[1].multiply
                        (BigInteger.valueOf (10).pow (val.scale - scale));
    else if (scale > val.scale)
      valParts[1] = valParts[1].multiply
                        (BigInteger.valueOf (10).pow (scale - val.scale));

    // and compare them
    return thisParts[1].compareTo (valParts[1]);
  }

  public boolean equals (Object o)
  {
    return (o instanceof BigDecimal
            && scale == ((BigDecimal) o).scale
            && compareTo ((BigDecimal) o) == 0);
  }

  public int hashCode()
  {
    return intValue() ^ scale;
  }

  public BigDecimal max (BigDecimal val)
  {
    switch (compareTo (val))
      {
      case 1:
        return this;
      default:
        return val;
      }
  }

  public BigDecimal min (BigDecimal val)
  {
    switch (compareTo (val))
      {
      case -1:
        return this;
      default:
        return val;
      }
  }

  public BigDecimal movePointLeft (int n)
  {
    return (n < 0) ? movePointRight (-n) : new BigDecimal (intVal, scale + n);
  }

  public BigDecimal movePointRight (int n)
  {
    if (n < 0)
      return movePointLeft (-n);

    if (scale >= n)
      return new BigDecimal (intVal, scale - n);

    return new BigDecimal (intVal.multiply
                           (BigInteger.TEN.pow (n - scale)), 0);
  }

  public int signum ()
  {
    return intVal.signum ();
  }

  public int scale ()
  {
    return scale;
  }

  public BigInteger unscaledValue()
  {
    return intVal;
  }

  public BigDecimal abs ()
  {
    return new BigDecimal (intVal.abs (), scale);
  }

  public BigDecimal negate ()
  {
    return new BigDecimal (intVal.negate (), scale);
  }

  /**
   * Returns a BigDecimal whose value is found first by negating this via
   * the negate() method, then by rounding according to the MathContext mc.
   * @param mc the MathContext for rounding
   * @return a BigDecimal whose value is approximately (-this)
   * @throws ArithmeticException if the value is inexact but the rounding mode
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal negate(MathContext mc)
  {
    BigDecimal result = negate();
    if (mc.getPrecision() != 0)
      result = result.round(mc);
    return result;
  }

  /**
   * Returns this BigDecimal.  This is included for symmetry with the
   * method negate().
   * @return this
   * @since 1.5
   */
  public BigDecimal plus()
  {
    return this;
  }

  /**
   * Returns a BigDecimal whose value is found by rounding <code>this</code>
   * according to the MathContext.  This is the same as round(MathContext).
   * @param mc the MathContext for rounding
   * @return a BigDecimal whose value is <code>this</code> before being rounded
   * @throws ArithmeticException if the value is inexact but the rounding mode
   * is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal plus(MathContext mc)
  {
    return round(mc);
  }

  /**
   * Returns a BigDecimal which is this BigDecimal rounded according to the
   * MathContext rounding settings.
   * @param mc the MathContext that tells us how to round
   * @return the rounded BigDecimal
   */
  public BigDecimal round(MathContext mc)
  {
    int mcPrecision = mc.getPrecision();
    int numToChop = precision() - mcPrecision;
    // If mc specifies not to chop any digits or if we've already chopped
    // enough digits (say by using a MathContext in the constructor for this
    // BigDecimal) then just return this.
    if (mcPrecision == 0 || numToChop <= 0)
      return this;

    // Make a new BigDecimal which is the correct power of 10 to chop off
    // the required number of digits and then call divide.
    BigDecimal div = new BigDecimal(BigInteger.TEN.pow(numToChop));
    BigDecimal rounded = divide(div, scale, mc.getRoundingMode().ordinal());
    rounded.scale -= numToChop;
    rounded.precision = mcPrecision;
    return rounded;
  }

  /**
   * Returns the precision of this BigDecimal (the number of digits in the
   * unscaled value).  The precision of a zero value is 1.
   * @return the number of digits in the unscaled value, or 1 if the value
   * is zero.
   */
  public int precision()
  {
    if (precision == 0)
      {
        String s = intVal.toString();
        precision = s.length() - (( s.charAt(0) == '-' ) ? 1 : 0);
      }
    return precision;
  }

  /**
   * Returns the String representation of this BigDecimal, using scientific
   * notation if necessary.  The following steps are taken to generate
   * the result:
   *
   * 1. the BigInteger unscaledValue's toString method is called and if
   * <code>scale == 0<code> is returned.
   * 2. an <code>int adjExp</code> is created which is equal to the negation
   * of <code>scale</code> plus the number of digits in the unscaled value,
   * minus one.
   * 3. if <code>scale >= 0 && adjExp >= -6</code> then we represent this
   * BigDecimal without scientific notation.  A decimal is added if the
   * scale is positive and zeros are prepended as necessary.
   * 4. if scale is negative or adjExp is less than -6 we use scientific
   * notation.  If the unscaled value has more than one digit, a decimal
   * as inserted after the first digit, the character 'E' is appended
   * and adjExp is appended.
   */
  public String toString()
  {
    // bigStr is the String representation of the unscaled value.  If
    // scale is zero we simply return this.
    String bigStr = intVal.toString();
    if (scale == 0)
      return bigStr;

    boolean negative = (bigStr.charAt(0) == '-');
    int point = bigStr.length() - scale - (negative ? 1 : 0);

    CPStringBuilder val = new CPStringBuilder();

    if (scale >= 0 && (point - 1) >= -6)
      {
        // Convert to character form without scientific notation.
        if (point <= 0)
          {
            // Zeros need to be prepended to the StringBuilder.
            if (negative)
              val.append('-');
            // Prepend a '0' and a '.' and then as many more '0's as necessary.
            val.append('0').append('.');
            while (point < 0)
              {
                val.append('0');
                point++;
              }
            // Append the unscaled value.
            val.append(bigStr.substring(negative ? 1 : 0));
          }
        else
          {
            // No zeros need to be prepended so the String is simply the
            // unscaled value with the decimal point inserted.
            val.append(bigStr);
            val.insert(point + (negative ? 1 : 0), '.');
          }
      }
    else
      {
        // We must use scientific notation to represent this BigDecimal.
        val.append(bigStr);
        // If there is more than one digit in the unscaled value we put a
        // decimal after the first digit.
        if (bigStr.length() > 1)
          val.insert( ( negative ? 2 : 1 ), '.');
        // And then append 'E' and the exponent = (point - 1).
        val.append('E');
        if (point - 1 >= 0)
          val.append('+');
        val.append( point - 1 );
      }
    return val.toString();
  }

  /**
   * Returns the String representation of this BigDecimal, using engineering
   * notation if necessary.  This is similar to toString() but when exponents
   * are used the exponent is made to be a multiple of 3 such that the integer
   * part is between 1 and 999.
   *
   * @return a String representation of this BigDecimal in engineering notation
   * @since 1.5
   */
  public String toEngineeringString()
  {
    // bigStr is the String representation of the unscaled value.  If
    // scale is zero we simply return this.
    String bigStr = intVal.toString();
    if (scale == 0)
      return bigStr;

    boolean negative = (bigStr.charAt(0) == '-');
    int point = bigStr.length() - scale - (negative ? 1 : 0);

    // This is the adjusted exponent described above.
    int adjExp = point - 1;
    CPStringBuilder val = new CPStringBuilder();

    if (scale >= 0 && adjExp >= -6)
      {
        // Convert to character form without scientific notation.
        if (point <= 0)
          {
            // Zeros need to be prepended to the StringBuilder.
            if (negative)
              val.append('-');
            // Prepend a '0' and a '.' and then as many more '0's as necessary.
            val.append('0').append('.');
            while (point < 0)
              {
                val.append('0');
                point++;
              }
            // Append the unscaled value.
            val.append(bigStr.substring(negative ? 1 : 0));
          }
        else
          {
            // No zeros need to be prepended so the String is simply the
            // unscaled value with the decimal point inserted.
            val.append(bigStr);
            val.insert(point + (negative ? 1 : 0), '.');
          }
      }
    else
      {
        // We must use scientific notation to represent this BigDecimal.
        // The exponent must be a multiple of 3 and the integer part
        // must be between 1 and 999.
        val.append(bigStr);
        int zeros = adjExp % 3;
        int dot = 1;
        if (adjExp > 0)
          {
            // If the exponent is positive we just move the decimal to the
            // right and decrease the exponent until it is a multiple of 3.
            dot += zeros;
            adjExp -= zeros;
          }
        else
          {
            // If the exponent is negative then we move the dot to the right
            // and decrease the exponent (increase its magnitude) until
            // it is a multiple of 3.  Note that this is not adjExp -= zeros
            // because the mod operator doesn't give us the distance to the
            // correct multiple of 3.  (-5 mod 3) is -2 but the distance from
            // -5 to the correct multiple of 3 (-6) is 1, not 2.
            if (zeros == -2)
              {
                dot += 1;
                adjExp -= 1;
              }
            else if (zeros == -1)
              {
                dot += 2;
                adjExp -= 2;
              }
          }

        // Either we have to append zeros because, for example, 1.1E+5 should
        // be 110E+3, or we just have to put the decimal in the right place.
        if (dot > val.length())
          {
            while (dot > val.length())
              val.append('0');
          }
        else if (bigStr.length() > dot)
          val.insert(dot + (negative ? 1 : 0), '.');

        // And then append 'E' and the exponent (adjExp).
        val.append('E');
        if (adjExp >= 0)
          val.append('+');
        val.append(adjExp);
      }
    return val.toString();
  }

  /**
   * Returns a String representation of this BigDecimal without using
   * scientific notation.  This is how toString() worked for releases 1.4
   * and previous.  Zeros may be added to the end of the String.  For
   * example, an unscaled value of 1234 and a scale of -3 would result in
   * the String 1234000, but the toString() method would return
   * 1.234E+6.
   * @return a String representation of this BigDecimal
   * @since 1.5
   */
  public String toPlainString()
  {
    // If the scale is zero we simply return the String representation of the
    // unscaled value.
    String bigStr = intVal.toString();
    if (scale == 0)
      return bigStr;

    // Remember if we have to put a negative sign at the start.
    boolean negative = (bigStr.charAt(0) == '-');

    int point = bigStr.length() - scale - (negative ? 1 : 0);

    CPStringBuilder sb = new CPStringBuilder(bigStr.length() + 2
                                             + (point <= 0 ? (-point + 1) : 0));
    if (point <= 0)
      {
        // We have to prepend zeros and a decimal point.
        if (negative)
          sb.append('-');
        sb.append('0').append('.');
        while (point < 0)
          {
            sb.append('0');
            point++;
          }
        sb.append(bigStr.substring(negative ? 1 : 0));
      }
    else if (point < bigStr.length())
      {
        // No zeros need to be prepended or appended, just put the decimal
        // in the right place.
        sb.append(bigStr);
        sb.insert(point + (negative ? 1 : 0), '.');
      }
    else
      {
        // We must append zeros instead of using scientific notation.
        sb.append(bigStr);
        for (int i = bigStr.length(); i < point; i++)
          sb.append('0');
      }
    return sb.toString();
  }

  /**
   * Converts this BigDecimal to a BigInteger.  Any fractional part will
   * be discarded.
   * @return a BigDecimal whose value is equal to floor[this]
   */
  public BigInteger toBigInteger ()
  {
    // If scale > 0 then we must divide, if scale > 0 then we must multiply,
    // and if scale is zero then we just return intVal;
    if (scale > 0)
      return intVal.divide (BigInteger.TEN.pow (scale));
    else if (scale < 0)
      return intVal.multiply(BigInteger.TEN.pow(-scale));
    return intVal;
  }

  /**
   * Converts this BigDecimal into a BigInteger, throwing an
   * ArithmeticException if the conversion is not exact.
   * @return a BigInteger whose value is equal to the value of this BigDecimal
   * @since 1.5
   */
  public BigInteger toBigIntegerExact()
  {
    if (scale > 0)
      {
        // If we have to divide, we must check if the result is exact.
        BigInteger[] result =
          intVal.divideAndRemainder(BigInteger.TEN.pow(scale));
        if (result[1].equals(BigInteger.ZERO))
          return result[0];
        throw new ArithmeticException("No exact BigInteger representation");
      }
    else if (scale < 0)
      // If we're multiplying instead, then we needn't check for exactness.
      return intVal.multiply(BigInteger.TEN.pow(-scale));
    // If the scale is zero we can simply return intVal.
    return intVal;
  }

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

  /**
   * Returns a BigDecimal which is numerically equal to this BigDecimal but
   * with no trailing zeros in the representation.  For example, if this
   * BigDecimal has [unscaledValue, scale] = [6313000, 4] this method returns
   * a BigDecimal with [unscaledValue, scale] = [6313, 1].  As another
   * example, [12400, -2] would become [124, -4].
   * @return a numerically equal BigDecimal with no trailing zeros
   */
  public BigDecimal stripTrailingZeros()
  {
    String intValStr = intVal.toString();
    int newScale = scale;
    int pointer = intValStr.length() - 1;
    // This loop adjusts pointer which will be used to give us the substring
    // of intValStr to use in our new BigDecimal, and also accordingly
    // adjusts the scale of our new BigDecimal.
    while (intValStr.charAt(pointer) == '0')
      {
        pointer --;
        newScale --;
      }
    // Create a new BigDecimal with the appropriate substring and then
    // set its scale.
    BigDecimal result = new BigDecimal(intValStr.substring(0, pointer + 1));
    result.scale = newScale;
    return result;
  }

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

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

  public double doubleValue()
  {
    return Double.valueOf(toString()).doubleValue();
  }

  public BigDecimal setScale (int scale) throws ArithmeticException
  {
    return setScale (scale, ROUND_UNNECESSARY);
  }

  public BigDecimal setScale (int scale, int roundingMode)
    throws ArithmeticException, IllegalArgumentException
  {
    // NOTE: The 1.5 JRE doesn't throw this, ones prior to it do and
    // the spec says it should. Nevertheless, if 1.6 doesn't fix this
    // we should consider removing it.
    if( scale < 0 ) throw new ArithmeticException("Scale parameter < 0.");
    return divide (ONE, scale, roundingMode);
  }

  /**
   * Returns a BigDecimal whose value is the same as this BigDecimal but whose
   * representation has a scale of <code>newScale</code>.  If the scale is
   * reduced then rounding may occur, according to the RoundingMode.
   * @param newScale
   * @param roundingMode
   * @return a BigDecimal whose scale is as given, whose value is
   * <code>this</code> with possible rounding
   * @throws ArithmeticException if the rounding mode is UNNECESSARY but
   * rounding is required
   * @since 1.5
   */
  public BigDecimal setScale(int newScale, RoundingMode roundingMode)
  {
    return setScale(newScale, roundingMode.ordinal());
  }

  /**
   * Returns a new BigDecimal constructed from the BigDecimal(String)
   * constructor using the Double.toString(double) method to obtain
   * the String.
   * @param val the double value used in Double.toString(double)
   * @return a BigDecimal representation of val
   * @throws NumberFormatException if val is NaN or infinite
   * @since 1.5
   */
  public static BigDecimal valueOf(double val)
  {
    if (Double.isInfinite(val) || Double.isNaN(val))
      throw new NumberFormatException("argument cannot be NaN or infinite.");
    return new BigDecimal(Double.toString(val));
  }

  /**
   * Returns a BigDecimal whose numerical value is the numerical value
   * of this BigDecimal multiplied by 10 to the power of <code>n</code>.
   * @param n the power of ten
   * @return the new BigDecimal
   * @since 1.5
   */
  public BigDecimal scaleByPowerOfTen(int n)
  {
    BigDecimal result = new BigDecimal(intVal, scale - n);
    result.precision = precision;
    return result;
  }

  /**
   * Returns a BigDecimal whose value is <code>this</code> to the power of
   * <code>n</code>.
   * @param n the power
   * @return the new BigDecimal
   * @since 1.5
   */
  public BigDecimal pow(int n)
  {
    if (n < 0 || n > 999999999)
      throw new ArithmeticException("n must be between 0 and 999999999");
    BigDecimal result = new BigDecimal(intVal.pow(n), scale * n);
    return result;
  }

  /**
   * Returns a BigDecimal whose value is determined by first calling pow(n)
   * and then by rounding according to the MathContext mc.
   * @param n the power
   * @param mc the MathContext
   * @return the new BigDecimal
   * @throws ArithmeticException if n < 0 or n > 999999999 or if the result is
   * inexact but the rounding is RoundingMode.UNNECESSARY
   * @since 1.5
   */
  public BigDecimal pow(int n, MathContext mc)
  {
    // FIXME: The specs claim to use the X3.274-1996 algorithm.  We
    // currently do not.
    return pow(n).round(mc);
  }

  /**
   * Returns a BigDecimal whose value is the absolute value of this BigDecimal
   * with rounding according to the given MathContext.
   * @param mc the MathContext
   * @return the new BigDecimal
   */
  public BigDecimal abs(MathContext mc)
  {
    BigDecimal result = abs();
    result = result.round(mc);
    return result;
  }

  /**
   * Returns the size of a unit in the last place of this BigDecimal.  This
   * returns a BigDecimal with [unscaledValue, scale] = [1, this.scale()].
   * @return the size of a unit in the last place of <code>this</code>.
   * @since 1.5
   */
  public BigDecimal ulp()
  {
    return new BigDecimal(BigInteger.ONE, scale);
  }

  /**
   * Converts this BigDecimal to a long value.
   * @return the long value
   * @throws ArithmeticException if rounding occurs or if overflow occurs
   * @since 1.5
   */
  public long longValueExact()
  {
    // Set scale will throw an exception if rounding occurs.
    BigDecimal temp = setScale(0, ROUND_UNNECESSARY);
    BigInteger tempVal = temp.intVal;
    // Check for overflow.
    long result = intVal.longValue();
    if (tempVal.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 1
        || (result < 0 && signum() == 1) || (result > 0 && signum() == -1))
      throw new ArithmeticException("this BigDecimal is too " +
            "large to fit into the return type");

    return intVal.longValue();
  }

  /**
   * Converts this BigDecimal into an int by first calling longValueExact
   * and then checking that the <code>long</code> returned from that
   * method fits into an <code>int</code>.
   * @return an int whose value is <code>this</code>
   * @throws ArithmeticException if this BigDecimal has a fractional part
   * or is too large to fit into an int.
   * @since 1.5
   */
  public int intValueExact()
  {
    long temp = longValueExact();
    int result = (int)temp;
    if (result != temp)
      throw new ArithmeticException ("this BigDecimal cannot fit into an int");
    return result;
  }

  /**
   * Converts this BigDecimal into a byte by first calling longValueExact
   * and then checking that the <code>long</code> returned from that
   * method fits into a <code>byte</code>.
   * @return a byte whose value is <code>this</code>
   * @throws ArithmeticException if this BigDecimal has a fractional part
   * or is too large to fit into a byte.
   * @since 1.5
   */
  public byte byteValueExact()
  {
    long temp = longValueExact();
    byte result = (byte)temp;
    if (result != temp)
      throw new ArithmeticException ("this BigDecimal cannot fit into a byte");
    return result;
  }

  /**
   * Converts this BigDecimal into a short by first calling longValueExact
   * and then checking that the <code>long</code> returned from that
   * method fits into a <code>short</code>.
   * @return a short whose value is <code>this</code>
   * @throws ArithmeticException if this BigDecimal has a fractional part
   * or is too large to fit into a short.
   * @since 1.5
   */
  public short shortValueExact()
  {
    long temp = longValueExact();
    short result = (short)temp;
    if (result != temp)
      throw new ArithmeticException ("this BigDecimal cannot fit into a short");
    return result;
  }
}
