package com.googlecode.aviator.runtime.type;
import java.math.BigInteger;
import java.util.Map;
import com.googlecode.aviator.AviatorEvaluator;
/**
* Aviator Big Integer
*
* @since 2.3.0
* @author dennis<killme2008@gmail.com>
*
*/
public class AviatorBigInt extends AviatorLong {
private static class BigIntCache {
private BigIntCache() {
}
static final AviatorBigInt cache[] = new AviatorBigInt[256];
static {
for (long i = 0; i < cache.length; i++) {
cache[(int) i] = new AviatorBigInt(BigInteger.valueOf(i - 128));
}
}
}
public AviatorBigInt(Number number) {
super(number);
}
public static final AviatorBigInt valueOf(BigInteger v) {
return new AviatorBigInt(v);
}
public static final AviatorBigInt valueOf(String v) {
return new AviatorBigInt(new BigInteger(v));
}
public static final AviatorBigInt valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) {
return BigIntCache.cache[(int) l + offset];
}
return valueOf(BigInteger.valueOf(l));
}
@Override
public AviatorObject neg(Map<String, Object> env) {
return AviatorBigInt.valueOf(this.toBigInt().negate());
}
@Override
public AviatorObject innerSub(AviatorNumber other) {
switch (other.getAviatorType()) {
case Decimal:
return AviatorDecimal.valueOf(this.toDecimal().subtract(other.toDecimal(),
AviatorEvaluator.getMathContext()));
case Double:
return AviatorDouble.valueOf(this.doubleValue() - other.doubleValue());
default:
return AviatorBigInt.valueOf(this.toBigInt().subtract(other.toBigInt()));
}
}
@Override
public AviatorObject innerMult(AviatorNumber other) {
switch (other.getAviatorType()) {
case Decimal:
return AviatorDecimal.valueOf(this.toDecimal().multiply(other.toDecimal(),
AviatorEvaluator.getMathContext()));
case Double:
return AviatorDouble.valueOf(this.doubleValue() * other.doubleValue());
default:
return AviatorBigInt.valueOf(this.toBigInt().multiply(other.toBigInt()));
}
}
@Override
public AviatorObject innerMod(AviatorNumber other) {
switch (other.getAviatorType()) {
case Decimal:
return AviatorDecimal.valueOf(this.toDecimal().remainder(other.toDecimal(),
AviatorEvaluator.getMathContext()));
case Double:
return AviatorDouble.valueOf(this.doubleValue() % other.doubleValue());
default:
return AviatorBigInt.valueOf(this.toBigInt().mod(other.toBigInt()));
}
}
@Override
public AviatorObject innerDiv(AviatorNumber other) {
switch (other.getAviatorType()) {
case Decimal:
return AviatorDecimal
.valueOf(this.toDecimal().divide(other.toDecimal(), AviatorEvaluator.getMathContext()));
case Double:
return AviatorDouble.valueOf(this.doubleValue() / other.doubleValue());
default:
return AviatorBigInt.valueOf(this.toBigInt().divide(other.toBigInt()));
}
}
@Override
public AviatorNumber innerAdd(AviatorNumber other) {
switch (other.getAviatorType()) {
case Decimal:
return AviatorDecimal.valueOf(this.toDecimal().add(other.toDecimal(), AviatorEvaluator.getMathContext()));
case Double:
return AviatorDouble.valueOf(this.doubleValue() + other.doubleValue());
default:
return AviatorBigInt.valueOf(this.toBigInt().add(other.toBigInt()));
}
}
@Override
public int innerCompare(AviatorNumber other) {
switch (other.getAviatorType()) {
case Decimal:
return this.toDecimal().compareTo(other.toDecimal());
case Double:
return Double.compare(this.doubleValue(), other.doubleValue());
default:
return this.toBigInt().compareTo(other.toBigInt());
}
}
@Override
protected AviatorObject innerBitAnd(AviatorObject other) {
return AviatorBigInt.valueOf(this.toBigInt().and(((AviatorNumber) other).toBigInt()));
}
@Override
protected AviatorObject innerBitOr(AviatorObject other) {
return AviatorBigInt.valueOf(this.toBigInt().or(((AviatorNumber) other).toBigInt()));
}
@Override
protected AviatorObject innerBitXor(AviatorObject other) {
return AviatorBigInt.valueOf(this.toBigInt().xor(((AviatorNumber) other).toBigInt()));
}
@Override
protected AviatorObject innerShiftLeft(AviatorObject other) {
this.ensureLong(other);
return AviatorBigInt.valueOf(this.toBigInt().shiftLeft((int) ((AviatorNumber) other).longValue()));
}
@Override
protected AviatorObject innerShiftRight(AviatorObject other) {
this.ensureLong(other);
return AviatorBigInt.valueOf(this.toBigInt().shiftRight((int) ((AviatorNumber) other).longValue()));
}
@Override
protected AviatorObject innerUnsignedShiftRight(AviatorObject other) {
return this.innerShiftRight(other);
}
@Override
public AviatorType getAviatorType() {
return AviatorType.BigInt;
}
}