/*
 * @(#)XBigInteger.java    2.4.0   4 July 2005
 *
 * Copyright 2005
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs;

import edu.neu.ccs.parser.*;
import java.beans.*;
import java.math.*;
import java.text.ParseException;

/**
 * <p><code>XBigInteger</code> is an object wrapper for the 
 * arbitrary precision <code>BigInteger</code> class that
 * also provides <code>{@link Stringable Stringable}</code>
 * capabilities. Hence, unlike <code>BigInteger</code>,
 * objects of this class are mutable.</p>
 *
 * <p>The default wrapped value for this class is
 * the <code>BigInteger</code> representation of zero,
 * <code>{@link BigInteger#ZERO BigInteger.ZERO}</code>.</p>
 * 
 * <p>This class provides the operations of the class
 * <code>BigInteger</code> in two forms.  Member methods
 * will mutate the object that is operated on but leave all
 * parameters unchanged and will return <code>void</code>.
 * Static methods will create new objects and change no
 * parameters. In all cases, if an argument to an operation
 * is <code>null</code>, it is treated as zero.</p>
 *
 * <p>In addition to the usual string representation of a
 * big integer as a signed decimal, this class supports a
 * string bit representation that shows the bits in a
 * two's complement form that makes it easier to see what
 * is happening with the bit operations.  See the method
 * <code>toBits</code> for more details.</p>
 * 
 * @author  Richard Rasala
 * @author  Jeff Raab
 * @version 2.4.0
 * @since   1.0
 */
public class XBigInteger extends XNumber implements Comparable {
    
    /** The zero BigInteger.*/
    private static final BigInteger ZERO = BigInteger.ZERO;
    
    /** The minus-one BigInteger.*/
    private static final BigInteger MINUSONE = new BigInteger("-1");
    
    
    /** The zero   character for bit parsing. */
    private static final char zero   = '0';
    
    /** The one    character for bit parsing. */
    private static final char one    = '1';
    
    /** The period character for bit parsing. */
    private static final char period = '.';
    
    
    /** The introductory string for the bit represention of positive numbers. */
    private static final String positive = "...0";
    
    /** The introductory string for the bit represention of negative numbers. */
    private static final String negative = "...1";
    
    
    /** The standard error message for fromStringData. */
    public static final String standardMessage =
        "\nXBigInteger Error: Data format must be\n"
        + "a big integer in decimal format with an optional sign\n"
        + "or a big integer expression with data in decimal format\n"
        + "or a binary bit representation formatted as follows.\n"
        + "Represent a positive big integer in binary bits as ...0bbb\n"
        + "Represent a negative big integer in binary bits as ...1bbb\n"
        + "The prefix ...0 or ...1 is mandatory and must be typed as is\n"
        + "The sequence bbb stands for zero or more additional 0,1 digits\n";
    
    
    /** The wrapped value of this object. */
    private BigInteger value = BigInteger.ZERO;
    
    
    /**
     * <p>Constructs a wrapper for the default <code>BigInteger</code>
     * value of <code>BigInteger.ZERO</code>.</p>
     */
    public XBigInteger() {}
    
    
    /**
     * <p>Constructs a wrapper for the given <code>BigInteger</code>
     * value.</p>
     *
     * <p>If the given value is <code>null</code>, the wrapped value
     * is set to <code>BigInteger.ZERO</code>.</p>
     * 
     * @param b the value to be wrapped
     */
    public XBigInteger(BigInteger b) {
        setValue(b);
    }
    
    
    /**
     * <p>Constructs an <code>XBigInteger</code> by copying the
     * internal value of the given <code>XBigInteger</code>.</p>
     *
     * <p>If the given value is <code>null</code>, the wrapped
     * value is set to <code>BigInteger.ZERO</code>.</p>
     * 
     * @param b the value to be copied
     */
    public XBigInteger(XBigInteger b) {
        setValue(b);
    }
    
    
    /**
     * <p>Constructs a wrapper for the <code>BigInteger</code> value
     * corresponding to the given <code>long</code> data.</p>
     * 
     * @param n a <code>long</code> to encapsulate
     */
    public XBigInteger(long n) {
        setValue(n);
    }
    
    
    /**
     * <p>Constructs an <code>XBigInteger</code> using the information
     * contained in the given string data.  Will parse and evaluate
     * simple big integer arithmetic expressions in decimal format and
     * will also read data in the special bit format output by the
     * method <code>toBits</code>.</p>
     *
     * <p>Makes use of the parsing capabilities of the method
     * <code>fromStringData(String)</code>.</p>
     *
     * @param s a string representation of the desired value
     * @throws ParseException if the string is <code>null</code>
     *         or malformed
     */
    public XBigInteger(String s) throws ParseException {
        fromStringData(s);
    }
    
    
    /**
     * <p>Constructs an <code>XBigInteger</code> using the information
     * contained in the given string of digit data in the given radix
     * with a possible minus sign in front.</p>
     * 
     * <p>This constructor makes use of the parsing capabilities of
     * the method <code>setValue(String, int)</code>.</p>
     *
     * <p>The character-to-digit mapping is provided by
     * <code>Character.digit</code>.</p>
     *
     * <p>The string may not contain any extraneous characters
     * (whitespace, for example).</p>
     *
     * <p>Throws <code>NumberFormatException</code> if:</p>
     *
     * <ul>
     *   <li>The string is not a valid representation of a
     *       <code>BigInteger</code> in the specified radix</li>
     *   <li>The radix is outside the range from
     *       <code>Character.MIN_RADIX</code> to
     *       <code>Character.MAX_RADIX</code>, inclusive.</li>
     * </ul>
     *
     * @param s a string representation of the desired value
     * @param radix radix to be used in interpreting s
     * @throws NumberFormatException as explained above
     */
    public XBigInteger(String s, int radix) {
        setValue(s, radix);
    }
    
    
    /**
     * <p>Translates a byte array containing the two's-complement
     * binary representation of a <code>BigInteger</code> into a
     * <code>BigInteger</code> that is stored internally.</p>
     *
     * <p>The input array is assumed to be in <i>big-endian</i>
     * byte-order: the most significant byte is in the zero-th
     * element.</p>
     *
     * <p>Unlike the corresponding constructor for the Java class
     * <code>BigInteger</code>, this constructor will set the
     * internal value to <code>BigInteger.ZERO</code>, if the
     * given array is <code>null</code> or of length 0.</p>
     *
     * @param val big-endian two's-complement binary representation
     *            of the internal BigInteger
     */
    public XBigInteger(byte[] val) {
        setValue(val);
    }
    
    
    /**
     * <p>Sets the state of this <code>XBigInteger</code> using the
     * information contained in the given string data.  Will parse
     * and evaluate simple big integer arithmetic expressions in
     * decimal format and will also read data in the format output
     * by the method <code>toBits</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     * 
     * @param data a string representation of the desired value
     * @throws ParseException if the data is <code>null</code> or malformed
     */
    public final void fromStringData(String data)
        throws ParseException
    {
        // sanity check for null data
        if (data == null)
            throw new ParseException
                ("\nXBigInteger fromStringData(String) Error: Data was null\n", -1);
        
        BigInteger oldValue = value;
        
        data = data.trim();
        
        int length = data.length();
        
        if ((length >= 4) && (data.charAt(0) == period)) {
            fromBits(data);
        }
        else {
            try {
                Parser p = ParserUtilities.getDefaultParser();
                Object obj = p.parse(data);

                // store extracted value
                if (obj instanceof XNumber) {
                    XBigInteger x = ParserUtilities.toXBigInteger((XNumber) obj);
                    value = x.getValue();
                }
            }
            // otherwise re-throw exception
            catch (Exception ex) {
                throw new ParseException(standardMessage, -1);
            }
        }
        
        // report property change
        changeAdapter.firePropertyChange(
            VALUE,
            oldValue,
            value);
    }
    
    
    /**
     * <p>Returns a string encapsulation of this <code>XBigInteger</code>
     * that contains the information needed to set the state of this
     * <code>XBigInteger</code> at a later time.</p>
     *
     * <p>Identical to <code>toString</code>.</p>
     */
    public final String toStringData() {
        return toString();
    }
    
    
    /**
     * <p>Returns the string representation of the wrapped
     * <code>BigInteger</code> value.</p>
     *
     * <p>The digit-to-character mapping provided by
     * <code>Character.forDigit</code> is used,
     * and a minus sign is prepended if appropriate.</p>
     *
     * <p>This representation is compatible with the (String)
     * constructor.</p>
     */
    public final String toString() {
        return getValue().toString();
    }
    
    
    /**
     * <p>Returns the string representation of the
     * wrapped <code>BigInteger</code> value in the given radix.</p>
     *
     * <p>If the radix is outside the range from
     * <code>Character.MIN_RADIX</code> to
     * <code>Character.MAX_RADIX</code> inclusive, it will default
     * to 10 (as is the case for <code>Integer.toString</code>).</p>
     *
     * <p>The digit-to-character mapping provided by
     * <code>Character.forDigit</code> is used,
     * and a minus sign is prepended if appropriate.</p>
     *
     * <p>This representation is compatible with the (String, int)
     * constructor.</p>
     *
     * @param radix radix of the string representation
     */
    public final String toString(int radix) {
        return getValue().toString(radix);
    }
    
    
    /**
     * <p>Returns a string representation of the
     * wrapped <code>BigInteger</code> value in a
     * binary bit representation that is in unsigned
     * two's complement format.</p>
     *
     * <p>This representation is quite different from
     * that returned by <code>this.toString(2)</code>
     * which is a signed representation with the bits
     * being those of the corresponding positive value.</p>
     *
     * <p>Here, a positive value is represented as:</p>
     *
     * <p><pre>    ...0bbb</pre></p>
     *
     * <p>and a negative value is represented as:</p>
     *
     * <p><pre>    ...1bbb</pre></p>
     *
     * <p>where <code>bbb</code> stands for zero or more
     * binary digits 0,1.</p>
     *
     * <p>The significance of <code>...0</code> is that
     * there are in principle infinitely many 0 bits to
     * the left in the bit representation of a positive
     * big integer.</p>
     *
     * <p>The significance of <code>...1</code> is that
     * there are in principle infinitely many 1 bits to
     * the left in the bit representation of a negative
     * big integer.</p>
     *
     * <p>The representations returned by this method are
     * visually compatible with the bit operations in
     * this class and therefore make these operations
     * much easier to understand.</p>
     *
     * <p>The method <code>fromStringData</code> can read
     * the representations output by this method.</p>
     */
    public String toBits() {
        String start = "";
        
        int compare = getValue().compareTo(BigInteger.ZERO);
        
        if (compare >= 0)
            start = positive;
        else
            start = negative;
        
        int length = getValue().bitLength();
        
        if (length == 0)
            return start;
        
        StringBuffer buffer = new StringBuffer(length);
        
        int k = length - 1;
        
        for (int i = 0; i <= k; i++) {
            if (getValue().testBit(k - i))
                buffer.append(one);
            else
                buffer.append(zero);
        }
        
        return start + buffer.toString();
    }
    
    
    /**
     * <p>Sets the state of this <code>XBigInteger</code> by reading
     * data in the format output by the method <code>toBits</code>.</p>
     *
     * <p>This is a private helper method for <code>fromStringData</code>.</p>
     *
     * @param bits the string containing the state information in bits
     * @throws ParseException if bits is <code>null</code> or malformed
     */
    private void fromBits(String bits)
        throws ParseException
    {
        // sanity check for null data
        if (bits == null)
            throw new ParseException
                ("\nXBigInteger fromBits(String) Error: Data was null\n", -1);
        
        BigInteger result;
        
        if (bits.startsWith(positive))
            result = ZERO;
        else
        if (bits.startsWith(negative))
            result = MINUSONE;
        else
            throw new ParseException(standardMessage, -1);
        
        bits = bits.substring(4);
        
        int length = bits.length();
        
        if (length == 0) {
            value = result;
            return;
        }
        
        int k = length - 1;
        
        result = result.shiftLeft(length);
            
        for (int i = 0; i <= k; i++) {
            if (bits.charAt(i) == one)
                result = result.setBit(k - i);
            else
            if (bits.charAt(i) == zero)
                result = result.clearBit(k - i);
            else
                throw new ParseException(standardMessage, -1);
        }
        
        value = result;
    }
    
    
    /**
     * <p>Returns the number of digits in <code>toString()</code>
     * excluding the sign if any.</p>
     */
    public final int digits() {
        String string = toString();
        int length = string.length();
        
        if (string.charAt(0) == '-')
            return length - 1;
        else
            return length;
    }
    
    
    /**
     * <p>Returns the number of digits in <code>toString(radix)</code>
     * excluding the sign if any.</p>
     *
     * <p>If the radix is outside the range from
     * <code>Character.MIN_RADIX</code> to
     * <code>Character.MAX_RADIX</code> inclusive, it will default
     * to 10.</p>
     *
     * @param radix radix of the string representation
     */
    public final int digits(int radix) {
        String string = toString(radix);
        int length = string.length();
        
        if (string.charAt(0) == '-')
            return length - 1;
        else
            return length;
    }
    
    
    /**
     * Returns <code>true</code> if the given object is of type
     * <code>XBigInteger</code> and its <code>BigInteger</code>
     * value is equal to the <code>BigInteger</code> value of
     * this <code>XBigInteger</code>; returns <code>false</code>
     * otherwise.</p> 
     *
     * @param the object to be compared
     */
    public final boolean equals(Object other) {
        if (other instanceof XBigInteger) {
            XBigInteger object = (XBigInteger) other;
            return getValue().equals(object.getValue());
        }
        
        return false;
    }
    
    
    /**
     * Returns the <code>int</code> hash code 
     * of the wrapped <code>BigInteger</code> value.
     */
    public final int hashCode() {
        return getValue().hashCode();
    }
    
    
    /**
     * <p>Sets the value wrapped by this object to the given
     * <code>BigInteger</code> value.</p>
     *
     * <p>If the given value is <code>null</code>, the internal
     * value is set to <code>BigInteger.ZERO</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     * 
     * @param b the value to be wrapped
     */
    public final void setValue(BigInteger b) {
        BigInteger oldValue = value;
        
        value = (b == null) ? BigInteger.ZERO : b;
        
        // if the value has changed
        if (!value.equals(oldValue)) {
        
            // notify listeners of property change
            changeAdapter.firePropertyChange(
                VALUE, 
                oldValue, 
                value);
        }
    }
    
    
    /**
     * <p>Sets the value wrapped by this object to the internal
     * value of the given <code>XBigInteger</code> value.</p>
     *
     * <p>If the given input is <code>null</code>, the internal
     * value is set to <code>BigInteger.ZERO</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     * 
     * @param b the value to be copied
     */
    public final void setValue(XBigInteger b) {
        setValue((b == null) ? BigInteger.ZERO : b.getValue());
    }
    
    
    /**
     * <p>Sets the value wrapped by this object to the
     * <code>BigInteger</code> value corresponding
     * to the given <code>long</code> value.</p>
     *
     * <p>Uses the static method <code>BigInteger.valueOf</code>
     * to take advantages of optimizations built into Java.</p>
     *
     * <p>Fires property change: VALUE.</p>
     * 
     * @param n a <code>long</code> to encapsulate
     */
    public final void setValue(long n) {
        setValue(BigInteger.valueOf(n));
    }
    
    
    /**
     * <p>Sets the state of this <code>XBigInteger</code> using the
     * information contained in the given string data.  Will parse
     * and evaluate simple big integer arithmetic expressions in
     * decimal format and will also read data in the format output
     * by the method <code>toBits</code>.</p>
     *
     * <p>Makes use of the parsing capabilities of the method
     * <code>fromStringData(String)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param data a string representation of the desired value
     * @throws ParseException if the data is <code>null</code> or malformed
     */
    public final void setValue(String data) throws ParseException {
        if (data == null)
            throw new ParseException
                ("\nXBigInteger setValue(String) Error: Data was null\n", -1);
        
        fromStringData(data);
    }
    
    
    /**
     * <p>Sets the state of this <code>XBigInteger</code> using the
     * information contained in the given string of digit data in
     * the given radix with a possible minus sign in front.</p>
     * 
     * <p>The character-to-digit mapping is provided by
     * <code>Character.digit</code>.</p>
     *
     * <p>The string may not contain any extraneous characters
     * (whitespace, for example).</p>
     *
     * <p>Throws <code>NumberFormatException</code> if:</p>
     *
     * <ul>
     *   <li>The string is not a valid representation of a
     *       <code>BigInteger</code> in the specified radix</li>
     *   <li>The radix is outside the range from
     *       <code>Character.MIN_RADIX</code> to
     *       <code>Character.MAX_RADIX</code>, inclusive.</li>
     * </ul>
     *
     * @param s a string representation of the desired value
     * @param radix radix to be used in interpreting s
     * @throws NumberFormatException as explained above
     */
    public final void setValue(String s, int radix) {
        if (s == null)
            throw new NumberFormatException
                ("\nXBigInteger setValue(String, int) Error: Data was null\n");
        
        setValue(new BigInteger(s, radix));
    }
    
    
    /**
     * <p>Translates a byte array containing the two's-complement
     * binary representation of a <code>BigInteger</code> into a
     * <code>BigInteger</code> that is stored internally in this
     * <code>XBigInteger</code>.</p>
     *
     * <p>The input array is assumed to be in <i>big-endian</i>
     * byte-order: the most significant byte is in the zero-th
     * element.</p>
     *
     * <p>This method will set the internal value to
     * <code>BigInteger.ZERO</code>, if the given array is
     * <code>null</code> or of length 0.</p>
     *
     * <p>Fires property change: VALUE.</p>
     * 
     * @param val big-endian two's-complement binary representation
     *            of the internal BigInteger
     */
    public final void setValue(byte[] val) {
        setValue(
            ((val == null) || (val.length == 0))
                ? BigInteger.ZERO
                : new BigInteger(val));
    }
    
    
    /**
     * <p>Returns the <code>BigInteger</code> value wrapped
     * by this object.</p>
     */
    public final BigInteger getValue() {
        return value;
    }
    
    
    public final byte byteValue() {
        BigInteger max = new BigInteger(Byte.MAX_VALUE + ""),
                   min = new BigInteger(Byte.MIN_VALUE + "");
    
        if ((getValue().compareTo(max) > 0) ||
            (getValue().compareTo(min) < 0))
        {
            throw new NumberFormatException(
                "Number beyond precision of a byte.");
        }
        
        return (byte)getValue().intValue();
    }
    

    public final short shortValue() {
        BigInteger max = new BigInteger(Short.MAX_VALUE + ""),
                   min = new BigInteger(Short.MIN_VALUE + "");
    
        if ((getValue().compareTo(max) > 0) ||
            (getValue().compareTo(min) < 0))
        {
            throw new NumberFormatException(
                "Number beyond precision of a short.");
        }
        
        return (short)getValue().intValue();
    }
    
    
    public final int intValue() {
        BigInteger max = new BigInteger(Integer.MAX_VALUE + ""),
                   min = new BigInteger(Integer.MIN_VALUE + "");
    
        if ((getValue().compareTo(max) > 0) ||
            (getValue().compareTo(min) < 0))
        {
            throw new NumberFormatException(
                "Number beyond precision of an int.");
        }
        
        return getValue().intValue();
    }
    
    
    public final long longValue() {
        BigInteger max = new BigInteger(Long.MAX_VALUE + ""),
                   min = new BigInteger(Long.MIN_VALUE + "");
    
        if ((getValue().compareTo(max) > 0) ||
            (getValue().compareTo(min) < 0))
        {
            throw new NumberFormatException(
                "Number beyond precision of a long.");
        }
        
        return getValue().longValue();
    }
    
    
    // Overflow handled by IEEE use of +Infinity or -Infinity
    public final float floatValue() {
        return getValue().floatValue();
    }
    
    
    // Overflow handled by IEEE use of +Infinity or -Infinity
    public final double doubleValue() {
        return getValue().doubleValue();
    }
    
    
    /**
     * <p>Returns -1, 0 or 1 as the value of this <code>XBigInteger</code>
     * is negative, zero or positive.</p>
     */
    public final int signum() {
        return getValue().signum();
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>abs(this)</code>.</p>
     * 
     * <p>Fires property change: VALUE.</p>
     */
    public final void abs() {
        setValue(getValue().abs());
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is the absolute
     * value of the given y.</p>
     *
     * @param y the explicit argument
     */
    public static XBigInteger abs(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(yy.abs());
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(-this)</code>.</p>
     *
     * <p>Mathematically, <code>(-this)</code> equals
     * <code>(~this)+1</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     */
    public final void negate() {
        setValue(getValue().negate());
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is the negation
     * of the given y.</p>
     *
     * <p>Mathematically, <code>(-y)</code> equals
     * <code>(~y)+1</code>.</p>
     *
     * @param y the explicit argument
     */
    public static XBigInteger negate(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(yy.negate());
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>max(this, y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void max(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().max(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * the maximum of the given x and y values.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger max(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.max(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>min(this, y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void min(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().min(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * the minimum of the given x and y values.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger min(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.min(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this + y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void add(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().add(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x + y</code>.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger add(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.add(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this - y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void subtract(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().subtract(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x - y</code>.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger subtract(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.subtract(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this * y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void multiply(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().multiply(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x * y</code>.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger multiply(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.multiply(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this / y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     * @throws ArithmeticException on division by zero
     */
    public final void divide(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.equals(BigInteger.ZERO))
            throw new ArithmeticException
                ("Zero divisor in XBigInteger.divide(y)");
        
        setValue(getValue().divide(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x / y</code>.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     * @throws ArithmeticException on division by zero
     */
    public static XBigInteger divide(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.equals(BigInteger.ZERO))
            throw new ArithmeticException
                ("Zero divisor in XBigInteger.divide(x,y)");
        
        return new XBigInteger(xx.divide(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this % y)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     * @throws ArithmeticException on division by zero
     */
    public final void remainder(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.equals(BigInteger.ZERO))
            throw new ArithmeticException
                ("Zero divisor in XBigInteger.remainder(y)");
        
        setValue(getValue().remainder(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x % y</code>.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     * @throws ArithmeticException on division by zero
     */
    public static XBigInteger remainder(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.value;
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.value;
        
        if (yy.equals(BigInteger.ZERO))
            throw new ArithmeticException
                ("Zero divisor in XBigInteger.remainder(x,y)");
        
        return new XBigInteger(xx.remainder(yy));
    }
    
    
    /**
     * <p>Returns an array {<code>quotient</code>, <code>remainder</code>}
     * after division of x by y.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     * @throws ArithmeticException on division by zero
     */
    public static XBigInteger[] divideAndRemainder(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.equals(BigInteger.ZERO))
            throw new ArithmeticException
                ("Zero divisor in XBigInteger.divideAndRemainder(x,y)");
        
        BigInteger[] array = xx.divideAndRemainder(yy);
        
        return new XBigInteger[]
            { new XBigInteger(array[0]), new XBigInteger(array[1]) };
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this mod y)</code>.</p>
     *
     * <p>This method differs from <code>remainder</code> in that it
     * always returns a <i>non-negative</i> <code>XBigInteger</code>.<p>
     *
     * <p>Throws an <code>ArithmeticException</code> if y is
     * <code>null</code> or is less than or equal to zero.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     * @throws ArithmeticException on division by zero
     */
    public final void mod(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.compareTo(BigInteger.ZERO) <= 0)
            throw new ArithmeticException
                ("Zero or negative divisor in XBigInteger.mod(y)");
        
        setValue(getValue().mod(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x mod y</code>.</p>
     *
     * <p>This method differs from <code>remainder</code> in that it
     * always returns a <i>non-negative</i> <code>XBigInteger</code>.<p>
     *
     * <p>Throws an <code>ArithmeticException</code> if y is
     * <code>null</code> or is less than or equal to zero.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     * @throws ArithmeticException on division by zero
     */
    public static XBigInteger mod(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.compareTo(BigInteger.ZERO) <= 0)
            throw new ArithmeticException
                ("Zero or negative divisor in XBigInteger.mod(x,y)");
        
        return new XBigInteger(xx.mod(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to the inverse modulo y of
     * <code>this</code>.</p>
     *
     * <p>Throws an <code>ArithmeticException</code> if y is
     * <code>null</code> or is less than or equal to zero
     * or if this number is not relatively prime to y.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     * @throws ArithmeticException as explained above
     */
    public final void modInverse(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.compareTo(BigInteger.ZERO) <= 0)
            throw new ArithmeticException
                ("Zero or negative divisor in XBigInteger.modInverse(y)");
        
        try {
            setValue(getValue().modInverse(yy));
        }
        catch (Exception ex) {
            throw new ArithmeticException
                ("Value not relatively prime in XBigInteger.modInverse(y)");
        }
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * the inverse of x modulo y.</p>
     *
     * <p>Throws an <code>ArithmeticException</code> if y is
     * <code>null</code> or is less than or equal to zero
     * or if x is <code>null</code> or is not relatively
     * prime to y.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     * @throws ArithmeticException as explained above
     */
    public static XBigInteger modInverse(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.compareTo(BigInteger.ZERO) <= 0)
            throw new ArithmeticException
                ("Zero or negative divisor in XBigInteger.modInverse(x,y)");
        
        try {
            return new XBigInteger(xx.modInverse(yy));
        }
        catch (Exception ex) {
            throw new ArithmeticException
                ("Value not relatively prime in XBigInteger.modInverse(x,y)");
        }
    }
    
    
    /**
     * <p>Sets <code>this</code> to the value of <code>this</code>
     * raised to the given integer exponent e which must be a
     * non-negative integer.</p>
     *
     * <p>Throws an <code>ArithmeticException</code> if the given
     * integer exponent is negative.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param e the non-negative integer exponent 
     * @throws ArithmeticException as explained above
     */
    public final void pow(int e) {
        if (e < 0)
            throw new ArithmeticException
                ("Negative exponent in XBigInteger.pow(e)");
        
        setValue(getValue().pow(e));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * the given base x raised to the given exponent e which must
     * be a non-negative integer.</p>
     *
     * <p>Throws an <code>ArithmeticException</code> if the given
     * integer exponent is negative.</p>
     *
     * @param x the base
     * @param e the non-negative integer exponent 
     * @throws ArithmeticException as explained above
     */
    public static XBigInteger pow(XBigInteger x, int e) {
        if (e < 0)
            throw new ArithmeticException
                ("Negative exponent in XBigInteger.pow(x, e)");
        
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        
        return new XBigInteger(xx.pow(e));
    }
    
    
    /**
     * <p>Sets <code>this</code> to the value of <code>this</code>
     * raised to the given exponent e modulo the given modulus y.</p>
     *
     * <p>Throws an <code>ArithmeticException</code> if:</p>
     *
     * <ul>
     *   <li>The modulus y is less or equal to zero</li>
     *   <li><code>this</code> is not <i>relatively prime</i> to y</li>
     * </ul>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param e the exponent
     * @param y the modulus 
     * @throws ArithmeticException as explained above
     */
    public final void modPow(XBigInteger e, XBigInteger y) {
        BigInteger ee = (e == null) ? BigInteger.ZERO : e.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.compareTo(BigInteger.ZERO) <= 0)
            throw new ArithmeticException
                ("Zero or negative modulus in XBigInteger.modPow(e,y)");
        
        try {
            setValue(getValue().modPow(ee, yy));
        }
        catch (Exception ex) {
            throw new ArithmeticException
                ("Value not relatively prime in XBigInteger.modPow(e,y)");
        }
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * the given base x raised to the given exponent e modulo the
     * given modulus y.</p>
     *
     * <p>Throws an <code>ArithmeticException</code> if:</p>
     *
     * <ul>
     *   <li>The modulus y is less or equal to zero</li>
     *   <li><code>x</code> is not <i>relatively prime</i> to y</li>
     * </ul>
     *
     * @param x the base
     * @param e the exponent 
     * @param y the modulus 
     * @throws ArithmeticException as explained above
     */
    public static XBigInteger modPow
        (XBigInteger x, XBigInteger e, XBigInteger y)
    {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger ee = (e == null) ? BigInteger.ZERO : e.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (yy.compareTo(BigInteger.ZERO) <= 0)
            throw new ArithmeticException
                ("Zero or negative modulus in XBigInteger.modPow(x,e,y)");
        
        try {
            return new XBigInteger(xx.modPow(ee, yy));
        }
        catch (Exception ex) {
            throw new ArithmeticException
                ("Value not relatively prime in XBigInteger.modPow(x,e,y)");
        }
    }
    
    
    
    
    
    /**
     * <p>Sets <code>this</code> to <code>gcd(this, y)</code>
     * where "gcd" stands for "greatest common divisor".</p>
     *
     * <p>The "gcd" is always greater than or equal to zero
     * and is zero if and only if both <code>this</code> and
     * <code>y</code> are zero.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void gcd(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().gcd(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>gcd(x, y)</code>  where "gcd" stands for
     * "greatest common divisor".</p>
     *
     * <p>The "gcd" is always greater than or equal to zero
     * and is zero if and only if both <code>x</code> and
     * <code>y</code> are zero.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger gcd(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.gcd(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>lcm(this, y)</code>
     * where "lcm" stands for "least common multiple".</p>
     *
     * <p>The "lcm" is always greater than or equal to zero
     * and is zero if and only if both <code>this</code> and
     * <code>y</code> are zero.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void lcm(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(lcm(this, y));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>lcm(x, y)</code>  where "lcm" stands for
     * "least common multiple".</p>
     *
     * <p>The "lcm" is always greater than or equal to zero
     * and is zero if and only if both <code>x</code> and
     * <code>y</code> are zero.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger lcm(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        if (xx.equals(BigInteger.ZERO))
            return new XBigInteger(yy.abs());
        
        if (yy.equals(BigInteger.ZERO))
            return new XBigInteger(xx.abs());
        
        xx = xx.abs();
        yy = yy.abs();
        
        BigInteger gg = xx.gcd(yy);
        
        return new XBigInteger(xx.multiply(yy.divide(gg)));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this &lt;&lt; n)</code>;
     * the shift distance, n, may be negative, in which case this
     * method performs a right shift.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param n the left shift in bits
     */
    public final void shiftLeft(int n) {
        setValue(getValue().shiftLeft(n));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>(x &lt;&lt; n)</code>; the shift distance, n, may be
     * negative, in which case this method performs a right shift.</p>
     *
     * @param x the value to shift
     * @param n the left shift in bits
     */
    public static XBigInteger shiftLeft(XBigInteger x, int n) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        
        return new XBigInteger(xx.shiftLeft(n));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this &gt;&gt; n)</code>;
     * the shift distance, n, may be negative, in which case this
     * method performs a left shift.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param n the right shift in bits
     */
    public final void shiftRight(int n) {
        setValue(getValue().shiftRight(n));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>(x &gt;&gt; n)</code>; the shift distance, n, may be
     * negative, in which case this method performs a left shift.</p>
     *
     * @param x the value to shift
     * @param n the right shift in bits
     */
    public static XBigInteger shiftRight(XBigInteger x, int n) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        
        return new XBigInteger(xx.shiftRight(n));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(~this)</code>,
     * which is the bitwise-not of the current value.</p>
     *
     * <p>Mathematically, <code>(~this)</code> equals
     * <code>-(this+1)</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     */
    public final void not() {
        setValue(getValue().not());
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is the
     * bitwise not of the given y.</p>
     *
     * <p>Mathematically, <code>(~y)</code> equals
     * <code>-(y+1)</code>.</p>
     *
     * @param y the explicit argument
     */
    public static XBigInteger not(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(yy.not());
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this & y)</code>.</p>
     *
     * <p>The value set is negative if and only if
     * <code>this</code> and <code>y</code> are both negative.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void and(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().and(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x & y</code>.</p>
     *
     * <p>The value returned is negative if and only if
     * <code>x</code> and <code>y</code> are both negative.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger and(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.and(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this | y)</code>.</p>
     *
     * <p>The value set is negative if and only if at least one
     * of <code>this</code> and <code>y</code> is negative.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void or(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().or(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x | y</code>.</p>
     *
     * <p>The value returned is negative if and only if at least
     * one of <code>x</code> and <code>y</code> is negative.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger or(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.or(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this ^ y)</code>.</p>
     *
     * <p>The value set is negative if and only if exactly one
     * of <code>this</code> and <code>y</code> is negative.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void xor(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().xor(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x ^ y</code>.</p>
     *
     * <p>The value returned is negative if and only if exactly
     * one of <code>x</code> and <code>y</code> is negative.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger xor(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.xor(yy));
    }
    
    
    /**
     * <p>Sets <code>this</code> to <code>(this & ~y)</code>.</p>
     *
     * <p>The value set is negative if and only if
     * <code>this</code> is negative and
     * <code>y</code> is positive.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * @param y the explicit argument
     */
    public final void andNot(XBigInteger y) {
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        setValue(getValue().andNot(yy));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value is
     * <code>x & ~y</code>.</p>
     *
     * <p>The value returned is negative if and only if
     * <code>x</code> is negative and
     * <code>y</code> is positive.</p>
     *
     * @param x the LHS argument
     * @param y the RHS argument
     */
    public static XBigInteger andNot(XBigInteger x, XBigInteger y) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        BigInteger yy = (y == null) ? BigInteger.ZERO : y.getValue();
        
        return new XBigInteger(xx.andNot(yy));
    }
    
    
    /**
     * <p>Returns true if and only if the designated bit is set.</p>
     *
     * <p>Computes <code>((this & (1&lt;&lt;n)) != 0)</code>.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param n index of bit to test
     * @throws ArithmeticException if n is negative
     */
    public final boolean testBit(int n) {
        return getValue().testBit(n);
    }
    
    
    /**
     * <p>Sets <code>this</code> to the equivalent value with the
     * <code>n</code>-th bit set.</p>
     *
     * <p>In other words, sets <code>this</code> to
     * <code>(this|(1&lt;&lt;n))</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param n the bit to modify
     */
    public final void setBit(int n) {
        setValue(getValue().setBit(n));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value
     * is equivalent to <code>x</code> with the
     * <code>n</code>-th bit set.</p>
     *
     * <p>In other words, returns
     * <code>(x|(1&lt;&lt;n))</code>.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param x the initial value
     * @param n the bit to modify
     */
    public static XBigInteger setBit(XBigInteger x, int n) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        
        return new XBigInteger(xx.setBit(n));
    }
    
    
    /**
     * <p>Sets <code>this</code> to the equivalent value with the
     * <code>n</code>-th bit cleared.</p>
     *
     * <p>In other words, sets <code>this</code> to
     * <code>(this&~(1&lt;&lt;n))</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param n the bit to modify
     */
    public final void clearBit(int n) {
        setValue(getValue().clearBit(n));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value
     * is equivalent to <code>x</code> with the
     * <code>n</code>-th bit cleared.</p>
     *
     * <p>In other words, returns
     * <code>(x&~(1&lt;&lt;n))</code>.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param x the initial value
     * @param n the bit to modify
     */
    public static XBigInteger clearBit(XBigInteger x, int n) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        
        return new XBigInteger(xx.clearBit(n));
    }
    
    
    /**
     * <p>Sets <code>this</code> to the equivalent value with the
     * <code>n</code>-th bit flipped.</p>
     *
     * <p>In other words, sets <code>this</code> to
     * <code>(this^(1&lt;&lt;n))</code>.</p>
     *
     * <p>Fires property change: VALUE.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param n the bit to modify
     */
    public final void flipBit(int n) {
        setValue(getValue().flipBit(n));
    }
    
    
    /**
     * <p>Returns a new <code>XBigInteger</code> whose value
     * is equivalent to <code>x</code> with the
     * <code>n</code>-th bit flipped.</p>
     *
     * <p>In other words, returns
     * <code>(x^(1&lt;&lt;n))</code>.</p>
     *
     * <p>Throws <code>ArithmeticException</code> if n is negative.</p>
     *
     * @param x the initial value
     * @param n the bit to modify
     */
    public static XBigInteger flipBit(XBigInteger x, int n) {
        BigInteger xx = (x == null) ? BigInteger.ZERO : x.getValue();
        
        return new XBigInteger(xx.flipBit(n));
    }
    
    
    /**
     * <p>Returns the index of the rightmost (lowest-order) one bit in this
     * <code>XBigInteger</code>, that is, the number of zero bits to the
     * right of the rightmost one bit.</p>
     *
     * <p>Returns -1 if this <code>XBigInteger</code> contains no one bits.</p>
     *
     * <p>Computes <code>((this == 0) ? -1 : log2(this & -this))</code>.</p>
     */
    public final int getLowestSetBit() {
        return getValue().getLowestSetBit();
    }
    
    
    /**
     * <p>Returns the number of bits in the minimal two's-complement
     * representation of this <code>XBigInteger</code>, excluding a sign bit.
     * For positive <code>XBigInteger</code>'s, this is equivalent to the
     * number of bits in the ordinary binary representation.</p>
     *
     * <p>Computes <code>(ceil(log2(this < 0 ? -this : (this+1))))</code>.</p>
     */
    public final int bitLength() {
        return getValue().bitLength();
    }
    
    
    /**
     * <p>Returns the number of bits in the two's complement representation
     * of this <code>XBigInteger</code> that differ from its sign bit. This
     * method is useful when implementing bit-vector style sets atop
     * <code>XBigInteger</code>'s.</p>
     */
    public final int bitCount() {
        return getValue().bitCount();
    }
    
    
    /**
     * <p>Returns true if this <code>XBigInteger</code> is probably prime,
     * false if it's definitely composite.</p>
     *
     * <p>If <code>certainty &lt;= 0</code>, true is returned.</p>
     *
     * <p>If the call returns true, the probability that this
     * <code>XBigInteger</code> is prime exceeds (1 - 1/n) where n equals
     * 2 raised to the power certainty. The execution time of this method
     * is proportional to the value of this parameter.</p>
     *
     * @param certainty a measure of the uncertainty that the caller is
     *        willing to tolerate
     */
    public final boolean isProbablePrime(int certainty) {
        return getValue().isProbablePrime(certainty);
    }
    
    
    /**
     * <p>Compares this <code>XBigInteger</code> with the specified
     * <code>XBigInteger</code> y.</p>
     *
     * <p>This method is provided in preference to individual methods
     * for each of the six boolean comparison operators:</p>
     *
     * <p><pre>    ==, !=, &lt;, &lt;=, &gt;, &gt;=</pre></p>
     *
     * The suggested idiom for performing these comparisons is:</p>
     *
     * <p><pre>    (x.compareTo(y) &lt;op&gt; 0)</pre></p>
     *
     * <p>where <code>&lt;op&gt;</code> is one of the six comparison
     * operators.</p>
     *
     * <p>Throws <code>NullPointerException</code> if the given object
     * y is <code>null</code>.  Since this method is not specified in
     * the interface <code>Comparable</code>, we throw the natural
     * exception rather than <code>ClassCastException</code> which
     * is required in the more generic <code>compareTo(Object)</code>
     * method.</p>
     *
     * @param y the explicit argument
     * @throws NullPointerException if y is <code>null</code>
     */
    public final int compareTo(XBigInteger y) {
        if (y == null)
            throw new NullPointerException
                ("Null object passed to XBigInteger.compareTo(XBigInteger)");
        
        return getValue().compareTo(y.getValue());
    }
    
    
    /**
     * <p>Compares this <code>XBigInteger</code> with the specified
     * <code>Object</code> o.</p>
     *
     * <p>This method is provided in preference to individual methods
     * for each of the six boolean comparison operators:</p>
     *
     * <p><pre>    ==, !=, &lt;, &lt;=, &gt;, &gt;=</pre></p>
     *
     * The suggested idiom for performing these comparisons is:</p>
     *
     * <p><pre>    (x.compareTo(y) &lt;op&gt; 0)</pre></p>
     *
     * <p>where <code>&lt;op&gt;</code> is one of the six comparison
     * operators.</p>
     *
     * <p>Throws <code>ClassCastException</code> if the given object is
     * <code>null</code> or is not of type <code>XBigInteger</code>.
     * This is consistent with the specification of the interface
     * <code>Comparable</code> which this method implements.</p>
     *
     * @param o the <code>Object</code> to compare
     * @throws ClassCastException if o is <code>null</code> or not of
     *         type <code>XBigInteger</code>
     */
    public final int compareTo(Object o) {
        if (o == null)
            throw new ClassCastException
                ("Null object passed to XBigInteger.compareTo(Object)");
        
        if (! (o instanceof XBigInteger))
            throw new ClassCastException
                ("Invalid object passed to XBigInteger.compareTo(Object)");
        
        return compareTo((XBigInteger) o);
    }
    
    
    /**
     * <p>Returns factorial(n), that is, the product of the
     * numbers from 1 to n.</p>
     *
     * <p>This is equal to the number of permutations of a set of size
     * n when n &gt;= 0.</p>
     *
     * <p>Returns 1 if n is 0 or 1 and returns 0 if n is negative.</p>
     *
     * @param n the set size
     */
    public static XBigInteger factorial(int n) {
        if (n < 0)
            return new XBigInteger();
        
        if (n < 2)
            return new XBigInteger(1);
        
        XBigInteger result = new XBigInteger(n--);
        
        while (n > 1) {
            result.multiply(new XBigInteger(n--));
        }
        
        return result;
    }
    
    
    /**
     * <p>Returns the binomial coefficient for n, k.</p>
     *
     * <p>When n &gt;= k &gt;= 0, this is equal to the number of
     * subsets of size k in a set of size n.</p>
     *
     * <p>Returns 1 if k is 0 and 0 if k is negative.</p>
     *
     * <p>Computes: <code>(n*...*(n-k+1)) / (k*...*1)</code>.</p>
     *
     * <p>For k &gt;= 0, the binomial coefficient is a polynomial
     * of degree k in the parameter n.  This polynomial is
     * characterized by two conditions.</p>
     *
     * <ul>
     *   <li>It has k roots at n = 0, ..., (k - 1).</li>
     *   <li>It has value 1 at n = k.</li>
     * </ul>
     *
     * <p>In particular, this polynomial has well-defined values
     * when n is negative.  These values are positive if k is even
     * and negative if k is odd as is easily seen from the formula
     * given above.</p>
     *
     * @param n the set size
     * @param k the subset size
     */
    public static XBigInteger binomial(int n, int k) {
        if (k < 0)
            return new XBigInteger();
        
        if (k == 0)
            return new XBigInteger(1);
        
        if ((n >= 0) && (n < k))
            return new XBigInteger();
        
        if ((n >= 0) && (n == k))
            return new XBigInteger(1);
        
        if ((n >= 0) && (n < (2 * k)))
            k = n - k;
        
        XBigInteger result = new XBigInteger(n--);
        
        int d = 2;
        
        while (k > 1) {
            result.multiply(new XBigInteger(n--));
            result.divide  (new XBigInteger(d++));
            k--;
        }
        
        return result;
    }
    
    
    /**
     * <p>Returns an array of <code>BigInteger</code> objects 
     * initialized from the given array 
     * of <code>XBigInteger</code> objects.</p>
     * 
     * @param x an array of <code>XBigInteger</code>s
     */
    public static BigInteger[] toPrimitiveArray(XBigInteger[] x) {
        // return null array if appropriate
        if (x == null)
            return null;
        
        // otherwise perform the type translation
        BigInteger[] temp = new BigInteger[x.length];
        
        for (int i = 0; i < temp.length; i++)
            if (x[i] != null)
                temp[i] = x[i].getValue();
        
        return temp;
    }
    
    
    /**
     * <p>Returns an array of <code>XBigInteger</code> objects
     * initialized from the given array 
     * of <code>BigInteger</code> objects.</p>
     * 
     * @param a an array of <code>BigInteger</code>s
     */
    public static XBigInteger[] toXArray(BigInteger[] a) {
        // return null array if appropriate
        if (a == null)
            return null;
        
        // otherwise perform the type translation
        XBigInteger[] temp = new XBigInteger[a.length];
        
        for (int i = 0; i < temp.length; i++)
            if (a[i] != null)
                temp[i] = new XBigInteger(a[i]);
        
        return temp;
    }
    
}
