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

import java.io.Serializable;
import java.util.Random;
import javaemul.internal.LongUtils;

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

  /**
   * 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) {
    return val >= 0 ? BigInteger.fromBits(val) : BigInteger.fromBits(-val).negate();
  }

  private static BigInteger fromBits(long bits) {
    int lowBits = (int) bits;
    int highBits = LongUtils.getHighBits(bits);
    if (highBits != 0) {
      return new BigInteger(1, lowBits, highBits);
    }
    if (lowBits > 10 || lowBits < 0) {
      return new BigInteger(1, lowBits);
    }
    return SMALL_VALUES[lowBits];
  }

  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);
  }

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

  /**
   * 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 bits) {
    this(sign, 1, new int[] {bits});
  }

  BigInteger(int sign, int lowBits, int highBits) {
    this(sign, 2, new int[] {lowBits, highBits});
  }

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

  /**
   * Returns a (new) {@code BigInteger} whose value is the absolute value of
   * {@code this}.
   *
   * @return {@code abs(this)}.
   */
  public BigInteger abs() {
    return sign < 0 ? negate() : 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 : ensureInt(-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
            ? LongUtils.fromBits(digits[0], digits[1])
            : LongUtils.fromBits(digits[0], 0);
    return sign > 0 ? value : -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 || 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);
    }
  }
}
