/*
 * Copyright 2009 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
 */
package java.math;

import com.google.gwt.core.client.JavaScriptObject;

import java.io.Serializable;

/**
 * This class represents immutable arbitrary precision decimal numbers. Each
 * {@code BigDecimal} instance is represented with a unscaled arbitrary
 * precision mantissa (the unscaled value) and a scale. The value of the {@code
 * BigDecimal} is {@code unscaledValue} 10^(-{@code scale}).
 */
public class BigDecimal extends Number implements Comparable<BigDecimal>,
    Serializable {

  /**
   * One more than the number of bits which can be stored in {@link #smallValue}.
   */
  private static final int SMALL_VALUE_BITS = 54;

  /**
   * The constant one as a {@code BigDecimal}.
   */
  public static final BigDecimal ONE = new BigDecimal(1, 0);

  /**
   * Rounding mode to round towards positive infinity. For positive values this
   * rounding mode behaves as {@link #ROUND_UP}, for negative values as
   * {@link #ROUND_DOWN}.
   * 
   * @see RoundingMode#CEILING
   */
  public static final int ROUND_CEILING = 2;

  /**
   * Rounding mode where the values are rounded towards zero.
   * 
   * @see RoundingMode#DOWN
   */
  public static final int ROUND_DOWN = 1;

  /**
   * Rounding mode to round towards negative infinity. For positive values this
   * rounding mode behaves as {@link #ROUND_DOWN}, for negative values as
   * {@link #ROUND_UP}.
   * 
   * @see RoundingMode#FLOOR
   */
  public static final int ROUND_FLOOR = 3;

  /**
   * Rounding mode where values are rounded towards the nearest neighbor. Ties
   * are broken by rounding down.
   * 
   * @see RoundingMode#HALF_DOWN
   */
  public static final int ROUND_HALF_DOWN = 5;

  /**
   * Rounding mode where values are rounded towards the nearest neighbor. Ties
   * are broken by rounding to the even neighbor.
   * 
   * @see RoundingMode#HALF_EVEN
   */
  public static final int ROUND_HALF_EVEN = 6;

  /**
   * Rounding mode where values are rounded towards the nearest neighbor. Ties
   * are broken by rounding up.
   * 
   * @see RoundingMode#HALF_UP
   */
  public static final int ROUND_HALF_UP = 4;

  /**
   * Rounding mode where the rounding operations throws an {@code
   * ArithmeticException} for the case that rounding is necessary, i.e. for the
   * case that the value cannot be represented exactly.
   * 
   * @see RoundingMode#UNNECESSARY
   */
  public static final int ROUND_UNNECESSARY = 7;

  /**
   * Rounding mode where positive values are rounded towards positive infinity
   * and negative values towards negative infinity.
   * 
   * @see RoundingMode#UP
   */
  public static final int ROUND_UP = 0;

  /**
   * The constant ten as a {@code BigDecimal}.
   */
  public static final BigDecimal TEN = new BigDecimal(10, 0);

  /**
   * The constant zero as a {@code BigDecimal}.
   */
  public static final BigDecimal ZERO = new BigDecimal(0, 0);

  protected static JavaScriptObject unscaledRegex;

  private static final int BI_SCALED_BY_ZERO_LENGTH = 11;

  /**
   * An array with the first <code>BigInteger</code> scaled by zero. (
   * <code>[0,0],[1,0],...,[10,0]</code>).
   */
  private static final BigDecimal BI_SCALED_BY_ZERO[] = new BigDecimal[BI_SCALED_BY_ZERO_LENGTH];

  /**
   * An array filled with characters <code>'0'</code>.
   */
  private static final char[] CH_ZEROS = new char[100];

  private static final double[] DOUBLE_FIVE_POW = new double[] {
      1D, 5D, 25D, 125D, 625D, 3125D, 15625D, 78125D, 390625D, 1953125D,
      9765625D, 48828125D, 244140625D, 1220703125D, 6103515625D, 30517578125D,
      152587890625D, 762939453125D, 3814697265625D, 19073486328125D,
      95367431640625D, 476837158203125D, 2384185791015625D,};

  private static final int[] DOUBLE_FIVE_POW_BIT_LENGTH = new int[DOUBLE_FIVE_POW.length];

  /**
   * An array with powers of ten that fit in the type <code>double</code> (
   * <code>10^0,10^1,...,10^18</code>).
   */
  private static final double[] DOUBLE_TEN_POW = new double[] {
      1D, 10D, 100D, 1000D, 10000D, 100000D, 1000000D, 10000000D, 100000000D,
      1000000000D, 10000000000D, 100000000000D, 1000000000000D,
      10000000000000D, 100000000000000D, 1000000000000000D,
      10000000000000000D,};

  private static final int[] DOUBLE_TEN_POW_BIT_LENGTH = new int[DOUBLE_TEN_POW.length];

  /**
   * An array with powers of five that fit in the type <code>double</code> (
   * <code>5^0,5^1,...,5^27</code>).
   */
  private static final BigInteger FIVE_POW[];

  /**
   * The double closest to <code>Math.log(2.0d)</code>.
   */
  private static final double LOG2 = 0.6931471805599453d;

  /**
   * The double closest to <code>Log10(2)</code>.
   */
  private static final double LOG10_2 = 0.3010299956639812;

  /**
   * The double closer to <code>Math.pow(2, 47)</code>.
   */
  private static final double POW47 = 140737488355328d;

  /**
   * This is the serialVersionUID used by the sun implementation.
   */
  private static final long serialVersionUID = 6108874887143696463L;

  /**
   * An array with powers of ten that fit in the type <code>double</code> (
   * <code>10^0,10^1,...,10^18</code>).
   */
  private static final BigInteger TEN_POW[];

  /**
   * An array with the zero number scaled by the first positive scales. (
   * <code>0*10^0, 0*10^1, ..., 0*10^10</code>).
   */
  private static final BigDecimal ZERO_SCALED_BY[] = new BigDecimal[11];

  static {
    // To fill all static arrays.
    int i = 0;

    for (; i < ZERO_SCALED_BY.length; i++) {
      BI_SCALED_BY_ZERO[i] = new BigDecimal(i, 0);
      ZERO_SCALED_BY[i] = new BigDecimal(0, i);
      CH_ZEROS[i] = '0';
    }

    for (; i < CH_ZEROS.length; i++) {
      CH_ZEROS[i] = '0';
    }
    for (int j = 0; j < DOUBLE_FIVE_POW_BIT_LENGTH.length; j++) {
      DOUBLE_FIVE_POW_BIT_LENGTH[j] = bitLength(DOUBLE_FIVE_POW[j]);
    }
    for (int j = 0; j < DOUBLE_TEN_POW_BIT_LENGTH.length; j++) {
      DOUBLE_TEN_POW_BIT_LENGTH[j] = bitLength(DOUBLE_TEN_POW[j]);
    }

    // Taking the references of useful powers.
    TEN_POW = Multiplication.bigTenPows;
    FIVE_POW = Multiplication.bigFivePows;
  }

  /**
   * Returns a new {@code BigDecimal} instance whose value is equal to {@code
   * val}. The new decimal is constructed as if the {@code BigDecimal(String)}
   * constructor is called with an argument which is equal to {@code
   * Double.toString(val)}. For example, {@code valueOf("0.1")} is converted to
   * (unscaled=1, scale=1), although the double {@code 0.1} cannot be
   * represented exactly as a double value. In contrast to that, a new {@code
   * BigDecimal(0.1)} instance has the value {@code
   * 0.1000000000000000055511151231257827021181583404541015625} with an unscaled
   * value {@code 1000000000000000055511151231257827021181583404541015625} and
   * the scale {@code 55}.
   * 
   * @param val double value to be converted to a {@code BigDecimal}.
   * @return {@code BigDecimal} instance with the value {@code val}.
   * @throws NumberFormatException if {@code val} is infinite or {@code val} is
   *           not a number
   */
  public static BigDecimal valueOf(double val) {
    if (Double.isInfinite(val) || Double.isNaN(val)) {
      // math.03=Infinity or NaN
      throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
    }
    return new BigDecimal(Double.toString(val));
  }

  /**
   * Returns a new {@code BigDecimal} instance whose value is equal to {@code
   * unscaledVal}. The scale of the result is {@code 0}, and its unscaled value
   * is {@code unscaledVal}.
   * 
   * @param unscaledVal value to be converted to a {@code BigDecimal}.
   * @return {@code BigDecimal} instance with the value {@code unscaledVal}.
   */
  public static BigDecimal valueOf(long unscaledVal) {
    if ((unscaledVal >= 0) && (unscaledVal < BI_SCALED_BY_ZERO_LENGTH)) {
      return BI_SCALED_BY_ZERO[(int) unscaledVal];
    }
    return new BigDecimal(unscaledVal, 0);
  }

  /**
   * Returns a new {@code BigDecimal} instance whose value is equal to {@code
   * unscaledVal} 10^(-{@code scale}). The scale of the result is {@code scale},
   * and its unscaled value is {@code unscaledVal}.
   * 
   * @param unscaledVal unscaled value to be used to construct the new {@code
   *          BigDecimal}.
   * @param scale scale to be used to construct the new {@code BigDecimal}.
   * @return {@code BigDecimal} instance with the value {@code unscaledVal}*
   *         10^(-{@code unscaledVal}).
   */
  public static BigDecimal valueOf(long unscaledVal, int scale) {
    if (scale == 0) {
      return valueOf(unscaledVal);
    }
    if ((unscaledVal == 0) && (scale >= 0) && (scale < ZERO_SCALED_BY.length)) {
      return ZERO_SCALED_BY[scale];
    }
    return new BigDecimal(unscaledVal, scale);
  }

  private static BigDecimal addAndMult10(BigDecimal thisValue,
      BigDecimal augend, double diffScale) {
    if (diffScale < DOUBLE_TEN_POW.length
        && Math.max(thisValue.bitLength, augend.bitLength
            + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale]) + 1
            < SMALL_VALUE_BITS) {
      return valueOf(thisValue.smallValue + augend.smallValue
          * DOUBLE_TEN_POW[(int) diffScale], thisValue.scale);
    }
    return new BigDecimal(thisValue.getUnscaledValue().add(
        Multiplication.multiplyByTenPow(augend.getUnscaledValue(),
            (int) diffScale)), thisValue.scale);
  }

  private static int bitLength(double value) {
    // if |value| is less than 2^47, use log
    if (value > -POW47 && value < POW47) {
      if (value == 0.0) {
        // special-case zero, otherwise we get -INFINITY below
        return 0;
      }
      boolean negative = (value < 0.0);
      if (negative) {
        value = -value;
      }
      int result = (int) Math.floor(Math.log(value) / LOG2);
      if (!negative || value != Math.pow(2, result)) {
        result++;
      }
      return result;
    }
    return bitLength((long) value);
  }

  private static int bitLength(long value) {
    if (value < 0) {
      value = ~value;
    }
    return 64 - Long.numberOfLeadingZeros(value);
  }

  private static BigDecimal divideBigIntegers(BigInteger scaledDividend,
      BigInteger scaledDivisor, int scale, RoundingMode roundingMode) {

    BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor); // quotient
                                                                                // and
                                                                                // remainder
    // If after division there is a remainder...
    BigInteger quotient = quotAndRem[0];
    BigInteger remainder = quotAndRem[1];
    if (remainder.signum() == 0) {
      return new BigDecimal(quotient, scale);
    }
    int sign = scaledDividend.signum() * scaledDivisor.signum();
    int compRem; // 'compare to remainder'
    if (scaledDivisor.bitLength() < SMALL_VALUE_BITS) {
      long rem = remainder.longValue();
      long divisor = scaledDivisor.longValue();
      compRem = longCompareTo(Math.abs(rem) << 1, Math.abs(divisor));
      // To look if there is a carry
      compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign
          * (5 + compRem), roundingMode);

    } else {
      // Checking if: remainder * 2 >= scaledDivisor
      compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs());
      compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign
          * (5 + compRem), roundingMode);
    }
    if (compRem != 0) {
      if (quotient.bitLength() < SMALL_VALUE_BITS) {
        return valueOf(quotient.longValue() + compRem, scale);
      }
      quotient = quotient.add(BigInteger.valueOf(compRem));
      return new BigDecimal(quotient, scale);
    }
    // Constructing the result with the appropriate unscaled value
    return new BigDecimal(quotient, scale);
  }

  private static BigDecimal dividePrimitiveDoubles(double scaledDividend,
      double scaledDivisor, int scale, RoundingMode roundingMode) {
    double quotient = intDivide(scaledDividend, scaledDivisor);
    double remainder = scaledDividend % scaledDivisor;
    int sign = Double.compare(scaledDividend * scaledDivisor, 0.0);
    if (remainder != 0) {
      // Checking if: remainder * 2 >= scaledDivisor
      int compRem; // 'compare to remainder'
      compRem = Double.compare(Math.abs(remainder) * 2,
          Math.abs(scaledDivisor));
      // To look if there is a carry
      quotient += roundingBehavior(((int) quotient) & 1, sign * (5 + compRem),
          roundingMode);
    }
    // Constructing the result with the appropriate unscaled value
    return valueOf(quotient, scale);
  }

  private static double intDivide(double dividend, double divisor) {
    double quotient = dividend / divisor;
    return quotient > 0 ? Math.floor(quotient) : Math.ceil(quotient);
  }

  private static int longCompareTo(long a, long b) {
    return Long.signum(a - b);
  }

  private static native double parseUnscaled(String str) /*-{
    var unscaledRegex = @java.math.BigDecimal::unscaledRegex;
    if (!unscaledRegex) {
      unscaledRegex = @java.math.BigDecimal::unscaledRegex = /^[+-]?\d*$/i;
    }
    if (unscaledRegex.test(str)) {
      return parseInt(str, 10);
    } else {
      return Number.NaN;
    }
  }-*/;

  /**
   * Return an increment that can be -1,0 or 1, depending of {@code
   * roundingMode}.
   * 
   * @param parityBit can be 0 or 1, it's only used in the case {@code
   *          HALF_EVEN}
   * @param fraction the mantisa to be analyzed
   * @param roundingMode the type of rounding
   * @return the carry propagated after rounding
   */
  private static int roundingBehavior(int parityBit, int fraction,
      RoundingMode roundingMode) {
    int increment = 0; // the carry after rounding

    switch (roundingMode) {
      case UNNECESSARY:
        if (fraction != 0) {
          // math.08=Rounding necessary
          throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
        }
        break;
      case UP:
        increment = Integer.signum(fraction);
        break;
      case DOWN:
        break;
      case CEILING:
        increment = Math.max(Integer.signum(fraction), 0);
        break;
      case FLOOR:
        increment = Math.min(Integer.signum(fraction), 0);
        break;
      case HALF_UP:
        if (Math.abs(fraction) >= 5) {
          increment = Integer.signum(fraction);
        }
        break;
      case HALF_DOWN:
        if (Math.abs(fraction) > 5) {
          increment = Integer.signum(fraction);
        }
        break;
      case HALF_EVEN:
        if (Math.abs(fraction) + parityBit > 5) {
          increment = Integer.signum(fraction);
        }
        break;
    }
    return increment;
  }

  /**
   * It tests if a scale of type {@code long} fits in 32 bits. It returns the
   * same scale being casted to {@code int} type when is possible, otherwise
   * throws an exception.
   * 
   * @param doubleScale a double bit scale
   * @return a 32 bit scale when is possible
   * @throws ArithmeticException when {@code scale} doesn't fit in {@code int}
   *           type
   * @see #scale
   */
  private static int toIntScale(double doubleScale) {
    if (doubleScale < Integer.MIN_VALUE) {
      // math.09=Overflow
      throw new ArithmeticException("Overflow"); //$NON-NLS-1$
    } else if (doubleScale > Integer.MAX_VALUE) {
      // math.0A=Underflow
      throw new ArithmeticException("Underflow"); //$NON-NLS-1$
    } else {
      return (int) doubleScale;
    }
  }

  /**
   * Convert a double to a string with {@code digits} precision.  The resulting
   * string may still be in exponential notation.
   * 
   * @param d double value
   * @param digits number of digits of precision to include
   * @return non-localized string representation of {@code d}
   */
  private static native String toPrecision(double d, int digits) /*-{
    return d.toPrecision(digits);
  }-*/;

  private static BigDecimal valueOf(double smallValue, double scale) {
    return new BigDecimal(smallValue, scale);
  }

  /**
   * It returns the value 0 with the most approximated scale of type {@code int}
   * . if {@code longScale > Integer.MAX_VALUE} the scale will be {@code
   * Integer.MAX_VALUE}; if {@code longScale < Integer.MIN_VALUE} the scale will
   * be {@code Integer.MIN_VALUE}; otherwise {@code longScale} is casted to the
   * type {@code int}.
   * 
   * @param doubleScale the scale to which the value 0 will be scaled.
   * @return the value 0 scaled by the closer scale of type {@code int}.
   * @see #scale
   */
  private static BigDecimal zeroScaledBy(double doubleScale) {
    if (doubleScale == (int) doubleScale) {
      return valueOf(0, (int) doubleScale);
    }
    if (doubleScale >= 0) {
      return new BigDecimal(0, Integer.MAX_VALUE);
    }
    return new BigDecimal(0, Integer.MIN_VALUE);
  }

  private transient int bitLength;

  /**
   * Cache for the hash code.
   */
  private transient int hashCode;

  /**
   * The arbitrary precision integer (unscaled value) in the internal
   * representation of {@code BigDecimal}.
   */
  private BigInteger intVal;

  /**
   * Represent the number of decimal digits in the unscaled value. This
   * precision is calculated the first time, and used in the following calls of
   * method <code>precision()</code>. Note that some call to the private method
   * <code>inplaceRound()</code> could update this field.
   * 
   * @see #precision()
   * @see #inplaceRound(MathContext)
   */
  private transient int precision;

  private double scale;

  /**
   * The unscaled integer value (stored in a double) if the number of bits is
   * less than {@link #SMALL_VALUE_BITS}.
   */
  private transient double smallValue;

  /**
   * The <code>String</code> representation is cached.
   */
  private transient String toStringImage;

  /**
   * Constructs a new {@code BigDecimal} instance from the given big integer
   * {@code val}. The scale of the result is {@code 0}.
   * 
   * @param val {@code BigInteger} value to be converted to a {@code BigDecimal}
   *          instance.
   */
  public BigDecimal(BigInteger val) {
    this(val, 0);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a given unscaled value
   * {@code unscaledVal} and a given scale. The value of this instance is
   * {@code unscaledVal} 10^(-{@code scale}).
   * 
   * @param unscaledVal {@code BigInteger} representing the unscaled value of
   *          this {@code BigDecimal} instance.
   * @param scale scale of this {@code BigDecimal} instance.
   * @throws NullPointerException if {@code unscaledVal == null}.
   */
  public BigDecimal(BigInteger unscaledVal, int scale) {
    if (unscaledVal == null) {
      throw new NullPointerException();
    }
    this.scale = scale;
    setUnscaledValue(unscaledVal);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a given unscaled value
   * {@code unscaledVal} and a given scale. The value of this instance is
   * {@code unscaledVal} 10^(-{@code scale}). The result is rounded according to
   * the specified math context.
   * 
   * @param unscaledVal {@code BigInteger} representing the unscaled value of
   *          this {@code BigDecimal} instance.
   * @param scale scale of this {@code BigDecimal} instance.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   * @throws NullPointerException if {@code unscaledVal == null}.
   */
  public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
    this(unscaledVal, scale);
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given big integer
   * {@code val}. The scale of the result is {@code 0}.
   * 
   * @param val {@code BigInteger} value to be converted to a {@code BigDecimal}
   *          instance.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(BigInteger val, MathContext mc) {
    this(val);
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a string representation
   * given as a character array.
   * 
   * @param in array of characters containing the string representation of this
   *          {@code BigDecimal}.
   * @throws NullPointerException if {@code in == null}.
   * @throws NumberFormatException if {@code in} does not contain a valid string
   *           representation of a big decimal.
   */
  public BigDecimal(char[] in) {
    this(in, 0, in.length);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a string representation
   * given as a character array.
   * 
   * @param in array of characters containing the string representation of this
   *          {@code BigDecimal}.
   * @param offset first index to be copied.
   * @param len number of characters to be used.
   * @throws NullPointerException if {@code in == null}.
   * @throws NumberFormatException if {@code offset < 0} or {@code len <= 0} or
   *           {@code offset+len-1 < 0} or {@code offset+len-1 >= in.length}.
   * @throws NumberFormatException if in does not contain a valid string
   *           representation of a big decimal.
   */
  public BigDecimal(char[] in, int offset, int len) {
    try {
      initFrom(new String(in, offset, len));
    } catch (StringIndexOutOfBoundsException e) {
      throw new NumberFormatException(e.getMessage());
    }
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a string representation
   * given as a character array.
   * 
   * @param in array of characters containing the string representation of this
   *          {@code BigDecimal}.
   * @param offset first index to be copied.
   * @param len number of characters to be used.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws NullPointerException if {@code in == null}.
   * @throws NumberFormatException if {@code offset < 0} or {@code len <= 0} or
   *           {@code offset+len-1 < 0} or {@code offset+len-1 >= in.length}.
   * @throws NumberFormatException if {@code in} does not contain a valid string
   *           representation of a big decimal.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(char[] in, int offset, int len, MathContext mc) {
    this(in, offset, len);
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a string representation
   * given as a character array. The result is rounded according to the
   * specified math context.
   * 
   * @param in array of characters containing the string representation of this
   *          {@code BigDecimal}.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws NullPointerException if {@code in == null}.
   * @throws NumberFormatException if {@code in} does not contain a valid string
   *           representation of a big decimal.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(char[] in, MathContext mc) {
    this(in, 0, in.length);
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given double {@code
   * val}. The scale of the result is 0.
   * 
   * @param val double value to be converted to a {@code BigDecimal} instance.
   * @throws NumberFormatException if {@code val} is infinite or a NaN
   */
  public BigDecimal(double val) {
    if (Double.isInfinite(val) || Double.isNaN(val)) {
      // math.03=Infinity or NaN
      throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
    }
    initFrom(toPrecision(val, 20));
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given double {@code
   * val}. The scale of the result is 0. The result is rounded according to the
   * specified math context.
   * 
   * @param val double value to be converted to a {@code BigDecimal} instance.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws NumberFormatException if {@code val} is infinite or a NaN
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(double val, MathContext mc) {
    if (Double.isInfinite(val) || Double.isNaN(val)) {
      // math.03=Infinity or NaN
      throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
    }
    initFrom(toPrecision(val, 20));
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given int {@code val}
   * . The scale of the result is 0.
   * 
   * @param val int value to be converted to a {@code BigDecimal} instance.
   */
  public BigDecimal(int val) {
    this(val, 0);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given int {@code val}
   * . The scale of the result is {@code 0}. The result is rounded according to
   * the specified math context.
   * 
   * @param val int value to be converted to a {@code BigDecimal} instance.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           c.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(int val, MathContext mc) {
    this(val, 0);
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given long {@code
   * val}. The scale of the result is {@code 0}.
   * 
   * @param val long value to be converted to a {@code BigDecimal} instance.
   */
  public BigDecimal(long val) {
    this(val, 0);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from the given long {@code
   * val}. The scale of the result is {@code 0}. The result is rounded according
   * to the specified math context.
   * 
   * @param val long value to be converted to a {@code BigDecimal} instance.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(long val, MathContext mc) {
    this(val);
    inplaceRound(mc);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a string representation.
   * 
   * @param val string containing the string representation of this {@code
   *          BigDecimal}.
   * @throws NumberFormatException if {@code val} does not contain a valid
   *           string representation of a big decimal.
   */
  public BigDecimal(String val) {
    initFrom(val);
  }

  /**
   * Constructs a new {@code BigDecimal} instance from a string representation.
   * The result is rounded according to the specified math context.
   * 
   * @param val string containing the string representation of this {@code
   *          BigDecimal}.
   * @param mc rounding mode and precision for the result of this operation.
   * @throws NumberFormatException if {@code val} does not contain a valid
   *           string representation of a big decimal.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
   *           represented within the given precision without rounding.
   */
  public BigDecimal(String val, MathContext mc) {
    this(val.toCharArray(), 0, val.length());
    inplaceRound(mc);
  }

  private BigDecimal(BigInteger unscaledVal, double scale) {
    if (unscaledVal == null) {
      throw new NullPointerException();
    }
    this.scale = scale;
    setUnscaledValue(unscaledVal);
  }

  private BigDecimal(double smallValue, double scale) {
    this.smallValue = smallValue;
    this.scale = scale;
    this.bitLength = bitLength(smallValue);
  }

  private BigDecimal(long smallValue, int scale) {
    this.scale = scale;
    this.bitLength = bitLength(smallValue);
    if (bitLength < SMALL_VALUE_BITS) {
      this.smallValue = smallValue;
    } else {
      this.intVal = BigInteger.valueOf(smallValue);
    }
  }

  /**
   * Returns a new {@code BigDecimal} whose value is the absolute value of
   * {@code this}. The scale of the result is the same as the scale of this.
   * 
   * @return {@code abs(this)}
   */
  public BigDecimal abs() {
    return ((signum() < 0) ? negate() : this);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is the absolute value of
   * {@code this}. The result is rounded according to the passed context {@code
   * mc}.
   * 
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code abs(this)}
   */
  public BigDecimal abs(MathContext mc) {
    return round(mc).abs();
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this + augend}. The
   * scale of the result is the maximum of the scales of the two arguments.
   * 
   * @param augend value to be added to {@code this}.
   * @return {@code this + augend}.
   * @throws NullPointerException if {@code augend == null}.
   */
  public BigDecimal add(BigDecimal augend) {
    double diffScale = this.scale - augend.scale;
    // Fast return when some operand is zero
    if (this.isZero()) {
      if (diffScale <= 0) {
        return augend;
      }
      if (augend.isZero()) {
        return this;
      }
    } else if (augend.isZero()) {
      if (diffScale >= 0) {
        return this;
      }
    }
    // Let be: this = [u1,s1] and augend = [u2,s2]
    if (diffScale == 0) {
      // case s1 == s2: [u1 + u2 , s1]
      if (Math.max(this.bitLength, augend.bitLength) + 1 < SMALL_VALUE_BITS) {
        return valueOf(this.smallValue + augend.smallValue, this.scale);
      }
      return new BigDecimal(this.getUnscaledValue().add(
          augend.getUnscaledValue()), this.scale);
    } else if (diffScale > 0) {
      // case s1 > s2 : [(u1 + u2) * 10 ^ (s1 - s2) , s1]
      return addAndMult10(this, augend, diffScale);
    } else {
      // case s2 > s1 : [(u2 + u1) * 10 ^ (s2 - s1) , s2]
      return addAndMult10(augend, this, -diffScale);
    }
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this + augend}. The
   * result is rounded according to the passed context {@code mc}.
   * 
   * @param augend value to be added to {@code this}.
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this + augend}.
   * @throws NullPointerException if {@code augend == null} or {@code mc ==
   *           null}.
   */
  public BigDecimal add(BigDecimal augend, MathContext mc) {
    BigDecimal larger; // operand with the largest unscaled value
    BigDecimal smaller; // operand with the smallest unscaled value
    BigInteger tempBI;
    double diffScale = this.scale - augend.scale;
    int largerSignum;
    // Some operand is zero or the precision is infinity
    if ((augend.isZero()) || (this.isZero()) || (mc.getPrecision() == 0)) {
      return add(augend).round(mc);
    }
    // Cases where there is room for optimizations
    if (this.approxPrecision() < diffScale - 1) {
      larger = augend;
      smaller = this;
    } else if (augend.approxPrecision() < -diffScale - 1) {
      larger = this;
      smaller = augend;
    } else {
      // No optimization is done
      return add(augend).round(mc);
    }
    if (mc.getPrecision() >= larger.approxPrecision()) {
      // No optimization is done
      return add(augend).round(mc);
    }
    // Cases where it's unnecessary to add two numbers with very different
    // scales
    largerSignum = larger.signum();
    if (largerSignum == smaller.signum()) {
      tempBI = Multiplication.multiplyByPositiveInt(larger.getUnscaledValue(),
          10).add(BigInteger.valueOf(largerSignum));
    } else {
      tempBI = larger.getUnscaledValue().subtract(
          BigInteger.valueOf(largerSignum));
      tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10).add(
          BigInteger.valueOf(largerSignum * 9));
    }
    // Rounding the improved adding
    larger = new BigDecimal(tempBI, larger.scale + 1);
    return larger.round(mc);
  }

  /**
   * Returns this {@code BigDecimal} as a byte value if it has no fractional
   * part and if its value fits to the byte range ([-128..127]). If these
   * conditions are not met, an {@code ArithmeticException} is thrown.
   * 
   * @return this {@code BigDecimal} as a byte value.
   * @throws ArithmeticException if rounding is necessary or the number doesn't
   *           fit in a byte.
   */
  public byte byteValueExact() {
    return (byte) valueExact(8);
  }

  /**
   * Compares this {@code BigDecimal} with {@code val}. Returns one of the three
   * values {@code 1}, {@code 0}, or {@code -1}. The method behaves as if
   * {@code this.subtract(val)} is computed. If this difference is > 0 then 1 is
   * returned, if the difference is < 0 then -1 is returned, and if the
   * difference is 0 then 0 is returned. This means, that if two decimal
   * instances are compared which are equal in value but differ in scale, then
   * these two instances are considered as equal.
   * 
   * @param val value to be compared with {@code this}.
   * @return {@code 1} if {@code this > val}, {@code -1} if {@code this < val},
   *         {@code 0} if {@code this == val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public int compareTo(BigDecimal val) {
    int thisSign = signum();
    int valueSign = val.signum();

    if (thisSign == valueSign) {
      if (this.scale == val.scale && this.bitLength < SMALL_VALUE_BITS
          && val.bitLength < SMALL_VALUE_BITS) {
        return (smallValue < val.smallValue) ? -1
            : (smallValue > val.smallValue) ? 1 : 0;
      }
      double diffScale = this.scale - val.scale;
      double diffPrecision = this.approxPrecision() - val.approxPrecision();
      if (diffPrecision > diffScale + 1) {
        return thisSign;
      } else if (diffPrecision < diffScale - 1) {
        return -thisSign;
      } else {
        // thisSign == val.signum() and diffPrecision is aprox. diffScale
        BigInteger thisUnscaled = this.getUnscaledValue();
        BigInteger valUnscaled = val.getUnscaledValue();
        // If any of both precision is bigger, append zeros to the shorter one
        if (diffScale < 0) {
          thisUnscaled = thisUnscaled.multiply(Multiplication.powerOf10(-diffScale));
        } else if (diffScale > 0) {
          valUnscaled = valUnscaled.multiply(Multiplication.powerOf10(diffScale));
        }
        return thisUnscaled.compareTo(valUnscaled);
      }
    } else if (thisSign < valueSign) {
      return -1;
    } else {
      return 1;
    }
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
   * scale of the result is the difference of the scales of {@code this} and
   * {@code divisor}. If the exact result requires more digits, then the scale
   * is adjusted accordingly. For example, {@code 1/128 = 0.0078125} which has a
   * scale of {@code 7} and precision {@code 5}.
   * 
   * @param divisor value by which {@code this} is divided.
   * @return {@code this / divisor}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if the result cannot be represented exactly.
   */
  public BigDecimal divide(BigDecimal divisor) {
    BigInteger p = this.getUnscaledValue();
    BigInteger q = divisor.getUnscaledValue();
    BigInteger gcd; // greatest common divisor between 'p' and 'q'
    BigInteger quotAndRem[];
    double diffScale = scale - divisor.scale;
    int newScale; // the new scale for final quotient
    int k; // number of factors "2" in 'q'
    int l = 0; // number of factors "5" in 'q'
    int i = 1;
    int lastPow = FIVE_POW.length - 1;

    if (divisor.isZero()) {
      // math.04=Division by zero
      throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
    }
    if (p.signum() == 0) {
      return zeroScaledBy(diffScale);
    }
    // To divide both by the GCD
    gcd = p.gcd(q);
    p = p.divide(gcd);
    q = q.divide(gcd);
    // To simplify all "2" factors of q, dividing by 2^k
    k = q.getLowestSetBit();
    q = q.shiftRight(k);
    // To simplify all "5" factors of q, dividing by 5^l
    do {
      quotAndRem = q.divideAndRemainder(FIVE_POW[i]);
      if (quotAndRem[1].signum() == 0) {
        l += i;
        if (i < lastPow) {
          i++;
        }
        q = quotAndRem[0];
      } else {
        if (i == 1) {
          break;
        }
        i = 1;
      }
    } while (true);
    // If abs(q) != 1 then the quotient is periodic
    if (!q.abs().equals(BigInteger.ONE)) {
      // math.05=Non-terminating decimal expansion; no exact representable
      // decimal result.
      throw new ArithmeticException(
          "Non-terminating decimal expansion; no exact representable decimal result"); //$NON-NLS-1$
    }
    // The sign of the is fixed and the quotient will be saved in 'p'
    if (q.signum() < 0) {
      p = p.negate();
    }
    // Checking if the new scale is out of range
    newScale = toIntScale(diffScale + Math.max(k, l));
    // k >= 0 and l >= 0 implies that k - l is in the 32-bit range
    i = k - l;

    p = (i > 0) ? Multiplication.multiplyByFivePow(p, i) : p.shiftLeft(-i);
    return new BigDecimal(p, newScale);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
   * scale of the result is the scale of {@code this}. If rounding is required
   * to meet the specified scale, then the specified rounding mode {@code
   * roundingMode} is applied.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param roundingMode rounding mode to be used to round the result.
   * @return {@code this / divisor} rounded according to the given rounding
   *         mode.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws IllegalArgumentException if {@code roundingMode} is not a valid
   *           rounding mode.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
   *           and rounding is necessary according to the scale of this.
   */
  public BigDecimal divide(BigDecimal divisor, int roundingMode) {
    return divide(divisor, (int) scale, RoundingMode.valueOf(roundingMode));
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. As
   * scale of the result the parameter {@code scale} is used. If rounding is
   * required to meet the specified scale, then the specified rounding mode
   * {@code roundingMode} is applied.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param scale the scale of the result returned.
   * @param roundingMode rounding mode to be used to round the result.
   * @return {@code this / divisor} rounded according to the given rounding
   *         mode.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws IllegalArgumentException if {@code roundingMode} is not a valid
   *           rounding mode.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
   *           and rounding is necessary according to the given scale.
   */
  public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
    return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. As
   * scale of the result the parameter {@code scale} is used. If rounding is
   * required to meet the specified scale, then the specified rounding mode
   * {@code roundingMode} is applied.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param scale the scale of the result returned.
   * @param roundingMode rounding mode to be used to round the result.
   * @return {@code this / divisor} rounded according to the given rounding
   *         mode.
   * @throws NullPointerException if {@code divisor == null} or {@code
   *           roundingMode == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code roundingMode ==
   *           RoundingMode.UNNECESSAR}Y and rounding is necessary according to
   *           the given scale and given precision.
   */
  public BigDecimal divide(BigDecimal divisor, int scale,
      RoundingMode roundingMode) {
    // Let be: this = [u1,s1] and divisor = [u2,s2]
    if (roundingMode == null) {
      throw new NullPointerException();
    }
    if (divisor.isZero()) {
      // math.04=Division by zero
      throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
    }

    double diffScale = this.scale - divisor.scale - scale;
    if (this.bitLength < SMALL_VALUE_BITS
        && divisor.bitLength < SMALL_VALUE_BITS) {
      if (diffScale == 0) {
        return dividePrimitiveDoubles(this.smallValue, divisor.smallValue,
            scale, roundingMode);
      } else if (diffScale > 0) {
        if (diffScale < DOUBLE_TEN_POW.length
            && divisor.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[
                (int) diffScale] < SMALL_VALUE_BITS) {
          return dividePrimitiveDoubles(this.smallValue, divisor.smallValue
              * DOUBLE_TEN_POW[(int) diffScale], scale, roundingMode);
        }
      } else { // diffScale < 0
        if (-diffScale < DOUBLE_TEN_POW.length
            && this.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) -diffScale]
                < SMALL_VALUE_BITS) {
          return dividePrimitiveDoubles(this.smallValue
              * DOUBLE_TEN_POW[(int) -diffScale], divisor.smallValue, scale,
              roundingMode);
        }
      }
    }

    BigInteger scaledDividend = this.getUnscaledValue();
    BigInteger scaledDivisor = divisor.getUnscaledValue(); // for scaling of
                                                           // 'u2'

    if (diffScale > 0) {
      // Multiply 'u2' by: 10^((s1 - s2) - scale)
      scaledDivisor = Multiplication.multiplyByTenPow(scaledDivisor,
          (int) diffScale);
    } else if (diffScale < 0) {
      // Multiply 'u1' by: 10^(scale - (s1 - s2))
      scaledDividend = Multiplication.multiplyByTenPow(scaledDividend,
          (int) -diffScale);
    }
    return divideBigIntegers(scaledDividend, scaledDivisor, scale, roundingMode);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
   * result is rounded according to the passed context {@code mc}. If the passed
   * math context specifies precision {@code 0}, then this call is equivalent to
   * {@code this.divide(divisor)}.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this / divisor}.
   * @throws NullPointerException if {@code divisor == null} or {@code mc ==
   *           null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code mc.getRoundingMode() == UNNECESSARY}
   *           and rounding is necessary according {@code mc.getPrecision()}.
   */
  public BigDecimal divide(BigDecimal divisor, MathContext mc) {
    /*
     * Calculating how many zeros must be append to 'dividend' to obtain a
     * quotient with at least 'mc.precision()' digits
     */
    double traillingZeros = mc.getPrecision() + 2L + divisor.approxPrecision()
        - approxPrecision();
    double diffScale = scale - divisor.scale;
    double newScale = diffScale; // scale of the final quotient
    int compRem; // to compare the remainder
    int i = 1; // index
    int lastPow = TEN_POW.length - 1; // last power of ten
    BigInteger integerQuot; // for temporal results
    BigInteger quotAndRem[] = {getUnscaledValue()};
    // In special cases it reduces the problem to call the dual method
    if ((mc.getPrecision() == 0) || (this.isZero()) || (divisor.isZero())) {
      return this.divide(divisor);
    }
    if (traillingZeros > 0) {
      // To append trailing zeros at end of dividend
      quotAndRem[0] = getUnscaledValue().multiply(
          Multiplication.powerOf10(traillingZeros));
      newScale += traillingZeros;
    }
    quotAndRem = quotAndRem[0].divideAndRemainder(divisor.getUnscaledValue());
    integerQuot = quotAndRem[0];
    // Calculating the exact quotient with at least 'mc.precision()' digits
    if (quotAndRem[1].signum() != 0) {
      // Checking if: 2 * remainder >= divisor ?
      compRem = quotAndRem[1].shiftLeftOneBit().compareTo(
          divisor.getUnscaledValue());
      // quot := quot * 10 + r; with 'r' in {-6,-5,-4, 0,+4,+5,+6}
      integerQuot = integerQuot.multiply(BigInteger.TEN).add(
          BigInteger.valueOf(quotAndRem[0].signum() * (5 + compRem)));
      newScale++;
    } else {
      // To strip trailing zeros until the preferred scale is reached
      while (!integerQuot.testBit(0)) {
        quotAndRem = integerQuot.divideAndRemainder(TEN_POW[i]);
        if ((quotAndRem[1].signum() == 0) && (newScale - i >= diffScale)) {
          newScale -= i;
          if (i < lastPow) {
            i++;
          }
          integerQuot = quotAndRem[0];
        } else {
          if (i == 1) {
            break;
          }
          i = 1;
        }
      }
    }
    // To perform rounding
    return new BigDecimal(integerQuot, toIntScale(newScale), mc);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
   * scale of the result is the scale of {@code this}. If rounding is required
   * to meet the specified scale, then the specified rounding mode {@code
   * roundingMode} is applied.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param roundingMode rounding mode to be used to round the result.
   * @return {@code this / divisor} rounded according to the given rounding
   *         mode.
   * @throws NullPointerException if {@code divisor == null} or {@code
   *           roundingMode == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code roundingMode ==
   *           RoundingMode.UNNECESSARY} and rounding is necessary according to
   *           the scale of this.
   */
  public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
    return divide(divisor, (int) scale, roundingMode);
  }

  /**
   * Returns a {@code BigDecimal} array which contains the integral part of
   * {@code this / divisor} at index 0 and the remainder {@code this % divisor}
   * at index 1. The quotient is rounded down towards zero to the next integer.
   * 
   * @param divisor value by which {@code this} is divided.
   * @return {@code [this.divideToIntegralValue(divisor),
   *         this.remainder(divisor)]}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @see #divideToIntegralValue
   * @see #remainder
   */
  public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
    BigDecimal quotAndRem[] = new BigDecimal[2];

    quotAndRem[0] = this.divideToIntegralValue(divisor);
    quotAndRem[1] = this.subtract(quotAndRem[0].multiply(divisor));
    return quotAndRem;
  }

  /**
   * Returns a {@code BigDecimal} array which contains the integral part of
   * {@code this / divisor} at index 0 and the remainder {@code this % divisor}
   * at index 1. The quotient is rounded down towards zero to the next integer.
   * The rounding mode passed with the parameter {@code mc} is not considered.
   * But if the precision of {@code mc > 0} and the integral part requires more
   * digits, then an {@code ArithmeticException} is thrown.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param mc math context which determines the maximal precision of the
   *          result.
   * @return {@code [this.divideToIntegralValue(divisor),
   *         this.remainder(divisor)]}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @see #divideToIntegralValue
   * @see #remainder
   */
  public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
    BigDecimal quotAndRem[] = new BigDecimal[2];

    quotAndRem[0] = this.divideToIntegralValue(divisor, mc);
    quotAndRem[1] = this.subtract(quotAndRem[0].multiply(divisor));
    return quotAndRem;
  }

  /**
   * Returns a new {@code BigDecimal} whose value is the integral part of
   * {@code this / divisor}. The quotient is rounded down towards zero to the
   * next integer. For example, {@code 0.5/0.2 = 2}.
   * 
   * @param divisor value by which {@code this} is divided.
   * @return integral part of {@code this / divisor}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   */
  public BigDecimal divideToIntegralValue(BigDecimal divisor) {
    BigInteger integralValue; // the integer of result
    BigInteger powerOfTen; // some power of ten
    BigInteger quotAndRem[] = {getUnscaledValue()};
    double newScale = this.scale - divisor.scale;
    double tempScale = 0;
    int i = 1;
    int lastPow = TEN_POW.length - 1;

    if (divisor.isZero()) {
      // math.04=Division by zero
      throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
    }
    if ((divisor.approxPrecision() + newScale > this.approxPrecision() + 1L)
        || (this.isZero())) {
      /*
       * If the divisor's integer part is greater than this's integer part, the
       * result must be zero with the appropriate scale
       */
      integralValue = BigInteger.ZERO;
    } else if (newScale == 0) {
      integralValue = getUnscaledValue().divide(divisor.getUnscaledValue());
    } else if (newScale > 0) {
      powerOfTen = Multiplication.powerOf10(newScale);
      integralValue = getUnscaledValue().divide(
          divisor.getUnscaledValue().multiply(powerOfTen));
      integralValue = integralValue.multiply(powerOfTen);
    } else {
      // (newScale < 0)
      powerOfTen = Multiplication.powerOf10(-newScale);
      integralValue = getUnscaledValue().multiply(powerOfTen).divide(
          divisor.getUnscaledValue());
      // To strip trailing zeros approximating to the preferred scale
      while (!integralValue.testBit(0)) {
        quotAndRem = integralValue.divideAndRemainder(TEN_POW[i]);
        if ((quotAndRem[1].signum() == 0) && (tempScale - i >= newScale)) {
          tempScale -= i;
          if (i < lastPow) {
            i++;
          }
          integralValue = quotAndRem[0];
        } else {
          if (i == 1) {
            break;
          }
          i = 1;
        }
      }
      newScale = tempScale;
    }
    return ((integralValue.signum() == 0) ? zeroScaledBy(newScale)
        : new BigDecimal(integralValue, toIntScale(newScale)));
  }

  /**
   * Returns a new {@code BigDecimal} whose value is the integral part of
   * {@code this / divisor}. The quotient is rounded down towards zero to the
   * next integer. The rounding mode passed with the parameter {@code mc} is not
   * considered. But if the precision of {@code mc > 0} and the integral part
   * requires more digits, then an {@code ArithmeticException} is thrown.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param mc math context which determines the maximal precision of the
   *          result.
   * @return integral part of {@code this / divisor}.
   * @throws NullPointerException if {@code divisor == null} or {@code mc ==
   *           null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code mc.getPrecision() > 0} and the result
   *           requires more digits to be represented.
   */
  public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
    int mcPrecision = mc.getPrecision();
    int diffPrecision = this.precision() - divisor.precision();
    int lastPow = TEN_POW.length - 1;
    double diffScale = this.scale - divisor.scale;
    double newScale = diffScale;
    double quotPrecision = diffPrecision - diffScale + 1;
    BigInteger quotAndRem[] = new BigInteger[2];
    // In special cases it call the dual method
    if ((mcPrecision == 0) || (this.isZero()) || (divisor.isZero())) {
      return this.divideToIntegralValue(divisor);
    }
    // Let be: this = [u1,s1] and divisor = [u2,s2]
    if (quotPrecision <= 0) {
      quotAndRem[0] = BigInteger.ZERO;
    } else if (diffScale == 0) {
      // CASE s1 == s2: to calculate u1 / u2
      quotAndRem[0] = this.getUnscaledValue().divide(divisor.getUnscaledValue());
    } else if (diffScale > 0) {
      // CASE s1 >= s2: to calculate u1 / (u2 * 10^(s1-s2)
      quotAndRem[0] = this.getUnscaledValue().divide(
          divisor.getUnscaledValue().multiply(
              Multiplication.powerOf10(diffScale)));
      // To chose 10^newScale to get a quotient with at least 'mc.precision()'
      // digits
      newScale = Math.min(diffScale, Math.max(mcPrecision - quotPrecision + 1,
          0));
      // To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
      quotAndRem[0] = quotAndRem[0].multiply(Multiplication.powerOf10(newScale));
    } else {
      // CASE s2 > s1:
      /*
       * To calculate the minimum power of ten, such that the quotient (u1 *
       * 10^exp) / u2 has at least 'mc.precision()' digits.
       */
      double exp = Math.min(-diffScale, Math.max((double) mcPrecision
          - diffPrecision, 0));
      double compRemDiv;
      // Let be: (u1 * 10^exp) / u2 = [q,r]
      quotAndRem = this.getUnscaledValue().multiply(
          Multiplication.powerOf10(exp)).divideAndRemainder(
          divisor.getUnscaledValue());
      newScale += exp; // To fix the scale
      exp = -newScale; // The remaining power of ten
      // If after division there is a remainder...
      if ((quotAndRem[1].signum() != 0) && (exp > 0)) {
        // Log10(r) + ((s2 - s1) - exp) > mc.precision ?
        compRemDiv = (new BigDecimal(quotAndRem[1])).precision() + exp
            - divisor.precision();
        if (compRemDiv == 0) {
          // To calculate: (r * 10^exp2) / u2
          quotAndRem[1] = quotAndRem[1].multiply(Multiplication.powerOf10(exp)).divide(
              divisor.getUnscaledValue());
          compRemDiv = Math.abs(quotAndRem[1].signum());
        }
        if (compRemDiv > 0) {
          // The quotient won't fit in 'mc.precision()' digits
          // math.06=Division impossible
          throw new ArithmeticException("Division impossible"); //$NON-NLS-1$
        }
      }
    }
    // Fast return if the quotient is zero
    if (quotAndRem[0].signum() == 0) {
      return zeroScaledBy(diffScale);
    }
    BigInteger strippedBI = quotAndRem[0];
    BigDecimal integralValue = new BigDecimal(quotAndRem[0]);
    int resultPrecision = integralValue.precision();
    int i = 1;
    // To strip trailing zeros until the specified precision is reached
    while (!strippedBI.testBit(0)) {
      quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
      if ((quotAndRem[1].signum() == 0)
          && ((resultPrecision - i >= mcPrecision) || (newScale - i >= diffScale))) {
        resultPrecision -= i;
        newScale -= i;
        if (i < lastPow) {
          i++;
        }
        strippedBI = quotAndRem[0];
      } else {
        if (i == 1) {
          break;
        }
        i = 1;
      }
    }
    // To check if the result fit in 'mc.precision()' digits
    if (resultPrecision > mcPrecision) {
      // math.06=Division impossible
      throw new ArithmeticException("Division impossible"); //$NON-NLS-1$
    }
    integralValue.scale = toIntScale(newScale);
    integralValue.setUnscaledValue(strippedBI);
    return integralValue;
  }

  /**
   * Returns this {@code BigDecimal} as a double value. If {@code this} is too
   * big to be represented as an float, then {@code Double.POSITIVE_INFINITY} or
   * {@code Double.NEGATIVE_INFINITY} is returned.
   * <p>
   * Note, that if the unscaled value has more than 53 significant digits, then
   * this decimal cannot be represented exactly in a double variable. In this
   * case the result is rounded.
   * <p>
   * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be
   * represented exactly as a double, and thus {@code x1.equals(new
   * BigDecimal(x1.doubleValue())} returns {@code false} for this case.
   * <p>
   * Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is
   * converted to a double, the result is {@code 9.007199254740992E15}.
   * <p>
   * 
   * @return this {@code BigDecimal} as a double value.
   */
  @Override
  public double doubleValue() {
    return Double.parseDouble(this.toString());
  }

  /**
   * Returns {@code true} if {@code x} is a {@code BigDecimal} instance and if
   * this instance is equal to this big decimal. Two big decimals are equal if
   * their unscaled value and their scale is equal. For example, 1.0
   * (10*10^(-1)) is not equal to 1.00 (100*10^(-2)). Similarly, zero instances
   * are not equal if their scale differs.
   * 
   * @param x object to be compared with {@code this}.
   * @return true if {@code x} is a {@code BigDecimal} and {@code this == x}.
   */
  @Override
  public boolean equals(Object x) {
    if (this == x) {
      return true;
    }
    if (x instanceof BigDecimal) {
      BigDecimal x1 = (BigDecimal) x;
      return x1.scale == scale
          && (bitLength < SMALL_VALUE_BITS ? (x1.smallValue == smallValue)
              : intVal.equals(x1.intVal));
    }
    return false;
  }

  /**
   * Returns this {@code BigDecimal} as a float value. If {@code this} is too
   * big to be represented as an float, then {@code Float.POSITIVE_INFINITY} or
   * {@code Float.NEGATIVE_INFINITY} is returned.
   * <p>
   * Note, that if the unscaled value has more than 24 significant digits, then
   * this decimal cannot be represented exactly in a float variable. In this
   * case the result is rounded.
   * <p>
   * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be
   * represented exactly as a float, and thus {@code x1.equals(new
   * BigDecimal(x1.folatValue())} returns {@code false} for this case.
   * <p>
   * Similarly, if the instance {@code new BigDecimal(16777217)} is converted to
   * a float, the result is {@code 1.6777216E}7.
   * 
   * @return this {@code BigDecimal} as a float value.
   */
  @Override
  public float floatValue() {
    /*
     * A similar code like in doubleValue() could be repeated here, but this
     * simple implementation is quite efficient.
     */
    float floatResult = signum();
    double powerOfTwo = this.bitLength - (scale / LOG10_2);
    if ((powerOfTwo < -149) || (floatResult == 0.0f)) {
      // Cases which 'this' is very small
      floatResult *= 0.0f;
    } else if (powerOfTwo > 129) {
      // Cases which 'this' is very large
      floatResult *= Float.POSITIVE_INFINITY;
    } else {
      floatResult = (float) doubleValue();
    }
    return floatResult;
  }

  /**
   * Returns a hash code for this {@code BigDecimal}.
   * 
   * @return hash code for {@code this}.
   */
  @Override
  public int hashCode() {
    if (hashCode != 0) {
      return hashCode;
    }
    if (bitLength < SMALL_VALUE_BITS) {
      long longValue = (long) smallValue;
      hashCode = (int) (longValue & 0xffffffff);
      hashCode = 33 * hashCode + (int) ((longValue >> 32) & 0xffffffff);
      hashCode = 17 * hashCode + (int) scale;
      return hashCode;
    }
    hashCode = 17 * intVal.hashCode() + (int) scale;
    return hashCode;
  }

  /**
   * Returns this {@code BigDecimal} as an int value. Any fractional part is
   * discarded. If the integral part of {@code this} is too big to be
   * represented as an int, then {@code this} % 2^32 is returned.
   * 
   * @return this {@code BigDecimal} as a int value.
   */
  @Override
  public int intValue() {
    /*
     * If scale <= -32 there are at least 32 trailing bits zero in 10^(-scale).
     * If the scale is positive and very large the long value could be zero.
     */
    return ((scale <= -32) || (scale > approxPrecision()) ? 0
        : toBigInteger().intValue());
  }

  /**
   * Returns this {@code BigDecimal} as a int value if it has no fractional part
   * and if its value fits to the int range ([-2^{31}..2^{31}-1]). If these
   * conditions are not met, an {@code ArithmeticException} is thrown.
   * 
   * @return this {@code BigDecimal} as a int value.
   * @throws ArithmeticException if rounding is necessary or the number doesn't
   *           fit in a int.
   */
  public int intValueExact() {
    return (int) valueExact(32);
  }

  /**
   * Returns this {@code BigDecimal} as an long value. Any fractional part is
   * discarded. If the integral part of {@code this} is too big to be
   * represented as an long, then {@code this} % 2^64 is returned.
   * 
   * @return this {@code BigDecimal} as a long value.
   */
  @Override
  public long longValue() {
    /*
     * If scale <= -64 there are at least 64 trailing bits zero in 10^(-scale).
     * If the scale is positive and very large the long value could be zero.
     */
    return ((scale <= -64) || (scale > approxPrecision()) ? 0L
        : toBigInteger().longValue());
  }

  /**
   * Returns this {@code BigDecimal} as a long value if it has no fractional
   * part and if its value fits to the int range ([-2^{63}..2^{63}-1]). If these
   * conditions are not met, an {@code ArithmeticException} is thrown.
   * 
   * @return this {@code BigDecimal} as a long value.
   * @throws ArithmeticException if rounding is necessary or the number doesn't
   *           fit in a long.
   */
  public long longValueExact() {
    return valueExact(64);
  }

  /**
   * Returns the maximum of this {@code BigDecimal} and {@code val}.
   * 
   * @param val value to be used to compute the maximum with this.
   * @return {@code max(this, val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigDecimal max(BigDecimal val) {
    return ((compareTo(val) >= 0) ? this : val);
  }

  /**
   * Returns the minimum of this {@code BigDecimal} and {@code val}.
   * 
   * @param val value to be used to compute the minimum with this.
   * @return {@code min(this, val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigDecimal min(BigDecimal val) {
    return ((compareTo(val) <= 0) ? this : val);
  }

  /**
   * Returns a new {@code BigDecimal} instance where the decimal point has been
   * moved {@code n} places to the left. If {@code n < 0} then the decimal point
   * is moved {@code -n} places to the right.
   * <p>
   * The result is obtained by changing its scale. If the scale of the result
   * becomes negative, then its precision is increased such that the scale is
   * zero.
   * <p>
   * Note, that {@code movePointLeft(0)} returns a result which is
   * mathematically equivalent, but which has {@code scale >= 0}.
   * 
   * @param n number of placed the decimal point has to be moved.
   * @return {@code this * 10^(-n}).
   */
  public BigDecimal movePointLeft(int n) {
    return movePoint(scale + n);
  }

  /**
   * Returns a new {@code BigDecimal} instance where the decimal point has been
   * moved {@code n} places to the right. If {@code n < 0} then the decimal
   * point is moved {@code -n} places to the left.
   * <p>
   * The result is obtained by changing its scale. If the scale of the result
   * becomes negative, then its precision is increased such that the scale is
   * zero.
   * <p>
   * Note, that {@code movePointRight(0)} returns a result which is
   * mathematically equivalent, but which has scale >= 0.
   * 
   * @param n number of placed the decimal point has to be moved.
   * @return {@code this * 10^n}.
   */
  public BigDecimal movePointRight(int n) {
    return movePoint(scale - n);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this * multiplicand}
   * . The scale of the result is the sum of the scales of the two arguments.
   * 
   * @param multiplicand value to be multiplied with {@code this}.
   * @return {@code this * multiplicand}.
   * @throws NullPointerException if {@code multiplicand == null}.
   */
  public BigDecimal multiply(BigDecimal multiplicand) {
    double newScale = this.scale + multiplicand.scale;

    if ((this.isZero()) || (multiplicand.isZero())) {
      return zeroScaledBy(newScale);
    }
    /*
     * Let be: this = [u1,s1] and multiplicand = [u2,s2] so: this x multiplicand
     * = [ s1 * s2 , s1 + s2 ]
     */
    if (this.bitLength + multiplicand.bitLength < SMALL_VALUE_BITS) {
      return valueOf(this.smallValue * multiplicand.smallValue,
          toIntScale(newScale));
    }
    return new BigDecimal(this.getUnscaledValue().multiply(
        multiplicand.getUnscaledValue()), toIntScale(newScale));
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this * multiplicand}
   * . The result is rounded according to the passed context {@code mc}.
   * 
   * @param multiplicand value to be multiplied with {@code this}.
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this * multiplicand}.
   * @throws NullPointerException if {@code multiplicand == null} or {@code mc
   *           == null}.
   */
  public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
    BigDecimal result = multiply(multiplicand);

    result.inplaceRound(mc);
    return result;
  }

  /**
   * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
   * scale of the result is the same as the scale of this.
   * 
   * @return {@code -this}
   */
  public BigDecimal negate() {
    if (bitLength < SMALL_VALUE_BITS) {
      return valueOf(-smallValue, scale);
    }
    return new BigDecimal(getUnscaledValue().negate(), scale);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
   * result is rounded according to the passed context {@code mc}.
   * 
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code -this}
   */
  public BigDecimal negate(MathContext mc) {
    return round(mc).negate();
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code +this}. The scale of
   * the result is the same as the scale of this.
   * 
   * @return {@code this}
   */
  public BigDecimal plus() {
    return this;
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code +this}. The result
   * is rounded according to the passed context {@code mc}.
   * 
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this}, rounded
   */
  public BigDecimal plus(MathContext mc) {
    return round(mc);
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The scale
   * of the result is {@code n} times the scales of {@code this}.
   * <p>
   * {@code x.pow(0)} returns {@code 1}, even if {@code x == 0}.
   * <p>
   * Implementation Note: The implementation is based on the ANSI standard
   * X3.274-1996 algorithm.
   * 
   * @param n exponent to which {@code this} is raised.
   * @return {@code this ^ n}.
   * @throws ArithmeticException if {@code n < 0} or {@code n > 999999999}.
   */
  public BigDecimal pow(int n) {
    if (n == 0) {
      return ONE;
    }
    if ((n < 0) || (n > 999999999)) {
      // math.07=Invalid Operation
      throw new ArithmeticException("Invalid Operation"); //$NON-NLS-1$
    }
    double newScale = scale * n;
    // Let be: this = [u,s] so: this^n = [u^n, s*n]
    return ((isZero()) ? zeroScaledBy(newScale) : new BigDecimal(
        getUnscaledValue().pow(n), toIntScale(newScale)));
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The
   * result is rounded according to the passed context {@code mc}.
   * <p>
   * Implementation Note: The implementation is based on the ANSI standard
   * X3.274-1996 algorithm.
   * 
   * @param n exponent to which {@code this} is raised.
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this ^ n}.
   * @throws ArithmeticException if {@code n < 0} or {@code n > 999999999}.
   */
  public BigDecimal pow(int n, MathContext mc) {
    // The ANSI standard X3.274-1996 algorithm
    int m = Math.abs(n);
    int mcPrecision = mc.getPrecision();
    int elength = (int) Math.log10(m) + 1; // decimal digits in 'n'
    int oneBitMask; // mask of bits
    BigDecimal accum; // the single accumulator
    MathContext newPrecision = mc; // MathContext by default

    // In particular cases, it reduces the problem to call the other 'pow()'
    if ((n == 0) || ((isZero()) && (n > 0))) {
      return pow(n);
    }
    if ((m > 999999999) || ((mcPrecision == 0) && (n < 0))
        || ((mcPrecision > 0) && (elength > mcPrecision))) {
      // math.07=Invalid Operation
      throw new ArithmeticException("Invalid Operation"); //$NON-NLS-1$
    }
    if (mcPrecision > 0) {
      newPrecision = new MathContext(mcPrecision + elength + 1,
          mc.getRoundingMode());
    }
    // The result is calculated as if 'n' were positive
    accum = round(newPrecision);
    oneBitMask = Integer.highestOneBit(m) >> 1;

    while (oneBitMask > 0) {
      accum = accum.multiply(accum, newPrecision);
      if ((m & oneBitMask) == oneBitMask) {
        accum = accum.multiply(this, newPrecision);
      }
      oneBitMask >>= 1;
    }
    // If 'n' is negative, the value is divided into 'ONE'
    if (n < 0) {
      accum = ONE.divide(accum, newPrecision);
    }
    // The final value is rounded to the destination precision
    accum.inplaceRound(mc);
    return accum;
  }

  /**
   * Returns the precision of this {@code BigDecimal}. The precision is the
   * number of decimal digits used to represent this decimal. It is equivalent
   * to the number of digits of the unscaled value. The precision of {@code 0}
   * is {@code 1} (independent of the scale).
   * 
   * @return the precision of this {@code BigDecimal}.
   */
  public int precision() {
    // Checking if the precision already was calculated
    if (precision > 0) {
      return precision;
    }
    double decimalDigits = 1; // the precision to be calculated
    double doubleUnsc = 1; // intVal in 'double'

    if (bitLength < SMALL_VALUE_BITS) {
      // To calculate the precision for small numbers
      if (bitLength >= 1) {
        doubleUnsc = smallValue;
      }
      decimalDigits += Math.log10(Math.abs(doubleUnsc));
    } else {
      // (bitLength >= 1024)
      /*
       * To calculate the precision for large numbers Note that: 2 ^(bitlength()
       * - 1) <= intVal < 10 ^(precision())
       */
      decimalDigits += (bitLength - 1) * LOG10_2;
      // If after division the number isn't zero, exists an aditional digit
      if (getUnscaledValue().divide(Multiplication.powerOf10(decimalDigits)).signum() != 0) {
        decimalDigits++;
      }
    }
    precision = (int) decimalDigits;
    return precision;
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
   * <p>
   * The remainder is defined as {@code this -
   * this.divideToIntegralValue(divisor) * divisor}.
   * 
   * @param divisor value by which {@code this} is divided.
   * @return {@code this % divisor}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   */
  public BigDecimal remainder(BigDecimal divisor) {
    return divideAndRemainder(divisor)[1];
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
   * <p>
   * The remainder is defined as {@code this -
   * this.divideToIntegralValue(divisor) * divisor}.
   * <p>
   * The specified rounding mode {@code mc} is used for the division only.
   * 
   * @param divisor value by which {@code this} is divided.
   * @param mc rounding mode and precision to be used.
   * @return {@code this % divisor}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @throws ArithmeticException if {@code mc.getPrecision() > 0} and the result
   *           of {@code this.divideToIntegralValue(divisor, mc)} requires more
   *           digits to be represented.
   */
  public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
    return divideAndRemainder(divisor, mc)[1];
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this}, rounded
   * according to the passed context {@code mc}.
   * <p>
   * If {@code mc.precision = 0}, then no rounding is performed.
   * <p>
   * If {@code mc.precision > 0} and {@code mc.roundingMode == UNNECESSARY},
   * then an {@code ArithmeticException} is thrown if the result cannot be
   * represented exactly within the given precision.
   * 
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this} rounded according to the passed context.
   * @throws ArithmeticException if {@code mc.precision > 0} and {@code
   *           mc.roundingMode == UNNECESSARY} and this cannot be represented
   *           within the given precision.
   */
  public BigDecimal round(MathContext mc) {
    BigDecimal thisBD = new BigDecimal(getUnscaledValue(), scale);

    thisBD.inplaceRound(mc);
    return thisBD;
  }

  /**
   * Returns the scale of this {@code BigDecimal}. The scale is the number of
   * digits behind the decimal point. The value of this {@code BigDecimal} is
   * the unsignedValue * 10^(-scale). If the scale is negative, then this
   * {@code BigDecimal} represents a big integer.
   * 
   * @return the scale of this {@code BigDecimal}.
   */
  public int scale() {
    return (int) scale;
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this} 10^{@code n}.
   * The scale of the result is {@code this.scale()} - {@code n}. The precision
   * of the result is the precision of {@code this}.
   * <p>
   * This method has the same effect as {@link #movePointRight}, except that the
   * precision is not changed.
   * 
   * @param n number of places the decimal point has to be moved.
   * @return {@code this * 10^n}
   */
  public BigDecimal scaleByPowerOfTen(int n) {
    double newScale = scale - n;
    if (bitLength < SMALL_VALUE_BITS) {
      // Taking care when a 0 is to be scaled
      if (smallValue == 0) {
        return zeroScaledBy(newScale);
      }
      return valueOf(smallValue, toIntScale(newScale));
    }
    return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
  }

  /**
   * Returns a new {@code BigDecimal} instance with the specified scale. If the
   * new scale is greater than the old scale, then additional zeros are added to
   * the unscaled value. If the new scale is smaller than the old scale, then
   * trailing zeros are removed. If the trailing digits are not zeros then an
   * ArithmeticException is thrown.
   * <p>
   * If no exception is thrown, then the following equation holds: {@code
   * x.setScale(s).compareTo(x) == 0}.
   * 
   * @param newScale scale of the result returned.
   * @return a new {@code BigDecimal} instance with the specified scale.
   * @throws ArithmeticException if rounding would be necessary.
   */
  public BigDecimal setScale(int newScale) {
    return setScale(newScale, RoundingMode.UNNECESSARY);
  }

  /**
   * Returns a new {@code BigDecimal} instance with the specified scale.
   * <p>
   * If the new scale is greater than the old scale, then additional zeros are
   * added to the unscaled value. In this case no rounding is necessary.
   * <p>
   * If the new scale is smaller than the old scale, then trailing digits are
   * removed. If these trailing digits are not zero, then the remaining unscaled
   * value has to be rounded. For this rounding operation the specified rounding
   * mode is used.
   * 
   * @param newScale scale of the result returned.
   * @param roundingMode rounding mode to be used to round the result.
   * @return a new {@code BigDecimal} instance with the specified scale.
   * @throws IllegalArgumentException if {@code roundingMode} is not a valid
   *           rounding mode.
   * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
   *           and rounding is necessary according to the given scale.
   */
  public BigDecimal setScale(int newScale, int roundingMode) {
    return setScale(newScale, RoundingMode.valueOf(roundingMode));
  }

  /**
   * Returns a new {@code BigDecimal} instance with the specified scale.
   * <p>
   * If the new scale is greater than the old scale, then additional zeros are
   * added to the unscaled value. In this case no rounding is necessary.
   * <p>
   * If the new scale is smaller than the old scale, then trailing digits are
   * removed. If these trailing digits are not zero, then the remaining unscaled
   * value has to be rounded. For this rounding operation the specified rounding
   * mode is used.
   * 
   * @param newScale scale of the result returned.
   * @param roundingMode rounding mode to be used to round the result.
   * @return a new {@code BigDecimal} instance with the specified scale.
   * @throws NullPointerException if {@code roundingMode == null}.
   * @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
   *           and rounding is necessary according to the given scale.
   */
  public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
    if (roundingMode == null) {
      throw new NullPointerException();
    }
    double diffScale = newScale - scale;
    // Let be: 'this' = [u,s]
    if (diffScale == 0) {
      return this;
    }
    if (diffScale > 0) {
      // return [u * 10^(s2 - s), newScale]
      if (diffScale < DOUBLE_TEN_POW.length
          && (this.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[
              (int) diffScale]) < SMALL_VALUE_BITS) {
        return valueOf(this.smallValue * DOUBLE_TEN_POW[(int) diffScale],
            newScale);
      }
      return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),
          (int) diffScale), newScale);
    }
    // diffScale < 0
    // return [u,s] / [1,newScale] with the appropriate scale and rounding
    if (this.bitLength < SMALL_VALUE_BITS
        && -diffScale < DOUBLE_TEN_POW.length) {
      return dividePrimitiveDoubles(this.smallValue,
          DOUBLE_TEN_POW[(int) -diffScale], newScale, roundingMode);
    }
    return divideBigIntegers(this.getUnscaledValue(),
        Multiplication.powerOf10(-diffScale), newScale, roundingMode);
  }

  /**
   * Returns this {@code BigDecimal} as a short value if it has no fractional
   * part and if its value fits to the short range ([-2^{15}..2^{15}-1]). If
   * these conditions are not met, an {@code ArithmeticException} is thrown.
   * 
   * @return this {@code BigDecimal} as a short value.
   * @throws ArithmeticException if rounding is necessary of the number doesn't
   *           fit in a short.
   */
  public short shortValueExact() {
    return (short) valueExact(16);
  }

  /**
   * Returns the sign of this {@code BigDecimal}.
   * 
   * @return {@code -1} if {@code this < 0}, {@code 0} if {@code this == 0},
   *         {@code 1} if {@code this > 0}.
   */
  public int signum() {
    if (bitLength < SMALL_VALUE_BITS) {
      return this.smallValue < 0 ? -1 : this.smallValue > 0 ? 1 : 0;
    }
    return getUnscaledValue().signum();
  }

  /**
   * Returns a new {@code BigDecimal} instance with the same value as {@code
   * this} but with a unscaled value where the trailing zeros have been removed.
   * If the unscaled value of {@code this} has n trailing zeros, then the scale
   * and the precision of the result has been reduced by n.
   * 
   * @return a new {@code BigDecimal} instance equivalent to this where the
   *         trailing zeros of the unscaled value have been removed.
   */
  public BigDecimal stripTrailingZeros() {
    int i = 1; // 1 <= i <= 18
    int lastPow = TEN_POW.length - 1;
    double newScale = scale;

    if (isZero()) {
      return new BigDecimal("0");
    }
    BigInteger strippedBI = getUnscaledValue();
    BigInteger[] quotAndRem;

    // while the number is even...
    while (!strippedBI.testBit(0)) {
      // To divide by 10^i
      quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
      // To look the remainder
      if (quotAndRem[1].signum() == 0) {
        // To adjust the scale
        newScale -= i;
        if (i < lastPow) {
          // To set to the next power
          i++;
        }
        strippedBI = quotAndRem[0];
      } else {
        if (i == 1) {
          // 'this' has no more trailing zeros
          break;
        }
        // To set to the smallest power of ten
        i = 1;
      }
    }
    return new BigDecimal(strippedBI, toIntScale(newScale));
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
   * The scale of the result is the maximum of the scales of the two arguments.
   * 
   * @param subtrahend value to be subtracted from {@code this}.
   * @return {@code this - subtrahend}.
   * @throws NullPointerException if {@code subtrahend == null}.
   */
  public BigDecimal subtract(BigDecimal subtrahend) {
    double diffScale = this.scale - subtrahend.scale;
    // Fast return when some operand is zero
    if (this.isZero()) {
      if (diffScale <= 0) {
        return subtrahend.negate();
      }
      if (subtrahend.isZero()) {
        return this;
      }
    } else if (subtrahend.isZero()) {
      if (diffScale >= 0) {
        return this;
      }
    }
    // Let be: this = [u1,s1] and subtrahend = [u2,s2] so:
    if (diffScale == 0) {
      // case s1 = s2 : [u1 - u2 , s1]
      if (Math.max(this.bitLength, subtrahend.bitLength) + 1
          < SMALL_VALUE_BITS) {
        return valueOf(this.smallValue - subtrahend.smallValue, this.scale);
      }
      return new BigDecimal(this.getUnscaledValue().subtract(
          subtrahend.getUnscaledValue()), this.scale);
    } else if (diffScale > 0) {
      // case s1 > s2 : [ u1 - u2 * 10 ^ (s1 - s2) , s1 ]
      if (diffScale < DOUBLE_TEN_POW.length
          && Math.max(this.bitLength, subtrahend.bitLength
              + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale]) + 1
              < SMALL_VALUE_BITS) {
        return valueOf(this.smallValue - subtrahend.smallValue
            * DOUBLE_TEN_POW[(int) diffScale], this.scale);
      }
      return new BigDecimal(this.getUnscaledValue().subtract(
          Multiplication.multiplyByTenPow(subtrahend.getUnscaledValue(),
              (int) diffScale)), this.scale);
    } else {
      // case s2 > s1 : [ u1 * 10 ^ (s2 - s1) - u2 , s2 ]
      diffScale = -diffScale;
      if (diffScale < DOUBLE_TEN_POW.length
          && Math.max(this.bitLength
              + DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale],
              subtrahend.bitLength) + 1 < SMALL_VALUE_BITS) {
        return valueOf(this.smallValue * DOUBLE_TEN_POW[(int) diffScale]
            - subtrahend.smallValue, subtrahend.scale);
      }
      return new BigDecimal(Multiplication.multiplyByTenPow(
          this.getUnscaledValue(), (int) diffScale).subtract(
          subtrahend.getUnscaledValue()), subtrahend.scale);
    }
  }

  /**
   * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
   * The result is rounded according to the passed context {@code mc}.
   * 
   * @param subtrahend value to be subtracted from {@code this}.
   * @param mc rounding mode and precision for the result of this operation.
   * @return {@code this - subtrahend}.
   * @throws NullPointerException if {@code subtrahend == null} or {@code mc ==
   *           null}.
   */
  public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
    double diffScale = subtrahend.scale - this.scale;
    int thisSignum;
    BigDecimal leftOperand; // it will be only the left operand (this)
    BigInteger tempBI;
    // Some operand is zero or the precision is infinity
    if ((subtrahend.isZero()) || (this.isZero()) || (mc.getPrecision() == 0)) {
      return subtract(subtrahend).round(mc);
    }
    // Now: this != 0 and subtrahend != 0
    if (subtrahend.approxPrecision() < diffScale - 1) {
      // Cases where it is unnecessary to subtract two numbers with very
      // different scales
      if (mc.getPrecision() < this.approxPrecision()) {
        thisSignum = this.signum();
        if (thisSignum != subtrahend.signum()) {
          tempBI = Multiplication.multiplyByPositiveInt(
              this.getUnscaledValue(), 10).add(BigInteger.valueOf(thisSignum));
        } else {
          tempBI = this.getUnscaledValue().subtract(
              BigInteger.valueOf(thisSignum));
          tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10).add(
              BigInteger.valueOf(thisSignum * 9));
        }
        // Rounding the improved subtracting
        leftOperand = new BigDecimal(tempBI, this.scale + 1);
        return leftOperand.round(mc);
      }
    }
    // No optimization is done
    return subtract(subtrahend).round(mc);
  }

  /**
   * Returns this {@code BigDecimal} as a big integer instance. A fractional
   * part is discarded.
   * 
   * @return this {@code BigDecimal} as a big integer instance.
   */
  public BigInteger toBigInteger() {
    if ((scale == 0) || (isZero())) {
      return getUnscaledValue();
    } else if (scale < 0) {
      return getUnscaledValue().multiply(Multiplication.powerOf10(-scale));
    } else {
      // (scale > 0)
      return getUnscaledValue().divide(Multiplication.powerOf10(scale));
    }
  }

  /**
   * Returns this {@code BigDecimal} as a big integer instance if it has no
   * fractional part. If this {@code BigDecimal} has a fractional part, i.e. if
   * rounding would be necessary, an {@code ArithmeticException} is thrown.
   * 
   * @return this {@code BigDecimal} as a big integer value.
   * @throws ArithmeticException if rounding is necessary.
   */
  public BigInteger toBigIntegerExact() {
    if ((scale == 0) || (isZero())) {
      return getUnscaledValue();
    } else if (scale < 0) {
      return getUnscaledValue().multiply(Multiplication.powerOf10(-scale));
    } else {
      // (scale > 0)
      BigInteger[] integerAndFraction;
      // An optimization before do a heavy division
      if ((scale > approxPrecision())
          || (scale > getUnscaledValue().getLowestSetBit())) {
        // math.08=Rounding necessary
        throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
      }
      integerAndFraction = getUnscaledValue().divideAndRemainder(
          Multiplication.powerOf10(scale));
      if (integerAndFraction[1].signum() != 0) {
        // It exists a non-zero fractional part
        // math.08=Rounding necessary
        throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
      }
      return integerAndFraction[0];
    }
  }

  /**
   * Returns a string representation of this {@code BigDecimal}. This
   * representation always prints all significant digits of this value.
   * <p>
   * If the scale is negative or if {@code scale - precision >= 6} then
   * engineering notation is used. Engineering notation is similar to the
   * scientific notation except that the exponent is made to be a multiple of 3
   * such that the integer part is >= 1 and < 1000.
   * 
   * @return a string representation of {@code this} in engineering notation if
   *         necessary.
   */
  public String toEngineeringString() {
    String intString = getUnscaledValue().toString();
    if (scale == 0) {
      return intString;
    }
    int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
    int end = intString.length();
    double exponent = -scale + end - begin;
    StringBuilder result = new StringBuilder(intString);

    if ((scale > 0) && (exponent >= -6)) {
      if (exponent >= 0) {
        result.insert(end - (int) scale, '.');
      } else {
        result.insert(begin - 1, "0."); //$NON-NLS-1$
        result.insert(begin + 1, CH_ZEROS, 0, -(int) exponent - 1);
      }
    } else {
      int delta = end - begin;
      int rem = (int) (exponent % 3);

      if (rem != 0) {
        // adjust exponent so it is a multiple of three
        if (getUnscaledValue().signum() == 0) {
          // zero value
          rem = (rem < 0) ? -rem : 3 - rem;
          exponent += rem;
        } else {
          // nonzero value
          rem = (rem < 0) ? rem + 3 : rem;
          exponent -= rem;
          begin += rem;
        }
        if (delta < 3) {
          for (int i = rem - delta; i > 0; i--) {
            result.insert(end++, '0');
          }
        }
      }
      if (end - begin >= 1) {
        result.insert(begin, '.');
        end++;
      }
      if (exponent != 0) {
        result.insert(end, 'E');
        if (exponent > 0) {
          result.insert(++end, '+');
        }
        result.insert(++end, Long.toString((long) exponent));
      }
    }
    return result.toString();
  }

  /**
   * Returns a string representation of this {@code BigDecimal}. No scientific
   * notation is used. This methods adds zeros where necessary.
   * <p>
   * If this string representation is used to create a new instance, this
   * instance is generally not identical to {@code this} as the precision
   * changes.
   * <p>
   * {@code x.equals(new BigDecimal(x.toPlainString())} usually returns {@code
   * false}.
   * <p>
   * {@code x.compareTo(new BigDecimal(x.toPlainString())} returns {@code 0}.
   * 
   * @return a string representation of {@code this} without exponent part.
   */
  public String toPlainString() {
    String intStr = getUnscaledValue().toString();
    if ((scale == 0) || ((isZero()) && (scale < 0))) {
      return intStr;
    }
    int begin = (signum() < 0) ? 1 : 0;
    double delta = scale;
    // We take space for all digits, plus a possible decimal point, plus 'scale'
    StringBuilder result = new StringBuilder(intStr.length() + 1
        + Math.abs((int) scale));

    if (begin == 1) {
      // If the number is negative, we insert a '-' character at front
      result.append('-');
    }
    if (scale > 0) {
      delta -= (intStr.length() - begin);
      if (delta >= 0) {
        result.append("0."); //$NON-NLS-1$
        // To append zeros after the decimal point
        for (; delta > CH_ZEROS.length; delta -= CH_ZEROS.length) {
          result.append(CH_ZEROS);
        }
        result.append(CH_ZEROS, 0, (int) delta);
        result.append(intStr.substring(begin));
      } else {
        delta = begin - delta;
        result.append(intStr.substring(begin, (int) delta));
        result.append('.');
        result.append(intStr.substring((int) delta));
      }
    } else {
      // (scale <= 0)
      result.append(intStr.substring(begin));
      // To append trailing zeros
      for (; delta < -CH_ZEROS.length; delta += CH_ZEROS.length) {
        result.append(CH_ZEROS);
      }
      result.append(CH_ZEROS, 0, (int) -delta);
    }
    return result.toString();
  }

  /**
   * Returns a canonical string representation of this {@code BigDecimal}. If
   * necessary, scientific notation is used. This representation always prints
   * all significant digits of this value.
   * <p>
   * If the scale is negative or if {@code scale - precision >= 6} then
   * scientific notation is used.
   * 
   * @return a string representation of {@code this} in scientific notation if
   *         necessary.
   */
  @Override
  public String toString() {
    if (toStringImage != null) {
      return toStringImage;
    }
    if (bitLength < 32) {
      // TODO convert to double math dont cast to long :-(
      toStringImage = Conversion.toDecimalScaledString((long) smallValue,
          (int) scale);
      return toStringImage;
    }
    String intString = getUnscaledValue().toString();
    if (scale == 0) {
      return intString;
    }
    int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
    int end = intString.length();
    double exponent = -scale + end - begin;
    StringBuilder result = new StringBuilder();

    result.append(intString);
    if ((scale > 0) && (exponent >= -6)) {
      if (exponent >= 0) {
        result.insert(end - (int) scale, '.');
      } else {
        result.insert(begin - 1, "0."); //$NON-NLS-1$
        result.insert(begin + 1, CH_ZEROS, 0, -(int) exponent - 1);
      }
    } else {
      if (end - begin >= 1) {
        result.insert(begin, '.');
        end++;
      }
      result.insert(end, 'E');
      if (exponent > 0) {
        result.insert(++end, '+');
      }
      result.insert(++end, Long.toString((long) exponent));
    }
    toStringImage = result.toString();
    return toStringImage;
  }

  /**
   * Returns the unit in the last place (ULP) of this {@code BigDecimal}
   * instance. An ULP is the distance to the nearest big decimal with the same
   * precision.
   * <p>
   * The amount of a rounding error in the evaluation of a floating-point
   * operation is often expressed in ULPs. An error of 1 ULP is often seen as a
   * tolerable error.
   * <p>
   * For class {@code BigDecimal}, the ULP of a number is simply 10^(-scale).
   * <p>
   * For example, {@code new BigDecimal(0.1).ulp()} returns {@code 1E-55}.
   * 
   * @return unit in the last place (ULP) of this {@code BigDecimal} instance.
   */
  public BigDecimal ulp() {
    return valueOf(1, scale);
  }

  /**
   * Returns the unscaled value (mantissa) of this {@code BigDecimal} instance
   * as a {@code BigInteger}. The unscaled value can be computed as {@code this}
   * 10^(scale).
   * 
   * @return unscaled value (this * 10^(scale)).
   */
  public BigInteger unscaledValue() {
    return getUnscaledValue();
  }

  /**
   * If the precision already was calculated it returns that value, otherwise it
   * calculates a very good approximation efficiently . Note that this value
   * will be {@code precision()} or {@code precision()-1} in the worst case.
   * 
   * @return an approximation of {@code precision()} value
   */
  private double approxPrecision() {
    return (precision > 0) ? precision
        : Math.floor((this.bitLength - 1) * LOG10_2) + 1;
  }

  private BigInteger getUnscaledValue() {
    if (intVal == null) {
      intVal = BigInteger.valueOf(smallValue);
    }
    return intVal;
  }

  private void initFrom(String val) {
    int begin = 0; // first index to be copied
    int offset = 0;
    int last = val.length(); // one past the last index to be copied
    String scaleString = null; // buffer for scale
    StringBuilder unscaledBuffer; // buffer for unscaled value

    unscaledBuffer = new StringBuilder(val.length());
    // To skip a possible '+' symbol
    if ((offset < last) && (val.charAt(offset) == '+')) {
      offset++;
      begin++;

      // Fail if the next character is another sign.
      if ((offset < last)
          && (val.charAt(offset) == '+' || val.charAt(offset) == '-')) {
        throw new NumberFormatException("For input string: \"" + val + "\"");
      }
    }
    // Accumulating all digits until a possible decimal point
    while ((offset < last) && (val.charAt(offset) != '.')
        && (val.charAt(offset) != 'e') && (val.charAt(offset) != 'E')) {
      offset++;
    }
    unscaledBuffer.append(val, begin, offset);
    // A decimal point was found
    if ((offset < last) && (val.charAt(offset) == '.')) {
      offset++;
      // Accumulating all digits until a possible exponent
      begin = offset;
      while ((offset < last) && (val.charAt(offset) != 'e')
          && (val.charAt(offset) != 'E')) {
        offset++;
      }
      scale = offset - begin;
      unscaledBuffer.append(val, begin, offset);
    } else {
      scale = 0;
    }
    // An exponent was found
    if ((offset < last)
        && ((val.charAt(offset) == 'e') || (val.charAt(offset) == 'E'))) {
      offset++;
      // Checking for a possible sign of scale
      begin = offset;
      if ((offset < last) && (val.charAt(offset) == '+')) {
        offset++;
        if ((offset < last) && (val.charAt(offset) != '-')) {
          begin++;
        }
      }
      // Accumulating all remaining digits
      scaleString = val.substring(begin, last);
      // Checking if the scale is defined
      scale = scale - Integer.parseInt(scaleString);
      if (scale != (int) scale) {
        // math.02=Scale out of range.
        throw new NumberFormatException("Scale out of range."); //$NON-NLS-1$
      }
    }
    // Parsing the unscaled value
    String unscaled = unscaledBuffer.toString();
    if (unscaled.length() < 16) {
      smallValue = parseUnscaled(unscaled);
      if (Double.isNaN(smallValue)) {
        throw new NumberFormatException("For input string: \"" + val + "\"");
      }
      bitLength = bitLength(smallValue);
    } else {
      setUnscaledValue(new BigInteger(unscaled));
    }
    precision = unscaledBuffer.length();
    // Don't count leading zeros in the precision
    for (int i = 0; i < unscaledBuffer.length(); ++i) {
      char ch = unscaledBuffer.charAt(i);
      if (ch != '-' && ch != '0') {
        break;
      }
      --precision;
    }
    // The precision of a zero value is 1
    if (precision == 0) {
      precision = 1;
    }
  }

  /**
   * It does all rounding work of the public method {@code round(MathContext)},
   * performing an inplace rounding without creating a new object.
   * 
   * @param mc the {@code MathContext} for perform the rounding.
   * @see #round(MathContext)
   */
  private void inplaceRound(MathContext mc) {
    int mcPrecision = mc.getPrecision();
    if (approxPrecision() - mcPrecision < 0 || mcPrecision == 0) {
      return;
    }
    int discardedPrecision = precision() - mcPrecision;
    // If no rounding is necessary it returns immediately
    if ((discardedPrecision <= 0)) {
      return;
    }
    // When the number is small perform an efficient rounding
    if (this.bitLength < SMALL_VALUE_BITS) {
      smallRound(mc, discardedPrecision);
      return;
    }
    // Getting the integer part and the discarded fraction
    BigInteger sizeOfFraction = Multiplication.powerOf10(discardedPrecision);
    BigInteger[] integerAndFraction = getUnscaledValue().divideAndRemainder(
        sizeOfFraction);
    double newScale = scale - discardedPrecision;
    int compRem;
    BigDecimal tempBD;
    // If the discarded fraction is non-zero, perform rounding
    if (integerAndFraction[1].signum() != 0) {
      // To check if the discarded fraction >= 0.5
      compRem = (integerAndFraction[1].abs().shiftLeftOneBit().compareTo(sizeOfFraction));
      // To look if there is a carry
      compRem = roundingBehavior(integerAndFraction[0].testBit(0) ? 1 : 0,
          integerAndFraction[1].signum() * (5 + compRem), mc.getRoundingMode());
      if (compRem != 0) {
        integerAndFraction[0] = integerAndFraction[0].add(BigInteger.valueOf(compRem));
      }
      tempBD = new BigDecimal(integerAndFraction[0]);
      // If after to add the increment the precision changed, we normalize the
      // size
      if (tempBD.precision() > mcPrecision) {
        integerAndFraction[0] = integerAndFraction[0].divide(BigInteger.TEN);
        newScale--;
      }
    }
    // To update all internal fields
    scale = toIntScale(newScale);
    precision = mcPrecision;
    setUnscaledValue(integerAndFraction[0]);
  }

  private boolean isZero() {
    return bitLength == 0 && this.smallValue != -1;
  }

  private BigDecimal movePoint(double newScale) {
    if (isZero()) {
      return zeroScaledBy(Math.max(newScale, 0));
    }
    /*
     * When: 'n'== Integer.MIN_VALUE isn't possible to call to
     * movePointRight(-n) since -Integer.MIN_VALUE == Integer.MIN_VALUE
     */
    if (newScale >= 0) {
      if (bitLength < SMALL_VALUE_BITS) {
        return valueOf(smallValue, toIntScale(newScale));
      }
      return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
    }
    if (-newScale < DOUBLE_TEN_POW.length
        && bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) -newScale]
            < SMALL_VALUE_BITS) {
      return valueOf(smallValue * DOUBLE_TEN_POW[(int) -newScale], 0);
    }
    return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),
        (int) -newScale), 0);
  }

  private void setUnscaledValue(BigInteger unscaledValue) {
    this.intVal = unscaledValue;
    this.bitLength = unscaledValue.bitLength();
    if (this.bitLength < SMALL_VALUE_BITS) {
      this.smallValue = unscaledValue.longValue();
    }
  }

  /**
   * This method implements an efficient rounding for numbers which unscaled
   * value fits in the type {@code long}.
   * 
   * @param mc the context to use
   * @param discardedPrecision the number of decimal digits that are discarded
   * @see #round(MathContext)
   */
  private void smallRound(MathContext mc, int discardedPrecision) {
    long sizeOfFraction = (long) DOUBLE_TEN_POW[discardedPrecision];
    long newScale = (long) scale - discardedPrecision;
    long unscaledVal = (long) smallValue; // TODO convert to double math dont
                                          // use longs
    // Getting the integer part and the discarded fraction
    long integer = unscaledVal / sizeOfFraction;
    long fraction = unscaledVal % sizeOfFraction;
    int compRem;
    // If the discarded fraction is non-zero perform rounding
    if (fraction != 0) {
      // To check if the discarded fraction >= 0.5
      compRem = longCompareTo(Math.abs(fraction) << 1, sizeOfFraction);
      // To look if there is a carry
      integer += roundingBehavior(((int) integer) & 1, Long.signum(fraction)
          * (5 + compRem), mc.getRoundingMode());
      // If after to add the increment the precision changed, we normalize the
      // size
      if (Math.log10(Math.abs(integer)) >= mc.getPrecision()) {
        integer /= 10;
        newScale--;
      }
    }
    // To update all internal fields
    scale = toIntScale(newScale);
    precision = mc.getPrecision();
    smallValue = integer;
    bitLength = bitLength(integer);
    intVal = null;
  }

  /**
   * If {@code intVal} has a fractional part throws an exception, otherwise it
   * counts the number of bits of value and checks if it's out of the range of
   * the primitive type. If the number fits in the primitive type returns this
   * number as {@code long}, otherwise throws an exception.
   * 
   * @param bitLengthOfType number of bits of the type whose value will be
   *          calculated exactly
   * @return the exact value of the integer part of {@code BigDecimal} when is
   *         possible
   * @throws ArithmeticException when rounding is necessary or the number don't
   *           fit in the primitive type
   */
  private long valueExact(int bitLengthOfType) {
    BigInteger bigInteger = toBigIntegerExact();

    if (bigInteger.bitLength() < bitLengthOfType) {
      // It fits in the primitive type
      return bigInteger.longValue();
    }
    // math.08=Rounding necessary
    throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
  }
}
