/*
 * 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 static javaemul.internal.InternalPreconditions.checkCriticalArgument;
import static javaemul.internal.InternalPreconditions.checkNotNull;

import java.io.Serializable;
import java.util.Random;

/**
 * This class represents immutable integer numbers of arbitrary length. Large
 * numbers are typically used in security applications and therefore BigIntegers
 * offer dedicated functionality like the generation of large prime numbers or
 * the computation of modular inverse.
 * <p>
 * Since the class was modeled to offer all the functionality as the
 * {@link Integer} class does, it provides even methods that operate bitwise on
 * a two's complement representation of large integers. Note however that the
 * implementations favors an internal representation where magnitude and sign
 * are treated separately. Hence such operations are inefficient and should be
 * discouraged. In simple words: Do NOT implement any bit fields based on
 * BigInteger.
 */
public class BigInteger extends Number implements Comparable<BigInteger>,
    Serializable {

  /**
   * The {@code BigInteger} constant 1.
   */
  public static final BigInteger ONE = new BigInteger(1, 1);

  /* Fields used for the internal representation. */

  /**
   * The {@code BigInteger} constant 10.
   */
  public static final BigInteger TEN = new BigInteger(1, 10);

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

  /**
   * The {@code BigInteger} constant 0 used for comparison.
   */
  static final int EQUALS = 0;

  /**
   * The {@code BigInteger} constant 1 used for comparison.
   */
  static final int GREATER = 1;

  /**
   * The {@code BigInteger} constant -1 used for comparison.
   */
  static final int LESS = -1;

  /**
   * The {@code BigInteger} constant -1.
   */
  static final BigInteger MINUS_ONE = new BigInteger(-1, 1);

  /**
   * 2^32.
   */
  static final double POW32 = 4294967296d;

  /**
   * All the {@code BigInteger} numbers in the range [0,10] are cached.
   */
  static final BigInteger[] SMALL_VALUES = {
      ZERO, ONE, new BigInteger(1, 2), new BigInteger(1, 3),
      new BigInteger(1, 4), new BigInteger(1, 5), new BigInteger(1, 6),
      new BigInteger(1, 7), new BigInteger(1, 8), new BigInteger(1, 9), TEN};

  static final BigInteger[] TWO_POWS;

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

  static {
    TWO_POWS = new BigInteger[32];
    for (int i = 0; i < TWO_POWS.length; i++) {
      TWO_POWS[i] = BigInteger.valueOf(1L << i);
    }
  }

  /**
   * Returns a random positive {@code BigInteger} instance in the range [0,
   * 2^(bitLength)-1] which is probably prime. The probability that the returned
   * {@code BigInteger} is prime is beyond (1-1/2^80).
   * <p>
   * <b>Implementation Note:</b> Currently {@code rnd} is ignored.
   *
   * @param bitLength length of the new {@code BigInteger} in bits.
   * @param rnd random generator used to generate the new {@code BigInteger}.
   * @return probably prime random {@code BigInteger} instance.
   * @throws ArithmeticException if {@code bitLength < 2}.
   */
  public static BigInteger probablePrime(int bitLength, Random rnd) {
    return new BigInteger(bitLength, 100, rnd);
  }

  public static BigInteger valueOf(long val) {
    if (val < 0) {
      if (val != -1) {
        return new BigInteger(-1, -val);
      }
      return MINUS_ONE;
    } else if (val <= 10) {
      return SMALL_VALUES[(int) val];
    } else {
      // (val > 10)
      return new BigInteger(1, val);
    }
  }

  static BigInteger getPowerOfTwo(int exp) {
    if (exp < TWO_POWS.length) {
      return TWO_POWS[exp];
    }
    int intCount = exp >> 5;
    int bitN = exp & 31;
    int resDigits[] = new int[intCount + 1];
    resDigits[intCount] = 1 << bitN;
    return new BigInteger(1, intCount + 1, resDigits);
  }

  public static BigInteger valueOf(double val) {
    if (val < 0) {
      if (val != -1) {
        return new BigInteger(-1, -val);
      }
      return MINUS_ONE;
    } else if (val <= 10) {
      return SMALL_VALUES[(int) val];
    } else {
      // (val > 10)
      return new BigInteger(1, val);
    }
  }

  /**
   * @see BigInteger#BigInteger(String, int)
   */
  private static void setFromString(BigInteger bi, String val, int radix) {
    int sign;
    int[] digits;
    int numberLength;
    int stringLength = val.length();
    int startChar;
    int endChar = stringLength;

    if (val.charAt(0) == '-') {
      sign = -1;
      startChar = 1;
      stringLength--;
    } else {
      sign = 1;
      startChar = 0;
    }
    /*
     * We use the following algorithm: split a string into portions of n
     * characters and convert each portion to an integer according to the radix.
     * Then convert an exp(radix, n) based number to binary using the
     * multiplication method. See D. Knuth, The Art of Computer Programming,
     * vol. 2.
     */

    int charsPerInt = Conversion.digitFitInInt[radix];
    int bigRadixDigitsLength = stringLength / charsPerInt;
    int topChars = stringLength % charsPerInt;

    if (topChars != 0) {
      bigRadixDigitsLength++;
    }
    digits = new int[bigRadixDigitsLength];
    // Get the maximal power of radix that fits in int
    int bigRadix = Conversion.bigRadices[radix - 2];
    // Parse an input string and accumulate the BigInteger's magnitude
    int digitIndex = 0; // index of digits array
    int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars);
    int newDigit;

    for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart
        + charsPerInt) {
      int bigRadixDigit = Integer.parseInt(
          val.substring(substrStart, substrEnd), radix);
      newDigit = Multiplication.multiplyByInt(digits, digitIndex, bigRadix);
      newDigit += Elementary.inplaceAdd(digits, digitIndex, bigRadixDigit);
      digits[digitIndex++] = newDigit;
    }
    numberLength = digitIndex;
    bi.sign = sign;
    bi.numberLength = numberLength;
    bi.digits = digits;
    bi.cutOffLeadingZeroes();
  }

  /**
   * Converts an integral double to an unsigned integer; ie 2^31 will be
   * returned as 0x80000000.
   *
   * @param val
   * @return val as an unsigned int
   */
  @SuppressWarnings("unusable-by-js")
  private static native int toUnsignedInt(double val) /*-{
    return val | 0;
  }-*/;

  /**
   * The magnitude of this big integer. This array is in little endian order and
   * each "digit" is a 32-bit unsigned integer. For example: {@code 13} is
   * represented as [ 13 ] {@code -13} is represented as [ 13 ] {@code 2^32 +
   * 13} is represented as [ 13, 1 ] {@code 2^64 + 13} is represented as [ 13,
   * 0, 1 ] {@code 2^31} is represented as [ Integer.MIN_VALUE ] The magnitude
   * array may be longer than strictly necessary, which results in additional
   * trailing zeros.
   *
   * <p>TODO(jat): consider changing to 24-bit integers for better performance
   * in browsers.
   */
  transient int digits[];

  /**
   * The length of this in measured in ints. Can be less than digits.length().
   */
  transient int numberLength;

  /**
   * The sign of this.
   */
  transient int sign;

  private transient int firstNonzeroDigit = -2;

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

  /**
   * Constructs a new {@code BigInteger} from the given two's complement
   * representation. The most significant byte is the entry at index 0. The most
   * significant bit of this entry determines the sign of the new {@code
   * BigInteger} instance. The given array must not be empty.
   *
   * @param val two's complement representation of the new {@code BigInteger}.
   * @throws NullPointerException if {@code val == null}.
   * @throws NumberFormatException if the length of {@code val} is zero.
   */
  public BigInteger(byte[] val) {
    if (val.length == 0) {
      // math.12=Zero length BigInteger
      throw new NumberFormatException("Zero length BigInteger"); //$NON-NLS-1$
    }
    if (val[0] < 0) {
      sign = -1;
      putBytesNegativeToIntegers(val);
    } else {
      sign = 1;
      putBytesPositiveToIntegers(val);
    }
    cutOffLeadingZeroes();
  }

  /**
   * Constructs a new {@code BigInteger} instance with the given sign and the
   * given magnitude. The sign is given as an integer (-1 for negative, 0 for
   * zero, 1 for positive). The magnitude is specified as a byte array. The most
   * significant byte is the entry at index 0.
   *
   * @param signum sign of the new {@code BigInteger} (-1 for negative, 0 for
   *          zero, 1 for positive).
   * @param magnitude magnitude of the new {@code BigInteger} with the most
   *          significant byte first.
   * @throws NullPointerException if {@code magnitude == null}.
   * @throws NumberFormatException if the sign is not one of -1, 0, 1 or if the
   *           sign is zero and the magnitude contains non-zero entries.
   */
  public BigInteger(int signum, byte[] magnitude) {
    checkNotNull(magnitude);

    if ((signum < -1) || (signum > 1)) {
      // math.13=Invalid signum value
      throw new NumberFormatException("Invalid signum value"); //$NON-NLS-1$
    }
    if (signum == 0) {
      for (byte element : magnitude) {
        if (element != 0) {
          // math.14=signum-magnitude mismatch
          throw new NumberFormatException("signum-magnitude mismatch"); //$NON-NLS-1$
        }
      }
    }
    if (magnitude.length == 0) {
      sign = 0;
      numberLength = 1;
      digits = new int[] {0};
    } else {
      sign = signum;
      putBytesPositiveToIntegers(magnitude);
      cutOffLeadingZeroes();
    }
  }

  /**
   * Constructs a random {@code BigInteger} instance in the range [0,
   * 2^(bitLength)-1] which is probably prime. The probability that the returned
   * {@code BigInteger} is prime is beyond (1-1/2^certainty).
   *
   * @param bitLength length of the new {@code BigInteger} in bits.
   * @param certainty tolerated primality uncertainty.
   * @param rnd is an optional random generator to be used.
   * @throws ArithmeticException if {@code bitLength} < 2.
   */
  public BigInteger(int bitLength, int certainty, Random rnd) {
    if (bitLength < 2) {
      // math.1C=bitLength < 2
      throw new ArithmeticException("bitLength < 2"); //$NON-NLS-1$
    }
    BigInteger me = Primality.consBigInteger(bitLength, certainty, rnd);
    sign = me.sign;
    numberLength = me.numberLength;
    digits = me.digits;
  }

  /**
   * Constructs a random non-negative {@code BigInteger} instance in the range
   * [0, 2^(numBits)-1].
   *
   * @param numBits maximum length of the new {@code BigInteger} in bits.
   * @param rnd is an optional random generator to be used.
   * @throws IllegalArgumentException if {@code numBits} < 0.
   */
  public BigInteger(int numBits, Random rnd) {
    checkCriticalArgument(numBits >= 0, "numBits must be non-negative");

    if (numBits == 0) {
      sign = 0;
      numberLength = 1;
      digits = new int[] {0};
    } else {
      sign = 1;
      numberLength = (numBits + 31) >> 5;
      digits = new int[numberLength];
      for (int i = 0; i < numberLength; i++) {
        digits[i] = rnd.nextInt();
      }
      // Using only the necessary bits
      digits[numberLength - 1] >>>= (-numBits) & 31;
      cutOffLeadingZeroes();
    }
  }

  /**
   * Constructs a new {@code BigInteger} instance from the string
   * representation. The string representation consists of an optional minus
   * sign followed by a non-empty sequence of decimal digits.
   *
   * @param val string representation of the new {@code BigInteger}.
   * @throws NullPointerException if {@code val == null}.
   * @throws NumberFormatException if {@code val} is not a valid representation
   *           of a {@code BigInteger}.
   */
  public BigInteger(String val) {
    this(val, 10);
  }

  /**
   * Constructs a new {@code BigInteger} instance from the string
   * representation. The string representation consists of an optional minus
   * sign followed by a non-empty sequence of digits in the specified radix. For
   * the conversion the method {@code Character.digit(char, radix)} is used.
   *
   * @param val string representation of the new {@code BigInteger}.
   * @param radix the base to be used for the conversion.
   * @throws NullPointerException if {@code val == null}.
   * @throws NumberFormatException if {@code val} is not a valid representation
   *           of a {@code BigInteger} or if {@code radix < Character.MIN_RADIX}
   *           or {@code radix > Character.MAX_RADIX}.
   */
  public BigInteger(String val, int radix) {
    checkNotNull(val);

    if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX)) {
      // math.11=Radix out of range
      throw new NumberFormatException("Radix out of range"); //$NON-NLS-1$
    }
    if (val.isEmpty()) {
      // math.12=Zero length BigInteger
      throw new NumberFormatException("Zero length BigInteger"); //$NON-NLS-1$
    }
    setFromString(this, val, radix);
  }

  /**
   * Constructs a number which array is of size 1.
   *
   * @param sign the sign of the number
   * @param value the only one digit of array
   */
  BigInteger(int sign, int value) {
    this.sign = sign;
    numberLength = 1;
    digits = new int[] {value};
  }

  /**
   * Creates a new {@code BigInteger} with the given sign and magnitude. This
   * constructor does not create a copy, so any changes to the reference will
   * affect the new number.
   *
   * @param signum The sign of the number represented by {@code digits}
   * @param digits The magnitude of the number
   */
  BigInteger(int signum, int digits[]) {
    if (digits.length == 0) {
      sign = 0;
      numberLength = 1;
      this.digits = new int[] {0};
    } else {
      sign = signum;
      numberLength = digits.length;
      this.digits = digits;
      cutOffLeadingZeroes();
    }
  }

  /**
   * Constructs a number without to create new space. This construct should be
   * used only if the three fields of representation are known.
   *
   * @param sign the sign of the number
   * @param numberLength the length of the internal array
   * @param digits a reference of some array created before
   */
  BigInteger(int sign, int numberLength, int[] digits) {
    this.sign = sign;
    this.numberLength = numberLength;
    this.digits = digits;
  }

  /**
   * Creates a new {@code BigInteger} whose value is equal to the specified
   * {@code long}.
   *
   * @param sign the sign of the number
   * @param val the value of the new {@code BigInteger}.
   */
  BigInteger(int sign, long val) {
    // PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
    this.sign = sign;
    if ((val & 0xFFFFFFFF00000000L) == 0) {
      // It fits in one 'int'
      numberLength = 1;
      digits = new int[] {(int) val};
    } else {
      numberLength = 2;
      digits = new int[] {(int) val, (int) (val >> 32)};
    }
  }

  /**
   * Creates a new {@code BigInteger} whose value is equal to the specified
   * {@code double} (which must be an integral value).
   *
   * @param sign the sign of the number
   * @param val the value of the new {@code BigInteger}.
   */
  private BigInteger(int sign, double val) {
    // PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
    this.sign = sign;
    if (val < POW32) {
      // It fits in one 'int'
      numberLength = 1;
      digits = new int[] { toUnsignedInt(val) };
    } else {
      numberLength = 2;
      digits = new int[] { toUnsignedInt(val % POW32), toUnsignedInt(val / POW32) };
    }
  }

  /**
   * Returns a (new) {@code BigInteger} whose value is the absolute value of
   * {@code this}.
   *
   * @return {@code abs(this)}.
   */
  public BigInteger abs() {
    return ((sign < 0) ? new BigInteger(1, numberLength, digits) : this);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this + val}.
   *
   * @param val value to be added to {@code this}.
   * @return {@code this + val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger add(BigInteger val) {
    return Elementary.add(this, val);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this & val}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param val value to be and'ed with {@code this}.
   * @return {@code this & val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger and(BigInteger val) {
    return Logical.and(this, val);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this & ~val}.
   * Evaluating {@code x.andNot(val)} returns the same result as {@code
   * x.and(val.not())}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param val value to be not'ed and then and'ed with {@code this}.
   * @return {@code this & ~val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger andNot(BigInteger val) {
    return Logical.andNot(this, val);
  }

  /**
   * Use {@code bitLength(0)} if you want to know the length of the binary value
   * in bits.
   * <p>
   * Returns the number of bits in the binary representation of {@code this}
   * which differ from the sign bit. If {@code this} is positive the result is
   * equivalent to the number of bits set in the binary representation of
   * {@code this}. If {@code this} is negative the result is equivalent to the
   * number of bits set in the binary representation of {@code -this-1}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @return number of bits in the binary representation of {@code this} which
   *         differ from the sign bit
   */
  public int bitCount() {
    return BitLevel.bitCount(this);
  }

  /**
   * Returns the length of the value's two's complement representation without
   * leading zeros for positive numbers / without leading ones for negative
   * values.
   * <p>
   * The two's complement representation of {@code this} will be at least
   * {@code bitLength() + 1} bits long.
   * <p>
   * The value will fit into an {@code int} if {@code bitLength() < 32} or into
   * a {@code long} if {@code bitLength() < 64}.
   *
   * @return the length of the minimal two's complement representation for
   *         {@code this} without the sign bit.
   */
  public int bitLength() {
    return BitLevel.bitLength(this);
  }

  /**
   * Converts value of this {@code BigInteger} to a {@code byte} if it fits it,
   * otherwise {@code ArithmeticException} is thrown.
   *
   * @return this {@code BigInteger} converted to a {@code byte}.
   * @throws ArithmeticException if the value of this {@code BigInteger}
   *         does not fit in a {@code byte}.
   */
  public byte byteValueExact() {
    if (numberLength <= 1 && bitLength() < Byte.SIZE) {
      return byteValue();
    }
    throw new ArithmeticException("out of byte range");
  }

  /**
   * Returns a new {@code BigInteger} which has the same binary representation
   * as {@code this} but with the bit at position n cleared. The result is
   * equivalent to {@code this & ~(2^n)}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param n position where the bit in {@code this} has to be cleared.
   * @return {@code this & ~(2^n)}.
   * @throws ArithmeticException if {@code n < 0}.
   */
  public BigInteger clearBit(int n) {
    if (testBit(n)) {
      return BitLevel.flipBit(this, n);
    }
    return this;
  }

  /**
   * Compares this {@code BigInteger} with {@code val}. Returns one of the three
   * values 1, 0, or -1.
   *
   * @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}.
   */
  @Override
  public int compareTo(BigInteger val) {
    if (sign > val.sign) {
      return GREATER;
    }
    if (sign < val.sign) {
      return LESS;
    }
    if (numberLength > val.numberLength) {
      return sign;
    }
    if (numberLength < val.numberLength) {
      return -val.sign;
    }
    // Equal sign and equal numberLength
    return (sign * Elementary.compareArrays(digits, val.digits, numberLength));
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this / 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 BigInteger divide(BigInteger divisor) {
    if (divisor.sign == 0) {
      // math.17=BigInteger divide by zero
      throw new ArithmeticException("BigInteger divide by zero"); //$NON-NLS-1$
    }
    int divisorSign = divisor.sign;
    if (divisor.isOne()) {
      return ((divisor.sign > 0) ? this : this.negate());
    }
    int thisSign = sign;
    int thisLen = numberLength;
    int divisorLen = divisor.numberLength;
    if (thisLen + divisorLen == 2) {
      long val = (digits[0] & 0xFFFFFFFFL) / (divisor.digits[0] & 0xFFFFFFFFL);
      if (thisSign != divisorSign) {
        val = -val;
      }
      return valueOf(val);
    }
    int cmp = ((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1)
        : Elementary.compareArrays(digits, divisor.digits, thisLen));
    if (cmp == EQUALS) {
      return ((thisSign == divisorSign) ? ONE : MINUS_ONE);
    }
    if (cmp == LESS) {
      return ZERO;
    }
    int resLength = thisLen - divisorLen + 1;
    int resDigits[] = new int[resLength];
    int resSign = ((thisSign == divisorSign) ? 1 : -1);
    if (divisorLen == 1) {
      Division.divideArrayByInt(resDigits, digits, thisLen, divisor.digits[0]);
    } else {
      Division.divide(resDigits, resLength, digits, thisLen, divisor.digits,
          divisorLen);
    }
    BigInteger result = new BigInteger(resSign, resLength, resDigits);
    result.cutOffLeadingZeroes();
    return result;
  }

  /**
   * Returns a {@code BigInteger} array which contains {@code this / divisor} at
   * index 0 and {@code this % divisor} at index 1.
   *
   * @param divisor value by which {@code this} is divided.
   * @return {@code [this / divisor, this % divisor]}.
   * @throws NullPointerException if {@code divisor == null}.
   * @throws ArithmeticException if {@code divisor == 0}.
   * @see #divide
   * @see #remainder
   */
  public BigInteger[] divideAndRemainder(BigInteger divisor) {
    int divisorSign = divisor.sign;
    if (divisorSign == 0) {
      // math.17=BigInteger divide by zero
      throw new ArithmeticException("BigInteger divide by zero"); //$NON-NLS-1$
    }
    int divisorLen = divisor.numberLength;
    int[] divisorDigits = divisor.digits;
    if (divisorLen == 1) {
      return Division.divideAndRemainderByInteger(this, divisorDigits[0],
          divisorSign);
    }
    // res[0] is a quotient and res[1] is a remainder:
    int[] thisDigits = digits;
    int thisLen = numberLength;
    int cmp = (thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1)
        : Elementary.compareArrays(thisDigits, divisorDigits, thisLen);
    if (cmp < 0) {
      return new BigInteger[] {ZERO, this};
    }
    int thisSign = sign;
    int quotientLength = thisLen - divisorLen + 1;
    int remainderLength = divisorLen;
    int quotientSign = ((thisSign == divisorSign) ? 1 : -1);
    int quotientDigits[] = new int[quotientLength];
    int remainderDigits[] = Division.divide(quotientDigits, quotientLength,
        thisDigits, thisLen, divisorDigits, divisorLen);
    BigInteger result0 = new BigInteger(quotientSign, quotientLength,
        quotientDigits);
    BigInteger result1 = new BigInteger(thisSign, remainderLength,
        remainderDigits);
    result0.cutOffLeadingZeroes();
    result1.cutOffLeadingZeroes();
    return new BigInteger[] {result0, result1};
  }

  /**
   * Returns this {@code BigInteger} as an double value. If {@code this} is too
   * big to be represented as an double, then {@code Double.POSITIVE_INFINITY}
   * or {@code Double.NEGATIVE_INFINITY} is returned. Note, that not all
   * integers x in the range [-Double.MAX_VALUE, Double.MAX_VALUE] can be
   * represented as a double. The double representation has a mantissa of length
   * 53. For example, 2^53+1 = 9007199254740993 is returned as double
   * 9007199254740992.0.
   *
   * @return this {@code BigInteger} as a double value
   */
  @Override
  public double doubleValue() {
    return Double.parseDouble(this.toString());
  }

  /**
   * Returns {@code true} if {@code x} is a BigInteger instance and if this
   * instance is equal to this {@code BigInteger}.
   *
   * @param x object to be compared with {@code this}.
   * @return true if {@code x} is a BigInteger and {@code this == x}, {@code
   *         false} otherwise.
   */
  @Override
  public boolean equals(Object x) {
    if (this == x) {
      return true;
    }
    if (x instanceof BigInteger) {
      BigInteger x1 = (BigInteger) x;
      return sign == x1.sign && numberLength == x1.numberLength
          && equalsArrays(x1.digits);
    }
    return false;
  }

  /**
   * Returns a new {@code BigInteger} which has the same binary representation
   * as {@code this} but with the bit at position n flipped. The result is
   * equivalent to {@code this ^ 2^n}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param n position where the bit in {@code this} has to be flipped.
   * @return {@code this ^ 2^n}.
   * @throws ArithmeticException if {@code n < 0}.
   */
  public BigInteger flipBit(int n) {
    if (n < 0) {
      // math.15=Negative bit address
      throw new ArithmeticException("Negative bit address"); //$NON-NLS-1$
    }
    return BitLevel.flipBit(this, n);
  }

  /**
   * Returns this {@code BigInteger} as an 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. Note, that not all integers x
   * in the range [-Float.MAX_VALUE, Float.MAX_VALUE] can be represented as a
   * float. The float representation has a mantissa of length 24. For example,
   * 2^24+1 = 16777217 is returned as float 16777216.0.
   *
   * @return this {@code BigInteger} as a float value.
   */
  @Override
  public float floatValue() {
    return Float.parseFloat(this.toString());
  }

  /**
   * Returns a new {@code BigInteger} whose value is greatest common divisor of
   * {@code this} and {@code val}. If {@code this==0} and {@code val==0} then
   * zero is returned, otherwise the result is positive.
   *
   * @param val value with which the greatest common divisor is computed.
   * @return {@code gcd(this, val)}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger gcd(BigInteger val) {
    BigInteger val1 = this.abs();
    BigInteger val2 = val.abs();
    // To avoid a possible division by zero
    if (val1.signum() == 0) {
      return val2;
    } else if (val2.signum() == 0) {
      return val1;
    }

    // Optimization for small operands
    // (op2.bitLength() < 64) and (op1.bitLength() < 64)
    if (((val1.numberLength == 1) || ((val1.numberLength == 2) && (val1.digits[1] > 0)))
        && (val2.numberLength == 1 || (val2.numberLength == 2 && val2.digits[1] > 0))) {
      return BigInteger.valueOf(Division.gcdBinary(val1.longValue(),
          val2.longValue()));
    }

    return Division.gcdBinary(val1.copy(), val2.copy());
  }

  /**
   * Returns the position of the lowest set bit in the two's complement
   * representation of this {@code BigInteger}. If all bits are zero (this=0)
   * then -1 is returned as result.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @return position of lowest bit if {@code this != 0}, {@code -1} otherwise
   */
  public int getLowestSetBit() {
    if (sign == 0) {
      return -1;
    }
    // (sign != 0) implies that exists some non zero digit
    int i = getFirstNonzeroDigit();
    return ((i << 5) + Integer.numberOfTrailingZeros(digits[i]));
  }

  /**
   * Returns a hash code for this {@code BigInteger}.
   *
   * @return hash code for {@code this}.
   */
  @Override
  public int hashCode() {
    if (hashCode != 0) {
      return hashCode;
    }
    for (int i = 0; i < digits.length; i++) {
      hashCode = (hashCode * 33 + (digits[i] & 0xffffffff));
    }
    hashCode = hashCode * sign;
    return hashCode;
  }

  /**
   * Returns this {@code BigInteger} as an int value. If {@code this} is too big
   * to be represented as an int, then {@code this} % 2^32 is returned.
   *
   * @return this {@code BigInteger} as an int value.
   */
  @Override
  public int intValue() {
    int i = digits[0];
    // i is always positive except for Integer.MIN_VALUE because of int overflow
    return (sign > 0 || i == Integer.MIN_VALUE) ? i : -i;
  }

  /**
   * Converts value of this {@code BigInteger} to an {@code int} if it fits it,
   * otherwise {@code ArithmeticException} is thrown.
   *
   * @return this {@code BigInteger} converted to an {@code int}.
   * @throws ArithmeticException if the value of this {@code BigInteger}
   *         does not fit in an {@code int}.
   */
  public int intValueExact() {
    if (numberLength <= 1 && bitLength() < Integer.SIZE) {
      return intValue();
    }
    throw new ArithmeticException("out of int range");
  }

  /**
   * Tests whether this {@code BigInteger} is probably prime. If {@code true} is
   * returned, then this is prime with a probability beyond (1-1/2^certainty).
   * If {@code false} is returned, then this is definitely composite. If the
   * argument {@code certainty} <= 0, then this method returns true.
   *
   * @param certainty tolerated primality uncertainty.
   * @return {@code true}, if {@code this} is probably prime, {@code false}
   *         otherwise.
   */
  public boolean isProbablePrime(int certainty) {
    return Primality.isProbablePrime(abs(), certainty);
  }

  /**
   * Returns this {@code BigInteger} as an long value. If {@code this} is too
   * big to be represented as an long, then {@code this} % 2^64 is returned.
   *
   * @return this {@code BigInteger} as a long value.
   */
  @Override
  public long longValue() {
    long value = (numberLength > 1) ? (((long) digits[1]) << 32)
        | (digits[0] & 0xFFFFFFFFL) : (digits[0] & 0xFFFFFFFFL);
    return (sign * value);
  }

  /**
   * Converts value of this {@code BigInteger} to a {@code long} if it fits it,
   * otherwise {@code ArithmeticException} is thrown.
   *
   * @return this {@code BigInteger} converted to a {@code long}.
   * @throws ArithmeticException if the value of this {@code BigInteger}
   *         does not fit in a {@code long}.
   */
  public long longValueExact() {
    if (numberLength <= 2 && bitLength() < Long.SIZE) {
      return longValue();
    }
    throw new ArithmeticException("out of long range");
  }

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

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

  /**
   * Returns a new {@code BigInteger} whose value is {@code this mod m}. The
   * modulus {@code m} must be positive. The result is guaranteed to be in the
   * interval {@code [0, m)} (0 inclusive, m exclusive). The behavior of this
   * function is not equivalent to the behavior of the % operator defined for
   * the built-in {@code int}'s.
   *
   * @param m the modulus.
   * @return {@code this mod m}.
   * @throws NullPointerException if {@code m == null}.
   * @throws ArithmeticException if {@code m < 0}.
   */
  public BigInteger mod(BigInteger m) {
    if (m.sign <= 0) {
      // math.18=BigInteger: modulus not positive
      throw new ArithmeticException("BigInteger: modulus not positive"); //$NON-NLS-1$
    }
    BigInteger rem = remainder(m);
    return ((rem.sign < 0) ? rem.add(m) : rem);
  }

  // @Override
  // public double doubleValue() {
  // return Conversion.bigInteger2Double(this);
  // }

  /**
   * Returns a new {@code BigInteger} whose value is {@code 1/this mod m}. The
   * modulus {@code m} must be positive. The result is guaranteed to be in the
   * interval {@code [0, m)} (0 inclusive, m exclusive). If {@code this} is not
   * relatively prime to m, then an exception is thrown.
   *
   * @param m the modulus.
   * @return {@code 1/this mod m}.
   * @throws NullPointerException if {@code m == null}
   * @throws ArithmeticException if {@code m < 0 or} if {@code this} is not
   *           relatively prime to {@code m}
   */
  public BigInteger modInverse(BigInteger m) {
    if (m.sign <= 0) {
      // math.18=BigInteger: modulus not positive
      throw new ArithmeticException("BigInteger: modulus not positive"); //$NON-NLS-1$
    }
    // If both are even, no inverse exists
    if (!(testBit(0) || m.testBit(0))) {
      // math.19=BigInteger not invertible.
      throw new ArithmeticException("BigInteger not invertible."); //$NON-NLS-1$
    }
    if (m.isOne()) {
      return ZERO;
    }

    // From now on: (m > 1)
    BigInteger res = Division.modInverseMontgomery(abs().mod(m), m);
    if (res.sign == 0) {
      // math.19=BigInteger not invertible.
      throw new ArithmeticException("BigInteger not invertible."); //$NON-NLS-1$
    }

    res = ((sign < 0) ? m.subtract(res) : res);
    return res;
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this^exponent mod m}
   * . The modulus {@code m} must be positive. The result is guaranteed to be in
   * the interval {@code [0, m)} (0 inclusive, m exclusive). If the exponent is
   * negative, then {@code this.modInverse(m)^(-exponent) mod m)} is computed.
   * The inverse of this only exists if {@code this} is relatively prime to m,
   * otherwise an exception is thrown.
   *
   * @param exponent the exponent.
   * @param m the modulus.
   * @return {@code this^exponent mod val}.
   * @throws NullPointerException if {@code m == null} or {@code exponent ==
   *           null}.
   * @throws ArithmeticException if {@code m < 0} or if {@code exponent<0} and
   *           this is not relatively prime to {@code m}.
   */
  public BigInteger modPow(BigInteger exponent, BigInteger m) {
    if (m.sign <= 0) {
      // math.18=BigInteger: modulus not positive
      throw new ArithmeticException("BigInteger: modulus not positive"); //$NON-NLS-1$
    }
    BigInteger base = this;

    if (m.isOne() | (exponent.sign > 0 & base.sign == 0)) {
      return BigInteger.ZERO;
    }
    if (base.sign == 0 && exponent.sign == 0) {
      return BigInteger.ONE;
    }
    if (exponent.sign < 0) {
      base = modInverse(m);
      exponent = exponent.negate();
    }
    // From now on: (m > 0) and (exponent >= 0)
    BigInteger res = (m.testBit(0)) ? Division.oddModPow(base.abs(), exponent,
        m) : Division.evenModPow(base.abs(), exponent, m);
    if ((base.sign < 0) && exponent.testBit(0)) {
      // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m
      res = m.subtract(BigInteger.ONE).multiply(res).mod(m);
    }
    // else exponent is even, so base^exp is positive
    return res;
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this * val}.
   *
   * @param val value to be multiplied with {@code this}.
   * @return {@code this * val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger multiply(BigInteger val) {
    // This let us to throw NullPointerException when val == null
    if (val.sign == 0) {
      return ZERO;
    }
    if (sign == 0) {
      return ZERO;
    }
    return Multiplication.multiply(this, val);
  }

  /**
   * Returns a new {@code BigInteger} whose value is the {@code -this}.
   *
   * @return {@code -this}.
   */
  public BigInteger negate() {
    return ((sign == 0) ? this : new BigInteger(-sign, numberLength, digits));
  }

  /**
   * Returns the smallest integer x > {@code this} which is probably prime as a
   * {@code BigInteger} instance. The probability that the returned {@code
   * BigInteger} is prime is beyond (1-1/2^80).
   *
   * @return smallest integer > {@code this} which is robably prime.
   * @throws ArithmeticException if {@code this < 0}.
   */
  public BigInteger nextProbablePrime() {
    if (sign < 0) {
      // math.1A=start < 0: {0}
      throw new ArithmeticException("start < 0: " + this); //$NON-NLS-1$
    }
    return Primality.nextProbablePrime(this);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code ~this}. The result
   * of this operation is {@code -this-1}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @return {@code ~this}.
   */
  public BigInteger not() {
    return Logical.not(this);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this | val}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param val value to be or'ed with {@code this}.
   * @return {@code this | val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger or(BigInteger val) {
    return Logical.or(this, val);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this ^ exp}.
   *
   * @param exp exponent to which {@code this} is raised.
   * @return {@code this ^ exp}.
   * @throws ArithmeticException if {@code exp < 0}.
   */
  public BigInteger pow(int exp) {
    if (exp < 0) {
      // math.16=Negative exponent
      throw new ArithmeticException("Negative exponent"); //$NON-NLS-1$
    }
    if (exp == 0) {
      return ONE;
    } else if (exp == 1 || equals(ONE) || equals(ZERO)) {
      return this;
    }

    // if even take out 2^x factor which we can
    // calculate by shifting.
    if (!testBit(0)) {
      int x = 1;
      while (!testBit(x)) {
        x++;
      }
      return getPowerOfTwo(x * exp).multiply(this.shiftRight(x).pow(exp));
    }
    return Multiplication.pow(this, exp);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this % divisor}.
   * Regarding signs this methods has the same behavior as the % operator on
   * int's, i.e. the sign of the remainder is the same as the sign of this.
   *
   * @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 BigInteger remainder(BigInteger divisor) {
    if (divisor.sign == 0) {
      // math.17=BigInteger divide by zero
      throw new ArithmeticException("BigInteger divide by zero"); //$NON-NLS-1$
    }
    int thisLen = numberLength;
    int divisorLen = divisor.numberLength;
    if (((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1)
        : Elementary.compareArrays(digits, divisor.digits, thisLen)) == LESS) {
      return this;
    }
    int resLength = divisorLen;
    int resDigits[] = new int[resLength];
    if (resLength == 1) {
      resDigits[0] = Division.remainderArrayByInt(digits, thisLen,
          divisor.digits[0]);
    } else {
      int qLen = thisLen - divisorLen + 1;
      resDigits = Division.divide(null, qLen, digits, thisLen, divisor.digits,
          divisorLen);
    }
    BigInteger result = new BigInteger(sign, resLength, resDigits);
    result.cutOffLeadingZeroes();
    return result;
  }

  /**
   * Returns a new {@code BigInteger} which has the same binary representation
   * as {@code this} but with the bit at position n set. The result is
   * equivalent to {@code this | 2^n}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param n position where the bit in {@code this} has to be set.
   * @return {@code this | 2^n}.
   * @throws ArithmeticException if {@code n < 0}.
   */
  public BigInteger setBit(int n) {
    if (!testBit(n)) {
      return BitLevel.flipBit(this, n);
    }
    return this;
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this << n}. The
   * result is equivalent to {@code this * 2^n} if n >= 0. The shift distance
   * may be negative which means that {@code this} is shifted right. The result
   * then corresponds to {@code floor(this / 2^(-n))}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method on negative values is not
   * recommended as the current implementation is not efficient.
   *
   * @param n shift distance.
   * @return {@code this << n} if {@code n >= 0}; {@code this >> (-n)}.
   *         otherwise
   */
  public BigInteger shiftLeft(int n) {
    if ((n == 0) || (sign == 0)) {
      return this;
    }
    return ((n > 0) ? BitLevel.shiftLeft(this, n) : BitLevel.shiftRight(this,
        -n));
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this >> n}. For
   * negative arguments, the result is also negative. The shift distance may be
   * negative which means that {@code this} is shifted left.
   * <p>
   * <b>Implementation Note:</b> Usage of this method on negative values is not
   * recommended as the current implementation is not efficient.
   *
   * @param n shift distance
   * @return {@code this >> n} if {@code n >= 0}; {@code this << (-n)} otherwise
   */
  public BigInteger shiftRight(int n) {
    if ((n == 0) || (sign == 0)) {
      return this;
    }
    return ((n > 0) ? BitLevel.shiftRight(this, n) : BitLevel.shiftLeft(this,
        -n));
  }

  /**
   * Converts value of this {@code BigInteger} to a {@code short} if it fits it,
   * otherwise {@code ArithmeticException} is thrown.
   *
   * @return this {@code BigInteger} converted to a {@code short}.
   * @throws ArithmeticException if the value of this {@code BigInteger}
   *         does not fit in a {@code short}.
   */
  public short shortValueExact() {
    if (numberLength <= 1 && bitLength() < Short.SIZE) {
      return shortValue();
    }
    throw new ArithmeticException("out of short range");
  }

  /**
   * Returns the sign of this {@code BigInteger}.
   *
   * @return {@code -1} if {@code this < 0}, {@code 0} if {@code this == 0},
   *         {@code 1} if {@code this > 0}.
   */
  public int signum() {
    return sign;
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this - val}.
   *
   * @param val value to be subtracted from {@code this}.
   * @return {@code this - val}.
   * @throws NullPointerException if {@code val == null}.
   */
  public BigInteger subtract(BigInteger val) {
    return Elementary.subtract(this, val);
  }

  /**
   * Tests whether the bit at position n in {@code this} is set. The result is
   * equivalent to {@code this & (2^n) != 0}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param n position where the bit in {@code this} has to be inspected.
   * @return {@code this & (2^n) != 0}.
   * @throws ArithmeticException if {@code n < 0}.
   */
  public boolean testBit(int n) {
    if (n == 0) {
      return ((digits[0] & 1) != 0);
    }
    if (n < 0) {
      // math.15=Negative bit address
      throw new ArithmeticException("Negative bit address"); //$NON-NLS-1$
    }
    int intCount = n >> 5;
    if (intCount >= numberLength) {
      return (sign < 0);
    }
    int digit = digits[intCount];
    n = (1 << (n & 31)); // int with 1 set to the needed position
    if (sign < 0) {
      int firstNonZeroDigit = getFirstNonzeroDigit();
      if (intCount < firstNonZeroDigit) {
        return false;
      } else if (firstNonZeroDigit == intCount) {
        digit = -digit;
      } else {
        digit = ~digit;
      }
    }
    return ((digit & n) != 0);
  }

  /**
   * Returns the two's complement representation of this BigInteger in a byte
   * array.
   *
   * @return two's complement representation of {@code this}.
   */
  public byte[] toByteArray() {
    if (this.sign == 0) {
      return new byte[] {0};
    }
    BigInteger temp = this;
    int bitLen = bitLength();
    int iThis = getFirstNonzeroDigit();
    int bytesLen = (bitLen >> 3) + 1;
    /*
     * Puts the little-endian int array representing the magnitude of this
     * BigInteger into the big-endian byte array.
     */
    byte[] bytes = new byte[bytesLen];
    int firstByteNumber = 0;
    int highBytes;
    int digitIndex = 0;
    int bytesInInteger = 4;
    int digit;
    int hB;

    if (bytesLen - (numberLength << 2) == 1) {
      bytes[0] = (byte) ((sign < 0) ? -1 : 0);
      highBytes = 4;
      firstByteNumber++;
    } else {
      hB = bytesLen & 3;
      highBytes = (hB == 0) ? 4 : hB;
    }

    digitIndex = iThis;
    bytesLen -= iThis << 2;

    if (sign < 0) {
      digit = -temp.digits[digitIndex];
      digitIndex++;
      if (digitIndex == numberLength) {
        bytesInInteger = highBytes;
      }
      for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
        bytes[--bytesLen] = (byte) digit;
      }
      while (bytesLen > firstByteNumber) {
        digit = ~temp.digits[digitIndex];
        digitIndex++;
        if (digitIndex == numberLength) {
          bytesInInteger = highBytes;
        }
        for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
          bytes[--bytesLen] = (byte) digit;
        }
      }
    } else {
      while (bytesLen > firstByteNumber) {
        digit = temp.digits[digitIndex];
        digitIndex++;
        if (digitIndex == numberLength) {
          bytesInInteger = highBytes;
        }
        for (int i = 0; i < bytesInInteger; i++, digit >>= 8) {
          bytes[--bytesLen] = (byte) digit;
        }
      }
    }
    return bytes;
  }

  /**
   * Returns a string representation of this {@code BigInteger} in decimal form.
   *
   * @return a string representation of {@code this} in decimal form.
   */
  @Override
  public String toString() {
    return Conversion.toDecimalScaledString(this, 0);
  }

  /**
   * Returns a string containing a string representation of this {@code
   * BigInteger} with base radix. If {@code radix} is less than
   * {@link Character#MIN_RADIX} or greater than {@link Character#MAX_RADIX}
   * then a decimal representation is returned. The characters of the string
   * representation are generated with method {@link Character#forDigit}.
   *
   * @param radix base to be used for the string representation.
   * @return a string representation of this with radix 10.
   */
  public String toString(int radix) {
    return Conversion.bigInteger2String(this, radix);
  }

  /**
   * Returns a new {@code BigInteger} whose value is {@code this ^ val}.
   * <p>
   * <b>Implementation Note:</b> Usage of this method is not recommended as the
   * current implementation is not efficient.
   *
   * @param val value to be xor'ed with {@code this}
   * @return {@code this ^ val}
   * @throws NullPointerException if {@code val == null}
   */
  public BigInteger xor(BigInteger val) {
    return Logical.xor(this, val);
  }

  /*
   * Returns a copy of the current instance to achieve immutability
   */
  BigInteger copy() {
    int[] copyDigits = new int[numberLength];
    System.arraycopy(digits, 0, copyDigits, 0, numberLength);
    return new BigInteger(sign, numberLength, copyDigits);
  }

  /* Private Methods */

  /**
   * Decreases {@code numberLength} if there are zero high elements.
   */
  final void cutOffLeadingZeroes() {
    while ((numberLength > 0) && (digits[--numberLength] == 0)) {
      // Empty
    }
    if (digits[numberLength++] == 0) {
      sign = 0;
    }
  }

  boolean equalsArrays(final int[] b) {
    int i;
    for (i = numberLength - 1; (i >= 0) && (digits[i] == b[i]); i--) {
      // Empty
    }
    return i < 0;
  }

  int getFirstNonzeroDigit() {
    if (firstNonzeroDigit == -2) {
      int i;
      if (this.sign == 0) {
        i = -1;
      } else {
        for (i = 0; digits[i] == 0; i++) {
          // Empty
        }
      }
      firstNonzeroDigit = i;
    }
    return firstNonzeroDigit;
  }

  /**
   * Tests if {@code this.abs()} is equals to {@code ONE}.
   */
  boolean isOne() {
    return ((numberLength == 1) && (digits[0] == 1));
  }

  BigInteger shiftLeftOneBit() {
    return (sign == 0) ? this : BitLevel.shiftLeftOneBit(this);
  }

  void unCache() {
    firstNonzeroDigit = -2;
  }

  /**
   * Puts a big-endian byte array into a little-endian applying two complement.
   */
  private void putBytesNegativeToIntegers(byte[] byteValues) {
    int bytesLen = byteValues.length;
    int highBytes = bytesLen & 3;
    numberLength = (bytesLen >> 2) + ((highBytes == 0) ? 0 : 1);
    digits = new int[numberLength];
    int i = 0;
    // Setting the sign
    digits[numberLength - 1] = -1;
    // Put bytes to the int array starting from the end of the byte array
    while (bytesLen > highBytes) {
      digits[i] = (byteValues[--bytesLen] & 0xFF)
          | (byteValues[--bytesLen] & 0xFF) << 8
          | (byteValues[--bytesLen] & 0xFF) << 16
          | (byteValues[--bytesLen] & 0xFF) << 24;
      if (digits[i] != 0) {
        digits[i] = -digits[i];
        firstNonzeroDigit = i;
        i++;
        while (bytesLen > highBytes) {
          digits[i] = (byteValues[--bytesLen] & 0xFF)
              | (byteValues[--bytesLen] & 0xFF) << 8
              | (byteValues[--bytesLen] & 0xFF) << 16
              | (byteValues[--bytesLen] & 0xFF) << 24;
          digits[i] = ~digits[i];
          i++;
        }
        break;
      }
      i++;
    }
    if (highBytes != 0) {
      // Put the first bytes in the highest element of the int array
      if (firstNonzeroDigit != -2) {
        for (int j = 0; j < bytesLen; j++) {
          digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
        }
        digits[i] = ~digits[i];
      } else {
        for (int j = 0; j < bytesLen; j++) {
          digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
        }
        digits[i] = -digits[i];
      }
    }
  }

  /**
   * Puts a big-endian byte array into a little-endian int array.
   */
  private void putBytesPositiveToIntegers(byte[] byteValues) {
    int bytesLen = byteValues.length;
    int highBytes = bytesLen & 3;
    numberLength = (bytesLen >> 2) + ((highBytes == 0) ? 0 : 1);
    digits = new int[numberLength];
    int i = 0;
    // Put bytes to the int array starting from the end of the byte array
    while (bytesLen > highBytes) {
      digits[i++] = (byteValues[--bytesLen] & 0xFF)
          | (byteValues[--bytesLen] & 0xFF) << 8
          | (byteValues[--bytesLen] & 0xFF) << 16
          | (byteValues[--bytesLen] & 0xFF) << 24;
    }
    // Put the first bytes in the highest element of the int array
    for (int j = 0; j < bytesLen; j++) {
      digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
    }
  }
}
