/** * Constructor for function definition in natural math language, * for instance providing on string "f(x,y) = sin(x) + cos(x)" * is enough to define function "f" with parameters "x and y" * and function body "sin(x) + cos(x)". * * @param functionDefinitionString Function definition in the form * of one String, ie "f(x,y) = sin(x) + cos(x)" * @param elements Optional elements list (variadic - comma separated) * of types: Argument, Constant, Function * * @see PrimitiveElement * */ public Function(String functionDefinitionString, params PrimitiveElement[] elements) : base(Function.TYPE_ID) { parametersNumber = 0; if (mXparser.regexMatch(functionDefinitionString, ParserSymbol.functionDefStrRegExp)) { HeadEqBody headEqBody = new HeadEqBody(functionDefinitionString); this.functionName = headEqBody.headTokens[0].tokenStr; functionExpression = new Expression(headEqBody.bodyStr, elements); functionExpression.setDescription(headEqBody.headStr); if (headEqBody.headTokens.Count > 1) { Token t; for (int i = 1; i < headEqBody.headTokens.Count; i++) { t = headEqBody.headTokens[i]; if (t.tokenTypeId != ParserSymbol.TYPE_ID) functionExpression.addArguments(new Argument(t.tokenStr)); } } parametersNumber = functionExpression.getArgumentsNumber() - countRecursiveArguments(); description = ""; addFunctions(this); } else { functionExpression = new Expression(); functionExpression.setDescription(functionDefinitionString); String errorMessage = ""; errorMessage = errorMessage + "\n [" + functionDefinitionString + "] " + "--> pattern not mathes: f(x1,...,xn) = ... reg exp: " + ParserSymbol.functionDefStrRegExp; functionExpression.setSyntaxStatus(Expression.SYNTAX_ERROR_OR_STATUS_UNKNOWN, errorMessage); } }
/** * Constructor - creates function from function name, * function expression string and argument names. * * @param functionName the function name * @param functionExpressionString the function expression string * @param argumentsNames the arguments names (variadic parameters) * comma separated list * * @see Expression */ public Function(String functionName ,String functionExpressionString ,params String[] argumentsNames) : base(Function.TYPE_ID) { if (mXparser.regexMatch(functionName, ParserSymbol.nameOnlyTokenRegExp)) { this.functionName = functionName; functionExpression = new Expression(functionExpressionString); functionExpression.setDescription(functionName); foreach (String argName in argumentsNames) functionExpression.addArguments(new Argument(argName)); parametersNumber = argumentsNames.Length - countRecursiveArguments(); description = ""; addFunctions(this); } else { parametersNumber = 0; description = ""; functionExpression = new Expression(""); functionExpression.setSyntaxStatus(SYNTAX_ERROR_OR_STATUS_UNKNOWN, "[" + functionName + "]" + "Invalid function name, pattern not matches: " + ParserSymbol.nameTokenRegExp); } }
/*================================================= * * Constructors * *================================================= */ /** * Constructor - creates function from function name * and function expression string. * * @param functionName the function name * @param functionExpressionString the function expression string * @param elements Optional elements list (variadic - comma separated) of types: Argument, Constant, Function * * @see PrimitiveElement * @see Expression */ public Function(String functionName ,String functionExpressionString, params PrimitiveElement[] elements) : base(Function.TYPE_ID) { if (mXparser.regexMatch(functionName, ParserSymbol.nameOnlyTokenRegExp)) { this.functionName = functionName; functionExpression = new Expression(functionExpressionString, elements); functionExpression.setDescription(functionName); parametersNumber = 0; description = ""; addFunctions(this); } else { parametersNumber = 0; description = ""; functionExpression = new Expression(""); functionExpression.setSyntaxStatus(SYNTAX_ERROR_OR_STATUS_UNKNOWN, "[" + functionName + "]" + "Invalid function name, pattern not matches: " + ParserSymbol.nameTokenRegExp); } }
/** * Gets recursive argument value * * @param index the index * * @return value as double */ public double getArgumentValue(double index) { /* * Remember starting index */ if (recursiveCounter == -1) startingIndex = (int)Math.Round(index); int recSize = baseValues.Count; int idx = (int)Math.Round(index); /* * Count recursive calls */ recursiveCounter++; if ((recursiveCounter <= startingIndex) && (idx <= startingIndex)) { /* * if recursive counter is still lower than starting index * and current index is not increasing */ if ((idx >= 0) && (idx < recSize) && (!Double.IsNaN( baseValues[idx] )) ) { /* * decrease recursive counter and return value * if recursive value for the current index was already * calculated and remembered in the base values table */ recursiveCounter--; return baseValues[idx]; } else if (idx >= 0) { /* * value is to be calculated by the recursive calls */ /* * Set n to the current index */ n.setArgumentValue(idx); /* * create new expression */ Expression newExp = new Expression( base.argumentExpression.expressionString , base.argumentExpression.argumentsList , base.argumentExpression.functionsList , base.argumentExpression.constantsList ,Expression.INTERNAL); newExp.setDescription(base.getArgumentName()); //newExp.setRecursiveMode(); if (base.getVerboseMode() == true) { //System.out.println(super.getVerboseMode() + ", " +super.getArgumentName() + ", " + super.argumentExpression.expressionString + "," + "VERBOSE MODE for recurssion"); newExp.setVerboseMode(); } /* * perform recursive call */ double value = newExp.calculate(); /* * remember calculated in the base values array */ addBaseCase(idx, value); /* * decrease recursive counter and return value */ recursiveCounter--; return value; } else { /* * decrease recursive counter and * return Double.NaN for negative index call */ recursiveCounter--; return Double.NaN; } } else { /* stop never ending loop * decrease recursive counter and * return Double.NaN */ recursiveCounter--; return Double.NaN; } }
/** * Constructor - creates dependent argument(with hidden * argument expression). * * @param argumentName the argument name * @param argumentExpressionString the argument expression string * @param elements Optional parameters (comma separated) * such as Arguments, Constants, Functions * * @see Expression * @see PrimitiveElement */ public Argument(String argumentName, String argumentExpressionString, params PrimitiveElement[] elements) : base(Argument.TYPE_ID) { if (mXparser.regexMatch(argumentName, ParserSymbol.nameOnlyTokenRegExp)) { this.argumentName=String.Copy(argumentName); argumentValue=ARGUMENT_INITIAL_VALUE; argumentExpression = new Expression(argumentExpressionString, elements); argumentExpression.setDescription(argumentName); argumentType = DEPENDENT_ARGUMENT; } else { this.argumentValue = ARGUMENT_INITIAL_VALUE; argumentExpression = new Expression(); argumentExpression.setSyntaxStatus(SYNTAX_ERROR_OR_STATUS_UNKNOWN, "[" + argumentName + "] " + "Invalid argument name, pattern not match: " + ParserSymbol.nameOnlyTokenRegExp); } setSilentMode(); description = ""; }
/*================================================= * * Constructors * *================================================= */ /** * Default constructor - creates argument based on the argument definition string. * * @param argumentDefinitionString Argument definition string, i.e.: * <ul> * <li>'x' - only argument name * <li>'x=5' - argument name and argument value * <li>'x=2*5' - argument name and argument value given as simple expression * <li>'x=2*y' - argument name and argument expression (dependent argument 'x' on argument 'y') * </ul> * * @param elements Optional parameters (comma separated) such as Arguments, Constants, Functions */ public Argument(String argumentDefinitionString, params PrimitiveElement[] elements) : base(Argument.TYPE_ID) { if (mXparser.regexMatch(argumentDefinitionString, ParserSymbol.nameOnlyTokenRegExp)) { argumentName = argumentDefinitionString; argumentValue = ARGUMENT_INITIAL_VALUE; argumentType = FREE_ARGUMENT; argumentExpression = new Expression(elements); } else if (mXparser.regexMatch(argumentDefinitionString, ParserSymbol.constArgDefStrRegExp)) { HeadEqBody headEqBody = new HeadEqBody(argumentDefinitionString); argumentName = headEqBody.headTokens[0].tokenStr; Expression bodyExpr = new Expression(headEqBody.bodyStr); double bodyValue = bodyExpr.calculate(); if ((bodyExpr.getSyntaxStatus() == Expression.NO_SYNTAX_ERRORS) && (bodyValue != Double.NaN)) { argumentExpression = new Expression(); argumentValue = bodyValue; argumentType = FREE_ARGUMENT; } else { argumentExpression = bodyExpr; addDefinitions(elements); argumentType = DEPENDENT_ARGUMENT; } } else if (mXparser.regexMatch(argumentDefinitionString, ParserSymbol.functionDefStrRegExp)) { HeadEqBody headEqBody = new HeadEqBody(argumentDefinitionString); argumentName = headEqBody.headTokens[0].tokenStr; argumentExpression = new Expression(headEqBody.bodyStr, elements); argumentExpression.setDescription(headEqBody.headStr); argumentValue = ARGUMENT_INITIAL_VALUE; argumentType = DEPENDENT_ARGUMENT; n = new Argument(headEqBody.headTokens[2].tokenStr); } else { argumentValue = ARGUMENT_INITIAL_VALUE; argumentType = FREE_ARGUMENT; argumentExpression = new Expression(); argumentExpression.setSyntaxStatus(SYNTAX_ERROR_OR_STATUS_UNKNOWN, "[" + argumentDefinitionString + "] " + "Invalid argument definition (patterns: 'x', 'x=5', 'x=5+3/2', 'x=2*y')."); } setSilentMode(); description = ""; }