예제 #1
0
  public GeoElement[] processFunctionNVar(ExpressionNode funNode, FunctionNVar fun) {
    fun.initFunction();

    String label = fun.getLabel();
    GeoElement[] ret = new GeoElement[1];

    GeoElement[] vars = fun.getGeoElementVariables();
    boolean isIndependent = (vars == null || vars.length == 0);

    if (isIndependent) {
      ret[0] = kernel.FunctionNVar(label, fun);
    } else {
      ret[0] = kernel.DependentFunctionNVar(label, fun);
    }
    return ret;
  }
예제 #2
0
  /**
   * Evaluates this function using the given CAS command. Caching is used for symbolic CAS
   * evaluations.
   *
   * @param ggbCasCmd the GeoGebraCAS command needs to include % in all places where the function f
   *     should be substituted, e.g. "Derivative(%,x)"
   * @param symbolic true for symbolic evaluation, false to use values of GeoElement variables
   * @return resulting function
   */
  public final FunctionNVar evalCasCommand(String ggbCasCmd, boolean symbolic) {
    // remember expression and its CAS string
    boolean useCaching = true;

    // for multi-variate functions we need to ensure value form,
    // i.e. f(x,m)=x^2+m, g(x)=f(x,2), Derivative[g] gets sent as Derivative[x^2+2] instead of
    // Derivative[f(x,2)]
    // see http://www.geogebra.org/trac/ticket/1466
    symbolic = symbolic && !expression.containsObjectType(GeoFunctionNVar.class);

    // make sure to use temporary variable names
    // e.g. a in Derivative[a*x^2,x] needs to be renamed temporarily when a exists in GeoGebra
    // see http://www.geogebra.org/trac/ticket/929
    boolean oldTempVariableValue = kernel.isUseTempVariablePrefix();
    kernel.setUseTempVariablePrefix(true);

    // did expression change since last time?
    if (casEvalExpression != expression) {
      casEvalExpression = expression;
      if (symbolic) {
        casEvalStringSymbolic = expression.getCASstring(ExpressionNode.STRING_TYPE_GEOGEBRA, true);
      }

      // caching should only be done if the expression doesn't contain
      // other functions
      // e.g. this is important for f(x) = x^2, g(x,y) = f(x) + y,
      // Derivative(g(x,y), x)
      // where we cannot cache the derivative of g because g may have
      // changed
      useCaching = symbolic && !expression.containsObjectType(CasEvaluableFunction.class);
    }

    // build command string for CAS
    String expString =
        symbolic
            ? casEvalStringSymbolic
            : expression.getCASstring(ExpressionNode.STRING_TYPE_GEOGEBRA, false);

    // set back kernel
    kernel.setUseTempVariablePrefix(oldTempVariableValue);

    // substitute % by expString in ggbCasCmd
    String casString = ggbCasCmd.replaceAll("%", expString);
    FunctionNVar resultFun = null;

    // eval with CAS
    try {
      if (useCaching) {
        // check if result is in cache
        resultFun = lookupCasEvalMap(casString);
        if (resultFun != null) {
          // System.out.println("caching worked: " + casString + " -> " + resultFun);
          return resultFun;
        }
      }

      // evaluate expression by CAS
      String result =
          symbolic
              ? kernel.evaluateGeoGebraCAS(casString)
              : // symbolic
              kernel.evaluateCachedGeoGebraCAS(casString); // value string
      // System.out.println("evaluateGeoGebraCAS: " + casString + " -> " + result);

      // parse CAS result back into GeoGebra
      sb.setLength(0);
      sb.append("f("); // this name is never used, just needed for parsing
      sb.append(getVarString());
      sb.append(") = ");
      sb.append(result);

      // parse result
      if (getVarNumber() == 1) {
        resultFun = kernel.getParser().parseFunction(sb.toString());
      } else {
        resultFun = kernel.getParser().parseFunctionNVar(sb.toString());
      }

      resultFun.initFunction();
    } catch (Error err) {
      err.printStackTrace();
      resultFun = null;
    } catch (Exception e) {
      e.printStackTrace();
      resultFun = null;
    } catch (Throwable e) {
      resultFun = null;
    }

    // cache result
    if (useCaching && resultFun != null) {
      getCasEvalMap().put(casString, resultFun);
    }

    // System.out.println("NO caching: " + casString + " -> " + resultFun);

    return resultFun;
  }