/*
 * 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) {
    this(val, 0, val.length);
  }

  /**
   * 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}.
   * @param offset the start offset of the binary representation.
   * @param length the number of bytes to use.
   * @throws NullPointerException if {@code val == null}.
   * @throws NumberFormatException if the length of {@code val} is zero.
   */
  public BigInteger(byte[] val, int offset, int length) {
    if (val.length == 0) {
      // math.12=Zero length BigInteger
      throw new NumberFormatException("Zero length BigInteger"); //$NON-NLS-1$
    }
    if (length < 0 || offset < 0 || length > val.length - offset) {
      throw new IndexOutOfBoundsException("Range check failed: offset=" + offset + ", length="
          + length + ", val.length=" + val.length);
    }
    if (length == 0) {
      sign = 0;
      numberLength = 1;
      digits = new int[] {0};
      return;
    }
    if (val[offset] < 0) {
      sign = -1;
      putBytesNegativeToIntegers(val, offset, length);
    } else {
      sign = 1;
      putBytesPositiveToIntegers(val, offset, length);
    }
    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) {
    this(signum, magnitude, 0, magnitude.length);
  }

  /**
   * 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.
   * @param offset the start offset of the binary representation.
   * @param length the number of bytes to use.
   * @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, int offset, int length) {
    checkNotNull(magnitude);

    if (length < 0 || offset < 0 || length > magnitude.length - offset) {
      throw new IndexOutOfBoundsException("Range check failed: offset=" + offset + ", length="
          + length + ", val.length=" + magnitude.length);
    }

    if ((signum < -1) || (signum > 1)) {
      // math.13=Invalid signum value
      throw new NumberFormatException("Invalid signum value"); //$NON-NLS-1$
    }
    if (signum == 0) {
      for (int index = offset; index < offset + length; index++) {
        byte element = magnitude[index];
        if (element != 0) {
          // math.14=signum-magnitude mismatch
          throw new NumberFormatException("signum-magnitude mismatch"); //$NON-NLS-1$
        }
      }
    }
    if (length == 0) {
      sign = 0;
      numberLength = 1;
      digits = new int[] {0};
    } else {
      sign = signum;
      putBytesPositiveToIntegers(magnitude, offset, length);
      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 offset, int length) {
    int bytesLen = 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 + offset] & 0xFF)
          | (byteValues[--bytesLen + offset] & 0xFF) << 8
          | (byteValues[--bytesLen + offset] & 0xFF) << 16
          | (byteValues[--bytesLen + offset] & 0xFF) << 24;
      if (digits[i] != 0) {
        digits[i] = -digits[i];
        firstNonzeroDigit = i;
        i++;
        while (bytesLen > highBytes) {
          digits[i] = (byteValues[--bytesLen + offset] & 0xFF)
              | (byteValues[--bytesLen + offset] & 0xFF) << 8
              | (byteValues[--bytesLen + offset] & 0xFF) << 16
              | (byteValues[--bytesLen + offset] & 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 = offset; j < bytesLen + offset; j++) {
          digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
        }
        digits[i] = ~digits[i];
      } else {
        for (int j = offset; j < bytesLen + offset; 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 offset, int length) {
    int bytesLen = 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 + offset] & 0xFF)
          | (byteValues[--bytesLen + offset] & 0xFF) << 8
          | (byteValues[--bytesLen + offset] & 0xFF) << 16
          | (byteValues[--bytesLen + offset] & 0xFF) << 24;
    }
    // Put the first bytes in the highest element of the int array
    for (int j = offset; j < bytesLen + offset; j++) {
      digits[i] = (digits[i] << 8) | (byteValues[j] & 0xFF);
    }
  }
}
