/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmathexpr.arithmetic.integer.impl;
import jmathexpr.arithmetic.ANumber;
import jmathexpr.arithmetic.Numbers;
import jmathexpr.arithmetic.integer.IntegerNumber;
import jmathexpr.arithmetic.natural.NaturalNumber;
import jmathexpr.arithmetic.natural.impl.LongNaturalNumber;
import jmathexpr.arithmetic.op.Exponentiation;
import jmathexpr.arithmetic.rational.RationalNumber;
import jmathexpr.arithmetic.rational.impl.LongRationalNumber;
import jmathexpr.arithmetic.real.RealNumber;
import jmathexpr.arithmetic.real.impl.DoubleRealNumber;
/**
*
* @author Elemér Furka
*/
public class LongIntegerNumber extends IntegerNumber {
final long value;
public LongIntegerNumber(long value) {
this.value = value;
}
@Override
public LongIntegerNumber evaluate() {
return this;
}
@Override
public ANumber add(ANumber addend) {
if (addend instanceof LongIntegerNumber) {
return new LongIntegerNumber(value + ((LongIntegerNumber) addend).value);
} else {
return Numbers.add(this, addend);
}
}
@Override
public ANumber subtract(ANumber subtrahend) {
if (subtrahend instanceof LongIntegerNumber) {
return new LongIntegerNumber(value - ((LongIntegerNumber) subtrahend).value);
} else {
return Numbers.subtract(this, subtrahend);
}
}
@Override
public ANumber multiply(ANumber multiplier) {
if (multiplier instanceof LongIntegerNumber) {
return new LongIntegerNumber(value * ((LongIntegerNumber) multiplier).value);
} else {
return Numbers.multiply(this, multiplier);
}
}
@Override
public boolean equals(Object object) {
if (object == null) return false;
if (this == object) return true;
if (object instanceof LongIntegerNumber) {
LongIntegerNumber other = (LongIntegerNumber) object;
return value == other.value;
} else if (object instanceof ANumber) {
return Numbers.equal(this, (ANumber) object);
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + (int) (this.value ^ (this.value >>> 32));
return hash;
}
@Override
public String toString() {
return Long.toString(value);
}
@Override
public boolean isNatural() {
return value >= 0;
}
@Override
public LongIntegerNumber negate() {
return new LongIntegerNumber(-value);
}
@Override
public boolean isNegative() {
return value < 0;
}
@Override
public boolean isZero() {
return value == 0;
}
@Override
public ANumber divide(ANumber divisor) {
if (divisor instanceof LongIntegerNumber) {
LongIntegerNumber rhs = (LongIntegerNumber) divisor;
if (value % rhs.value == 0) {
return new LongIntegerNumber(value / rhs.value);
} else {
return rhs.value > 0 ? new LongRationalNumber(value, rhs.value).evaluate() :
new LongRationalNumber(-value, -rhs.value).evaluate();
}
} else {
return Numbers.divide(this, divisor);
}
}
@Override
public IntegerNumber mod(NaturalNumber modulus) {
return new LongIntegerNumber(value % modulus.longValue());
}
@Override
public boolean isOne() {
return value == 1;
}
@Override
public ANumber pow(ANumber exponent) {
if (exponent instanceof LongNaturalNumber) {
LongIntegerNumber exp = (LongIntegerNumber) ((LongNaturalNumber) exponent).toInteger();
if (exp.value == 0) {
if (value != 0) {
return new LongNaturalNumber(1);
} else {
throw new ArithmeticException(
String.format("Result is undefined: %s", new Exponentiation(this, exponent)));
}
} else if (exp.value == 1) {
return this;
} else {
return new LongIntegerNumber(pow(value, exp.value));
}
} else {
throw new IllegalArgumentException(exponent.getClass() + " Expected: LongNaturalNumber");
}
}
/**
* Returns a^b (a raised to b) where the parameters are of type Java long.
* Should only used internally!
*
* @param base the base (a)
* @param exponent the exponent (b)
* @return the base raised to the exponent as a Java long value
*/
private static long pow(long base, long exponent) {
long result = 1;
long b = base;
while (exponent != 0) {
if ((exponent & 1) == 1) {
result *= b;
}
exponent >>= 1;
b *= b;
}
return result;
}
@Override
public RealNumber toReal() {
return new DoubleRealNumber(value);
}
@Override
public boolean le(ANumber expr) {
if (expr instanceof LongIntegerNumber) {
return value <= ((LongIntegerNumber) expr).value;
} else {
throw new IllegalArgumentException(expr.getClass() + " Expected: LongIntegerNumber");
}
}
@Override
public boolean lt(ANumber expr) {
if (expr instanceof LongIntegerNumber) {
return value < ((LongIntegerNumber) expr).value;
} else {
return Numbers.lt(this, expr);
}
}
@Override
public RationalNumber toRational() {
return new LongRationalNumber(value, 1);
}
@Override
public NaturalNumber toNatural() {
if (value >= 0) {
return new LongNaturalNumber(value);
} else {
throw new IllegalStateException("Cannot convert into a natural number: " + value);
}
}
}