public object Clone() { QsFunction f = (QsFunction)this.MemberwiseClone(); var fdname = f.FunctionDeclaration.Substring(0, f.FunctionDeclaration.IndexOf('(')); f.FunctionDeclaration = f.FunctionDeclaration.Replace(fdname, "_"); return(f); }
/// <summary> /// Differentiate operation for function. /// </summary> /// <param name="value">object of <see cref="QsScalar"/> that hold <see cref="AnyQuantity<SymbolicVariable>"/></param> /// <returns></returns> public override QsValue DifferentiateOperation(QsValue value) { QsScalar sval = (QsScalar)value; if (sval.ScalarType == ScalarTypes.SymbolicQuantity) { var dsv = sval.SymbolicQuantity.Value; string fname = "_"; string WholeFunction = string.Empty; if (this.FunctionBodyToken[0].TokenClassType == typeof(CurlyBracketGroupToken)) { // vector differentiation // take every term in the vector and differentiate it var vcs = QsVar.VectorComponents(this.FunctionBodyToken[0]); StringBuilder sc = new StringBuilder(); sc.Append(fname + "(" + RemoveRedundantParameters(this.ParametersNames) + ") = "); sc.Append("{ "); foreach (var c in vcs) { SymbolicVariable nsv = SymbolicVariable.Parse(c); int times = (int)dsv.SymbolPower; while (times > 0) { nsv = nsv.Differentiate(dsv.Symbol); times--; } sc.Append(nsv.ToString()); sc.Append(" "); } sc.Append("}"); WholeFunction = sc.ToString(); } else { SymbolicVariable nsv = ToSymbolicVariable(); int times = (int)dsv.SymbolPower; while (times > 0) { nsv = nsv.Differentiate(dsv.Symbol); times--; } WholeFunction = fname + "(" + RemoveRedundantParameters(this.ParametersNames) + ") = " + nsv.ToString(); } return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, WholeFunction)); } else { return(base.DifferentiateOperation(value)); } }
/// <summary> /// Get the default function. /// Default function is on the form f#2 f#3 without decoration for parameters. /// </summary> /// <param name="scope"></param> /// <param name="nameSpace"></param> /// <param name="functionName"></param> /// <param name="parameterCount"></param> /// <returns></returns> public static QsFunction GetDefaultFunction( QsScope scope, string nameSpace, string functionName, int parametersCount) { string functionRealName = QsFunction.FormFunctionSymbolicName(functionName, parametersCount); QsFunction func = QsFunction.GetFunction(scope, nameSpace, functionRealName); return(func); }
/// <summary> /// Join any set of given functions and returns the tokens of the new function along /// with the new function text. /// </summary> /// <param name="operation"></param> /// <param name="functionDeclaration"></param> /// <param name="functions"></param> /// <returns></returns> internal static Token JoinFunctionsArrayTokensWithOperation(string operation, out string functionDeclaration, params QsFunction[] functions) { var fname = "_"; var fbody = ""; List <string> fparamList = new List <string>(); foreach (var f in functions) { fbody += " " + f.FunctionBody + " " + operation; fparamList.AddRange(f.ParametersNames); } fbody = fbody.TrimEnd(operation.ToCharArray()); string[] fparam = fparamList.ToArray(); var fNameParamPart = fname + "(" + RemoveRedundantParameters(fparam) + ") ="; functionDeclaration = fNameParamPart + fbody; Token fTokens = new Token(); // add first part tokens foreach (var t in QsFunction.TokenizeFunction(fNameParamPart)) { fTokens.AppendSubToken(t); } for (int i = 0; i < functions.Length; i++) { // prepare function body tokens foreach (var t in functions[i].FunctionBodyToken) { fTokens.AppendSubToken(t); } if (i < functions.Length - 1) { fTokens.AppendSubToken(Token.ParseText(operation.Trim())[0]); //operation is only one charachter } } return(fTokens); }
/// <summary> /// Get the function that is stored in the scope. /// </summary> /// <param name="scope"></param> /// <param name="realName"></param> /// <returns></returns> public static QsFunction GetFunction(QsScope scope, string qsNamespace, string functionName) { if (string.IsNullOrEmpty(qsNamespace)) { // no namespace included then it is from the local scope. // I am adding the mathmatical functions in the root namespace // so I will test for the function namespace and QsFunction function = (QsFunction)MathNamespace.GetValueOrNull(functionName); // built int math functions will be overwrite any other functions if (function != null) { return(function); } else { function = (QsFunction)QsEvaluator.GetScopeValueOrNull(scope, qsNamespace, functionName); } return(function); } else { try { QsNamespace ns = QsNamespace.GetNamespace(scope, qsNamespace); return((QsFunction)ns.GetValue(functionName)); } catch (QsVariableNotFoundException) { return(null); } } }
/// <summary> /// Take the value and operation in text and return the current function operationed by value. /// </summary> /// <param name="value"></param> /// <param name="operation"></param> /// <returns></returns> private QsFunction FOperation(QsValue value, string operation) { if (value is QsFunction) { QsFunction fn2 = (QsFunction)value; string fParameters = RemoveRedundantParameters(this.ParametersNames.Union(fn2.ParametersNames).ToArray()); string thisFunctionBody = this.FunctionBody; foreach (string p in this.ParametersNames) { thisFunctionBody = thisFunctionBody.Replace(p, "$" + p); } string targetFunctionBody = fn2.FunctionBody; foreach (string p in fn2.ParametersNames) { targetFunctionBody = targetFunctionBody.Replace(p, "$" + p); } // form the expressions that will be parsed. string fpt = "(" + thisFunctionBody + ")" + operation + "(" + targetFunctionBody + ")"; fpt = fpt.Replace("!", "__FAC__"); // replacing the ! sign with __FAC__ to include the '!' sign into the calculations {because '!' is operator in parsing so it doesn't enter the algebraic calculations} //evaulate fpt try { QsScalar sc = (QsScalar)QsEvaluator.CurrentEvaluator.SilentEvaluate(fpt); string FuncBody = sc.SymbolicQuantity.Value.ToString().Replace("__FAC__", "!"); string WholeFunction = "_(" + fParameters + ") = " + FuncBody; return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, WholeFunction)); } catch (QsIncompleteExpression) { // something happened make the operation in old fashion string WholeFunction; Token FunctionToken = JoinFunctionsArrayTokensWithOperation(operation, out WholeFunction, this, fn2); return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, WholeFunction, FunctionToken)); } } else if (value is QsScalar) { QsScalar svl = (QsScalar)value; var fname = "_"; var fbody = this.FunctionBody; if (svl.ScalarType == ScalarTypes.SymbolicQuantity) { fbody = "(" + fbody + ")" + operation + "(" + svl.SymbolicQuantity.Value.ToString() + ")"; } else if (svl.ScalarType == ScalarTypes.NumericalQuantity) { fbody = "(" + fbody + ")" + operation + svl.NumericalQuantity.Value.ToString(); } else if (svl.ScalarType == ScalarTypes.RationalNumberQuantity) { fbody = "(" + fbody + ")" + operation + svl.RationalQuantity.Value.Value.ToString(); } else if (svl.ScalarType == ScalarTypes.FunctionQuantity) { fbody = "(" + fbody + ")" + operation + "(" + svl.FunctionQuantity.Value.FunctionBody + ")"; } else { throw new QsException("Operation '" + operation + "' for the target scalar type (" + svl.ScalarType + ") is not supported"); } QsScalar fb = SymbolicVariable.Parse(fbody).ToQuantity().ToScalar(); string FuncBody = string.Empty; if (fb.ScalarType == ScalarTypes.SymbolicQuantity) { FuncBody = fb.SymbolicQuantity.Value.ToString().Replace("__FAC__", "!"); } else { FuncBody = fb.ToExpressionParsableString(); } string[] functionParametersArray = this.ParametersNames; // this is the available parameters for the original function. if (svl.ScalarType == ScalarTypes.SymbolicQuantity) { List <string> newParametersList = new List <string>(functionParametersArray); newParametersList.AddRange(svl.SymbolicQuantity.Value.InvolvedSymbols); functionParametersArray = newParametersList.ToArray(); } if (svl.ScalarType == ScalarTypes.FunctionQuantity) { List <string> newParametersList = new List <string>(functionParametersArray); newParametersList.AddRange(svl.FunctionQuantity.Value.ParametersNames); functionParametersArray = newParametersList.ToArray(); } var f = fname + "(" + RemoveRedundantParameters(functionParametersArray) + ") = " + FuncBody; return(QsFunction.ParseFunction(QsEvaluator.CurrentEvaluator, f)); } else { throw new NotImplementedException(); } }
/// <summary> /// if we consider the <see cref="ParameterRawText"/> as a function name. /// then this function will get the actual function name which include parameters count. /// This function is only used in making expressions. /// </summary> /// <param name="paramCount"></param> /// <returns></returns> public string GetTrueFunctionName(int paramCount) { return(QsFunction.FormFunctionSymbolicName(ParameterRawText, paramCount)); }
public static QsFunction ParseFunction(QsEvaluator qse, string functionDeclaration, Token functionToken) { int nsidx = 0; // surve as a base for indexing token if there is namespace it will be 1 otherwise remain 0 // specify the namespaces end token. string functionNamespace = ""; foreach (var tok in functionToken) { if (tok.TokenClassType == typeof(NamespaceToken)) { nsidx++; functionNamespace += tok.TokenValue; } else { break; } } if ( functionToken[nsidx].TokenClassType == typeof(WordToken) && (functionToken.Count > (nsidx + 1) ? functionToken[nsidx + 1].TokenClassType == typeof(ParenthesisGroupToken) : false) && (functionToken.Count > (nsidx + 2) ? functionToken[nsidx + 2].TokenClassType == typeof(EqualToken) : false) ) { //get function name // will be the first token after excluding namespace. string functionName = string.Empty; functionName = functionToken[nsidx].TokenValue; //remove the last : from namespace functionNamespace = functionNamespace.TrimEnd(':'); List <string> textParams = new List <string>(); List <QsParamInfo> prms = new List <QsParamInfo>(); foreach (var c in functionToken[nsidx + 1]) { if ( c.TokenValue.StartsWith("(") || c.TokenValue.StartsWith(")") || c.TokenValue.StartsWith(",") || c.TokenClassType == typeof(MultipleSpaceToken) ) { //ignore these things. } else { if (char.IsLetter(c.TokenValue[0])) { textParams.Add(c.TokenValue); prms.Add(new QsParamInfo { Name = c.TokenValue, Type = QsParamType.Value }); } else { throw new QsSyntaxErrorException("Parameter name must statrt with a letter"); } } } //declared for first time a default function. QsFunction qf = new QsFunction(functionDeclaration) { FunctionNamespace = functionNamespace, FunctionName = functionName, Parameters = prms.ToArray() }; //LambdaBuilder lb = Utils.Lambda(typeof(QsValue), functionName); SimpleLambdaBuilder lb = SimpleLambdaBuilder.Create(typeof(QsValue), functionName); foreach (QsParamInfo prm in prms) { lb.Parameter(typeof(QsParameter), prm.Name); } List <Expression> statements = new List <Expression>(); qf.FunctionBody = functionDeclaration.Substring(functionToken[nsidx + 2].IndexInText + functionToken[nsidx + 2].TokenValueLength).Trim(); Token functionBodyTokens; QsVar qv = new QsVar(qse, qf.FunctionBody, qf, lb, out functionBodyTokens); statements.Add(qv.ResultExpression); //making the variable expression itself make it the return value of the function. lb.Body = Expression.Block(statements); LambdaExpression lbe = lb.MakeLambda(); qf.FunctionExpression = lbe; qf.FunctionBodyToken = functionBodyTokens; return(qf); } else { return(null); } }