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.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IInteger;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.parser.client.SyntaxError;
import com.google.common.base.Function;
/**
*
*/
public class Coefficient extends AbstractFunctionEvaluator {
private class PlusFunction implements Function {
IExpr arg2;
IInteger n;
public PlusFunction(IExpr arg2, IInteger n) {
this.arg2 = arg2;
this.n = n;
}
@Override
public IExpr apply(IExpr from) throws ArithmeticException {
if (from.isPower()) {
return coefficientPower((IAST) from, arg2, n);
} else if (from.isTimes()) {
return coefficientTimes((IAST) from, arg2, n);
} else {
return coefficientAtom(from, arg2, n);
}
}
}
public Coefficient() {
}
@Override
public IExpr evaluate(final IAST ast) {
Validate.checkRange(ast, 3, 4);
IExpr expr = F.evalExpandAll(ast.arg1());
IExpr arg2 = ast.arg2();
if (!arg2.isSymbol()) {
// TODO allow multinomials
return null;
}
try {
IInteger n = F.C1;
if (ast.size() == 4) {
n = Validate.checkIntegerType(ast, 3);
}
if (expr.isAST()) {
IAST expAST = (IAST) expr;
Function plusFunction = new PlusFunction(arg2, n);
if (expAST.isPlus()) {
// TODO implement a special sum() method instead of map
IAST filterAST = expAST.map(plusFunction);
if (filterAST.size() == 1) {
return F.C0;
}
return F.eval(filterAST);
} else {
return plusFunction.apply(expAST);
}
} else {
return coefficientAtom(expr, arg2, n);
}
} catch (ArithmeticException ae) {
}
return null;
}
private static IExpr coefficientTimes(IAST times, IExpr arg2, IInteger n) throws ArithmeticException {
for (int i = 1; i < times.size(); i++) {
if (times.get(i).isPower()) {
IAST pow = (IAST) times.get(i);
if (pow.arg1().equals(arg2)) {
if (pow.arg2().isNumEqualInteger(n)) {
times = times.clone();
times.remove(i);
return times;
}
return F.C0;
}
} else if (times.get(i).equals(arg2)) {
if (n.equals(F.C0)) {
return F.C0;
} else if (n.equals(F.C1)) {
times = times.clone();
times.remove(i);
return times;
}
return F.C0;
}
}
if (n.equals(F.C0)) {
return times;
}
return F.C0;
}
private static IExpr coefficientPower(IAST powerAST, IExpr arg2, IInteger n) {
if (powerAST.arg1().equals(arg2)) {
if (powerAST.arg2().isNumEqualInteger(n)) {
return F.C1;
}
return F.C0;
}
return powerAST;
}
private static IExpr coefficientAtom(IExpr expr, IExpr arg2, IInteger n) {
if (n.equals(F.C0)) {
if (expr.equals(arg2)) {
return F.C0;
}
return expr;
} else if (n.equals(F.C1)) {
if (expr.equals(arg2)) {
return F.C1;
}
return F.C0;
}
return F.C0;
}
@Override
public void setUp(final ISymbol symbol) throws SyntaxError {
symbol.setAttributes(ISymbol.LISTABLE);
super.setUp(symbol);
}
}
Ads help maintain this website.