package org.geogebra.common.kernel.commands; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.algos.AlgoFoldExpression; import org.geogebra.common.kernel.algos.AlgoFoldFunctions; import org.geogebra.common.kernel.algos.AlgoSum; import org.geogebra.common.kernel.algos.FoldComputer; import org.geogebra.common.kernel.algos.FunctionFold; import org.geogebra.common.kernel.algos.FunctionNvarFold; import org.geogebra.common.kernel.algos.ListFold; import org.geogebra.common.kernel.algos.NumberFold; import org.geogebra.common.kernel.algos.PointNDFold; import org.geogebra.common.kernel.algos.TextFold; import org.geogebra.common.kernel.arithmetic.Command; import org.geogebra.common.kernel.arithmetic.VectorValue; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoFunction; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoNumberValue; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.main.MyError; import org.geogebra.common.plugin.GeoClass; import org.geogebra.common.plugin.Operation; /** * Sum[ list ] adapted from CmdLcm by Michael Borcherds 2008-02-16 */ public class CmdSum extends CommandProcessor { /** * Creates new command processor * * @param kernel * kernel */ public CmdSum(Kernel kernel) { super(kernel); } @Override public GeoElement[] process(Command c) throws MyError { int n = c.getArgumentNumber(); GeoElement[] arg; // needed for Sum[] if (c.getArgumentNumber() == 0) { throw argNumErr(app, c, n); } if (c.getArgumentNumber() == 4) { GeoElement[] res = processSymb(this, c, Operation.PLUS); if (res != null) { return res; } } arg = resArgs(c); // set all to either true or false GeoList list = null; FoldComputer fold = null; if (arg[0].isGeoList()) { list = (GeoList) arg[0]; fold = getComputer(list); } // this is bad - list can be saved later with size 0 // if (size == 0) throw argErr(app, c, arg[0]); switch (n) { case 1: if (fold instanceof NumberFold) { GeoElement[] ret = { Sum(c.getLabel(), list) }; return ret; } else if (fold != null) { GeoElement[] ret = { Sum(c.getLabel(), list, null, fold) }; return ret; } throw argErr(app, c, arg[0]); case 2: if (arg[1].isGeoNumeric()) { if (fold instanceof NumberFold) { AlgoSum algo = new AlgoSum(cons, c.getLabel(), list, (GeoNumeric) arg[1]); GeoElement[] ret = { algo.getResult() }; return ret; } else if (fold != null) { GeoElement[] ret = { Sum(c.getLabel(), list, (GeoNumeric) arg[1], fold) }; return ret; } else { throw argErr(app, c, arg[0]); } } else if (arg[1].isGeoList()) { if (((GeoList) arg[0]) .getGeoElementForPropertiesDialog() instanceof GeoNumberValue) { AlgoSum algo = new AlgoSum(cons, c.getLabel(), list, (GeoList) arg[1]); GeoElement[] ret = { algo.getResult() }; return ret; } throw argErr(app, c, arg[0]); } throw argErr(app, c, arg[0]); default: // try to create list of numbers if (arg[0] instanceof GeoNumberValue) { GeoList wrapList = wrapInList(kernelA, arg, arg.length, GeoClass.NUMERIC); if (wrapList != null) { GeoElement[] ret = { Sum(c.getLabel(), wrapList) }; return ret; } } else if (arg[0] instanceof VectorValue) { // try to create list of points GeoList wrapList = wrapInList(kernelA, arg, arg.length, GeoClass.POINT); if (wrapList != null) { GeoElement[] ret = { Sum(c.getLabel(), wrapList, null, new PointNDFold()) }; return ret; } } else if (arg[0].isGeoFunction()) { // try to create list of functions GeoList wrapList = wrapInList(kernelA, arg, arg.length, GeoClass.FUNCTION); if (wrapList != null) { GeoElement[] ret = { Sum(c.getLabel(), wrapList, null, new FunctionFold()) }; return ret; } } else if (arg[0].isGeoFunction()) { // try to create list of functions GeoList wrapList = wrapInList(kernelA, arg, arg.length, GeoClass.FUNCTION_NVAR); if (wrapList != null) { GeoElement[] ret = { Sum(c.getLabel(), wrapList, null, new FunctionNvarFold()) }; return ret; } } else if (arg[0].isGeoText()) { // try to create list of functions GeoList wrapList = wrapInList(kernelA, arg, arg.length, GeoClass.TEXT); if (wrapList != null) { GeoElement[] ret = { Sum(c.getLabel(), wrapList, null, new TextFold()) }; return ret; } } else if (arg[0].isGeoList()) { // try to create list of functions GeoList wrapList = wrapInList(kernelA, arg, arg.length, GeoClass.LIST); if (wrapList != null) { GeoElement[] ret = { Sum(c.getLabel(), wrapList, null, new ListFold()) }; return ret; } } throw argNumErr(app, c, n); } } /** * @param list * list * @return helper for Sum/Product commands */ public static FoldComputer getComputer(GeoList list) { boolean allNumbers = true; boolean allFunctions = allNumbers; boolean allFunctionsND = allNumbers; boolean allNumbersVectorsPoints = allNumbers; boolean allText = allNumbers; boolean allList = allNumbers; int size = list.size(); for (int i = 0; i < size; i++) { GeoElement geo = list.get(i); if (!geo.isGeoFunctionable() && !geo.isGeoFunctionNVar()) { allFunctionsND = false; } if (!geo.isGeoFunctionable() || (geo.isGeoFunction() && ((GeoFunction) geo).isFunctionOfY())) { allFunctions = false; } if (!(geo instanceof GeoNumberValue)) { allNumbers = false; } if (!(geo.isGeoList())) { allList = false; } if (!(geo instanceof GeoNumberValue) && !geo.isGeoVector() && !geo.isGeoPoint()) { allNumbersVectorsPoints = false; } if (!geo.isGeoText()) { allText = false; } } if (allNumbers) { return new NumberFold(); } if (allNumbersVectorsPoints) { return new PointNDFold(); } if (allFunctions) { return new FunctionFold(); } if (allFunctionsND) { return new FunctionNvarFold(); } if (allText) { return new TextFold(); } if (allList) { return new ListFold(); } return null; } /** * @param proc * processor (product/sum) * @param c * command * @param op * operation * @return sum/product object if applicable */ static GeoElement[] processSymb(CommandProcessor proc, Command c, Operation op) { GeoElement[] arg = proc.resArgsLocalNumVar(c, 1, 2); if (!arg[1].isGeoNumeric() || !arg[2].isGeoNumeric() || !arg[3].isGeoNumeric()) { return null; } AlgoFoldExpression algo = new AlgoFoldExpression(proc.cons, c.getLabel(), arg[0], (GeoNumeric) arg[1], (GeoNumeric) arg[2], (GeoNumeric) arg[3], op); return algo.getOutput(); } final private GeoElement Sum(String label, GeoList list) { AlgoSum algo = new AlgoSum(cons, label, list); GeoElement ret = algo.getResult(); return ret; } /** * Sum[list of text,n] Michael Borcherds */ final private GeoElement Sum(String label, GeoList list, GeoNumeric num, FoldComputer fold) { AlgoFoldFunctions algo = new AlgoFoldFunctions(cons, label, list, num, Operation.PLUS, fold); GeoElement ret = algo.getResult(); return ret; } }