package org.matheclipse.core.reflection.system;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractFunctionEvaluator;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.generic.BinaryBindIth1st;
import org.matheclipse.core.generic.BinaryEval;
import org.matheclipse.core.generic.Functors;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
/**
* Differentiation of a function. See Wikipedia:Derivative
*/
public class D extends AbstractFunctionEvaluator {
public D() {
}
/**
* Search for one of the Derivative[..] rules from the System.mep file read at startup time.
*
* Examples for rules from the System.mep file:
* Derivative[Cos]=(-1)*Sin[#]&
* Derivative[Sin]=Cos[#]&
* Derivative[Tan]=Cos[#]^(-2)&
*
* @param x
* @param arg1
* @param header
* @return
*/
private IExpr getDerivativeArg1(IExpr x, final IExpr arg1, final IExpr header) {
IExpr der = F.evalNull(F.Derivative, header);
if (der != null) {
// we've found a derivative for a function of the form f[x_]
IExpr derivative = F.eval(F.$(der, arg1));
return F.Times(derivative, F.D(arg1, x));
}
return null;
}
@Override
public IExpr evaluate(final IAST ast) {
if (ast.size() < 3) {
return null;
}
IExpr fx = ast.arg1();
if (ast.size() > 3) {
// reduce arguments by folding D[fxy, x, y] to D[ D[fxy, x], y] ...
return ast.range(2).foldLeft(new BinaryEval(F.D), fx);
}
if (fx.isList()) {
// thread over first list
return ((IAST) fx).args().map(F.List(), Functors.replace1st(ast));
}
IExpr x = ast.arg2();
int n = 1;
if (x.isList()) {
// D[fx_, {...}]
IAST xList = (IAST) x;
if (xList.size() == 2 && xList.arg1().isList()) {
IAST subList = (IAST) xList.arg1();
return subList.args().mapLeft(F.List(), new BinaryEval(F.D), fx);
} else if (xList.size() == 3 && xList.arg2().isInteger()) {
n = Validate.checkIntType(xList, 2, 1);
if (xList.arg1().isList()) {
x = F.List(xList.arg1());
} else {
x = xList.arg1();
}
for (int i = 0; i < n; i++) {
fx = F.eval(F.D, fx, x);
}
return fx;
}
return null;
}
if (!(x.isList()) && fx.isFree(x, true)) {
return F.C0;
}
if (fx.isNumber()) {
// D[x_NumberQ,y_] -> 0
return F.C0;
}
if (fx.equals(x)) {
if (n == 1) {
// D[x_,x_] -> 1
return F.C1;
}
return F.C0;
}
if (fx.isAST()) {
final IAST listArg1 = (IAST) fx;
final IExpr header = listArg1.head();
if (header == F.Plus) {
// D[a_+b_+c_,x_] -> D[a,x]+D[b,x]+D[c,x]
return listArg1.map(Functors.replace1st(F.D(F.Null, x)));
} else if (header == F.Times) {
return listArg1.args().map(F.Plus(), new BinaryBindIth1st(listArg1, F.D(F.Null, x)));
} else if (listArg1.isPower()) {
if (listArg1.arg2().isFree(x, true)) {
// D[x_^i_NumberQ, z_]:= i*x^(i-1)*D[x,z];
final IAST timesList = F.Times();
timesList.add(listArg1.arg2());
final IAST powerList = F.Power();
powerList.add(listArg1.arg1());
final IAST plusList = F.Plus();
plusList.add(listArg1.arg2());
plusList.add(F.CN1);
powerList.add(plusList);
timesList.add(powerList);
timesList.add(F.D(listArg1.arg1(), ast.arg2()));
return timesList;
} else {
// D[f_^g_,y_]:= f^g*(((g*D[f,y])/f)+Log[f]*D[g,y])
final IAST resultList = F.Times();
final IExpr f = listArg1.arg1();
final IExpr g = listArg1.arg2();
final IExpr y = ast.arg2();
IAST powerList = F.Power();
powerList.add(f);
powerList.add(g);
resultList.add(powerList);
final IAST plusList = F.Plus();
IAST timesList = F.Times();
timesList.add(g);
timesList.add(F.D(f, y));
timesList.add(F.Power(f, F.CN1));
plusList.add(timesList);
timesList = F.Times(F.Log(f), F.D(g, y));
plusList.add(timesList);
resultList.add(plusList);
return resultList;
}
} else if ((header == F.Log) && (listArg1.size() == 3)) {
if (listArg1.arg1().isFree(x, true)) {
// D[Log[i_FreeQ(x), x_], z_]:= (x*Log[a])^(-1)*D[x,z];
return F.Times(F.Power(F.Times(listArg1.arg2(), F.Log(listArg1.arg1())), F.CN1), F.D(listArg1.arg2(), x));
}
} else if (listArg1.size() == 2) {
return getDerivativeArg1(x, listArg1.arg1(), header);
}
}
return null;
}
}
Ads help maintain this website.