예제 #1
0
            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);
            }
예제 #2
0
            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);
            }
예제 #3
0
            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);
            }
예제 #4
0
        /// <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)));
            }
        }
예제 #5
0
            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);
            }
예제 #6
0
            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);
            }
예제 #7
0
            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);
            }
예제 #8
0
            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);
            }
예제 #9
0
        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);
        }
예제 #10
0
            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);
                    }
                }
            }
예제 #11
0
            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);
            }
예제 #12
0
            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);
                }
            }
예제 #13
0
        /// <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)))());
            }
        }
예제 #14
0
 /// <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));
 }