package builtin.math;
import builtin.BuiltinSub;
import gui.Constants;
import gui.Environment;
import gui.Heap;
import gui.Interpreter;
import gui.MintException;
import gui.Pointer;
import gui.PointerTools;
import gui.SmartList;
import gui.Subprogram;
/**
*
* @author Oliver Chu
*/
public class Differentiate extends BuiltinSub {
private class Fprime extends BuiltinSub {
private Subprogram function;
public void setSub(Subprogram f) {
function = f;
}
private double evaluate(double x) throws MintException {
double dx = 0.000001;
SmartList<Pointer> funcArgs = new SmartList<Pointer>();
funcArgs.add(Heap.allocateReal(x + dx));
SmartList<Pointer> funcArgs2 = new SmartList<Pointer>();
funcArgs2.add(Heap.allocateReal(x));
double df = PointerTools.dereferenceReal(
function.execute(new Environment(),
new SmartList<String>(), funcArgs, new Interpreter())) -
PointerTools.dereferenceReal(
function.execute(new Environment(),
new SmartList<String>(), funcArgs2, new Interpreter()));
return df / dx;
}
@Override
public Pointer apply(SmartList<Pointer> args) throws MintException {
Pointer a0 = args.get(0);
double ex;
if (a0.type == Constants.INT_TYPE) {
ex = (double) PointerTools.dereferenceInt(a0);
} else {
ex = PointerTools.dereferenceReal(a0);
}
return Heap.allocateReal(evaluate(ex));
}
}
@Override
public Pointer apply(SmartList<Pointer> args) throws MintException {
Pointer arg0 = args.get(0);
if (arg0.type != Constants.SUBPROGRAM_TYPE) {
throw new MintException("Must differentiate a subprogram that " +
"represents a one-argument mathematical function.");
}
Fprime fPrime = new Fprime();
fPrime.setSub(PointerTools.dereferenceSub(arg0));
SmartList<Pointer> sOfPtrs = new SmartList<Pointer>();
sOfPtrs.add(Heap.allocateName("x"));
Subprogram diffedSub = new Subprogram("fPrime", sOfPtrs, fPrime);
return Heap.allocateSub(diffedSub);
}
}