mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			2679 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			2679 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			Java
		
	
	
	
/* java.math.BigInteger -- Arbitary precision integers
 | 
						|
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2010
 | 
						|
   Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package java.math;
 | 
						|
 | 
						|
import gnu.classpath.Configuration;
 | 
						|
 | 
						|
import gnu.java.lang.CPStringBuilder;
 | 
						|
import gnu.java.math.GMP;
 | 
						|
import gnu.java.math.MPN;
 | 
						|
 | 
						|
import java.io.IOException;
 | 
						|
import java.io.ObjectInputStream;
 | 
						|
import java.io.ObjectOutputStream;
 | 
						|
import java.util.Random;
 | 
						|
import java.util.logging.Logger;
 | 
						|
 | 
						|
/**
 | 
						|
 * Written using on-line Java Platform 1.2 API Specification, as well
 | 
						|
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998) and
 | 
						|
 * "Applied Cryptography, Second Edition" by Bruce Schneier (Wiley, 1996).
 | 
						|
 *
 | 
						|
 * Based primarily on IntNum.java BitOps.java by Per Bothner (per@bothner.com)
 | 
						|
 * (found in Kawa 1.6.62).
 | 
						|
 *
 | 
						|
 * @author Warren Levy (warrenl@cygnus.com)
 | 
						|
 * @date December 20, 1999.
 | 
						|
 * @status believed complete and correct.
 | 
						|
 */
 | 
						|
public class BigInteger extends Number implements Comparable<BigInteger>
 | 
						|
{
 | 
						|
  private static final Logger log = Configuration.DEBUG ?
 | 
						|
                        Logger.getLogger(BigInteger.class.getName()) : null;
 | 
						|
 | 
						|
  /** All integers are stored in 2's-complement form.
 | 
						|
   * If words == null, the ival is the value of this BigInteger.
 | 
						|
   * Otherwise, the first ival elements of words make the value
 | 
						|
   * of this BigInteger, stored in little-endian order, 2's-complement form. */
 | 
						|
  private transient int ival;
 | 
						|
  private transient int[] words;
 | 
						|
 | 
						|
  // Serialization fields.
 | 
						|
  // the first three, although not used in the code, are present for
 | 
						|
  // compatibility with older RI versions of this class. DO NOT REMOVE.
 | 
						|
  private int bitCount = -1;
 | 
						|
  private int bitLength = -1;
 | 
						|
  private int lowestSetBit = -2;
 | 
						|
  private byte[] magnitude;
 | 
						|
  private int signum;
 | 
						|
  private static final long serialVersionUID = -8287574255936472291L;
 | 
						|
 | 
						|
 | 
						|
  /** We pre-allocate integers in the range minFixNum..maxFixNum.
 | 
						|
   * Note that we must at least preallocate 0, 1, and 10.  */
 | 
						|
  private static final int minFixNum = -100;
 | 
						|
  private static final int maxFixNum = 1024;
 | 
						|
  private static final int numFixNum = maxFixNum-minFixNum+1;
 | 
						|
  private static final BigInteger[] smallFixNums;
 | 
						|
 | 
						|
  /** The alter-ego GMP instance for this. */
 | 
						|
  private transient GMP mpz;
 | 
						|
 | 
						|
  private static final boolean USING_NATIVE = Configuration.WANT_NATIVE_BIG_INTEGER
 | 
						|
                                              && initializeLibrary();
 | 
						|
 | 
						|
  static
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        smallFixNums = null;
 | 
						|
        ZERO = valueOf(0L);
 | 
						|
        ONE = valueOf(1L);
 | 
						|
        TEN = valueOf(10L);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        smallFixNums = new BigInteger[numFixNum];
 | 
						|
        for (int i = numFixNum;  --i >= 0; )
 | 
						|
          smallFixNums[i] = new BigInteger(i + minFixNum);
 | 
						|
 | 
						|
        ZERO = smallFixNums[-minFixNum];
 | 
						|
        ONE = smallFixNums[1 - minFixNum];
 | 
						|
        TEN = smallFixNums[10 - minFixNum];
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * The constant zero as a BigInteger.
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  public static final BigInteger ZERO;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The constant one as a BigInteger.
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  public static final BigInteger ONE;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The constant ten as a BigInteger.
 | 
						|
   * @since 1.5
 | 
						|
   */
 | 
						|
  public static final BigInteger TEN;
 | 
						|
 | 
						|
  /* Rounding modes: */
 | 
						|
  private static final int FLOOR = 1;
 | 
						|
  private static final int CEILING = 2;
 | 
						|
  private static final int TRUNCATE = 3;
 | 
						|
  private static final int ROUND = 4;
 | 
						|
 | 
						|
  /** When checking the probability of primes, it is most efficient to
 | 
						|
   * first check the factoring of small primes, so we'll use this array.
 | 
						|
   */
 | 
						|
  private static final int[] primes =
 | 
						|
    {   2,   3,   5,   7,  11,  13,  17,  19,  23,  29,  31,  37,  41,  43,
 | 
						|
       47,  53,  59,  61,  67,  71,  73,  79,  83,  89,  97, 101, 103, 107,
 | 
						|
      109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
 | 
						|
      191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 };
 | 
						|
 | 
						|
  /** HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Table 4.4. */
 | 
						|
  private static final int[] k =
 | 
						|
      {100,150,200,250,300,350,400,500,600,800,1250, Integer.MAX_VALUE};
 | 
						|
  private static final int[] t =
 | 
						|
      { 27, 18, 15, 12,  9,  8,  7,  6,  5,  4,   3, 2};
 | 
						|
 | 
						|
  private BigInteger()
 | 
						|
  {
 | 
						|
    super();
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      mpz = new GMP();
 | 
						|
  }
 | 
						|
 | 
						|
  /* Create a new (non-shared) BigInteger, and initialize to an int. */
 | 
						|
  private BigInteger(int value)
 | 
						|
  {
 | 
						|
    super();
 | 
						|
 | 
						|
    ival = value;
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger(String s, int radix)
 | 
						|
  {
 | 
						|
    this();
 | 
						|
 | 
						|
    int len = s.length();
 | 
						|
    int i, digit;
 | 
						|
    boolean negative;
 | 
						|
    byte[] bytes;
 | 
						|
    char ch = s.charAt(0);
 | 
						|
    if (ch == '-')
 | 
						|
      {
 | 
						|
        negative = true;
 | 
						|
        i = 1;
 | 
						|
        bytes = new byte[len - 1];
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        negative = false;
 | 
						|
        i = 0;
 | 
						|
        bytes = new byte[len];
 | 
						|
      }
 | 
						|
    int byte_len = 0;
 | 
						|
    for ( ; i < len;  i++)
 | 
						|
      {
 | 
						|
        ch = s.charAt(i);
 | 
						|
        digit = Character.digit(ch, radix);
 | 
						|
        if (digit < 0)
 | 
						|
          throw new NumberFormatException("Invalid character at position #" + i);
 | 
						|
        bytes[byte_len++] = (byte) digit;
 | 
						|
      }
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        bytes = null;
 | 
						|
        if (mpz.fromString(s, radix) != 0)
 | 
						|
          throw new NumberFormatException("String \"" + s
 | 
						|
                                          + "\" is NOT a valid number in base "
 | 
						|
                                          + radix);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        BigInteger result;
 | 
						|
        // Testing (len < MPN.chars_per_word(radix)) would be more accurate,
 | 
						|
        // but slightly more expensive, for little practical gain.
 | 
						|
        if (len <= 15 && radix <= 16)
 | 
						|
          result = valueOf(Long.parseLong(s, radix));
 | 
						|
        else
 | 
						|
          result = valueOf(bytes, byte_len, negative, radix);
 | 
						|
 | 
						|
        this.ival = result.ival;
 | 
						|
        this.words = result.words;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger(String val)
 | 
						|
  {
 | 
						|
    this(val, 10);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Create a new (non-shared) BigInteger, and initialize from a byte array. */
 | 
						|
  public BigInteger(byte[] val)
 | 
						|
  {
 | 
						|
    this();
 | 
						|
 | 
						|
    if (val == null || val.length < 1)
 | 
						|
      throw new NumberFormatException();
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      mpz.fromByteArray(val);
 | 
						|
    else
 | 
						|
      {
 | 
						|
        words = byteArrayToIntArray(val, val[0] < 0 ? -1 : 0);
 | 
						|
        BigInteger result = make(words, words.length);
 | 
						|
        this.ival = result.ival;
 | 
						|
        this.words = result.words;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger(int signum, byte[] magnitude)
 | 
						|
  {
 | 
						|
    this();
 | 
						|
 | 
						|
    if (magnitude == null || signum > 1 || signum < -1)
 | 
						|
      throw new NumberFormatException();
 | 
						|
 | 
						|
    if (signum == 0)
 | 
						|
      {
 | 
						|
        int i;
 | 
						|
        for (i = magnitude.length - 1; i >= 0 && magnitude[i] == 0; --i)
 | 
						|
          ;
 | 
						|
        if (i >= 0)
 | 
						|
          throw new NumberFormatException();
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      mpz.fromSignedMagnitude(magnitude, signum == -1);
 | 
						|
    else
 | 
						|
      {
 | 
						|
        // Magnitude is always positive, so don't ever pass a sign of -1.
 | 
						|
        words = byteArrayToIntArray(magnitude, 0);
 | 
						|
        BigInteger result = make(words, words.length);
 | 
						|
        this.ival = result.ival;
 | 
						|
        this.words = result.words;
 | 
						|
 | 
						|
        if (signum < 0)
 | 
						|
          setNegative();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger(int numBits, Random rnd)
 | 
						|
  {
 | 
						|
    this();
 | 
						|
 | 
						|
    if (numBits < 0)
 | 
						|
      throw new IllegalArgumentException();
 | 
						|
 | 
						|
    init(numBits, rnd);
 | 
						|
  }
 | 
						|
 | 
						|
  private void init(int numBits, Random rnd)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int length = (numBits + 7) / 8;
 | 
						|
        byte[] magnitude = new byte[length];
 | 
						|
        rnd.nextBytes(magnitude);
 | 
						|
        int discardedBitCount = numBits % 8;
 | 
						|
        if (discardedBitCount != 0)
 | 
						|
          {
 | 
						|
            discardedBitCount = 8 - discardedBitCount;
 | 
						|
            magnitude[0] = (byte)((magnitude[0] & 0xFF) >>> discardedBitCount);
 | 
						|
          }
 | 
						|
        mpz.fromSignedMagnitude(magnitude, false);
 | 
						|
        magnitude = null;
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
    int highbits = numBits & 31;
 | 
						|
    // minimum number of bytes to store the above number of bits
 | 
						|
    int highBitByteCount = (highbits + 7) / 8;
 | 
						|
    // number of bits to discard from the last byte
 | 
						|
    int discardedBitCount = highbits % 8;
 | 
						|
    if (discardedBitCount != 0)
 | 
						|
      discardedBitCount = 8 - discardedBitCount;
 | 
						|
    byte[] highBitBytes = new byte[highBitByteCount];
 | 
						|
    if (highbits > 0)
 | 
						|
      {
 | 
						|
        rnd.nextBytes(highBitBytes);
 | 
						|
        highbits = (highBitBytes[highBitByteCount - 1] & 0xFF) >>> discardedBitCount;
 | 
						|
        for (int i = highBitByteCount - 2; i >= 0; i--)
 | 
						|
          highbits = (highbits << 8) | (highBitBytes[i] & 0xFF);
 | 
						|
      }
 | 
						|
    int nwords = numBits / 32;
 | 
						|
 | 
						|
    while (highbits == 0 && nwords > 0)
 | 
						|
      {
 | 
						|
        highbits = rnd.nextInt();
 | 
						|
        --nwords;
 | 
						|
      }
 | 
						|
    if (nwords == 0 && highbits >= 0)
 | 
						|
      {
 | 
						|
        ival = highbits;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        ival = highbits < 0 ? nwords + 2 : nwords + 1;
 | 
						|
        words = new int[ival];
 | 
						|
        words[nwords] = highbits;
 | 
						|
        while (--nwords >= 0)
 | 
						|
          words[nwords] = rnd.nextInt();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger(int bitLength, int certainty, Random rnd)
 | 
						|
  {
 | 
						|
    this();
 | 
						|
 | 
						|
    BigInteger result = new BigInteger();
 | 
						|
    while (true)
 | 
						|
      {
 | 
						|
        result.init(bitLength, rnd);
 | 
						|
        result = result.setBit(bitLength - 1);
 | 
						|
        if (result.isProbablePrime(certainty))
 | 
						|
          break;
 | 
						|
      }
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      mpz.fromBI(result.mpz);
 | 
						|
    else
 | 
						|
      {
 | 
						|
        this.ival = result.ival;
 | 
						|
        this.words = result.words;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   *  Return a BigInteger that is bitLength bits long with a
 | 
						|
   *  probability < 2^-100 of being composite.
 | 
						|
   *
 | 
						|
   *  @param bitLength length in bits of resulting number
 | 
						|
   *  @param rnd random number generator to use
 | 
						|
   *  @throws ArithmeticException if bitLength < 2
 | 
						|
   *  @since 1.4
 | 
						|
   */
 | 
						|
  public static BigInteger probablePrime(int bitLength, Random rnd)
 | 
						|
  {
 | 
						|
    if (bitLength < 2)
 | 
						|
      throw new ArithmeticException();
 | 
						|
 | 
						|
    return new BigInteger(bitLength, 100, rnd);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return a (possibly-shared) BigInteger with a given long value. */
 | 
						|
  public static BigInteger valueOf(long val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        result.mpz.fromLong(val);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (val >= minFixNum && val <= maxFixNum)
 | 
						|
      return smallFixNums[(int) val - minFixNum];
 | 
						|
    int i = (int) val;
 | 
						|
    if ((long) i == val)
 | 
						|
      return new BigInteger(i);
 | 
						|
    BigInteger result = alloc(2);
 | 
						|
    result.ival = 2;
 | 
						|
    result.words[0] = i;
 | 
						|
    result.words[1] = (int)(val >> 32);
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @return <code>true</code> if the GMP-based native implementation library
 | 
						|
   *         was successfully loaded. Returns <code>false</code> otherwise.
 | 
						|
   */
 | 
						|
  private static boolean initializeLibrary()
 | 
						|
  {
 | 
						|
    boolean result;
 | 
						|
    try
 | 
						|
    {
 | 
						|
      System.loadLibrary("javamath");
 | 
						|
      GMP.natInitializeLibrary();
 | 
						|
      result = true;
 | 
						|
    }
 | 
						|
    catch (Throwable x)
 | 
						|
    {
 | 
						|
      result = false;
 | 
						|
      if (Configuration.DEBUG)
 | 
						|
        {
 | 
						|
          log.info("Unable to use native BigInteger: " + x);
 | 
						|
          log.info("Will use a pure Java implementation instead");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Make a canonicalized BigInteger from an array of words.
 | 
						|
   * The array may be reused (without copying). */
 | 
						|
  private static BigInteger make(int[] words, int len)
 | 
						|
  {
 | 
						|
    if (words == null)
 | 
						|
      return valueOf(len);
 | 
						|
    len = BigInteger.wordsNeeded(words, len);
 | 
						|
    if (len <= 1)
 | 
						|
      return len == 0 ? ZERO : valueOf(words[0]);
 | 
						|
    BigInteger num = new BigInteger();
 | 
						|
    num.words = words;
 | 
						|
    num.ival = len;
 | 
						|
    return num;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Convert a big-endian byte array to a little-endian array of words. */
 | 
						|
  private static int[] byteArrayToIntArray(byte[] bytes, int sign)
 | 
						|
  {
 | 
						|
    // Determine number of words needed.
 | 
						|
    int[] words = new int[bytes.length/4 + 1];
 | 
						|
    int nwords = words.length;
 | 
						|
 | 
						|
    // Create a int out of modulo 4 high order bytes.
 | 
						|
    int bptr = 0;
 | 
						|
    int word = sign;
 | 
						|
    for (int i = bytes.length % 4; i > 0; --i, bptr++)
 | 
						|
      word = (word << 8) | (bytes[bptr] & 0xff);
 | 
						|
    words[--nwords] = word;
 | 
						|
 | 
						|
    // Elements remaining in byte[] are a multiple of 4.
 | 
						|
    while (nwords > 0)
 | 
						|
      words[--nwords] = bytes[bptr++] << 24 |
 | 
						|
                        (bytes[bptr++] & 0xff) << 16 |
 | 
						|
                        (bytes[bptr++] & 0xff) << 8 |
 | 
						|
                        (bytes[bptr++] & 0xff);
 | 
						|
    return words;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Allocate a new non-shared BigInteger.
 | 
						|
   * @param nwords number of words to allocate
 | 
						|
   */
 | 
						|
  private static BigInteger alloc(int nwords)
 | 
						|
  {
 | 
						|
    BigInteger result = new BigInteger();
 | 
						|
    if (nwords > 1)
 | 
						|
    result.words = new int[nwords];
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Change words.length to nwords.
 | 
						|
   * We allow words.length to be upto nwords+2 without reallocating.
 | 
						|
   */
 | 
						|
  private void realloc(int nwords)
 | 
						|
  {
 | 
						|
    if (nwords == 0)
 | 
						|
      {
 | 
						|
        if (words != null)
 | 
						|
          {
 | 
						|
            if (ival > 0)
 | 
						|
              ival = words[0];
 | 
						|
            words = null;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else if (words == null
 | 
						|
             || words.length < nwords
 | 
						|
             || words.length > nwords + 2)
 | 
						|
      {
 | 
						|
        int[] new_words = new int [nwords];
 | 
						|
        if (words == null)
 | 
						|
          {
 | 
						|
            new_words[0] = ival;
 | 
						|
            ival = 1;
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            if (nwords < ival)
 | 
						|
              ival = nwords;
 | 
						|
            System.arraycopy(words, 0, new_words, 0, ival);
 | 
						|
          }
 | 
						|
        words = new_words;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private boolean isNegative()
 | 
						|
  {
 | 
						|
    return (words == null ? ival : words[ival - 1]) < 0;
 | 
						|
  }
 | 
						|
 | 
						|
  public int signum()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.compare(ZERO.mpz);
 | 
						|
 | 
						|
    if (ival == 0 && words == null)
 | 
						|
      return 0;
 | 
						|
    int top = words == null ? ival : words[ival-1];
 | 
						|
    return top < 0 ? -1 : 1;
 | 
						|
  }
 | 
						|
 | 
						|
  private static int compareTo(BigInteger x, BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        return x.mpz.compare(y.mpz);
 | 
						|
      }
 | 
						|
 | 
						|
    if (x.words == null && y.words == null)
 | 
						|
      return x.ival < y.ival ? -1 : x.ival > y.ival ? 1 : 0;
 | 
						|
    boolean x_negative = x.isNegative();
 | 
						|
    boolean y_negative = y.isNegative();
 | 
						|
    if (x_negative != y_negative)
 | 
						|
      return x_negative ? -1 : 1;
 | 
						|
    int x_len = x.words == null ? 1 : x.ival;
 | 
						|
    int y_len = y.words == null ? 1 : y.ival;
 | 
						|
    if (x_len != y_len)
 | 
						|
      return (x_len > y_len) != x_negative ? 1 : -1;
 | 
						|
    return MPN.cmp(x.words, y.words, x_len);
 | 
						|
  }
 | 
						|
 | 
						|
  /** @since 1.2 */
 | 
						|
  public int compareTo(BigInteger val)
 | 
						|
  {
 | 
						|
    return compareTo(this, val);
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger min(BigInteger val)
 | 
						|
  {
 | 
						|
    return compareTo(this, val) < 0 ? this : val;
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger max(BigInteger val)
 | 
						|
  {
 | 
						|
    return compareTo(this, val) > 0 ? this : val;
 | 
						|
  }
 | 
						|
 | 
						|
  private boolean isZero()
 | 
						|
  {
 | 
						|
    return words == null && ival == 0;
 | 
						|
  }
 | 
						|
 | 
						|
  private boolean isOne()
 | 
						|
  {
 | 
						|
    return words == null && ival == 1;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Calculate how many words are significant in words[0:len-1].
 | 
						|
   * Returns the least value x such that x>0 && words[0:x-1]==words[0:len-1],
 | 
						|
   * when words is viewed as a 2's complement integer.
 | 
						|
   */
 | 
						|
  private static int wordsNeeded(int[] words, int len)
 | 
						|
  {
 | 
						|
    int i = len;
 | 
						|
    if (i > 0)
 | 
						|
      {
 | 
						|
        int word = words[--i];
 | 
						|
        if (word == -1)
 | 
						|
          {
 | 
						|
            while (i > 0 && (word = words[i - 1]) < 0)
 | 
						|
              {
 | 
						|
                i--;
 | 
						|
                if (word != -1) break;
 | 
						|
              }
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            while (word == 0 && i > 0 && (word = words[i - 1]) >= 0)  i--;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return i + 1;
 | 
						|
  }
 | 
						|
 | 
						|
  private BigInteger canonicalize()
 | 
						|
  {
 | 
						|
    if (words != null
 | 
						|
        && (ival = BigInteger.wordsNeeded(words, ival)) <= 1)
 | 
						|
      {
 | 
						|
        if (ival == 1)
 | 
						|
          ival = words[0];
 | 
						|
        words = null;
 | 
						|
      }
 | 
						|
    if (words == null && ival >= minFixNum && ival <= maxFixNum)
 | 
						|
      return smallFixNums[ival - minFixNum];
 | 
						|
    return this;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Add two ints, yielding a BigInteger. */
 | 
						|
  private static BigInteger add(int x, int y)
 | 
						|
  {
 | 
						|
    return valueOf((long) x + (long) y);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Add a BigInteger and an int, yielding a new BigInteger. */
 | 
						|
  private static BigInteger add(BigInteger x, int y)
 | 
						|
  {
 | 
						|
    if (x.words == null)
 | 
						|
      return BigInteger.add(x.ival, y);
 | 
						|
    BigInteger result = new BigInteger(0);
 | 
						|
    result.setAdd(x, y);
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  /** Set this to the sum of x and y.
 | 
						|
   * OK if x==this. */
 | 
						|
  private void setAdd(BigInteger x, int y)
 | 
						|
  {
 | 
						|
    if (x.words == null)
 | 
						|
      {
 | 
						|
        set((long) x.ival + (long) y);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    int len = x.ival;
 | 
						|
    realloc(len + 1);
 | 
						|
    long carry = y;
 | 
						|
    for (int i = 0;  i < len;  i++)
 | 
						|
      {
 | 
						|
        carry += ((long) x.words[i] & 0xffffffffL);
 | 
						|
        words[i] = (int) carry;
 | 
						|
        carry >>= 32;
 | 
						|
      }
 | 
						|
    if (x.words[len - 1] < 0)
 | 
						|
      carry--;
 | 
						|
    words[len] = (int) carry;
 | 
						|
    ival = wordsNeeded(words, len + 1);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Destructively add an int to this. */
 | 
						|
  private void setAdd(int y)
 | 
						|
  {
 | 
						|
    setAdd(this, y);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Destructively set the value of this to a long. */
 | 
						|
  private void set(long y)
 | 
						|
  {
 | 
						|
    int i = (int) y;
 | 
						|
    if ((long) i == y)
 | 
						|
      {
 | 
						|
        ival = i;
 | 
						|
        words = null;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        realloc(2);
 | 
						|
        words[0] = i;
 | 
						|
        words[1] = (int) (y >> 32);
 | 
						|
        ival = 2;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /** Destructively set the value of this to the given words.
 | 
						|
  * The words array is reused, not copied. */
 | 
						|
  private void set(int[] words, int length)
 | 
						|
  {
 | 
						|
    this.ival = length;
 | 
						|
    this.words = words;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Destructively set the value of this to that of y. */
 | 
						|
  private void set(BigInteger y)
 | 
						|
  {
 | 
						|
    if (y.words == null)
 | 
						|
      set(y.ival);
 | 
						|
    else if (this != y)
 | 
						|
      {
 | 
						|
        realloc(y.ival);
 | 
						|
        System.arraycopy(y.words, 0, words, 0, y.ival);
 | 
						|
        ival = y.ival;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /** Add two BigIntegers, yielding their sum as another BigInteger. */
 | 
						|
  private static BigInteger add(BigInteger x, BigInteger y, int k)
 | 
						|
  {
 | 
						|
    if (x.words == null && y.words == null)
 | 
						|
      return valueOf((long) k * (long) y.ival + (long) x.ival);
 | 
						|
    if (k != 1)
 | 
						|
      {
 | 
						|
        if (k == -1)
 | 
						|
          y = BigInteger.neg(y);
 | 
						|
        else
 | 
						|
          y = BigInteger.times(y, valueOf(k));
 | 
						|
      }
 | 
						|
    if (x.words == null)
 | 
						|
      return BigInteger.add(y, x.ival);
 | 
						|
    if (y.words == null)
 | 
						|
      return BigInteger.add(x, y.ival);
 | 
						|
    // Both are big
 | 
						|
    if (y.ival > x.ival)
 | 
						|
      { // Swap so x is longer then y.
 | 
						|
        BigInteger tmp = x;  x = y;  y = tmp;
 | 
						|
      }
 | 
						|
    BigInteger result = alloc(x.ival + 1);
 | 
						|
    int i = y.ival;
 | 
						|
    long carry = MPN.add_n(result.words, x.words, y.words, i);
 | 
						|
    long y_ext = y.words[i - 1] < 0 ? 0xffffffffL : 0;
 | 
						|
    for (; i < x.ival;  i++)
 | 
						|
      {
 | 
						|
        carry += ((long) x.words[i] & 0xffffffffL) + y_ext;
 | 
						|
        result.words[i] = (int) carry;
 | 
						|
        carry >>>= 32;
 | 
						|
      }
 | 
						|
    if (x.words[i - 1] < 0)
 | 
						|
      y_ext--;
 | 
						|
    result.words[i] = (int) (carry + y_ext);
 | 
						|
    result.ival = i+1;
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger add(BigInteger val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = val.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.add(val.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return add(this, val, 1);
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger subtract(BigInteger val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = val.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.subtract(val.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return add(this, val, -1);
 | 
						|
  }
 | 
						|
 | 
						|
  private static BigInteger times(BigInteger x, int y)
 | 
						|
  {
 | 
						|
    if (y == 0)
 | 
						|
      return ZERO;
 | 
						|
    if (y == 1)
 | 
						|
      return x;
 | 
						|
    int[] xwords = x.words;
 | 
						|
    int xlen = x.ival;
 | 
						|
    if (xwords == null)
 | 
						|
      return valueOf((long) xlen * (long) y);
 | 
						|
    boolean negative;
 | 
						|
    BigInteger result = BigInteger.alloc(xlen + 1);
 | 
						|
    if (xwords[xlen - 1] < 0)
 | 
						|
      {
 | 
						|
        negative = true;
 | 
						|
        negate(result.words, xwords, xlen);
 | 
						|
        xwords = result.words;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      negative = false;
 | 
						|
    if (y < 0)
 | 
						|
      {
 | 
						|
        negative = !negative;
 | 
						|
        y = -y;
 | 
						|
      }
 | 
						|
    result.words[xlen] = MPN.mul_1(result.words, xwords, xlen, y);
 | 
						|
    result.ival = xlen + 1;
 | 
						|
    if (negative)
 | 
						|
      result.setNegative();
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  private static BigInteger times(BigInteger x, BigInteger y)
 | 
						|
  {
 | 
						|
    if (y.words == null)
 | 
						|
      return times(x, y.ival);
 | 
						|
    if (x.words == null)
 | 
						|
      return times(y, x.ival);
 | 
						|
    boolean negative = false;
 | 
						|
    int[] xwords;
 | 
						|
    int[] ywords;
 | 
						|
    int xlen = x.ival;
 | 
						|
    int ylen = y.ival;
 | 
						|
    if (x.isNegative())
 | 
						|
      {
 | 
						|
        negative = true;
 | 
						|
        xwords = new int[xlen];
 | 
						|
        negate(xwords, x.words, xlen);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        negative = false;
 | 
						|
        xwords = x.words;
 | 
						|
      }
 | 
						|
    if (y.isNegative())
 | 
						|
      {
 | 
						|
        negative = !negative;
 | 
						|
        ywords = new int[ylen];
 | 
						|
        negate(ywords, y.words, ylen);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      ywords = y.words;
 | 
						|
    // Swap if x is shorter then y.
 | 
						|
    if (xlen < ylen)
 | 
						|
      {
 | 
						|
        int[] twords = xwords;  xwords = ywords;  ywords = twords;
 | 
						|
        int tlen = xlen;  xlen = ylen;  ylen = tlen;
 | 
						|
      }
 | 
						|
    BigInteger result = BigInteger.alloc(xlen+ylen);
 | 
						|
    MPN.mul(result.words, xwords, xlen, ywords, ylen);
 | 
						|
    result.ival = xlen+ylen;
 | 
						|
    if (negative)
 | 
						|
      result.setNegative();
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger multiply(BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.multiply(y.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return times(this, y);
 | 
						|
  }
 | 
						|
 | 
						|
  private static void divide(long x, long y,
 | 
						|
                             BigInteger quotient, BigInteger remainder,
 | 
						|
                             int rounding_mode)
 | 
						|
  {
 | 
						|
    boolean xNegative, yNegative;
 | 
						|
    if (x < 0)
 | 
						|
      {
 | 
						|
        xNegative = true;
 | 
						|
        if (x == Long.MIN_VALUE)
 | 
						|
          {
 | 
						|
            divide(valueOf(x), valueOf(y),
 | 
						|
                   quotient, remainder, rounding_mode);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
        x = -x;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      xNegative = false;
 | 
						|
 | 
						|
    if (y < 0)
 | 
						|
      {
 | 
						|
        yNegative = true;
 | 
						|
        if (y == Long.MIN_VALUE)
 | 
						|
          {
 | 
						|
            if (rounding_mode == TRUNCATE)
 | 
						|
              { // x != Long.Min_VALUE implies abs(x) < abs(y)
 | 
						|
                if (quotient != null)
 | 
						|
                  quotient.set(0);
 | 
						|
                if (remainder != null)
 | 
						|
                  remainder.set(x);
 | 
						|
              }
 | 
						|
            else
 | 
						|
              divide(valueOf(x), valueOf(y),
 | 
						|
                      quotient, remainder, rounding_mode);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
        y = -y;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      yNegative = false;
 | 
						|
 | 
						|
    long q = x / y;
 | 
						|
    long r = x % y;
 | 
						|
    boolean qNegative = xNegative ^ yNegative;
 | 
						|
 | 
						|
    boolean add_one = false;
 | 
						|
    if (r != 0)
 | 
						|
      {
 | 
						|
        switch (rounding_mode)
 | 
						|
          {
 | 
						|
          case TRUNCATE:
 | 
						|
            break;
 | 
						|
          case CEILING:
 | 
						|
          case FLOOR:
 | 
						|
            if (qNegative == (rounding_mode == FLOOR))
 | 
						|
              add_one = true;
 | 
						|
            break;
 | 
						|
          case ROUND:
 | 
						|
            add_one = r > ((y - (q & 1)) >> 1);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    if (quotient != null)
 | 
						|
      {
 | 
						|
        if (add_one)
 | 
						|
          q++;
 | 
						|
        if (qNegative)
 | 
						|
          q = -q;
 | 
						|
        quotient.set(q);
 | 
						|
      }
 | 
						|
    if (remainder != null)
 | 
						|
      {
 | 
						|
        // The remainder is by definition: X-Q*Y
 | 
						|
        if (add_one)
 | 
						|
          {
 | 
						|
            // Subtract the remainder from Y.
 | 
						|
            r = y - r;
 | 
						|
            // In this case, abs(Q*Y) > abs(X).
 | 
						|
            // So sign(remainder) = -sign(X).
 | 
						|
            xNegative = ! xNegative;
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            // If !add_one, then: abs(Q*Y) <= abs(X).
 | 
						|
            // So sign(remainder) = sign(X).
 | 
						|
          }
 | 
						|
        if (xNegative)
 | 
						|
          r = -r;
 | 
						|
        remainder.set(r);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /** Divide two integers, yielding quotient and remainder.
 | 
						|
   * @param x the numerator in the division
 | 
						|
   * @param y the denominator in the division
 | 
						|
   * @param quotient is set to the quotient of the result (iff quotient!=null)
 | 
						|
   * @param remainder is set to the remainder of the result
 | 
						|
   *  (iff remainder!=null)
 | 
						|
   * @param rounding_mode one of FLOOR, CEILING, TRUNCATE, or ROUND.
 | 
						|
   */
 | 
						|
  private static void divide(BigInteger x, BigInteger y,
 | 
						|
                             BigInteger quotient, BigInteger remainder,
 | 
						|
                             int rounding_mode)
 | 
						|
  {
 | 
						|
    if ((x.words == null || x.ival <= 2)
 | 
						|
        && (y.words == null || y.ival <= 2))
 | 
						|
      {
 | 
						|
        long x_l = x.longValue();
 | 
						|
        long y_l = y.longValue();
 | 
						|
        if (x_l != Long.MIN_VALUE && y_l != Long.MIN_VALUE)
 | 
						|
          {
 | 
						|
            divide(x_l, y_l, quotient, remainder, rounding_mode);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
      }
 | 
						|
 | 
						|
    boolean xNegative = x.isNegative();
 | 
						|
    boolean yNegative = y.isNegative();
 | 
						|
    boolean qNegative = xNegative ^ yNegative;
 | 
						|
 | 
						|
    int ylen = y.words == null ? 1 : y.ival;
 | 
						|
    int[] ywords = new int[ylen];
 | 
						|
    y.getAbsolute(ywords);
 | 
						|
    while (ylen > 1 && ywords[ylen - 1] == 0)  ylen--;
 | 
						|
 | 
						|
    int xlen = x.words == null ? 1 : x.ival;
 | 
						|
    int[] xwords = new int[xlen+2];
 | 
						|
    x.getAbsolute(xwords);
 | 
						|
    while (xlen > 1 && xwords[xlen-1] == 0)  xlen--;
 | 
						|
 | 
						|
    int qlen, rlen;
 | 
						|
 | 
						|
    int cmpval = MPN.cmp(xwords, xlen, ywords, ylen);
 | 
						|
    if (cmpval < 0)  // abs(x) < abs(y)
 | 
						|
      { // quotient = 0;  remainder = num.
 | 
						|
        int[] rwords = xwords;  xwords = ywords;  ywords = rwords;
 | 
						|
        rlen = xlen;  qlen = 1;  xwords[0] = 0;
 | 
						|
      }
 | 
						|
    else if (cmpval == 0)  // abs(x) == abs(y)
 | 
						|
      {
 | 
						|
        xwords[0] = 1;  qlen = 1;  // quotient = 1
 | 
						|
        ywords[0] = 0;  rlen = 1;  // remainder = 0;
 | 
						|
      }
 | 
						|
    else if (ylen == 1)
 | 
						|
      {
 | 
						|
        qlen = xlen;
 | 
						|
        // Need to leave room for a word of leading zeros if dividing by 1
 | 
						|
        // and the dividend has the high bit set.  It might be safe to
 | 
						|
        // increment qlen in all cases, but it certainly is only necessary
 | 
						|
        // in the following case.
 | 
						|
        if (ywords[0] == 1 && xwords[xlen-1] < 0)
 | 
						|
          qlen++;
 | 
						|
        rlen = 1;
 | 
						|
        ywords[0] = MPN.divmod_1(xwords, xwords, xlen, ywords[0]);
 | 
						|
      }
 | 
						|
    else  // abs(x) > abs(y)
 | 
						|
      {
 | 
						|
        // Normalize the denominator, i.e. make its most significant bit set by
 | 
						|
        // shifting it normalization_steps bits to the left.  Also shift the
 | 
						|
        // numerator the same number of steps (to keep the quotient the same!).
 | 
						|
 | 
						|
        int nshift = MPN.count_leading_zeros(ywords[ylen - 1]);
 | 
						|
        if (nshift != 0)
 | 
						|
          {
 | 
						|
            // Shift up the denominator setting the most significant bit of
 | 
						|
            // the most significant word.
 | 
						|
            MPN.lshift(ywords, 0, ywords, ylen, nshift);
 | 
						|
 | 
						|
            // Shift up the numerator, possibly introducing a new most
 | 
						|
            // significant word.
 | 
						|
            int x_high = MPN.lshift(xwords, 0, xwords, xlen, nshift);
 | 
						|
            xwords[xlen++] = x_high;
 | 
						|
          }
 | 
						|
 | 
						|
        if (xlen == ylen)
 | 
						|
          xwords[xlen++] = 0;
 | 
						|
        MPN.divide(xwords, xlen, ywords, ylen);
 | 
						|
        rlen = ylen;
 | 
						|
        MPN.rshift0 (ywords, xwords, 0, rlen, nshift);
 | 
						|
 | 
						|
        qlen = xlen + 1 - ylen;
 | 
						|
        if (quotient != null)
 | 
						|
          {
 | 
						|
            for (int i = 0;  i < qlen;  i++)
 | 
						|
              xwords[i] = xwords[i+ylen];
 | 
						|
          }
 | 
						|
      }
 | 
						|
 | 
						|
    if (ywords[rlen-1] < 0)
 | 
						|
      {
 | 
						|
        ywords[rlen] = 0;
 | 
						|
        rlen++;
 | 
						|
      }
 | 
						|
 | 
						|
    // Now the quotient is in xwords, and the remainder is in ywords.
 | 
						|
 | 
						|
    boolean add_one = false;
 | 
						|
    if (rlen > 1 || ywords[0] != 0)
 | 
						|
      { // Non-zero remainder i.e. in-exact quotient.
 | 
						|
        switch (rounding_mode)
 | 
						|
          {
 | 
						|
          case TRUNCATE:
 | 
						|
            break;
 | 
						|
          case CEILING:
 | 
						|
          case FLOOR:
 | 
						|
            if (qNegative == (rounding_mode == FLOOR))
 | 
						|
              add_one = true;
 | 
						|
            break;
 | 
						|
          case ROUND:
 | 
						|
            // int cmp = compareTo(remainder<<1, abs(y));
 | 
						|
            BigInteger tmp = remainder == null ? new BigInteger() : remainder;
 | 
						|
            tmp.set(ywords, rlen);
 | 
						|
            tmp = shift(tmp, 1);
 | 
						|
            if (yNegative)
 | 
						|
              tmp.setNegative();
 | 
						|
            int cmp = compareTo(tmp, y);
 | 
						|
            // Now cmp == compareTo(sign(y)*(remainder<<1), y)
 | 
						|
            if (yNegative)
 | 
						|
              cmp = -cmp;
 | 
						|
            add_one = (cmp == 1) || (cmp == 0 && (xwords[0]&1) != 0);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    if (quotient != null)
 | 
						|
      {
 | 
						|
        quotient.set(xwords, qlen);
 | 
						|
        if (qNegative)
 | 
						|
          {
 | 
						|
            if (add_one)  // -(quotient + 1) == ~(quotient)
 | 
						|
              quotient.setInvert();
 | 
						|
            else
 | 
						|
              quotient.setNegative();
 | 
						|
          }
 | 
						|
        else if (add_one)
 | 
						|
          quotient.setAdd(1);
 | 
						|
      }
 | 
						|
    if (remainder != null)
 | 
						|
      {
 | 
						|
        // The remainder is by definition: X-Q*Y
 | 
						|
        remainder.set(ywords, rlen);
 | 
						|
        if (add_one)
 | 
						|
          {
 | 
						|
            // Subtract the remainder from Y:
 | 
						|
            // abs(R) = abs(Y) - abs(orig_rem) = -(abs(orig_rem) - abs(Y)).
 | 
						|
            BigInteger tmp;
 | 
						|
            if (y.words == null)
 | 
						|
              {
 | 
						|
                tmp = remainder;
 | 
						|
                tmp.set(yNegative ? ywords[0] + y.ival : ywords[0] - y.ival);
 | 
						|
              }
 | 
						|
            else
 | 
						|
              tmp = BigInteger.add(remainder, y, yNegative ? 1 : -1);
 | 
						|
            // Now tmp <= 0.
 | 
						|
            // In this case, abs(Q) = 1 + floor(abs(X)/abs(Y)).
 | 
						|
            // Hence, abs(Q*Y) > abs(X).
 | 
						|
            // So sign(remainder) = -sign(X).
 | 
						|
            if (xNegative)
 | 
						|
              remainder.setNegative(tmp);
 | 
						|
            else
 | 
						|
              remainder.set(tmp);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            // If !add_one, then: abs(Q*Y) <= abs(X).
 | 
						|
            // So sign(remainder) = sign(X).
 | 
						|
            if (xNegative)
 | 
						|
              remainder.setNegative();
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger divide(BigInteger val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        if (val.compareTo(ZERO) == 0)
 | 
						|
          throw new ArithmeticException("divisor is zero");
 | 
						|
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.quotient(val.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (val.isZero())
 | 
						|
      throw new ArithmeticException("divisor is zero");
 | 
						|
 | 
						|
    BigInteger quot = new BigInteger();
 | 
						|
    divide(this, val, quot, null, TRUNCATE);
 | 
						|
    return quot.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger remainder(BigInteger val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        if (val.compareTo(ZERO) == 0)
 | 
						|
          throw new ArithmeticException("divisor is zero");
 | 
						|
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.remainder(val.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (val.isZero())
 | 
						|
      throw new ArithmeticException("divisor is zero");
 | 
						|
 | 
						|
    BigInteger rem = new BigInteger();
 | 
						|
    divide(this, val, null, rem, TRUNCATE);
 | 
						|
    return rem.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger[] divideAndRemainder(BigInteger val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        if (val.compareTo(ZERO) == 0)
 | 
						|
          throw new ArithmeticException("divisor is zero");
 | 
						|
 | 
						|
        BigInteger q = new BigInteger();
 | 
						|
        BigInteger r = new BigInteger();
 | 
						|
        mpz.quotientAndRemainder(val.mpz, q.mpz, r.mpz);
 | 
						|
        return new BigInteger[] { q, r };
 | 
						|
      }
 | 
						|
 | 
						|
    if (val.isZero())
 | 
						|
      throw new ArithmeticException("divisor is zero");
 | 
						|
 | 
						|
    BigInteger[] result = new BigInteger[2];
 | 
						|
    result[0] = new BigInteger();
 | 
						|
    result[1] = new BigInteger();
 | 
						|
    divide(this, val, result[0], result[1], TRUNCATE);
 | 
						|
    result[0].canonicalize();
 | 
						|
    result[1].canonicalize();
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger mod(BigInteger m)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = m.signum; // force NPE check
 | 
						|
        if (m.compareTo(ZERO) < 1)
 | 
						|
          throw new ArithmeticException("non-positive modulus");
 | 
						|
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.modulo(m.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (m.isNegative() || m.isZero())
 | 
						|
      throw new ArithmeticException("non-positive modulus");
 | 
						|
 | 
						|
    BigInteger rem = new BigInteger();
 | 
						|
    divide(this, m, null, rem, FLOOR);
 | 
						|
    return rem.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  /** Calculate the integral power of a BigInteger.
 | 
						|
   * @param exponent the exponent (must be non-negative)
 | 
						|
   */
 | 
						|
  public BigInteger pow(int exponent)
 | 
						|
  {
 | 
						|
    if (exponent <= 0)
 | 
						|
      {
 | 
						|
        if (exponent == 0)
 | 
						|
          return ONE;
 | 
						|
          throw new ArithmeticException("negative exponent");
 | 
						|
      }
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.pow(exponent, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (isZero())
 | 
						|
      return this;
 | 
						|
    int plen = words == null ? 1 : ival;  // Length of pow2.
 | 
						|
    int blen = ((bitLength() * exponent) >> 5) + 2 * plen;
 | 
						|
    boolean negative = isNegative() && (exponent & 1) != 0;
 | 
						|
    int[] pow2 = new int [blen];
 | 
						|
    int[] rwords = new int [blen];
 | 
						|
    int[] work = new int [blen];
 | 
						|
    getAbsolute(pow2);  // pow2 = abs(this);
 | 
						|
    int rlen = 1;
 | 
						|
    rwords[0] = 1; // rwords = 1;
 | 
						|
    for (;;)  // for (i = 0;  ; i++)
 | 
						|
      {
 | 
						|
        // pow2 == this**(2**i)
 | 
						|
        // prod = this**(sum(j=0..i-1, (exponent>>j)&1))
 | 
						|
        if ((exponent & 1) != 0)
 | 
						|
          { // r *= pow2
 | 
						|
            MPN.mul(work, pow2, plen, rwords, rlen);
 | 
						|
            int[] temp = work;  work = rwords;  rwords = temp;
 | 
						|
            rlen += plen;
 | 
						|
            while (rwords[rlen - 1] == 0)  rlen--;
 | 
						|
          }
 | 
						|
        exponent >>= 1;
 | 
						|
        if (exponent == 0)
 | 
						|
          break;
 | 
						|
        // pow2 *= pow2;
 | 
						|
        MPN.mul(work, pow2, plen, pow2, plen);
 | 
						|
        int[] temp = work;  work = pow2;  pow2 = temp;  // swap to avoid a copy
 | 
						|
        plen *= 2;
 | 
						|
        while (pow2[plen - 1] == 0)  plen--;
 | 
						|
      }
 | 
						|
    if (rwords[rlen - 1] < 0)
 | 
						|
      rlen++;
 | 
						|
    if (negative)
 | 
						|
      negate(rwords, rwords, rlen);
 | 
						|
    return BigInteger.make(rwords, rlen);
 | 
						|
  }
 | 
						|
 | 
						|
  private static int[] euclidInv(int a, int b, int prevDiv)
 | 
						|
  {
 | 
						|
    if (b == 0)
 | 
						|
      throw new ArithmeticException("not invertible");
 | 
						|
 | 
						|
    if (b == 1)
 | 
						|
        // Success:  values are indeed invertible!
 | 
						|
        // Bottom of the recursion reached; start unwinding.
 | 
						|
        return new int[] { -prevDiv, 1 };
 | 
						|
 | 
						|
    int[] xy = euclidInv(b, a % b, a / b);      // Recursion happens here.
 | 
						|
    a = xy[0]; // use our local copy of 'a' as a work var
 | 
						|
    xy[0] = a * -prevDiv + xy[1];
 | 
						|
    xy[1] = a;
 | 
						|
    return xy;
 | 
						|
  }
 | 
						|
 | 
						|
  private static void euclidInv(BigInteger a, BigInteger b,
 | 
						|
                                BigInteger prevDiv, BigInteger[] xy)
 | 
						|
  {
 | 
						|
    if (b.isZero())
 | 
						|
      throw new ArithmeticException("not invertible");
 | 
						|
 | 
						|
    if (b.isOne())
 | 
						|
      {
 | 
						|
        // Success:  values are indeed invertible!
 | 
						|
        // Bottom of the recursion reached; start unwinding.
 | 
						|
        xy[0] = neg(prevDiv);
 | 
						|
        xy[1] = ONE;
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
    // Recursion happens in the following conditional!
 | 
						|
 | 
						|
    // If a just contains an int, then use integer math for the rest.
 | 
						|
    if (a.words == null)
 | 
						|
      {
 | 
						|
        int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival);
 | 
						|
        xy[0] = new BigInteger(xyInt[0]);
 | 
						|
        xy[1] = new BigInteger(xyInt[1]);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        BigInteger rem = new BigInteger();
 | 
						|
        BigInteger quot = new BigInteger();
 | 
						|
        divide(a, b, quot, rem, FLOOR);
 | 
						|
        // quot and rem may not be in canonical form. ensure
 | 
						|
        rem.canonicalize();
 | 
						|
        quot.canonicalize();
 | 
						|
        euclidInv(b, rem, quot, xy);
 | 
						|
      }
 | 
						|
 | 
						|
    BigInteger t = xy[0];
 | 
						|
    xy[0] = add(xy[1], times(t, prevDiv), -1);
 | 
						|
    xy[1] = t;
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger modInverse(BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        if (mpz.compare(ZERO.mpz) < 1)
 | 
						|
          throw new ArithmeticException("non-positive modulo");
 | 
						|
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.modInverse(y.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (y.isNegative() || y.isZero())
 | 
						|
      throw new ArithmeticException("non-positive modulo");
 | 
						|
 | 
						|
    // Degenerate cases.
 | 
						|
    if (y.isOne())
 | 
						|
      return ZERO;
 | 
						|
    if (isOne())
 | 
						|
      return ONE;
 | 
						|
 | 
						|
    // Use Euclid's algorithm as in gcd() but do this recursively
 | 
						|
    // rather than in a loop so we can use the intermediate results as we
 | 
						|
    // unwind from the recursion.
 | 
						|
    // Used http://www.math.nmsu.edu/~crypto/EuclideanAlgo.html as reference.
 | 
						|
    BigInteger result = new BigInteger();
 | 
						|
    boolean swapped = false;
 | 
						|
 | 
						|
    if (y.words == null)
 | 
						|
      {
 | 
						|
        // The result is guaranteed to be less than the modulus, y (which is
 | 
						|
        // an int), so simplify this by working with the int result of this
 | 
						|
        // modulo y.  Also, if this is negative, make it positive via modulo
 | 
						|
        // math.  Note that BigInteger.mod() must be used even if this is
 | 
						|
        // already an int as the % operator would provide a negative result if
 | 
						|
        // this is negative, BigInteger.mod() never returns negative values.
 | 
						|
        int xval = (words != null || isNegative()) ? mod(y).ival : ival;
 | 
						|
        int yval = y.ival;
 | 
						|
 | 
						|
        // Swap values so x > y.
 | 
						|
        if (yval > xval)
 | 
						|
          {
 | 
						|
            int tmp = xval; xval = yval; yval = tmp;
 | 
						|
            swapped = true;
 | 
						|
          }
 | 
						|
        // Normally, the result is in the 2nd element of the array, but
 | 
						|
        // if originally x < y, then x and y were swapped and the result
 | 
						|
        // is in the 1st element of the array.
 | 
						|
        result.ival =
 | 
						|
          euclidInv(yval, xval % yval, xval / yval)[swapped ? 0 : 1];
 | 
						|
 | 
						|
        // Result can't be negative, so make it positive by adding the
 | 
						|
        // original modulus, y.ival (not the possibly "swapped" yval).
 | 
						|
        if (result.ival < 0)
 | 
						|
          result.ival += y.ival;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        // As above, force this to be a positive value via modulo math.
 | 
						|
        BigInteger x = isNegative() ? this.mod(y) : this;
 | 
						|
 | 
						|
        // Swap values so x > y.
 | 
						|
        if (x.compareTo(y) < 0)
 | 
						|
          {
 | 
						|
            result = x; x = y; y = result; // use 'result' as a work var
 | 
						|
            swapped = true;
 | 
						|
          }
 | 
						|
        // As above (for ints), result will be in the 2nd element unless
 | 
						|
        // the original x and y were swapped.
 | 
						|
        BigInteger rem = new BigInteger();
 | 
						|
        BigInteger quot = new BigInteger();
 | 
						|
        divide(x, y, quot, rem, FLOOR);
 | 
						|
        // quot and rem may not be in canonical form. ensure
 | 
						|
        rem.canonicalize();
 | 
						|
        quot.canonicalize();
 | 
						|
        BigInteger[] xy = new BigInteger[2];
 | 
						|
        euclidInv(y, rem, quot, xy);
 | 
						|
        result = swapped ? xy[0] : xy[1];
 | 
						|
 | 
						|
        // Result can't be negative, so make it positive by adding the
 | 
						|
        // original modulus, y (which is now x if they were swapped).
 | 
						|
        if (result.isNegative())
 | 
						|
          result = add(result, swapped ? x : y, 1);
 | 
						|
      }
 | 
						|
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger modPow(BigInteger exponent, BigInteger m)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = exponent.signum; // force NPE check
 | 
						|
        if (m.mpz.compare(ZERO.mpz) < 1)
 | 
						|
          throw new ArithmeticException("non-positive modulo");
 | 
						|
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.modPow(exponent.mpz, m.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (m.isNegative() || m.isZero())
 | 
						|
      throw new ArithmeticException("non-positive modulo");
 | 
						|
 | 
						|
    if (exponent.isNegative())
 | 
						|
      return modInverse(m).modPow(exponent.negate(), m);
 | 
						|
    if (exponent.isOne())
 | 
						|
      return mod(m);
 | 
						|
 | 
						|
    // To do this naively by first raising this to the power of exponent
 | 
						|
    // and then performing modulo m would be extremely expensive, especially
 | 
						|
    // for very large numbers.  The solution is found in Number Theory
 | 
						|
    // where a combination of partial powers and moduli can be done easily.
 | 
						|
    //
 | 
						|
    // We'll use the algorithm for Additive Chaining which can be found on
 | 
						|
    // p. 244 of "Applied Cryptography, Second Edition" by Bruce Schneier.
 | 
						|
    BigInteger s = ONE;
 | 
						|
    BigInteger t = this;
 | 
						|
    BigInteger u = exponent;
 | 
						|
 | 
						|
    while (!u.isZero())
 | 
						|
      {
 | 
						|
        if (u.and(ONE).isOne())
 | 
						|
          s = times(s, t).mod(m);
 | 
						|
        u = u.shiftRight(1);
 | 
						|
        t = times(t, t).mod(m);
 | 
						|
      }
 | 
						|
 | 
						|
    return s;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Calculate Greatest Common Divisor for non-negative ints. */
 | 
						|
  private static int gcd(int a, int b)
 | 
						|
  {
 | 
						|
    // Euclid's algorithm, copied from libg++.
 | 
						|
    int tmp;
 | 
						|
    if (b > a)
 | 
						|
      {
 | 
						|
        tmp = a; a = b; b = tmp;
 | 
						|
      }
 | 
						|
    for(;;)
 | 
						|
      {
 | 
						|
        if (b == 0)
 | 
						|
          return a;
 | 
						|
        if (b == 1)
 | 
						|
          return b;
 | 
						|
        tmp = b;
 | 
						|
            b = a % b;
 | 
						|
            a = tmp;
 | 
						|
          }
 | 
						|
      }
 | 
						|
 | 
						|
  public BigInteger gcd(BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.gcd(y.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    int xval = ival;
 | 
						|
    int yval = y.ival;
 | 
						|
    if (words == null)
 | 
						|
      {
 | 
						|
        if (xval == 0)
 | 
						|
          return abs(y);
 | 
						|
        if (y.words == null
 | 
						|
            && xval != Integer.MIN_VALUE && yval != Integer.MIN_VALUE)
 | 
						|
          {
 | 
						|
            if (xval < 0)
 | 
						|
              xval = -xval;
 | 
						|
            if (yval < 0)
 | 
						|
              yval = -yval;
 | 
						|
            return valueOf(gcd(xval, yval));
 | 
						|
          }
 | 
						|
        xval = 1;
 | 
						|
      }
 | 
						|
    if (y.words == null)
 | 
						|
      {
 | 
						|
        if (yval == 0)
 | 
						|
          return abs(this);
 | 
						|
        yval = 1;
 | 
						|
      }
 | 
						|
    int len = (xval > yval ? xval : yval) + 1;
 | 
						|
    int[] xwords = new int[len];
 | 
						|
    int[] ywords = new int[len];
 | 
						|
    getAbsolute(xwords);
 | 
						|
    y.getAbsolute(ywords);
 | 
						|
    len = MPN.gcd(xwords, ywords, len);
 | 
						|
    BigInteger result = new BigInteger(0);
 | 
						|
    result.ival = len;
 | 
						|
    result.words = xwords;
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Returns <code>true</code> if this BigInteger is probably prime,
 | 
						|
   * <code>false</code> if it's definitely composite. If <code>certainty</code>
 | 
						|
   * is <code><= 0</code>, <code>true</code> is returned.</p>
 | 
						|
   *
 | 
						|
   * @param certainty a measure of the uncertainty that the caller is willing
 | 
						|
   * to tolerate: if the call returns <code>true</code> the probability that
 | 
						|
   * this BigInteger is prime exceeds <code>(1 - 1/2<sup>certainty</sup>)</code>.
 | 
						|
   * The execution time of this method is proportional to the value of this
 | 
						|
   * parameter.
 | 
						|
   * @return <code>true</code> if this BigInteger is probably prime,
 | 
						|
   * <code>false</code> if it's definitely composite.
 | 
						|
   */
 | 
						|
  public boolean isProbablePrime(int certainty)
 | 
						|
  {
 | 
						|
    if (certainty < 1)
 | 
						|
      return true;
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.testPrimality(certainty) != 0;
 | 
						|
 | 
						|
    /** We'll use the Rabin-Miller algorithm for doing a probabilistic
 | 
						|
     * primality test.  It is fast, easy and has faster decreasing odds of a
 | 
						|
     * composite passing than with other tests.  This means that this
 | 
						|
     * method will actually have a probability much greater than the
 | 
						|
     * 1 - .5^certainty specified in the JCL (p. 117), but I don't think
 | 
						|
     * anyone will complain about better performance with greater certainty.
 | 
						|
     *
 | 
						|
     * The Rabin-Miller algorithm can be found on pp. 259-261 of "Applied
 | 
						|
     * Cryptography, Second Edition" by Bruce Schneier.
 | 
						|
     */
 | 
						|
 | 
						|
    // First rule out small prime factors
 | 
						|
    BigInteger rem = new BigInteger();
 | 
						|
    int i;
 | 
						|
    for (i = 0; i < primes.length; i++)
 | 
						|
      {
 | 
						|
        if (words == null && ival == primes[i])
 | 
						|
          return true;
 | 
						|
 | 
						|
        divide(this, smallFixNums[primes[i] - minFixNum], null, rem, TRUNCATE);
 | 
						|
        if (rem.canonicalize().isZero())
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
 | 
						|
    // Now perform the Rabin-Miller test.
 | 
						|
 | 
						|
    // Set b to the number of times 2 evenly divides (this - 1).
 | 
						|
    // I.e. 2^b is the largest power of 2 that divides (this - 1).
 | 
						|
    BigInteger pMinus1 = add(this, -1);
 | 
						|
    int b = pMinus1.getLowestSetBit();
 | 
						|
 | 
						|
    // Set m such that this = 1 + 2^b * m.
 | 
						|
    BigInteger m = pMinus1.divide(valueOf(2L).pow(b));
 | 
						|
 | 
						|
    // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
 | 
						|
    // 4.49 (controlling the error probability) gives the number of trials
 | 
						|
    // for an error probability of 1/2**80, given the number of bits in the
 | 
						|
    // number to test.  we shall use these numbers as is if/when 'certainty'
 | 
						|
    // is less or equal to 80, and twice as much if it's greater.
 | 
						|
    int bits = this.bitLength();
 | 
						|
    for (i = 0; i < k.length; i++)
 | 
						|
      if (bits <= k[i])
 | 
						|
        break;
 | 
						|
    int trials = t[i];
 | 
						|
    if (certainty > 80)
 | 
						|
      trials *= 2;
 | 
						|
    BigInteger z;
 | 
						|
    for (int t = 0; t < trials; t++)
 | 
						|
      {
 | 
						|
        // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al.
 | 
						|
        // Remark 4.28 states: "...A strategy that is sometimes employed
 | 
						|
        // is to fix the bases a to be the first few primes instead of
 | 
						|
        // choosing them at random.
 | 
						|
        z = smallFixNums[primes[t] - minFixNum].modPow(m, this);
 | 
						|
        if (z.isOne() || z.equals(pMinus1))
 | 
						|
          continue;                     // Passes the test; may be prime.
 | 
						|
 | 
						|
        for (i = 0; i < b; )
 | 
						|
          {
 | 
						|
            if (z.isOne())
 | 
						|
              return false;
 | 
						|
            i++;
 | 
						|
            if (z.equals(pMinus1))
 | 
						|
              break;                    // Passes the test; may be prime.
 | 
						|
 | 
						|
            z = z.modPow(valueOf(2), this);
 | 
						|
          }
 | 
						|
 | 
						|
        if (i == b && !z.equals(pMinus1))
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  private void setInvert()
 | 
						|
  {
 | 
						|
    if (words == null)
 | 
						|
      ival = ~ival;
 | 
						|
    else
 | 
						|
      {
 | 
						|
        for (int i = ival;  --i >= 0; )
 | 
						|
          words[i] = ~words[i];
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private void setShiftLeft(BigInteger x, int count)
 | 
						|
  {
 | 
						|
    int[] xwords;
 | 
						|
    int xlen;
 | 
						|
    if (x.words == null)
 | 
						|
      {
 | 
						|
        if (count < 32)
 | 
						|
          {
 | 
						|
            set((long) x.ival << count);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
        xwords = new int[1];
 | 
						|
        xwords[0] = x.ival;
 | 
						|
        xlen = 1;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        xwords = x.words;
 | 
						|
        xlen = x.ival;
 | 
						|
      }
 | 
						|
    int word_count = count >> 5;
 | 
						|
    count &= 31;
 | 
						|
    int new_len = xlen + word_count;
 | 
						|
    if (count == 0)
 | 
						|
      {
 | 
						|
        realloc(new_len);
 | 
						|
        for (int i = xlen;  --i >= 0; )
 | 
						|
          words[i+word_count] = xwords[i];
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        new_len++;
 | 
						|
        realloc(new_len);
 | 
						|
        int shift_out = MPN.lshift(words, word_count, xwords, xlen, count);
 | 
						|
        count = 32 - count;
 | 
						|
        words[new_len-1] = (shift_out << count) >> count;  // sign-extend.
 | 
						|
      }
 | 
						|
    ival = new_len;
 | 
						|
    for (int i = word_count;  --i >= 0; )
 | 
						|
      words[i] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  private void setShiftRight(BigInteger x, int count)
 | 
						|
  {
 | 
						|
    if (x.words == null)
 | 
						|
      set(count < 32 ? x.ival >> count : x.ival < 0 ? -1 : 0);
 | 
						|
    else if (count == 0)
 | 
						|
      set(x);
 | 
						|
    else
 | 
						|
      {
 | 
						|
        boolean neg = x.isNegative();
 | 
						|
        int word_count = count >> 5;
 | 
						|
        count &= 31;
 | 
						|
        int d_len = x.ival - word_count;
 | 
						|
        if (d_len <= 0)
 | 
						|
          set(neg ? -1 : 0);
 | 
						|
        else
 | 
						|
          {
 | 
						|
            if (words == null || words.length < d_len)
 | 
						|
              realloc(d_len);
 | 
						|
            MPN.rshift0 (words, x.words, word_count, d_len, count);
 | 
						|
            ival = d_len;
 | 
						|
            if (neg)
 | 
						|
              words[d_len-1] |= -2 << (31 - count);
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private void setShift(BigInteger x, int count)
 | 
						|
  {
 | 
						|
    if (count > 0)
 | 
						|
      setShiftLeft(x, count);
 | 
						|
    else
 | 
						|
      setShiftRight(x, -count);
 | 
						|
  }
 | 
						|
 | 
						|
  private static BigInteger shift(BigInteger x, int count)
 | 
						|
  {
 | 
						|
    if (x.words == null)
 | 
						|
      {
 | 
						|
        if (count <= 0)
 | 
						|
          return valueOf(count > -32 ? x.ival >> (-count) : x.ival < 0 ? -1 : 0);
 | 
						|
        if (count < 32)
 | 
						|
          return valueOf((long) x.ival << count);
 | 
						|
      }
 | 
						|
    if (count == 0)
 | 
						|
      return x;
 | 
						|
    BigInteger result = new BigInteger(0);
 | 
						|
    result.setShift(x, count);
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger shiftLeft(int n)
 | 
						|
  {
 | 
						|
    if (n == 0)
 | 
						|
      return this;
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        if (n < 0)
 | 
						|
          mpz.shiftRight(-n, result.mpz);
 | 
						|
        else
 | 
						|
          mpz.shiftLeft(n, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return shift(this, n);
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger shiftRight(int n)
 | 
						|
  {
 | 
						|
    if (n == 0)
 | 
						|
      return this;
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        if (n < 0)
 | 
						|
          mpz.shiftLeft(-n, result.mpz);
 | 
						|
        else
 | 
						|
          mpz.shiftRight(n, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return shift(this, -n);
 | 
						|
  }
 | 
						|
 | 
						|
  private void format(int radix, CPStringBuilder buffer)
 | 
						|
  {
 | 
						|
    if (words == null)
 | 
						|
      buffer.append(Integer.toString(ival, radix));
 | 
						|
    else if (ival <= 2)
 | 
						|
      buffer.append(Long.toString(longValue(), radix));
 | 
						|
    else
 | 
						|
      {
 | 
						|
        boolean neg = isNegative();
 | 
						|
        int[] work;
 | 
						|
        if (neg || radix != 16)
 | 
						|
          {
 | 
						|
            work = new int[ival];
 | 
						|
            getAbsolute(work);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          work = words;
 | 
						|
        int len = ival;
 | 
						|
 | 
						|
        if (radix == 16)
 | 
						|
          {
 | 
						|
            if (neg)
 | 
						|
              buffer.append('-');
 | 
						|
            int buf_start = buffer.length();
 | 
						|
            for (int i = len;  --i >= 0; )
 | 
						|
              {
 | 
						|
                int word = work[i];
 | 
						|
                for (int j = 8;  --j >= 0; )
 | 
						|
                  {
 | 
						|
                    int hex_digit = (word >> (4 * j)) & 0xF;
 | 
						|
                    // Suppress leading zeros:
 | 
						|
                    if (hex_digit > 0 || buffer.length() > buf_start)
 | 
						|
                      buffer.append(Character.forDigit(hex_digit, 16));
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            int i = buffer.length();
 | 
						|
            for (;;)
 | 
						|
              {
 | 
						|
                int digit = MPN.divmod_1(work, work, len, radix);
 | 
						|
                buffer.append(Character.forDigit(digit, radix));
 | 
						|
                while (len > 0 && work[len-1] == 0) len--;
 | 
						|
                if (len == 0)
 | 
						|
                  break;
 | 
						|
              }
 | 
						|
            if (neg)
 | 
						|
              buffer.append('-');
 | 
						|
            /* Reverse buffer. */
 | 
						|
            int j = buffer.length() - 1;
 | 
						|
            while (i < j)
 | 
						|
              {
 | 
						|
                char tmp = buffer.charAt(i);
 | 
						|
                buffer.setCharAt(i, buffer.charAt(j));
 | 
						|
                buffer.setCharAt(j, tmp);
 | 
						|
                i++;  j--;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public String toString()
 | 
						|
  {
 | 
						|
    return toString(10);
 | 
						|
  }
 | 
						|
 | 
						|
  public String toString(int radix)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.toString(radix);
 | 
						|
 | 
						|
    if (words == null)
 | 
						|
      return Integer.toString(ival, radix);
 | 
						|
    if (ival <= 2)
 | 
						|
      return Long.toString(longValue(), radix);
 | 
						|
    int buf_size = ival * (MPN.chars_per_word(radix) + 1);
 | 
						|
    CPStringBuilder buffer = new CPStringBuilder(buf_size);
 | 
						|
    format(radix, buffer);
 | 
						|
    return buffer.toString();
 | 
						|
  }
 | 
						|
 | 
						|
  public int intValue()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int result = mpz.absIntValue();
 | 
						|
        return mpz.compare(ZERO.mpz) < 0 ? - result : result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (words == null)
 | 
						|
      return ival;
 | 
						|
    return words[0];
 | 
						|
  }
 | 
						|
 | 
						|
  public long longValue()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        long result;
 | 
						|
        result = (abs().shiftRight(32)).mpz.absIntValue();
 | 
						|
        result <<= 32;
 | 
						|
        result |= mpz.absIntValue() & 0xFFFFFFFFL;
 | 
						|
        return this.compareTo(ZERO) < 0 ? - result : result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (words == null)
 | 
						|
      return ival;
 | 
						|
    if (ival == 1)
 | 
						|
      return words[0];
 | 
						|
    return ((long)words[1] << 32) + ((long)words[0] & 0xffffffffL);
 | 
						|
  }
 | 
						|
 | 
						|
  public int hashCode()
 | 
						|
  {
 | 
						|
    // FIXME: May not match hashcode of JDK.
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        // TODO: profile to decide whether to make it native
 | 
						|
        byte[] bytes = this.toByteArray();
 | 
						|
        int result = 0;
 | 
						|
        for (int i = 0; i < bytes.length; i++)
 | 
						|
          result ^= (bytes[i] & 0xFF) << (8 * (i % 4));
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return words == null ? ival : (words[0] + words[ival - 1]);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Assumes x and y are both canonicalized. */
 | 
						|
  private static boolean equals(BigInteger x, BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return x.mpz.compare(y.mpz) == 0;
 | 
						|
 | 
						|
    if (x.words == null && y.words == null)
 | 
						|
      return x.ival == y.ival;
 | 
						|
    if (x.words == null || y.words == null || x.ival != y.ival)
 | 
						|
      return false;
 | 
						|
    for (int i = x.ival; --i >= 0; )
 | 
						|
      {
 | 
						|
        if (x.words[i] != y.words[i])
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Assumes this and obj are both canonicalized. */
 | 
						|
  public boolean equals(Object obj)
 | 
						|
  {
 | 
						|
    if (! (obj instanceof BigInteger))
 | 
						|
      return false;
 | 
						|
    return equals(this, (BigInteger) obj);
 | 
						|
  }
 | 
						|
 | 
						|
  private static BigInteger valueOf(byte[] digits, int byte_len,
 | 
						|
                                    boolean negative, int radix)
 | 
						|
  {
 | 
						|
    int chars_per_word = MPN.chars_per_word(radix);
 | 
						|
    int[] words = new int[byte_len / chars_per_word + 1];
 | 
						|
    int size = MPN.set_str(words, digits, byte_len, radix);
 | 
						|
    if (size == 0)
 | 
						|
      return ZERO;
 | 
						|
    if (words[size-1] < 0)
 | 
						|
      words[size++] = 0;
 | 
						|
    if (negative)
 | 
						|
      negate(words, words, size);
 | 
						|
    return make(words, size);
 | 
						|
  }
 | 
						|
 | 
						|
  public double doubleValue()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.doubleValue();
 | 
						|
 | 
						|
    if (words == null)
 | 
						|
      return (double) ival;
 | 
						|
    if (ival <= 2)
 | 
						|
      return (double) longValue();
 | 
						|
    if (isNegative())
 | 
						|
      return neg(this).roundToDouble(0, true, false);
 | 
						|
      return roundToDouble(0, false, false);
 | 
						|
  }
 | 
						|
 | 
						|
  public float floatValue()
 | 
						|
  {
 | 
						|
    return (float) doubleValue();
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return true if any of the lowest n bits are one.
 | 
						|
   * (false if n is negative).  */
 | 
						|
  private boolean checkBits(int n)
 | 
						|
  {
 | 
						|
    if (n <= 0)
 | 
						|
      return false;
 | 
						|
    if (words == null)
 | 
						|
      return n > 31 || ((ival & ((1 << n) - 1)) != 0);
 | 
						|
    int i;
 | 
						|
    for (i = 0; i < (n >> 5) ; i++)
 | 
						|
      if (words[i] != 0)
 | 
						|
        return true;
 | 
						|
    return (n & 31) != 0 && (words[i] & ((1 << (n & 31)) - 1)) != 0;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Convert a semi-processed BigInteger to double.
 | 
						|
   * Number must be non-negative.  Multiplies by a power of two, applies sign,
 | 
						|
   * and converts to double, with the usual java rounding.
 | 
						|
   * @param exp power of two, positive or negative, by which to multiply
 | 
						|
   * @param neg true if negative
 | 
						|
   * @param remainder true if the BigInteger is the result of a truncating
 | 
						|
   * division that had non-zero remainder.  To ensure proper rounding in
 | 
						|
   * this case, the BigInteger must have at least 54 bits.  */
 | 
						|
  private double roundToDouble(int exp, boolean neg, boolean remainder)
 | 
						|
  {
 | 
						|
    // Compute length.
 | 
						|
    int il = bitLength();
 | 
						|
 | 
						|
    // Exponent when normalized to have decimal point directly after
 | 
						|
    // leading one.  This is stored excess 1023 in the exponent bit field.
 | 
						|
    exp += il - 1;
 | 
						|
 | 
						|
    // Gross underflow.  If exp == -1075, we let the rounding
 | 
						|
    // computation determine whether it is minval or 0 (which are just
 | 
						|
    // 0x0000 0000 0000 0001 and 0x0000 0000 0000 0000 as bit
 | 
						|
    // patterns).
 | 
						|
    if (exp < -1075)
 | 
						|
      return neg ? -0.0 : 0.0;
 | 
						|
 | 
						|
    // gross overflow
 | 
						|
    if (exp > 1023)
 | 
						|
      return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
 | 
						|
 | 
						|
    // number of bits in mantissa, including the leading one.
 | 
						|
    // 53 unless it's denormalized
 | 
						|
    int ml = (exp >= -1022 ? 53 : 53 + exp + 1022);
 | 
						|
 | 
						|
    // Get top ml + 1 bits.  The extra one is for rounding.
 | 
						|
    long m;
 | 
						|
    int excess_bits = il - (ml + 1);
 | 
						|
    if (excess_bits > 0)
 | 
						|
      m = ((words == null) ? ival >> excess_bits
 | 
						|
           : MPN.rshift_long(words, ival, excess_bits));
 | 
						|
    else
 | 
						|
      m = longValue() << (- excess_bits);
 | 
						|
 | 
						|
    // Special rounding for maxval.  If the number exceeds maxval by
 | 
						|
    // any amount, even if it's less than half a step, it overflows.
 | 
						|
    if (exp == 1023 && ((m >> 1) == (1L << 53) - 1))
 | 
						|
      {
 | 
						|
        if (remainder || checkBits(il - ml))
 | 
						|
          return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
 | 
						|
        else
 | 
						|
          return neg ? - Double.MAX_VALUE : Double.MAX_VALUE;
 | 
						|
      }
 | 
						|
 | 
						|
    // Normal round-to-even rule: round up if the bit dropped is a one, and
 | 
						|
    // the bit above it or any of the bits below it is a one.
 | 
						|
    if ((m & 1) == 1
 | 
						|
        && ((m & 2) == 2 || remainder || checkBits(excess_bits)))
 | 
						|
      {
 | 
						|
        m += 2;
 | 
						|
        // Check if we overflowed the mantissa
 | 
						|
        if ((m & (1L << 54)) != 0)
 | 
						|
          {
 | 
						|
            exp++;
 | 
						|
            // renormalize
 | 
						|
            m >>= 1;
 | 
						|
          }
 | 
						|
        // Check if a denormalized mantissa was just rounded up to a
 | 
						|
        // normalized one.
 | 
						|
        else if (ml == 52 && (m & (1L << 53)) != 0)
 | 
						|
          exp++;
 | 
						|
      }
 | 
						|
 | 
						|
    // Discard the rounding bit
 | 
						|
    m >>= 1;
 | 
						|
 | 
						|
    long bits_sign = neg ? (1L << 63) : 0;
 | 
						|
    exp += 1023;
 | 
						|
    long bits_exp = (exp <= 0) ? 0 : ((long)exp) << 52;
 | 
						|
    long bits_mant = m & ~(1L << 52);
 | 
						|
    return Double.longBitsToDouble(bits_sign | bits_exp | bits_mant);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Copy the abolute value of this into an array of words.
 | 
						|
   * Assumes words.length >= (this.words == null ? 1 : this.ival).
 | 
						|
   * Result is zero-extended, but need not be a valid 2's complement number.
 | 
						|
   */
 | 
						|
  private void getAbsolute(int[] words)
 | 
						|
  {
 | 
						|
    int len;
 | 
						|
    if (this.words == null)
 | 
						|
      {
 | 
						|
        len = 1;
 | 
						|
        words[0] = this.ival;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        len = this.ival;
 | 
						|
        for (int i = len;  --i >= 0; )
 | 
						|
          words[i] = this.words[i];
 | 
						|
      }
 | 
						|
    if (words[len - 1] < 0)
 | 
						|
      negate(words, words, len);
 | 
						|
    for (int i = words.length;  --i > len; )
 | 
						|
      words[i] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Set dest[0:len-1] to the negation of src[0:len-1].
 | 
						|
   * Return true if overflow (i.e. if src is -2**(32*len-1)).
 | 
						|
   * Ok for src==dest. */
 | 
						|
  private static boolean negate(int[] dest, int[] src, int len)
 | 
						|
  {
 | 
						|
    long carry = 1;
 | 
						|
    boolean negative = src[len-1] < 0;
 | 
						|
    for (int i = 0;  i < len;  i++)
 | 
						|
      {
 | 
						|
        carry += ((long) (~src[i]) & 0xffffffffL);
 | 
						|
        dest[i] = (int) carry;
 | 
						|
        carry >>= 32;
 | 
						|
      }
 | 
						|
    return (negative && dest[len-1] < 0);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Destructively set this to the negative of x.
 | 
						|
   * It is OK if x==this.*/
 | 
						|
  private void setNegative(BigInteger x)
 | 
						|
  {
 | 
						|
    int len = x.ival;
 | 
						|
    if (x.words == null)
 | 
						|
      {
 | 
						|
        if (len == Integer.MIN_VALUE)
 | 
						|
          set(- (long) len);
 | 
						|
        else
 | 
						|
          set(-len);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    realloc(len + 1);
 | 
						|
    if (negate(words, x.words, len))
 | 
						|
      words[len++] = 0;
 | 
						|
    ival = len;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Destructively negate this. */
 | 
						|
  private void setNegative()
 | 
						|
  {
 | 
						|
    setNegative(this);
 | 
						|
  }
 | 
						|
 | 
						|
  private static BigInteger abs(BigInteger x)
 | 
						|
  {
 | 
						|
    return x.isNegative() ? neg(x) : x;
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger abs()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.abs(result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return abs(this);
 | 
						|
  }
 | 
						|
 | 
						|
  private static BigInteger neg(BigInteger x)
 | 
						|
  {
 | 
						|
    if (x.words == null && x.ival != Integer.MIN_VALUE)
 | 
						|
      return valueOf(- x.ival);
 | 
						|
    BigInteger result = new BigInteger(0);
 | 
						|
    result.setNegative(x);
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger negate()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.negate(result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return neg(this);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Calculates ceiling(log2(this < 0 ? -this : this+1))
 | 
						|
   * See Common Lisp: the Language, 2nd ed, p. 361.
 | 
						|
   */
 | 
						|
  public int bitLength()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.bitLength();
 | 
						|
 | 
						|
    if (words == null)
 | 
						|
      return MPN.intLength(ival);
 | 
						|
      return MPN.intLength(words, ival);
 | 
						|
  }
 | 
						|
 | 
						|
  public byte[] toByteArray()
 | 
						|
  {
 | 
						|
    if (signum() == 0)
 | 
						|
      return new byte[1];
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        // the minimal number of bytes required to represent the MPI is function
 | 
						|
        // of (a) its bit-length, and (b) its sign.  only when this MPI is both
 | 
						|
        // positive, and its bit-length is a multiple of 8 do we add one zero
 | 
						|
        // bit for its sign.  we do this so if we construct a new MPI from the
 | 
						|
        // resulting byte array, we wouldn't mistake a positive number, whose
 | 
						|
        // bit-length is a multiple of 8, for a similar-length negative one.
 | 
						|
        int bits = bitLength();
 | 
						|
        if (bits % 8 == 0 || this.signum() == 1)
 | 
						|
          bits++;
 | 
						|
        byte[] bytes = new byte[(bits + 7) / 8];
 | 
						|
        mpz.toByteArray(bytes);
 | 
						|
        return bytes;
 | 
						|
      }
 | 
						|
 | 
						|
    // Determine number of bytes needed.  The method bitlength returns
 | 
						|
    // the size without the sign bit, so add one bit for that and then
 | 
						|
    // add 7 more to emulate the ceil function using integer math.
 | 
						|
    byte[] bytes = new byte[(bitLength() + 1 + 7) / 8];
 | 
						|
    int nbytes = bytes.length;
 | 
						|
 | 
						|
    int wptr = 0;
 | 
						|
    int word;
 | 
						|
 | 
						|
    // Deal with words array until one word or less is left to process.
 | 
						|
    // If BigInteger is an int, then it is in ival and nbytes will be <= 4.
 | 
						|
    while (nbytes > 4)
 | 
						|
      {
 | 
						|
        word = words[wptr++];
 | 
						|
        for (int i = 4; i > 0; --i, word >>= 8)
 | 
						|
          bytes[--nbytes] = (byte) word;
 | 
						|
      }
 | 
						|
 | 
						|
    // Deal with the last few bytes.  If BigInteger is an int, use ival.
 | 
						|
    word = (words == null) ? ival : words[wptr];
 | 
						|
    for ( ; nbytes > 0; word >>= 8)
 | 
						|
      bytes[--nbytes] = (byte) word;
 | 
						|
 | 
						|
    return bytes;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return the boolean opcode (for bitOp) for swapped operands.
 | 
						|
   * I.e. bitOp(swappedOp(op), x, y) == bitOp(op, y, x).
 | 
						|
   */
 | 
						|
  private static int swappedOp(int op)
 | 
						|
  {
 | 
						|
    return
 | 
						|
    "\000\001\004\005\002\003\006\007\010\011\014\015\012\013\016\017"
 | 
						|
    .charAt(op);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
 | 
						|
  private static BigInteger bitOp(int op, BigInteger x, BigInteger y)
 | 
						|
  {
 | 
						|
    switch (op)
 | 
						|
      {
 | 
						|
        case 0:  return ZERO;
 | 
						|
        case 1:  return x.and(y);
 | 
						|
        case 3:  return x;
 | 
						|
        case 5:  return y;
 | 
						|
        case 15: return valueOf(-1);
 | 
						|
      }
 | 
						|
    BigInteger result = new BigInteger();
 | 
						|
    setBitOp(result, op, x, y);
 | 
						|
    return result.canonicalize();
 | 
						|
  }
 | 
						|
 | 
						|
  /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
 | 
						|
  private static void setBitOp(BigInteger result, int op,
 | 
						|
                               BigInteger x, BigInteger y)
 | 
						|
  {
 | 
						|
    if ((y.words != null) && (x.words == null || x.ival < y.ival))
 | 
						|
      {
 | 
						|
        BigInteger temp = x;  x = y;  y = temp;
 | 
						|
        op = swappedOp(op);
 | 
						|
      }
 | 
						|
    int xi;
 | 
						|
    int yi;
 | 
						|
    int xlen, ylen;
 | 
						|
    if (y.words == null)
 | 
						|
      {
 | 
						|
        yi = y.ival;
 | 
						|
        ylen = 1;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        yi = y.words[0];
 | 
						|
        ylen = y.ival;
 | 
						|
      }
 | 
						|
    if (x.words == null)
 | 
						|
      {
 | 
						|
        xi = x.ival;
 | 
						|
        xlen = 1;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        xi = x.words[0];
 | 
						|
        xlen = x.ival;
 | 
						|
      }
 | 
						|
    if (xlen > 1)
 | 
						|
      result.realloc(xlen);
 | 
						|
    int[] w = result.words;
 | 
						|
    int i = 0;
 | 
						|
    // Code for how to handle the remainder of x.
 | 
						|
    // 0:  Truncate to length of y.
 | 
						|
    // 1:  Copy rest of x.
 | 
						|
    // 2:  Invert rest of x.
 | 
						|
    int finish = 0;
 | 
						|
    int ni;
 | 
						|
    switch (op)
 | 
						|
      {
 | 
						|
      case 0:  // clr
 | 
						|
        ni = 0;
 | 
						|
        break;
 | 
						|
      case 1: // and
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = xi & yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi < 0) finish = 1;
 | 
						|
        break;
 | 
						|
      case 2: // andc2
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = xi & ~yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi >= 0) finish = 1;
 | 
						|
        break;
 | 
						|
      case 3:  // copy x
 | 
						|
        ni = xi;
 | 
						|
        finish = 1;  // Copy rest
 | 
						|
        break;
 | 
						|
      case 4: // andc1
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = ~xi & yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi < 0) finish = 2;
 | 
						|
        break;
 | 
						|
      case 5: // copy y
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        break;
 | 
						|
      case 6:  // xor
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = xi ^ yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        finish = yi < 0 ? 2 : 1;
 | 
						|
        break;
 | 
						|
      case 7:  // ior
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = xi | yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi >= 0) finish = 1;
 | 
						|
        break;
 | 
						|
      case 8:  // nor
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = ~(xi | yi);
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi >= 0)  finish = 2;
 | 
						|
        break;
 | 
						|
      case 9:  // eqv [exclusive nor]
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = ~(xi ^ yi);
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        finish = yi >= 0 ? 2 : 1;
 | 
						|
        break;
 | 
						|
      case 10:  // c2
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = ~yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        break;
 | 
						|
      case 11:  // orc2
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = xi | ~yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi < 0)  finish = 1;
 | 
						|
        break;
 | 
						|
      case 12:  // c1
 | 
						|
        ni = ~xi;
 | 
						|
        finish = 2;
 | 
						|
        break;
 | 
						|
      case 13:  // orc1
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = ~xi | yi;
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi >= 0) finish = 2;
 | 
						|
        break;
 | 
						|
      case 14:  // nand
 | 
						|
        for (;;)
 | 
						|
          {
 | 
						|
            ni = ~(xi & yi);
 | 
						|
            if (i+1 >= ylen) break;
 | 
						|
            w[i++] = ni;  xi = x.words[i];  yi = y.words[i];
 | 
						|
          }
 | 
						|
        if (yi < 0) finish = 2;
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
      case 15:  // set
 | 
						|
        ni = -1;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    // Here i==ylen-1; w[0]..w[i-1] have the correct result;
 | 
						|
    // and ni contains the correct result for w[i+1].
 | 
						|
    if (i+1 == xlen)
 | 
						|
      finish = 0;
 | 
						|
    switch (finish)
 | 
						|
      {
 | 
						|
      case 0:
 | 
						|
        if (i == 0 && w == null)
 | 
						|
          {
 | 
						|
            result.ival = ni;
 | 
						|
            return;
 | 
						|
          }
 | 
						|
        w[i++] = ni;
 | 
						|
        break;
 | 
						|
      case 1:  w[i] = ni;  while (++i < xlen)  w[i] = x.words[i];  break;
 | 
						|
      case 2:  w[i] = ni;  while (++i < xlen)  w[i] = ~x.words[i];  break;
 | 
						|
      }
 | 
						|
    result.ival = i;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return the logical (bit-wise) "and" of a BigInteger and an int. */
 | 
						|
  private static BigInteger and(BigInteger x, int y)
 | 
						|
  {
 | 
						|
    if (x.words == null)
 | 
						|
      return valueOf(x.ival & y);
 | 
						|
    if (y >= 0)
 | 
						|
      return valueOf(x.words[0] & y);
 | 
						|
    int len = x.ival;
 | 
						|
    int[] words = new int[len];
 | 
						|
    words[0] = x.words[0] & y;
 | 
						|
    while (--len > 0)
 | 
						|
      words[len] = x.words[len];
 | 
						|
    return make(words, x.ival);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return the logical (bit-wise) "and" of two BigIntegers. */
 | 
						|
  public BigInteger and(BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.and(y.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    if (y.words == null)
 | 
						|
      return and(this, y.ival);
 | 
						|
    else if (words == null)
 | 
						|
      return and(y, ival);
 | 
						|
 | 
						|
    BigInteger x = this;
 | 
						|
    if (ival < y.ival)
 | 
						|
      {
 | 
						|
        BigInteger temp = this;  x = y;  y = temp;
 | 
						|
      }
 | 
						|
    int i;
 | 
						|
    int len = y.isNegative() ? x.ival : y.ival;
 | 
						|
    int[] words = new int[len];
 | 
						|
    for (i = 0;  i < y.ival;  i++)
 | 
						|
      words[i] = x.words[i] & y.words[i];
 | 
						|
    for ( ; i < len;  i++)
 | 
						|
      words[i] = x.words[i];
 | 
						|
    return make(words, len);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */
 | 
						|
  public BigInteger or(BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.or(y.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return bitOp(7, this, y);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return the logical (bit-wise) "exclusive or" of two BigIntegers. */
 | 
						|
  public BigInteger xor(BigInteger y)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = y.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.xor(y.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return bitOp(6, this, y);
 | 
						|
  }
 | 
						|
 | 
						|
  /** Return the logical (bit-wise) negation of a BigInteger. */
 | 
						|
  public BigInteger not()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.not(result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return bitOp(12, this, ZERO);
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger andNot(BigInteger val)
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        int dummy = val.signum; // force NPE check
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.andNot(val.mpz, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return and(val.not());
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger clearBit(int n)
 | 
						|
  {
 | 
						|
    if (n < 0)
 | 
						|
      throw new ArithmeticException();
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.setBit(n, false, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return and(ONE.shiftLeft(n).not());
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger setBit(int n)
 | 
						|
  {
 | 
						|
    if (n < 0)
 | 
						|
      throw new ArithmeticException();
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.setBit(n, true, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return or(ONE.shiftLeft(n));
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean testBit(int n)
 | 
						|
  {
 | 
						|
    if (n < 0)
 | 
						|
      throw new ArithmeticException();
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.testBit(n) != 0;
 | 
						|
 | 
						|
    return !and(ONE.shiftLeft(n)).isZero();
 | 
						|
  }
 | 
						|
 | 
						|
  public BigInteger flipBit(int n)
 | 
						|
  {
 | 
						|
    if (n < 0)
 | 
						|
      throw new ArithmeticException();
 | 
						|
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        BigInteger result = new BigInteger();
 | 
						|
        mpz.flipBit(n, result.mpz);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
 | 
						|
    return xor(ONE.shiftLeft(n));
 | 
						|
  }
 | 
						|
 | 
						|
  public int getLowestSetBit()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.compare(ZERO.mpz) == 0 ? -1 : mpz.lowestSetBit();
 | 
						|
 | 
						|
    if (isZero())
 | 
						|
      return -1;
 | 
						|
 | 
						|
    if (words == null)
 | 
						|
      return MPN.findLowestBit(ival);
 | 
						|
    else
 | 
						|
      return MPN.findLowestBit(words);
 | 
						|
  }
 | 
						|
 | 
						|
  // bit4count[I] is number of '1' bits in I.
 | 
						|
  private static final byte[] bit4_count = { 0, 1, 1, 2,  1, 2, 2, 3,
 | 
						|
                                             1, 2, 2, 3,  2, 3, 3, 4};
 | 
						|
 | 
						|
  private static int bitCount(int i)
 | 
						|
  {
 | 
						|
    int count = 0;
 | 
						|
    while (i != 0)
 | 
						|
      {
 | 
						|
        count += bit4_count[i & 15];
 | 
						|
        i >>>= 4;
 | 
						|
      }
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
 | 
						|
  private static int bitCount(int[] x, int len)
 | 
						|
  {
 | 
						|
    int count = 0;
 | 
						|
    while (--len >= 0)
 | 
						|
      count += bitCount(x[len]);
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
 | 
						|
  /** Count one bits in a BigInteger.
 | 
						|
   * If argument is negative, count zero bits instead. */
 | 
						|
  public int bitCount()
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      return mpz.bitCount();
 | 
						|
 | 
						|
    int i, x_len;
 | 
						|
    int[] x_words = words;
 | 
						|
    if (x_words == null)
 | 
						|
      {
 | 
						|
        x_len = 1;
 | 
						|
        i = bitCount(ival);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        x_len = ival;
 | 
						|
        i = bitCount(x_words, x_len);
 | 
						|
      }
 | 
						|
    return isNegative() ? x_len * 32 - i : i;
 | 
						|
  }
 | 
						|
 | 
						|
  private void readObject(ObjectInputStream s)
 | 
						|
    throws IOException, ClassNotFoundException
 | 
						|
  {
 | 
						|
    if (USING_NATIVE)
 | 
						|
      {
 | 
						|
        mpz = new GMP();
 | 
						|
        s.defaultReadObject();
 | 
						|
        if (signum != 0)
 | 
						|
          mpz.fromByteArray(magnitude);
 | 
						|
        // else it's zero and we need to do nothing
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        s.defaultReadObject();
 | 
						|
        if (magnitude.length == 0 || signum == 0)
 | 
						|
          {
 | 
						|
            this.ival = 0;
 | 
						|
            this.words = null;
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            words = byteArrayToIntArray(magnitude, signum < 0 ? -1 : 0);
 | 
						|
            BigInteger result = make(words, words.length);
 | 
						|
            this.ival = result.ival;
 | 
						|
            this.words = result.words;
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private void writeObject(ObjectOutputStream s)
 | 
						|
    throws IOException, ClassNotFoundException
 | 
						|
  {
 | 
						|
    signum = signum();
 | 
						|
    magnitude = signum == 0 ? new byte[0] : toByteArray();
 | 
						|
    s.defaultWriteObject();
 | 
						|
    magnitude = null; // not needed anymore
 | 
						|
  }
 | 
						|
 | 
						|
  // inner class(es) ..........................................................
 | 
						|
 | 
						|
}
 |