public void GenerateDouble(ILGenerator generator, FunctionSet set, FunctionParams pars) { // We check constants. double s1, s2; if (src2.HasConstantValue(set, pars, out s2)) { if (src1.HasConstantValue(set, pars, out s1)) { generator.Emit(OpCodes.Ldc_R8, s1 / s2); return; } else { // Because division sucks, we convert it to multiplication. double inv_s2 = 1.0 / s2; src1.GenerateDouble(generator, set, pars); generator.Emit(OpCodes.Ldc_R8, inv_s2); generator.Emit(OpCodes.Mul); return; } } src1.GenerateDouble(generator, set, pars); src2.GenerateDouble(generator, set, pars); // We just generate add. generator.Emit(OpCodes.Div); }
public bool HasConstantValue(FunctionSet set, FunctionParams pars, out double val) { double s1, s2; if (src1.HasConstantValue(set, pars, out s1)) { if (src2.HasConstantValue(set, pars, out s2)) { val = s1 * s2; return(true); } // We check if src is 0.0. if (s1 == 0.0) { val = 0.0; return(true); } } // Src2 may be 0.0. if (src2.HasConstantValue(set, pars, out s2)) { if (s2 == 0.0) { val = 0.0; return(true); } } val = 0.0; return(false); }
public bool HasConstantValue(FunctionSet set, FunctionParams pars, out double val) { double s1, s2; if (src1.HasConstantValue(set, pars, out s1)) { if (src2.HasConstantValue(set, pars, out s2)) { val = global::System.Math.Pow(s1, s2); return(true); } // Anything 1.0^x is 1.0. if (s1 == 1.0) { val = 1.0; return(true); } } if (src2.HasConstantValue(set, pars, out s2)) { // Anything x^0.0 is 1.0 (except 0.0^0.0 what is not defined ...). if (s2 == 0.0) { val = 1.0; return(true); } } val = 0.0; return(false); }
/// <summary> /// Obtains floating point function (64-bit). If expression is in vector form, /// this will return the function defined for x. /// </summary> /// <param name="m">The module we should append this delegate to.</param> /// <param name="set">The function set, use null or FunctionSet.Default if you do not /// want anything specific.</param> /// <param name="pars">The parameters, cannot be null.</param> public Function4d GetFunction4d([NotNull] FunctionParams pars, FunctionSet set, [NotNull] Module m) { if (pars.Creator != this) { throw new ArgumentException("Parameters not generated by expression."); } if (!pars.IsDefined) { throw new ArgumentException("The parameters for the function are not defined fully."); } if (pars.VariableCount > 4) { throw new ArgumentException("Too many variables are used for 4D function."); } lock (root) { if (set == null) { set = FunctionSet.Default; } // We define method. DynamicMethod method = new DynamicMethod(name + "4d", typeof(double), new Type[] { typeof(double), typeof(double), typeof(double), typeof(double) }, m); // We emit body. ILGenerator g = method.GetILGenerator(); root.GenerateDouble(g, set, pars); g.Emit(OpCodes.Ret); // We create delegate. return((Function4d)method.CreateDelegate(typeof(Function4d))); } }
public bool HasConstantValue(FunctionSet set, FunctionParams pars, out double val) { double s1, s2; if (src2.HasConstantValue(set, pars, out s2) && src1.HasConstantValue(set, pars, out s1)) { val = s1 / s2; return(true); } val = 0.0; return(false); }
public bool HasConstantValue(FunctionSet set, FunctionParams pars, out double val) { // We have constant value if and only if subelement is constant. double[] v = new double[arguments.Length]; int index = 0; foreach (IElement el in arguments) { if (el.HasConstantValue(set, pars, out v[index])) { continue; } val = 0.0; return(false); } // We find delegate Delegate s = null; switch (arguments.Length) { case 1: s = set.Findd(Name); break; case 2: s = set.Find2d(Name); break; case 3: s = set.Find3d(Name); break; case 4: s = set.Find4d(Name); break; default: throw new InvalidMathExpression("Trying to call method with more then 4 arguments, unsuported."); } if (s == null) { throw new InvalidMathExpression("We cannot compile expression because the function " + Name + " does not exist in set."); } // We execute it. val = (double)s.DynamicInvoke(v[0]); return(true); }
public void GenerateDouble(ILGenerator generator, FunctionSet set, FunctionParams pars) { // We check if we have const value expression. double constValue; if (HasConstantValue(set, pars, out constValue)) { generator.Emit(OpCodes.Ldc_R8, constValue); return; } foreach (IElement el in arguments) { el.GenerateDouble(generator, set, pars); } // We perform the call of this function. The function is prototyped // float F(float x). Delegate s = null; switch (arguments.Length) { case 1: s = set.Findd(Name); break; case 2: s = set.Find2d(Name); break; case 3: s = set.Find3d(Name); break; case 4: s = set.Find4d(Name); break; default: throw new InvalidMathExpression("Trying to call method with more then 4 arguments, unsuported."); } if (s == null) { throw new InvalidMathExpression("We cannot compile expression because the function " + Name + " does not exist in set."); } // Call the method with argument. generator.EmitCall(OpCodes.Call, s.Method, null); }
public void GenerateDouble(ILGenerator generator, FunctionSet set, FunctionParams pars) { double val; if (HasConstantValue(set, pars, out val)) { generator.Emit(OpCodes.Ldc_R8, val); return; } src1.GenerateDouble(generator, set, pars); src2.GenerateDouble(generator, set, pars); // We just generate add. generator.Emit(OpCodes.Mul); }
static FunctionSet() { Default = new FunctionSet(); // Append some defaults. Default.Add("sin", Sin, global::System.Math.Sin); Default.Add("cos", Cos, global::System.Math.Cos); Default.Add("sqrt", Sqrt, global::System.Math.Sqrt); Default.Add("tan", Tan, global::System.Math.Tan); Default.Add("asin", Asin, global::System.Math.Asin); Default.Add("acos", Acos, global::System.Math.Acos); Default.Add("atan", Atan, global::System.Math.Atan); Default.Add("log", Log, global::System.Math.Log); Default.Add("ln", Ln, global::System.Math.Log); Default.Add("exp", Exp, global::System.Math.Exp); Default.Add("floor", Floor, global::System.Math.Floor); Default.Add("trunc", Truncate, global::System.Math.Truncate); }
public void GenerateDouble(ILGenerator generator, FunctionSet set, FunctionParams pars) { if (isNumeric) { // We push argument on stack. generator.Emit(OpCodes.Ldc_R8, numericValue); } else { // Check for binding. if (pars.HasBinding(value)) { VariableBinding binding; pars.GetBinding(value, out binding); switch (binding.Position) { case 0: generator.Emit(OpCodes.Ldarg_0); break; case 1: generator.Emit(OpCodes.Ldarg_1); break; case 2: generator.Emit(OpCodes.Ldarg_2); break; case 3: generator.Emit(OpCodes.Ldarg_3); break; default: throw new InvalidMathExpression("Trying non-used position."); } } else { // Must succeed. double v = pars[value]; generator.Emit(OpCodes.Ldc_R8, v); } } }
public void GenerateDouble(ILGenerator generator, FunctionSet set, FunctionParams pars) { double val; if (HasConstantValue(set, pars, out val)) { generator.Emit(OpCodes.Ldc_R8, val); return; } // We must make sure all params are in double form! src1.GenerateDouble(generator, set, pars); src2.GenerateDouble(generator, set, pars); // We generate the call on those two params. PowDelegate pow = global::System.Math.Pow; generator.EmitCall(OpCodes.Call, pow.Method, null); }
public bool HasConstantValue(FunctionSet set, FunctionParams pars, out double val) { if (isNumeric) { val = numericValue; return(true); } // Parameters (not variables) are also constants. if (pars.HasBinding(value)) { val = 0.0; return(false); } else { val = pars[value]; return(true); } }
/// <summary> /// Evaluates constant expression /// </summary> /// <returns></returns> public double Evalf([NotNull] FunctionParams pars, FunctionSet set, Module m) { if (pars.Creator != this) { throw new ArgumentException("Parameters not generated by expression."); } if (!pars.IsDefined) { throw new ArgumentException("The parameters for the function are not defined fully."); } if (pars.VariableCount > 0) { throw new ArgumentException("Too many variables are used for constant function."); } lock (root) { if (set == null) { set = FunctionSet.Default; } if (pars == null) { throw new ArgumentNullException("The parameters of function are null."); } // We define method. DynamicMethod method = new DynamicMethod(name + "f", typeof(float), new Type[] { }, m); // We emit body. ILGenerator g = method.GetILGenerator(); root.GenerateSingle(g, set, pars); g.Emit(OpCodes.Ret); // We create delegate. return(((ConstFunctionf)method.CreateDelegate(typeof(ConstFunctionf)))()); } }
/// <summary> /// Obtains floating point function (64-bit). If expression is in vector form, /// this will return the function defined for x. /// </summary> /// <param name="set">The function set, use null or FunctionSet.Default if you do not /// want anything specific.</param> /// <param name="pars">The parameters, cannot be null.</param> public Function4d GetFunction4d(FunctionParams p, FunctionSet set) { return(GetFunction4d(p, set, typeof(Expression).Module)); }