protected final void compute() { size = inputList.size(); if (!inputList.isDefined()) { outputList.setUndefined(); return; } outputList.setDefined(true); outputList.clear(); if (size == 0) return; // <Zbynek Konecny 2010-05-13> /* * If val is not numeric, we use the underlying Expression of the function and * plug the list element as variable. * Deep copy is needed so that we can plug the value repeatedly. */ FunctionVariable var = boolFun.getFunction().getFunctionVariable(); for (int i = 0; i < size; i++) { GeoElement geo = inputList.get(i); if (geo.isGeoNumeric()) { if (boolFun.evaluateBoolean(((GeoNumeric) geo).getValue())) outputList.add(geo.copyInternal(cons)); ; } else { ExpressionNode ex = (ExpressionNode) boolFun.getFunction().getExpression().deepCopy(kernel); ex.replaceAndWrap(var, geo.evaluate()); if (((MyBoolean) ex.evaluate()).getBoolean()) outputList.add(geo.copyInternal(cons)); ; } } // </Zbynek> }
/** * Parses given String str and tries to evaluate it to a double. Returns Double.NaN if something * went wrong. */ public double evaluateToDouble(String str, boolean suppressErrors) { try { ValidExpression ve = parser.parseExpression(str); ExpressionNode en = (ExpressionNode) ve; en.resolveVariables(); NumberValue nv = (NumberValue) en.evaluate(); return nv.getDouble(); } catch (Exception e) { e.printStackTrace(); if (!suppressErrors) app.showError("InvalidInput", str); return Double.NaN; } catch (MyError e) { e.printStackTrace(); if (!suppressErrors) app.showError(e); return Double.NaN; } catch (Error e) { e.printStackTrace(); if (!suppressErrors) app.showError("InvalidInput", str); return Double.NaN; } }
// evaluate the current value of the arithmetic tree protected final void compute() { // get resulting list of ExpressionNodes ExpressionValue evlist = root.evaluate(); MyList myList = (evlist instanceof MyList) ? (MyList) evlist : ((GeoList) evlist).getMyList(); int evalListSize = myList.size(); int cachedListSize = list.getCacheSize(); list.clear(); for (int i = 0; i < evalListSize; i++) { ExpressionValue element = myList.getListElement(i).evaluate(); GeoElement geo = null; // number result if (element.isNumberValue()) { double val = ((NumberValue) element).getDouble(); // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a number: set value if (cachedGeo.isGeoNumeric()) { ((GeoNumeric) cachedGeo).setValue(val); geo = cachedGeo; } } // no cached number: create new one if (geo == null) { geo = new GeoNumeric(cons, val); } // add number to list list.add(geo); } // point else if (element.isVectorValue()) { GeoVec2D vec = ((VectorValue) element).getVector(); // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoPoint()) { ((GeoPoint) cachedGeo).setCoords(vec); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoPoint point = new GeoPoint(cons); point.setCoords(vec); geo = point; } // add point to list list.add(geo); } // needed for matrix multiplication // eg {{1,3,5},{2,4,6}}*{{11,14},{12,15},{13,a}} else if (element instanceof MyList) { MyList myList2 = (MyList) element; GeoList list2 = new GeoList(cons); list2.clear(); /* removed Michael Borcherds 20080602 * bug: 9PointCubic.ggb (matrix multiplication) // try to use cached element of type GeoList GeoList list2 = null; if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a number: set value if (cachedGeo.isGeoList()) { list2 = (GeoList) cachedGeo; } } if (list2 == null) { list2 = new GeoList(cons); } */ for (int j = 0; j < myList2.size(); j++) { ExpressionValue en = myList2.getListElement(j); ExpressionValue ev = en.evaluate(); if (ev instanceof MyDouble) { GeoNumeric geo2 = new GeoNumeric(cons); geo2.setValue(((NumberValue) ev).getDouble()); list2.add(geo2); } } list.add(list2); } else if (element instanceof MyStringBuffer) { MyStringBuffer str = (MyStringBuffer) element; // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoText()) { ((GeoText) cachedGeo).setTextString(str.toValueString()); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoText text = new GeoText(cons); text.setTextString(str.toValueString()); geo = text; } // add point to list list.add(geo); } else if (element instanceof MyBoolean) { MyBoolean bool = (MyBoolean) element; // try to use cached element of same type if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoBoolean()) { ((GeoBoolean) cachedGeo).setValue(bool.getBoolean()); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoBoolean geoBool = new GeoBoolean(cons); geoBool.setValue(bool.getBoolean()); geo = geoBool; } // add point to list list.add(geo); } else if (element instanceof GeoFunction) { GeoFunction fun = (GeoFunction) element; if (i < cachedListSize) { GeoElement cachedGeo = list.getCached(i); // the cached element is a point: set value if (cachedGeo.isGeoFunction()) { ((GeoFunction) cachedGeo).set(fun); geo = cachedGeo; } } // no cached point: create new one if (geo == null) { GeoFunction geoFun = new GeoFunction(cons); geoFun.set(fun); geo = geoFun; } list.add(geo); } else { Application.debug("unsupported list addition: " + element.getClass() + ""); } } }
public GeoElement[] processExpressionNode(ExpressionNode n) throws MyError { // command is leaf: process command if (n.isLeaf()) { ExpressionValue leaf = n.getLeft(); if (leaf instanceof Command) { Command c = (Command) leaf; c.setLabels(n.getLabels()); return cmdDispatcher.processCommand(c, true); } else if (leaf instanceof Equation) { Equation eqn = (Equation) leaf; eqn.setLabels(n.getLabels()); return processEquation(eqn); } else if (leaf instanceof Function) { Function fun = (Function) leaf; fun.setLabels(n.getLabels()); return processFunction(n, fun); } else if (leaf instanceof FunctionNVar) { FunctionNVar fun = (FunctionNVar) leaf; fun.setLabels(n.getLabels()); return processFunctionNVar(n, fun); } } // ELSE: resolve variables and evaluate expressionnode n.resolveVariables(); eval = n.evaluate(); boolean dollarLabelFound = false; ExpressionNode myNode = n; if (myNode.isLeaf()) myNode = myNode.getLeftTree(); // leaf (no new label specified): just return the existing GeoElement if (eval.isGeoElement() && n.getLabel() == null && !(n.operation.equals(Operation.ELEMENT_OF))) { // take care of spreadsheet $ names: don't loose the wrapper ExpressionNode here // check if we have a Variable switch (myNode.getOperation()) { case $VAR_COL: case $VAR_ROW: case $VAR_ROW_COL: // don't do anything here: we need to keep the wrapper ExpressionNode // and must not return the GeoElement here dollarLabelFound = true; break; default: // return the GeoElement GeoElement[] ret = {(GeoElement) eval}; return ret; } } if (eval.isBooleanValue()) return processBoolean(n, eval); else if (eval.isNumberValue()) return processNumber(n, eval); else if (eval.isVectorValue()) return processPointVector(n, eval); else if (eval.isVector3DValue()) return processPointVector3D(n, eval); else if (eval.isTextValue()) return processText(n, eval); else if (eval instanceof MyList) { return processList(n, (MyList) eval); } else if (eval instanceof Function) { return processFunction(n, (Function) eval); } else if (eval instanceof FunctionNVar) { return processFunctionNVar(n, (FunctionNVar) eval); } // we have to process list in case list=matrix1(1), but not when list=list2 else if (eval instanceof GeoList && myNode.hasOperations()) { Application.debug("should work"); return processList(n, ((GeoList) eval).getMyList()); } else if (eval.isGeoElement()) { // e.g. B1 = A1 where A1 is a GeoElement and B1 does not exist yet // create a copy of A1 if (n.getLabel() != null || dollarLabelFound) { return processGeoCopy(n.getLabel(), n); } } // REMOVED due to issue 131: http://code.google.com/p/geogebra/issues/detail?id=131 // // expressions like 2 a (where a:x + y = 1) // // A1=b doesn't work for these objects // else if (eval instanceof GeoLine) { // if (((GeoLine)eval).getParentAlgorithm() instanceof AlgoDependentLine) { // GeoElement[] ret = {(GeoElement) eval }; // return ret; // } // // } // if we get here, nothing worked Application.debug("Unhandled ExpressionNode: " + eval + ", " + eval.getClass()); return null; }