// @(#)$Id: JMLFiniteInteger.java,v 1.22 2007/02/08 14:05:50 leavens Exp $
// Copyright (C) 2005 Iowa State University
//
// This file is part of the runtime library of the Java Modeling Language.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either version 2.1,
// of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with JML; see the file LesserGPL.txt. If not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
// 02110-1301 USA.
package org.jmlspecs.unfinished;
import java.math.BigInteger;
/** Arbitrary precision integers with a finite value.
*
* @version $Revision: 1.22 $
* @author Gary T. Leavens
* @see java.math.BigInteger
*/
//-@ immutable
public /*@ pure @*/ class JMLFiniteInteger extends JMLInfiniteIntegerClass {
protected final /*@ non_null */ BigInteger val;
//@ in sign, finite_value, is_infinite;
//@ protected represents finite_value <- val;
//@ protected represents sign <- val.signum();
//@ protected represents is_infinite <- false;
//@ public invariant !is_infinite;
/** The number zero (0).
*/
public static final JMLFiniteInteger ZERO
= new JMLFiniteInteger();
/** The number one (1).
*/
public static final JMLFiniteInteger ONE
= new JMLFiniteInteger(BigInteger.ONE);
/** Initialize this finite integer to zero (0).
*/
/*@ public normal_behavior
@ assignable nonnegative, sign, is_infinite, finite_value;
@ ensures !is_infinite;
@ ensures finite_value.equals(BigInteger.ZERO);
also private normal_behavior
modifies val;
@*/
public JMLFiniteInteger() { val = BigInteger.ZERO; }
/** Initialize this finite integer from the given BigInteger.
*/
/*@ public behavior
@ assignable nonnegative, sign, is_infinite, finite_value;
@ ensures !is_infinite && finite_value.equals(n);
@ signals_only IllegalArgumentException;
@ signals (IllegalArgumentException) n == null;
@*/
public JMLFiniteInteger(/*@ non_null @*/ BigInteger n)
throws IllegalArgumentException
{
if (n != null) {
val = n;
} else {
throw new IllegalArgumentException();
}
}
/** Initialize this finite integer from the given long.
*/
public JMLFiniteInteger(long n) { val = BigInteger.valueOf(n); }
/** Return the sign of this integer.
*/
public int signum() { return val.signum(); }
/** Return true.
*/
public boolean isFinite() { return true; }
/** Return the value of this integer.
*/
public BigInteger finiteValue() { return val; }
/** Compare this to the given integer, returning a comparison code.
*/
public int compareTo(JMLInfiniteInteger n) {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
return val.compareTo(((JMLFiniteInteger)n).val);
} else {
return -1 * n.signum();
}
}
/** Compare this to o, returning a comparison code.
* @param o the object this is compared to.
* @exception ClassCastException when o is not
* a JMLInfiniteInteger or a BigInteger.
*/
public int compareTo(/*@ non_null @*/ Object o)
throws NullPointerException, ClassCastException
{
if (o == null) {
throw new NullPointerException();
} else if (o instanceof BigInteger) {
return val.compareTo((BigInteger)o);
} else if (o instanceof JMLFiniteInteger) {
return val.compareTo(((JMLFiniteInteger)o).val);
} else if (o instanceof JMLPositiveInfinity) {
return -1;
} else if (o instanceof JMLNegativeInfinity) {
return +1;
} else {
throw new ClassCastException();
}
}
/** Return a hash code for this object.
*/
public int hashCode() { return val.hashCode(); }
/** Return the negation of this integer.
*/
public JMLInfiniteInteger negate() {
BigInteger n = val.negate();
//@ assume n != null;
return new JMLFiniteInteger(n);
}
/** Return the sum of this integer and the argument.
*/
public JMLInfiniteInteger add(JMLInfiniteInteger n) {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
BigInteger s = val.add(((JMLFiniteInteger)n).val);
//@ assume s != null;
return new JMLFiniteInteger(s);
} else {
return n;
}
}
/** Return the difference between this integer and the argument.
*/
public JMLInfiniteInteger subtract(JMLInfiniteInteger n) {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
BigInteger s = val.subtract(((JMLFiniteInteger)n).val);
//@ assume s != null;
return new JMLFiniteInteger(s);
} else {
return n.negate();
}
}
/** Return the product of this integer and the argument.
*/
public JMLInfiniteInteger multiply(JMLInfiniteInteger n) {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
BigInteger s = val.multiply(((JMLFiniteInteger)n).val);
//@ assume s != null;
return new JMLFiniteInteger(s);
} else if (val.equals(BigInteger.ZERO)) {
return ZERO; //FIXME - ZERO * infinity ????
} else if (val.signum() == +1) {
return n;
} else {
JMLInfiniteInteger ret = n.negate();
//@ assume ret != null;
return ret;
}
}
/** Return the quotient of this integer divided by the argument.
*/
public JMLInfiniteInteger divide(JMLInfiniteInteger n) {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
BigInteger s = val.divide(((JMLFiniteInteger)n).val);
//@ assume s != null;
return new JMLFiniteInteger(s);
} else {
return ZERO;
}
}
/** Return the remainder of this integer divided by the argument.
*/
public JMLInfiniteInteger remainder(JMLInfiniteInteger n) {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
BigInteger s = val.remainder(((JMLFiniteInteger)n).val);
//@ assume s != null;
return new JMLFiniteInteger(s);
} else if (n.signum() == +1) {
return this;
} else {
return this.negate();
}
}
/** Return this integer modulo the argument.
*/
public JMLInfiniteInteger mod(JMLInfiniteInteger n)
throws ArithmeticException {
//@ assume n != null;
if (n instanceof JMLFiniteInteger) {
BigInteger s = val.mod(((JMLFiniteInteger)n).val);
//@ assume s != null;
return new JMLFiniteInteger(s);
} else if (n.signum() == +1) {
return n;
} else {
throw new ArithmeticException("negative divisor for mod");
}
}
/** Return this integer raised to the argument's power.
*/
public JMLInfiniteInteger pow(int n) {
BigInteger s = val.pow(n);
//@ assume s != null;
return new JMLFiniteInteger(s);
}
/** Return this integer approximated by a double.
*/
public double doubleValue() { return val.doubleValue(); }
/** Return this integer approximated by a float.
*/
public float floatValue() { return val.floatValue(); }
/** Return the decimal representation of this integer.
*/
public String toString() { return val.toString(); }
/** Return the digits representing this integer in the given radix.
*/
public String toString(int radix) { return val.toString(radix); }
/** Converts this BigInteger to a long
*/
public long longValue() { return val.longValue(); }
/** Converts this BigInteger to an integer
*/
public int intValue() { return val.intValue(); }
}