package builtin.math;
import builtin.BuiltinSub;
import java.math.BigInteger;
import gui.Heap;
import gui.MintException;
import gui.Pointer;
import gui.PointerTools;
import gui.SmartList;
/**
*
* @author Oliver Chu
*/
public class Factorial extends BuiltinSub {
private static final int[] preComputed = {1, 1, 2, 6, 24, 120, 720, 5040,
40320, 362880, 3628800, 39916800, 479001600};
public int factorial(int x) {
if (x < 0) {
return 1;
} else if (x <= 12) {
return preComputed[x];
}
return x * factorial(x - 1);
}
private BigInteger factorial(BigInteger x) {
BigInteger one = new BigInteger("1");
int cmp = x.compareTo(one);
if (cmp <= 0) {
return one;
}
return x.multiply(factorial(x.subtract(one)));
}
@Override
public Pointer apply(SmartList<Pointer> args) throws MintException {
Integer operand0 = PointerTools.dereferenceInt(args.get(0));
if (operand0 == null) {
BigInteger op0 = PointerTools.dereferenceBigInt(args.get(0));
if (op0 == null) {
throw new MintException("Factorial can only be applied to " +
"integers.");
}
return Heap.allocateBigInt(factorial(op0));
}
return Heap.allocateInt(factorial(operand0));
}
}