private bool EmitFunc(FuncNode funcNode, bool negExpAbs = false)
        {
            switch (funcNode.FunctionType)
            {
            case KnownFuncType.Add:
                return(EmitAddFunc(funcNode));

            case KnownFuncType.Sub:
                return(EmitSubFunc(funcNode));

            case KnownFuncType.Mult:
                return(EmitMultFunc(funcNode));

            case KnownFuncType.Div:
                return(EmitDivFunc(funcNode));

            case KnownFuncType.Neg:
                return(EmitNegFunc(funcNode, negExpAbs));

            case KnownFuncType.Pow:
                return(EmitExpFunc(funcNode, negExpAbs));

            case KnownFuncType.Diff:
                return(EmitDiffFunc(funcNode));
            }

            if (!EmitKnownFunc(funcNode))             // Unknown function (from input args).
            {
                EmitUnknownFunc(funcNode);
            }

            return(true);
        }
 private MathFuncNode MakeSubstitution(MathFuncNode left, MathFuncNode right, FuncNode currentFunc)
 {
     LeftNode     = left;
     RightNode    = right;
     _currentFunc = currentFunc;
     return(MakeSubstitution(right));
 }
Example #3
0
        protected string ToString(FuncNode parent,
                                  KnownFuncType funcType,
                                  IList <KnownFuncType> types)
        {
            var builder = new StringBuilder();

            if (parent == null || parent.Name == null || parent.Children.Count <= 1)
            {
                AppendMathFunctionNode(builder, funcType);
                return(builder.ToString());
            }

            var funcNodeParent = parent as FuncNode;

            if (funcNodeParent != null && funcNodeParent.IsKnown)
            {
                if (types.Contains((KnownFuncType)funcNodeParent.FunctionType))
                {
                    AppendMathFunctionNode(builder, funcType);
                    return(builder.ToString());
                }
            }

            builder.Append("(");
            AppendMathFunctionNode(builder, funcType);
            builder.Append(")");
            return(builder.ToString());
        }
        private bool EmitDiffFunc(FuncNode funcNode)
        {
            var  diffFunc      = funcNode.Childs[0];
            var  arg           = diffFunc.Childs[0];
            bool isUnknownFunc = diffFunc.Type == MathNodeType.Function && !((FuncNode)diffFunc).IsKnown;

            var diff = FuncNodes[(FuncNode)diffFunc];

            // f(x + dx)
            if (isUnknownFunc)
            {
                IlInstructions.Add(new OpCodeArg(OpCodes.Ldarg, diffFunc.ArgNumber));
            }
            EmitNode(arg);
            IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, DerivativeDelta));
            IlInstructions.Add(new OpCodeArg(OpCodes.Add));
            if (isUnknownFunc)
            {
                IlInstructions.Add(new OpCodeArg(OpCodes.Callvirt, MathFuncAssembly.InvokeFuncRef));
            }
            else
            {
                EmitNode(diffFunc);
            }

            // f(x)
            EmitNode(diffFunc);

            IlInstructions.Add(new OpCodeArg(OpCodes.Sub));
            IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0 / DerivativeDelta));
            IlInstructions.Add(new OpCodeArg(OpCodes.Mul));

            return(true);
        }
        private void BuildMultichildTree(FuncNode beginNode)
        {
            var newChilds = new List <MathFuncNode>();

            BuildMultichildTree(beginNode, beginNode, newChilds, false);
            beginNode.Childs = newChilds;
        }
        private MathFuncNode ExpValue(FuncNode funcNode)
        {
            var bValue = funcNode.Children[1] as ValueNode;

            if (bValue != null)
            {
                if (bValue.Value == 0)
                {
                    return(new ValueNode(1));
                }
                else if (bValue.Value == 1)
                {
                    return(funcNode.Children[0]);
                }

                /*else if (funcNode.Children[0].Type == MathNodeType.Value)
                 * {
                 *      double a = funcNode.Children[0].Value.ToDouble();
                 *      double b = bValue.Value.ToDouble();
                 *      double r = b == 0.5 ? Math.Sqrt(a) : Math.Pow(a, b);
                 *      Rational<long> result;
                 *      Rational<long>.FromDecimal((decimal)r, out result);
                 *      return new ValueNode(result);
                 * }*/
                else if (bValue.Value.IsInteger && funcNode.Children[0] is FuncNode childFuncNode &&
                         childFuncNode.FunctionType == KnownFuncType.Neg)
                {
                    if (bValue.Value.Numerator % 2 == 0)
                    {
                        return(new FuncNode(KnownFuncType.Pow, funcNode.Children[0].Children[0], new ValueNode(bValue.Value)));
                    }
                    else
                    {
                        return(new FuncNode(KnownFuncType.Neg, new FuncNode(KnownFuncType.Pow, funcNode.Children[0].Children[0], new ValueNode(bValue.Value))));
                    }
                }
            }

            if (funcNode.Children[0] is ValueNode aValue)
            {
                if (aValue.Value == 0)
                {
                    return(new ValueNode(0));
                }
                else if (aValue.Value == 1)
                {
                    return(new ValueNode(1));
                }
                else if (bValue != null)
                {
                    return((MathFuncNode)SimplifyValues(KnownFuncType.Pow, new List <ValueNode>()
                    {
                        aValue, bValue
                    })
                           ?? (MathFuncNode)funcNode);
                }
            }

            return(funcNode);
        }
 private FuncNode PrecompileExpFunc(MathFuncNode parent, FuncNode funcNode)
 {
     if ((parent == null ||
          ((FuncNode)parent).FunctionType != KnownFuncType.Mult) &&
         funcNode.Childs[1].LessThenZero())
     {
         if (!funcNode.Childs[1].IsValueOrCalculated || funcNode.Childs[1].DoubleValue != -1.0)
         {
             FuncNode second;
             if (!funcNode.Childs[1].IsValueOrCalculated)
             {
                 second = new FuncNode(KnownFuncType.Pow, funcNode.Childs[0], funcNode.Childs[1].Abs());
             }
             else
             {
                 second = Math.Abs(funcNode.Childs[1].DoubleValue) != 0.5 ?
                          new FuncNode(KnownFuncType.Pow, funcNode.Childs[0], funcNode.Childs[1].Abs()) :
                          new FuncNode(KnownFuncType.Sqrt, funcNode.Childs[0]);
             }
             return(new FuncNode(KnownFuncType.Div, new CalculatedNode(1.0), second));
         }
         else
         {
             return(new FuncNode(KnownFuncType.Div, new CalculatedNode(1.0), funcNode.Childs[0]));
         }
     }
     if (funcNode.Childs[1].IsValueOrCalculated && funcNode.Childs[1].DoubleValue == 0.5)
     {
         return(new FuncNode(KnownFuncType.Sqrt, funcNode.Childs[0]));
     }
     return(funcNode);
 }
        private MathFuncNode BreakOnAddNodes(FuncNode funcNode)
        {
            var addNodes = funcNode.Childs.Where(child =>
                                                 child.Type == MathNodeType.Function &&
                                                 ((FuncNode)child).FunctionType == KnownFuncType.Add).ToList();

            if (addNodes.Count != 0)
            {
                var funcNodesExceptAddNodes = funcNode.Childs.Except(addNodes);
                var ar       = new int[addNodes.Count];
                var lengthAr = addNodes.Select(addNode => addNode.Childs.Count).ToArray();

                var newAddChilds = new List <MathFuncNode>();
                var newChilds    = new List <MathFuncNode>();

                do
                {
                    newAddChilds.Clear();
                    newAddChilds.AddRange(funcNodesExceptAddNodes);
                    for (int j = 0; j < ar.Length; j++)
                    {
                        newAddChilds.Add(addNodes[j].Childs[ar[j]]);
                    }

                    newChilds.Add(Simplify(new FuncNode(KnownFuncType.Mult, newAddChilds)));
                }while (IncArray(ar, lengthAr));

                return(Simplify(new FuncNode(KnownFuncType.Add, newChilds)));
            }
            else
            {
                return(null);
            }
        }
		private MathFuncNode PrecompileAddFunc(FuncNode funcNode)
		{
			MathFuncNode firstItem;
			MathFuncNode result = null;

			var funcNode2 = FoldCalculatedSummands(funcNode);

			firstItem = funcNode2.Childs.FirstOrDefault(node =>
			{
				var func = node as FuncNode;
				return !(func != null && func.LessThenZero());
			});

			if (firstItem == null)
				firstItem = funcNode2.Childs[0];

			result = firstItem;

			for (int i = 0; i < funcNode2.Childs.Count; i++)
			{
				if (funcNode2.Childs[i] == firstItem)
					continue;

				if (funcNode2.Childs[i].LessThenZero())
					result = new FuncNode(KnownFuncType.Sub, result, funcNode2.Childs[i].Abs());
				else
					result = new FuncNode(KnownFuncType.Add, result, funcNode2.Childs[i]);
			}

			return result;
		}
Example #10
0
        public MathFuncNode VisitBinaryExpression(BinaryExpressionContext context)
        {
            MathFuncNode arg1 = Visit(context.expression(0));
            MathFuncNode arg2 = Visit(context.expression(1));

            KnownFuncType funcType;

            if (context.Plus() != null)
            {
                funcType = KnownFuncType.Add;
            }
            else if (context.Minus() != null)
            {
                funcType = KnownFuncType.Sub;
                var second = new FuncNode(KnownFuncType.Neg, new MathFuncNode[] { arg2 });
                var result = new FuncNode(KnownFuncType.Add, new MathFuncNode[] { arg1, second });
                return(result);
            }
            else if (context.Mult() != null)
            {
                funcType = KnownFuncType.Mult;
            }
            else if (context.Div() != null)
            {
                var second = new FuncNode(KnownFuncType.Pow, new MathFuncNode[] { arg2, new ValueNode(-1) });
                var result = new FuncNode(KnownFuncType.Mult, new MathFuncNode[] { arg1, second });
                return(result);
            }
            else
            {
                funcType = KnownFuncType.Pow;
            }

            return(new FuncNode(funcType, new MathFuncNode[] { arg1, arg2 }));
        }
Example #11
0
        public override string ToString(FuncNode parent)
        {
            if (IsKnown)
            {
                var funcType = (KnownFuncType)FunctionType;
                switch ((KnownFuncType)FunctionType)
                {
                case KnownFuncType.Add:
                case KnownFuncType.Sub:
                    return(ToString(parent, funcType, KnownFunc.AddKnownFuncs));

                case KnownFuncType.Mult:
                case KnownFuncType.Div:
                    return(ToString(parent, funcType, KnownFunc.MultKnownFuncs));

                case KnownFuncType.Pow:
                    return(ToString(parent, funcType, KnownFunc.ExpKnownFuncs));

                case KnownFuncType.Neg:
                    if (Childs[0].Type == MathNodeType.Function)
                    {
                        var func = (FuncNode)Childs[0];
                        if (KnownFunc.NegKnownFuncs.Contains((KnownFuncType)func.FunctionType))
                        {
                            return("-(" + Childs[0].ToString(this) + ")");
                        }
                        else
                        {
                            return("-" + Childs[0].ToString(this));
                        }
                    }
                    else
                    {
                        return("-" + Childs[0].ToString(this));
                    }

                case KnownFuncType.Diff:
                    return(Childs[0].Type == MathNodeType.Function && ((FuncNode)Childs[0]).FunctionType != KnownFuncType.Diff ?
                           Childs[0].ToString(this) + "'" : "(" +
                           Childs[0].ToString(this) + ")'");

                case KnownFuncType.Abs:
                    return(string.Format("|{0}|", Childs[0].ToString(this)));
                }
            }
            var builder = new StringBuilder((FunctionType == KnownFuncType.Sqrt ? "√" : Name) + "(");

            foreach (var arg in Childs)
            {
                builder.AppendFormat("{0}, ", arg.ToString(this));
            }
            if (Childs.Count != 0)
            {
                builder.Remove(builder.Length - 2, 2);
            }
            builder.Append(')');
            return(builder.ToString());
        }
Example #12
0
        public MathFuncNode VisitParenthesisExpression(ParenthesisExpressionContext context)
        {
            var result = Visit(context.expression());

            if (context.Quote() != null)
            {
                result = new FuncNode(KnownFuncType.Diff, result);
            }
            return(result);
        }
Example #13
0
        public MathFuncNode VisitAbsoluteExpression(AbsoluteExpressionContext context)
        {
            var result = new FuncNode(KnownFuncType.Abs, Visit(context.expression()));

            if (context.Quote() != null)
            {
                result = new FuncNode(KnownFuncType.Diff, result);
            }
            return(result);
        }
        private bool EmitNegFunc(FuncNode funcNode, bool negExpAbs)
        {
            EmitNode(funcNode.Childs[0]);

            if (!negExpAbs)
            {
                IlInstructions.Add(new OpCodeArg(OpCodes.Neg));
            }

            return(true);
        }
        private bool EmitDivFunc(FuncNode funcNode)
        {
            EmitNode(funcNode.Childs[0]);
            for (int i = 1; i < funcNode.Childs.Count; i++)
            {
                EmitNode(funcNode.Childs[i]);
                IlInstructions.Add(new OpCodeArg(OpCodes.Div));
            }

            return(true);
        }
        private bool EmitUnknownFunc(FuncNode funcNode)
        {
            IlInstructions.Add(new OpCodeArg(OpCodes.Ldarg, funcNode.ArgNumber));

            foreach (var child in funcNode.Childs)
            {
                EmitNode(child);
            }

            IlInstructions.Add(new OpCodeArg(OpCodes.Callvirt, MathFuncAssembly.InvokeFuncRef));

            return(true);
        }
Example #17
0
        public MathFuncNode VisitFuncExpression(FuncExpressionContext context)
        {
            IEnumerable <MathFuncNode> expressions = context.expressionList().expression()
                                                     .Select(e => Visit(e));

            var result = new FuncNode(context.Id().GetText(), expressions);

            if (context.Quote() != null)
            {
                result = new FuncNode(KnownFuncType.Diff, result);
            }
            return(result);
        }
        private bool EmitMultFunc(FuncNode funcNode)
        {
            MathFuncNode firstItem = null;

            firstItem = funcNode.Childs.FirstOrDefault(node =>
            {
                var func = node as FuncNode;
                return(!(func != null && FuncNodes[func].Count == 1 && func.FunctionType == KnownFuncType.Pow && func.Childs[1].LessThenZero()));
            });

            if (firstItem == null)
            {
                firstItem = funcNode.Childs[0];
            }

            EmitNode(firstItem);

            for (int i = 0; i < funcNode.Childs.Count; i++)
            {
                if (funcNode.Childs[i] == firstItem)
                {
                    continue;
                }

                var func = funcNode.Childs[i] as FuncNode;

                if (func != null && FuncNodes[func].Count == 1 && func.FunctionType == KnownFuncType.Pow && func.Childs[1].LessThenZero())
                {
                    EmitNode(funcNode.Childs[i], true);
                    IlInstructions.Add(new OpCodeArg(OpCodes.Div));
                }
                else
                {
                    EmitNode(funcNode.Childs[i]);
                    if (IlInstructions[IlInstructions.Count - 1].OpCode == OpCodes.Ldc_R8 && (double)IlInstructions[IlInstructions.Count - 1].Arg == 1.0)
                    {
                        IlInstructions.RemoveAt(IlInstructions.Count - 1);
                    }
                    else
                    {
                        IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
                    }
                }
            }

            return(true);
        }
        public override string ToString(FuncNode parent)
        {
            if (Value.Denominator == 1 || !parent.IsKnown)
            {
                return(Name);
            }

            if (parent.FunctionType == KnownFuncType.Mult || parent.FunctionType == KnownFuncType.Div ||
                parent.FunctionType == KnownFuncType.Pow || parent.FunctionType == KnownFuncType.Neg)
            {
                return('(' + Name + ')');
            }
            else
            {
                return(Name);
            }
        }
Example #20
0
        public MathFuncNode VisitUnaryExpression(UnaryExpressionContext context)
        {
            var result = Visit(context.expression());

            if (context.Minus() != null)
            {
                if (result is ValueNode valueNode)
                {
                    result = new ValueNode(-valueNode.Value);
                }
                else
                {
                    result = new FuncNode(KnownFuncType.Neg, result);
                }
            }
            return(result);
        }
        private MathFuncNode Precompile(MathFuncNode parent, MathFuncNode node)
        {
            if (node.Type == MathNodeType.Value)
            {
                return(new CalculatedNode(((ValueNode)node).Value));
            }
            else if (node.Type == MathNodeType.Function)
            {
                for (int i = 0; i < node.Childs.Count; i++)
                {
                    node.Childs[i] = Precompile(node, node.Childs[i]);
                }

                FuncNode func = (FuncNode)node;
                switch (func.FunctionType)
                {
                case KnownFuncType.Add:
                    node = PrecompileAddFunc(func);
                    break;

                case KnownFuncType.Mult:
                    node = PrecompileMultFunc(func);
                    break;

                case KnownFuncType.Pow:
                    node = PrecompileExpFunc(parent, func);
                    break;
                }

                if (node.Childs.Count > 0 && node.Childs.All(child => child.Type == MathNodeType.Value || child.Type == MathNodeType.Calculated))
                {
                    return((MathFuncNode)CalculateValues(((FuncNode)node).FunctionType, node.Childs) ?? (MathFuncNode)node);
                }
                else
                {
                    return(node);
                }
            }
            else
            {
                return(node);
            }
        }
        private FuncNode MultCalculatedFactors(FuncNode mult)
        {
            var result = mult.Childs
                         .Where(child => child.Type == MathNodeType.Calculated || child.Type == MathNodeType.Value)
                         .Select(factor => factor.DoubleValue)
                         .Aggregate(1.0, (t, factor) => t *= factor);

            if (result != 1.0)
            {
                var newChilds = new List <MathFuncNode>()
                {
                    new CalculatedNode(result)
                };
                newChilds.AddRange(mult.Childs.Where(c => c.Type != MathNodeType.Calculated && c.Type != MathNodeType.Value));

                return(new FuncNode(KnownFuncType.Mult, newChilds));
            }
            else
            {
                return(mult);
            }
        }
        private bool EmitAddFunc(FuncNode funcNode)
        {
            MathFuncNode firstItem = null;

            firstItem = funcNode.Childs.FirstOrDefault(node =>
            {
                var func = node as FuncNode;
                return(!(func != null && FuncNodes[func].Count == 1 && func.LessThenZero()));
            });

            if (firstItem == null)
            {
                firstItem = funcNode.Childs[0];
            }

            EmitNode(firstItem);

            for (int i = 0; i < funcNode.Childs.Count; i++)
            {
                if (funcNode.Childs[i] == firstItem)
                {
                    continue;
                }

                var func = funcNode.Childs[i] as FuncNode;
                if (func != null && FuncNodes[func].Count == 1 && func.LessThenZero())
                {
                    EmitNode(func.Childs[0], true);
                    IlInstructions.Add(new OpCodeArg(OpCodes.Sub));
                }
                else
                {
                    EmitNode(funcNode.Childs[i]);
                    IlInstructions.Add(new OpCodeArg(OpCodes.Add));
                }
            }

            return(true);
        }
        private FuncNode FoldCalculatedSummands(FuncNode sum)
        {
            var result = sum.Childs
                         .Where(child => child.Type == MathNodeType.Calculated || child.Type == MathNodeType.Value)
                         .Select(summand => summand.DoubleValue)
                         .Aggregate(0.0, (t, factor) => t += factor);

            if (result != 0.0)
            {
                var newChilds = new List <MathFuncNode>()
                {
                    new CalculatedNode(result)
                };
                newChilds.AddRange(sum.Childs.Where(c => c.Type != MathNodeType.Calculated && c.Type != MathNodeType.Value));

                return(new FuncNode(KnownFuncType.Sub, newChilds));
            }
            else
            {
                return(sum);
            }
        }
        private MathFuncNode PrecompileAddFunc(FuncNode funcNode)
        {
            MathFuncNode firstItem;
            MathFuncNode result = null;

            var funcNode2 = FoldCalculatedSummands(funcNode);

            firstItem = funcNode2.Childs.FirstOrDefault(node =>
            {
                var func = node as FuncNode;
                return(!(func != null && func.LessThenZero()));
            });

            if (firstItem == null)
            {
                firstItem = funcNode2.Childs[0];
            }

            result = firstItem;

            for (int i = 0; i < funcNode2.Childs.Count; i++)
            {
                if (funcNode2.Childs[i] == firstItem)
                {
                    continue;
                }

                if (funcNode2.Childs[i].LessThenZero())
                {
                    result = new FuncNode(KnownFuncType.Sub, result, funcNode2.Childs[i].Abs());
                }
                else
                {
                    result = new FuncNode(KnownFuncType.Add, result, funcNode2.Childs[i]);
                }
            }

            return(result);
        }
        private void ReduceSummands(FuncNode funcNode)
        {
            int i = 0;

            while (i < funcNode.Childs.Count)
            {
                int j = i + 1;
                while (j < funcNode.Childs.Count)
                {
                    var newNode = ReduceAddition(funcNode.Childs[i], funcNode.Childs[j]);
                    if (newNode != null)
                    {
                        funcNode.Childs[i] = newNode;
                        funcNode.Childs.RemoveAt(j);
                    }
                    else
                    {
                        j++;
                    }
                }
                i++;
            }
        }
        private void BuildMultichildTree(FuncNode beginNode, FuncNode funcNode, List <MathFuncNode> newChilds, bool neg)
        {
            foreach (var child in funcNode.Childs)
            {
                var childFuncNode = child as FuncNode;
                if (childFuncNode != null)
                {
                    if (childFuncNode.FunctionType == beginNode.FunctionType)
                    {
                        BuildMultichildTree(beginNode, childFuncNode, newChilds, neg);
                        continue;
                    }
                    else if (childFuncNode.FunctionType == KnownFuncType.Neg)
                    {
                        BuildMultichildTree(beginNode, childFuncNode, newChilds, !neg);
                        continue;
                    }
                }

                if (neg && (beginNode.FunctionType == KnownFuncType.Add ||
                            (beginNode.FunctionType == KnownFuncType.Mult && child == funcNode.Childs.First())))
                {
                    if (child.Type == MathNodeType.Value)
                    {
                        newChilds.Add(new ValueNode(-((ValueNode)child).Value));
                    }
                    else
                    {
                        newChilds.Add(new FuncNode(KnownFuncType.Neg, child));
                    }
                }
                else
                {
                    newChilds.Add(child);
                }
            }
        }
Example #28
0
        public FuncNode(FuncNode node)
        {
            FunctionType = node.FunctionType;
            Name         = node.Name;
            Number       = node.Number;
            for (int i = 0; i < node.Childs.Count; i++)
            {
                switch (node.Childs[i].Type)
                {
                case MathNodeType.Value:
                    Childs.Add(new ValueNode(((ValueNode)node.Childs[i]).Value));
                    break;

                case MathNodeType.Constant:
                case MathNodeType.Variable:
                    Childs.Add(node.Childs[i]);
                    break;

                case MathNodeType.Function:
                    Childs.Add(new FuncNode((FuncNode)node.Childs[i]));
                    break;
                }
            }
        }
Example #29
0
        public FuncNode(FuncNode node)
        {
            FunctionType = node.FunctionType;
            Name         = node.Name;
            Number       = node.Number;
            for (int i = 0; i < node.Children.Count; i++)
            {
                switch (node.Children[i])
                {
                case ValueNode valueNode:
                    Children.Add(new ValueNode(valueNode.Value));
                    break;

                case ConstNode constNode:
                case VarNode varNode:
                    Children.Add(node.Children[i]);
                    break;

                case FuncNode funcNode:
                    Children.Add(new FuncNode(funcNode));
                    break;
                }
            }
        }
        private MathFuncNode FoldValues(FuncNode funcNode)
        {
            var values = funcNode.Childs
                         .Where(child => child.Type == MathNodeType.Value)
                         .Select(valueChild => ((ValueNode)valueChild).Value);

            Rational <long> result = 0;

            foreach (var value in values)
            {
                result += value;
            }

            var notValuesNodes = funcNode.Childs
                                 .Where(child => child.Type != MathNodeType.Value).ToList();

            if (result == 0)
            {
                return
                    (notValuesNodes.Count == 0 ? new ValueNode(0) :
                     notValuesNodes.Count == 1 ? notValuesNodes.First() :
                     new FuncNode(KnownFuncType.Add, notValuesNodes.ToList()));
            }
            else
            {
                if (notValuesNodes.Count == 0)
                {
                    return(new ValueNode(result));
                }
                else
                {
                    notValuesNodes.Add(new ValueNode(result));
                    return(new FuncNode(KnownFuncType.Add, notValuesNodes));
                }
            }
        }
		private bool EmitDivFunc(FuncNode funcNode)
		{
			EmitNode(funcNode.Childs[0]);
			for (int i = 1; i < funcNode.Childs.Count; i++)
			{
				EmitNode(funcNode.Childs[i]);
				IlInstructions.Add(new OpCodeArg(OpCodes.Div));
			}

			return true;
		}
Example #32
0
		public FuncNode(FuncNode node)
		{
			FunctionType = node.FunctionType;
			Name = node.Name;
			Number = node.Number;
			for (int i = 0; i < node.Childs.Count; i++)
				switch (node.Childs[i].Type)
				{
					case MathNodeType.Value:
						Childs.Add(new ValueNode(((ValueNode)node.Childs[i]).Value));
						break;
					case MathNodeType.Constant:
					case MathNodeType.Variable:
						Childs.Add(node.Childs[i]);
						break;
					case MathNodeType.Function:
						Childs.Add(new FuncNode((FuncNode)node.Childs[i]));
						break;
				}
		}
		private MathFuncNode FoldValues(FuncNode funcNode)
		{
			var values = funcNode.Childs
				.Where(child => child.Type == MathNodeType.Value)
				.Select(valueChild => ((ValueNode)valueChild).Value);

			Rational<long> result = 0;
			foreach (var value in values)
				result += value;

			var notValuesNodes = funcNode.Childs
				.Where(child => child.Type != MathNodeType.Value).ToList();

			if (result == 0)
				return
					notValuesNodes.Count == 0 ? new ValueNode(0) :
					notValuesNodes.Count == 1 ? notValuesNodes.First() :
					new FuncNode(KnownFuncType.Add, notValuesNodes.ToList());
			else
			{
				if (notValuesNodes.Count == 0)
					return new ValueNode(result);
				else
				{
					notValuesNodes.Add(new ValueNode(result));
					return new FuncNode(KnownFuncType.Add, notValuesNodes);
				}
			}
		}
		private MathFuncNode ExpValue(FuncNode funcNode)
		{
			var bValue = funcNode.Childs[1] as ValueNode;
			if (bValue != null)
			{
				if (bValue.Value == 0)
					return new ValueNode(1);
				else if (bValue.Value == 1)
					return funcNode.Childs[0];
				/*else if (funcNode.Childs[0].Type == MathNodeType.Value)
				{
					double a = funcNode.Childs[0].Value.ToDouble();
					double b = bValue.Value.ToDouble();
					double r = b == 0.5 ? Math.Sqrt(a) : Math.Pow(a, b);
					Rational<long> result;
					Rational<long>.FromDecimal((decimal)r, out result);
					return new ValueNode(result);
				}*/
				else if (bValue.Value.IsInteger && funcNode.Childs[0].Type == MathNodeType.Function &&
					((FuncNode)funcNode.Childs[0]).FunctionType == KnownFuncType.Neg)
				{
					if (bValue.Value.Numerator % 2 == 0)
						return new FuncNode(KnownFuncType.Exp, funcNode.Childs[0].Childs[0], new ValueNode(bValue.Value));
					else
						return new FuncNode(KnownFuncType.Neg, new FuncNode(KnownFuncType.Exp, funcNode.Childs[0].Childs[0], new ValueNode(bValue.Value)));
				}
			}

			var aValue = funcNode.Childs[0] as ValueNode;
			if (aValue != null)
			{
				if (aValue.Value == 0)
					return new ValueNode(0);
				else if (aValue.Value == 1)
					return new ValueNode(1);
				else if (bValue != null)
					return (MathFuncNode)SimplifyValues(KnownFuncType.Exp, new List<ValueNode>() { aValue, bValue }) 
						?? (MathFuncNode)funcNode;
			}

			return funcNode;
		}
		private MathFuncNode BreakOnAddNodes(FuncNode funcNode)
		{
			var addNodes = funcNode.Childs.Where(child =>
						child.Type == MathNodeType.Function &&
						((FuncNode)child).FunctionType == KnownFuncType.Add).ToList();

			if (addNodes.Count != 0)
			{
				var funcNodesExceptAddNodes = funcNode.Childs.Except(addNodes);
				var ar = new int[addNodes.Count];
				var lengthAr = addNodes.Select(addNode => addNode.Childs.Count).ToArray();

				var newAddChilds = new List<MathFuncNode>();
				var newChilds = new List<MathFuncNode>();

				do
				{
					newAddChilds.Clear();
					newAddChilds.AddRange(funcNodesExceptAddNodes);
					for (int j = 0; j < ar.Length; j++)
						newAddChilds.Add(addNodes[j].Childs[ar[j]]);

					newChilds.Add(Simplify(new FuncNode(KnownFuncType.Mult, newAddChilds)));
				}
				while (IncArray(ar, lengthAr));

				return Simplify(new FuncNode(KnownFuncType.Add, newChilds));
			}
			else
				return null;
		}
		private FuncNode PrecompileExpFunc(MathFuncNode parent, FuncNode funcNode)
		{
			if ((parent == null ||
				((FuncNode)parent).FunctionType != KnownFuncType.Mult) &&
				funcNode.Childs[1].LessThenZero())
			{
				if (!funcNode.Childs[1].IsValueOrCalculated || funcNode.Childs[1].DoubleValue != -1.0)
				{
					FuncNode second;
					if (!funcNode.Childs[1].IsValueOrCalculated)
						second = new FuncNode(KnownFuncType.Pow, funcNode.Childs[0], funcNode.Childs[1].Abs());
					else
						second = Math.Abs(funcNode.Childs[1].DoubleValue) != 0.5 ?
							new FuncNode(KnownFuncType.Pow, funcNode.Childs[0], funcNode.Childs[1].Abs()) :
							new FuncNode(KnownFuncType.Sqrt, funcNode.Childs[0]);
					return new FuncNode(KnownFuncType.Div, new CalculatedNode(1.0), second);
				}
				else
					return new FuncNode(KnownFuncType.Div, new CalculatedNode(1.0), funcNode.Childs[0]);
			}
			if (funcNode.Childs[1].IsValueOrCalculated && funcNode.Childs[1].DoubleValue == 0.5)
				return new FuncNode(KnownFuncType.Sqrt, funcNode.Childs[0]);
			return funcNode;
		}
		private bool EmitUnknownFunc(FuncNode funcNode)
		{
			IlInstructions.Add(new OpCodeArg(OpCodes.Ldarg, funcNode.ArgNumber));

			foreach (var child in funcNode.Childs)
				EmitNode(child);

			IlInstructions.Add(new OpCodeArg(OpCodes.Callvirt, MathFuncAssembly.InvokeFuncRef));

			return true;
		}
		private bool EmitMultFunc(FuncNode funcNode)
		{
			MathFuncNode firstItem = null;

			firstItem = funcNode.Childs.FirstOrDefault(node =>
			{
				var func = node as FuncNode;
				return !(func != null && FuncNodes[func].Count == 1 && func.FunctionType == KnownFuncType.Pow && func.Childs[1].LessThenZero());
			});

			if (firstItem == null)
				firstItem = funcNode.Childs[0];

			EmitNode(firstItem);

			for (int i = 0; i < funcNode.Childs.Count; i++)
			{
				if (funcNode.Childs[i] == firstItem)
					continue;

				var func = funcNode.Childs[i] as FuncNode;

				if (func != null && FuncNodes[func].Count == 1 && func.FunctionType == KnownFuncType.Pow && func.Childs[1].LessThenZero())
				{
					EmitNode(funcNode.Childs[i], true);
					IlInstructions.Add(new OpCodeArg(OpCodes.Div));
				}
				else
				{
					EmitNode(funcNode.Childs[i]);
					if (IlInstructions[IlInstructions.Count - 1].OpCode == OpCodes.Ldc_R8 && (double)IlInstructions[IlInstructions.Count - 1].Arg == 1.0)
						IlInstructions.RemoveAt(IlInstructions.Count - 1);
					else
						IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
				}
			}

			return true;
		}
        private MathFuncNode PrecompileMultFunc(FuncNode funcNode)
        {
            MathFuncNode firstItem;
            MathFuncNode result = null;

            var funcNode2 = MultCalculatedFactors(funcNode);

            //var funcNode2 = funcNode;

            firstItem = funcNode2.Childs.FirstOrDefault(node =>
            {
                var func = node as FuncNode;
                return(!(func != null && func.FunctionType == KnownFuncType.Pow && func.Childs[1].LessThenZero()));
            });

            if (firstItem == null)
            {
                firstItem = funcNode2.Childs[0];
                result    = PrecompileExpFunc(null, (FuncNode)funcNode2.Childs[0]);
            }
            else
            {
                result = firstItem;
            }

            for (int i = 0; i < funcNode2.Childs.Count; i++)
            {
                if (funcNode2.Childs[i] == firstItem)
                {
                    continue;
                }

                FuncNode funcChildNode = funcNode2.Childs[i] as FuncNode;
                if (funcChildNode != null && funcChildNode.FunctionType == KnownFuncType.Pow && funcChildNode.Childs[1].LessThenZero())
                {
                    if (!funcChildNode.Childs[1].IsValueOrCalculated || funcChildNode.Childs[1].DoubleValue != -1.0)
                    {
                        FuncNode second;
                        if (!funcChildNode.Childs[1].IsValueOrCalculated)
                        {
                            second = new FuncNode(KnownFuncType.Pow, funcChildNode.Childs[0], funcChildNode.Childs[1].Abs());
                        }
                        else
                        {
                            second = Math.Abs(funcChildNode.Childs[1].DoubleValue) != 0.5 ?
                                     new FuncNode(KnownFuncType.Pow, funcChildNode.Childs[0], funcChildNode.Childs[1].Abs()) :
                                     new FuncNode(KnownFuncType.Sqrt, funcChildNode.Childs[0]);
                        }
                        result = new FuncNode(KnownFuncType.Div, result, second);
                    }
                    else
                    {
                        result = new FuncNode(KnownFuncType.Div, result, funcChildNode.Childs[0]);
                    }
                }
                else
                {
                    result = new FuncNode(KnownFuncType.Mult, result, funcNode2.Childs[i]);
                }
            }

            return(result);
        }
		private MathFuncNode PrecompileMultFunc(FuncNode funcNode)
		{
			MathFuncNode firstItem;
			MathFuncNode result = null;

			var funcNode2 = MultCalculatedFactors(funcNode);
			//var funcNode2 = funcNode;

			firstItem = funcNode2.Childs.FirstOrDefault(node =>
			{
				var func = node as FuncNode;
				return !(func != null && func.FunctionType == KnownFuncType.Pow && func.Childs[1].LessThenZero());
			});

			if (firstItem == null)
			{
				firstItem = funcNode2.Childs[0];
				result = PrecompileExpFunc(null, (FuncNode)funcNode2.Childs[0]);
			}
			else
				result = firstItem;

			for (int i = 0; i < funcNode2.Childs.Count; i++)
			{
				if (funcNode2.Childs[i] == firstItem)
					continue;

				FuncNode funcChildNode = funcNode2.Childs[i] as FuncNode;
				if (funcChildNode != null && funcChildNode.FunctionType == KnownFuncType.Pow && funcChildNode.Childs[1].LessThenZero())
				{
					if (!funcChildNode.Childs[1].IsValueOrCalculated || funcChildNode.Childs[1].DoubleValue != -1.0)
					{
						FuncNode second;
						if (!funcChildNode.Childs[1].IsValueOrCalculated)
							second = new FuncNode(KnownFuncType.Pow, funcChildNode.Childs[0], funcChildNode.Childs[1].Abs());
						else
							second = Math.Abs(funcChildNode.Childs[1].DoubleValue) != 0.5 ?
								new FuncNode(KnownFuncType.Pow, funcChildNode.Childs[0], funcChildNode.Childs[1].Abs()) :
								new FuncNode(KnownFuncType.Sqrt, funcChildNode.Childs[0]);
						result = new FuncNode(KnownFuncType.Div, result, second);
					}
					else
						result = new FuncNode(KnownFuncType.Div, result, funcChildNode.Childs[0]);
				}
				else
					result = new FuncNode(KnownFuncType.Mult, result, funcNode2.Childs[i]);
			}

			return result;
		}
		private bool EmitAddFunc(FuncNode funcNode)
		{
			MathFuncNode firstItem = null;

			firstItem = funcNode.Childs.FirstOrDefault(node =>
			{
				var func = node as FuncNode;
				return !(func != null && FuncNodes[func].Count == 1 && func.LessThenZero());
			});

			if (firstItem == null)
				firstItem = funcNode.Childs[0];

			EmitNode(firstItem);

			for (int i = 0; i < funcNode.Childs.Count; i++)
			{
				if (funcNode.Childs[i] == firstItem)
					continue;

				var func = funcNode.Childs[i] as FuncNode;
				if (func != null && FuncNodes[func].Count == 1 && func.LessThenZero())
				{
					EmitNode(func.Childs[0], true);
					IlInstructions.Add(new OpCodeArg(OpCodes.Sub));
				}
				else
				{
					EmitNode(funcNode.Childs[i]);
					IlInstructions.Add(new OpCodeArg(OpCodes.Add));
				}
			}

			return true;
		}
		private FuncNode FoldCalculatedSummands(FuncNode sum)
		{
			var result = sum.Childs
				.Where(child => child.Type == MathNodeType.Calculated || child.Type == MathNodeType.Value)
				.Select(summand => summand.DoubleValue)
				.Aggregate(0.0, (t, factor) => t += factor);

			if (result != 0.0)
			{
				var newChilds = new List<MathFuncNode>() { new CalculatedNode(result) };
				newChilds.AddRange(sum.Childs.Where(c => c.Type != MathNodeType.Calculated && c.Type != MathNodeType.Value));

				return new FuncNode(KnownFuncType.Sub, newChilds);
			}
			else
				return sum;
		}
		private bool EmitExpFunc(FuncNode funcNode, bool negExpAbs)
		{
			if ((funcNode.Childs[1].Type == MathNodeType.Value && ((ValueNode)funcNode.Childs[1]).Value.IsInteger) ||
				(funcNode.Childs[1].Type == MathNodeType.Calculated && ((CalculatedNode)funcNode.Childs[1]).Value % 1 == 0))
			{
				int powerValue = (int)funcNode.Childs[1].DoubleValue;
				int power = Math.Abs(powerValue);
				if (negExpAbs)
					powerValue = power;

				if (powerValue < 0)
					IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));

				EmitNode(funcNode.Childs[0]);

				if (power == 1)
				{
				}
				else
					if (power <= 3)
					{
						IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
						for (int i = 1; i < power; i++)
						{
							IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
							IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
						}
					}
					else if (power == 4)
					{
						IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
						IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
						IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
					}
					else
					{
						// result: funcNode.Number
						// x: funcNode.Number + 1

						//int result = x;
						IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number + 1));
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1));

						power--;
						do
						{
							if ((power & 1) == 1)
							{
								IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1));
								IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
							}

							if (power <= 1)
								break;

							//x = x * x;
							IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1));
							IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1));
							IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
							IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number + 1));

							power = power >> 1;
						}
						while (power != 0);
					}

				if (powerValue < 0)
					IlInstructions.Add(new OpCodeArg(OpCodes.Div));
			}
			else
			{
				var child1 = funcNode.Childs[1];
				if ((child1.Type == MathNodeType.Value && ((ValueNode)child1).Value.Abs() == new Rational<long>(1, 2, false)) ||
					(child1.Type == MathNodeType.Calculated && Math.Abs(((CalculatedNode)child1).Value) == 0.5))
				{
					if (!negExpAbs && ((child1.Type == MathNodeType.Value && ((ValueNode)child1).Value < 0) ||
							(child1.Type == MathNodeType.Calculated && ((CalculatedNode)child1).Value < 0)))
					{
						IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));
						EmitNode(funcNode.Childs[0]);
						IlInstructions.Add(new OpCodeArg(OpCodes.Call, MathFuncAssembly.TypesReferences[KnownFuncType.Sqrt]));
						IlInstructions.Add(new OpCodeArg(OpCodes.Div));
					}
					else
					{
						EmitNode(funcNode.Childs[0]);
						IlInstructions.Add(new OpCodeArg(OpCodes.Call, MathFuncAssembly.TypesReferences[KnownFuncType.Sqrt]));
					}
				}
				else
				{
					EmitNode(funcNode.Childs[0]);
					if (negExpAbs)
						EmitNode(funcNode.Childs[1].Abs());
					else
						EmitNode(funcNode.Childs[1]);

					IlInstructions.Add(new OpCodeArg(OpCodes.Call, MathFuncAssembly.TypesReferences[(KnownFuncType)funcNode.FunctionType]));
				}
			}

			return true;
		}
Example #44
0
		protected string ToString(FuncNode parent,
			KnownFuncType funcType,
			IList<KnownFuncType> types)
		{
			var builder = new StringBuilder();

			if (parent == null || parent.Name == null || parent.Childs.Count <= 1)
			{
				AppendMathFunctionNode(builder, funcType);
				return builder.ToString();
			}

			var funcNodeParent = parent as FuncNode;
			if (funcNodeParent != null && funcNodeParent.IsKnown)
				if (types.Contains((KnownFuncType)funcNodeParent.FunctionType))
				{
					AppendMathFunctionNode(builder, funcType);
					return builder.ToString();
				}

			builder.Append("(");
			AppendMathFunctionNode(builder, funcType);
			builder.Append(")");
			return builder.ToString();
		}
		private MathFuncNode GetFuncDerivative(FuncNode funcNode)
		{
			MathFunc value;
			if (funcNode.IsKnown)
			{
				if (funcNode.FunctionType == KnownFuncType.Add ||
					funcNode.FunctionType == KnownFuncType.Sub)
				{
					var newChilds = new List<MathFuncNode>(funcNode.Childs.Count);
					for (int i = 0; i < funcNode.Childs.Count; i++)
						newChilds.Add(GetDerivative(funcNode.Childs[i]));
					return new FuncNode(KnownFuncType.Add, newChilds);
				}
				else if (funcNode.FunctionType == KnownFuncType.Mult)
				{
					var newChilds = new List<MathFuncNode>(funcNode.Childs.Count);
					for (int i = 0; i < funcNode.Childs.Count; i++)
					{
						var addNode = new List<MathFuncNode>();
						for (int j = 0; j < funcNode.Childs.Count; j++)
						{
							if (i == j)
								addNode.Add(GetDerivative(funcNode.Childs[i]));
							else
								addNode.Add((MathFuncNode)funcNode.Childs[j].Clone());
						}
						newChilds.Add(new FuncNode(KnownFuncType.Mult, addNode));
					}
					return new FuncNode(KnownFuncType.Add, newChilds);
				}
				else if (funcNode.FunctionType == KnownFuncType.Pow)
				{
					if (funcNode.Childs[1].IsValueOrCalculated)
					{
						var node1 = funcNode.Childs[1].Type == MathNodeType.Value ? (MathFuncNode)
							new ValueNode((ValueNode)funcNode.Childs[1]) :
							new CalculatedNode((CalculatedNode)funcNode.Childs[1]);
						var node2 = funcNode.Childs[1].Type == MathNodeType.Value ? (MathFuncNode)
							new ValueNode(((ValueNode)funcNode.Childs[1]).Value - 1) :
							new CalculatedNode(((CalculatedNode)funcNode.Childs[1]).Value - 1);

						return new FuncNode(KnownFuncType.Mult,
								node1,
								new FuncNode(KnownFuncType.Pow, (MathFuncNode)funcNode.Childs[0].Clone(), node2),
								GetDerivative(funcNode.Childs[0]));
					}

					var constNode = funcNode.Childs[1] as ConstNode;
					if (constNode != null)
						return new FuncNode(KnownFuncType.Mult,
								new ConstNode(constNode.Name),
								new FuncNode(KnownFuncType.Pow,
									(MathFuncNode)funcNode.Childs[0].Clone(),
									new FuncNode(KnownFuncType.Add, new ConstNode(constNode.Name), new ValueNode(-1))
								),
								GetDerivative(funcNode.Childs[0])
							);
				}
				else if (funcNode.FunctionType == KnownFuncType.Diff)
				{
					if (funcNode.Childs[0].Type == MathNodeType.Function)
					{
						if (((FuncNode)funcNode.Childs[0]).IsKnown)
						{
							var der = GetDerivative(funcNode.Childs[0]);
							if (der.Childs[0].Type == MathNodeType.Function && ((FuncNode)der).FunctionType == KnownFuncType.Diff)
								return new FuncNode(KnownFuncType.Diff, der, Variable);
							else
								return GetDerivative(der);
						}
						else
							return new FuncNode(KnownFuncType.Diff, GetDerivative(funcNode.Childs[0]), Variable);
					}
					else
						return new ValueNode(0);
				}
				else if (funcNode.FunctionType == KnownFuncType.Neg)
				{
					return new FuncNode(KnownFuncType.Neg, GetDerivative(funcNode.Childs[0]));
				}
			}

			if (Helper.Derivatives.TryGetValue(funcNode.Name, out value))
			{
				var sub = value;
				var subNode = MakeSubstitution(sub.LeftNode.Childs[0], sub.RightNode, funcNode);
				GetDerivatives(subNode);
				return subNode;
			}
			else
			{
				return new FuncNode(KnownFuncType.Mult,
					new FuncNode(KnownFuncType.Diff, (MathFuncNode)funcNode.Clone(), Variable),
					GetDerivative(funcNode.Childs[0]));
			}
		}
Example #46
0
		public override string ToString(FuncNode parent)
		{
			if (IsKnown)
			{
				var funcType = (KnownFuncType)FunctionType;
				switch ((KnownFuncType)FunctionType)
				{
					case KnownFuncType.Add:
					case KnownFuncType.Sub:
						return ToString(parent, funcType, KnownFunc.AddKnownFuncs);

					case KnownFuncType.Mult:
					case KnownFuncType.Div:
						return ToString(parent, funcType, KnownFunc.MultKnownFuncs);

					case KnownFuncType.Exp:
						return ToString(parent, funcType, KnownFunc.ExpKnownFuncs);

					case KnownFuncType.Neg:
						if (Childs[0].Type == MathNodeType.Function)
						{
							var func = (FuncNode)Childs[0];
							if (KnownFunc.NegKnownFuncs.Contains((KnownFuncType)func.FunctionType))
								return "-(" + Childs[0].ToString(this) + ")";
							else
								return "-" + Childs[0].ToString(this);
						}
						else
							return "-" + Childs[0].ToString(this);

					case KnownFuncType.Diff:
						return Childs[0].Type == MathNodeType.Function && ((FuncNode)Childs[0]).FunctionType != KnownFuncType.Diff ?
							Childs[0].ToString(this) + "'" : "(" + 
							Childs[0].ToString(this) + ")'";

					case KnownFuncType.Abs:
						return string.Format("|{0}|", Childs[0].ToString(this));
				}
			}
			var builder = new StringBuilder((FunctionType == KnownFuncType.Sqrt ? "√" : Name) + "(");
			foreach (var arg in Childs)
				builder.AppendFormat("{0}, ", arg.ToString(this));
			if (Childs.Count != 0)
				builder.Remove(builder.Length - 2, 2);
			builder.Append(')');
			return builder.ToString();
		}
		private bool EmitDiffFunc(FuncNode funcNode)
		{
			var diffFunc = funcNode.Childs[0];
			var arg = diffFunc.Childs[0];
			bool isUnknownFunc = diffFunc.Type == MathNodeType.Function && !((FuncNode)diffFunc).IsKnown;

			var diff = FuncNodes[(FuncNode)diffFunc];

			// f(x + dx)
			if (isUnknownFunc)
				IlInstructions.Add(new OpCodeArg(OpCodes.Ldarg, diffFunc.ArgNumber));
			EmitNode(arg);
			IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, DerivativeDelta));
			IlInstructions.Add(new OpCodeArg(OpCodes.Add));
			if (isUnknownFunc)
				IlInstructions.Add(new OpCodeArg(OpCodes.Callvirt, MathFuncAssembly.InvokeFuncRef));
			else
				EmitNode(diffFunc);

			// f(x)
			EmitNode(diffFunc);

			IlInstructions.Add(new OpCodeArg(OpCodes.Sub));
			IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0 / DerivativeDelta));
			IlInstructions.Add(new OpCodeArg(OpCodes.Mul));

			return true;
		}
Example #48
0
		public override string ToString(FuncNode parent)
		{
			if (Value.Denominator == 1 || !parent.IsKnown)
				return Name;

			if (parent.FunctionType == KnownFuncType.Mult || parent.FunctionType == KnownFuncType.Div ||
				parent.FunctionType == KnownFuncType.Exp || parent.FunctionType == KnownFuncType.Neg)
			{
				return '(' + Name + ')';
			}
			else
				return Name;
		}
		private bool EmitKnownFunc(FuncNode funcNode)
		{
			MethodReference value;
			if (funcNode.FunctionType != null && MathFuncAssembly.TypesReferences.TryGetValue((KnownFuncType)funcNode.FunctionType, out value))
			{
				foreach (var child in funcNode.Childs)
					EmitNode(child);

				IlInstructions.Add(new OpCodeArg(OpCodes.Call, value));

				return true;
			}
			else if (funcNode.FunctionType == KnownFuncType.Cot)
			{
				IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));
				EmitNode(funcNode.Childs[0]);
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Tan]));
				IlInstructions.Add(new OpCodeArg(OpCodes.Div));

				return true;
			}
			else if (funcNode.FunctionType == KnownFuncType.Arccot)
			{
				IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));
				EmitNode(funcNode.Childs[0]);
				IlInstructions.Add(new OpCodeArg(OpCodes.Div));
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Arctan]));

				return true;
			}
			else if (funcNode.FunctionType == KnownFuncType.Arcsinh)
			{
				EmitNode(funcNode.Childs[0]);
				EmitNode(funcNode.Childs[0]);
				EmitNode(funcNode.Childs[0]);
				IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
				IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));
				IlInstructions.Add(new OpCodeArg(OpCodes.Add));
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Sqrt]));
				IlInstructions.Add(new OpCodeArg(OpCodes.Add));
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Log]));

				return true;
			}
			else if (funcNode.FunctionType == KnownFuncType.Arcosh)
			{
				EmitNode(funcNode.Childs[0]);
				EmitNode(funcNode.Childs[0]);
				IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));
				IlInstructions.Add(new OpCodeArg(OpCodes.Add));
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Sqrt]));
				EmitNode(funcNode.Childs[0]);
				IlInstructions.Add(new OpCodeArg(OpCodes.Ldc_R8, 1.0));
				IlInstructions.Add(new OpCodeArg(OpCodes.Sub));
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Sqrt]));
				IlInstructions.Add(new OpCodeArg(OpCodes.Mul));
				IlInstructions.Add(new OpCodeArg(OpCodes.Add));
				IlInstructions.Add(new OpCodeArg(OpCodes.Call, KnownFunc.TypesMethods[KnownFuncType.Log]));

				return true;
			}
			else
				return false;
		}
		private bool EmitFunc(FuncNode funcNode, bool negExpAbs = false)
		{
			switch (funcNode.FunctionType)
			{
				case KnownFuncType.Add:
					return EmitAddFunc(funcNode);
				case KnownFuncType.Sub:
					return EmitSubFunc(funcNode);
				case KnownFuncType.Mult:
					return EmitMultFunc(funcNode);
				case KnownFuncType.Div:
					return EmitDivFunc(funcNode);
				case KnownFuncType.Neg:
					return EmitNegFunc(funcNode, negExpAbs);
				case KnownFuncType.Pow:
					return EmitExpFunc(funcNode, negExpAbs);
				case KnownFuncType.Diff:
					return EmitDiffFunc(funcNode);
			}

			if (!EmitKnownFunc(funcNode)) // Unknown function (from input args).
				EmitUnknownFunc(funcNode);

			return true;
		}
		private void ReduceSummands(FuncNode funcNode)
		{
			int i = 0;
			while (i < funcNode.Childs.Count)
			{
				int j = i + 1;
				while (j < funcNode.Childs.Count)
				{
					var newNode = ReduceAddition(funcNode.Childs[i], funcNode.Childs[j]);
					if (newNode != null)
					{
						funcNode.Childs[i] = newNode;
						funcNode.Childs.RemoveAt(j);
					}
					else
						j++;
				}
				i++;
			}
		}
		private void BuildMultichildTree(FuncNode beginNode)
		{
			var newChilds = new List<MathFuncNode>();
			BuildMultichildTree(beginNode, beginNode, newChilds, false);
			beginNode.Childs = newChilds;
		}
		private bool EmitNegFunc(FuncNode funcNode, bool negExpAbs)
		{
			EmitNode(funcNode.Childs[0]);

			if (!negExpAbs)
				IlInstructions.Add(new OpCodeArg(OpCodes.Neg));

			return true;
		}
		private void BuildMultichildTree(FuncNode beginNode, FuncNode funcNode, List<MathFuncNode> newChilds, bool neg)
		{
			foreach (var child in funcNode.Childs)
			{
				var childFuncNode = child as FuncNode;
				if (childFuncNode != null)
				{
					if (childFuncNode.FunctionType == beginNode.FunctionType)
					{
						BuildMultichildTree(beginNode, childFuncNode, newChilds, neg);
						continue;
					}
					else if (childFuncNode.FunctionType == KnownFuncType.Neg)
					{
						BuildMultichildTree(beginNode, childFuncNode, newChilds, !neg);
						continue;
					}
				}

				if (neg && (beginNode.FunctionType == KnownFuncType.Add ||
					(beginNode.FunctionType == KnownFuncType.Mult && child == funcNode.Childs.First())))
				{
					if (child.Type == MathNodeType.Value)
						newChilds.Add(new ValueNode(-((ValueNode)child).Value));
					else
						newChilds.Add(new FuncNode(KnownFuncType.Neg, child));
				}
				else
					newChilds.Add(child);
			}
		}
		private MathFuncNode ReduceAddition(MathFuncNode node1, MathFuncNode node2)
		{
			var node1neg = node1.Type == MathNodeType.Function && (node1 as FuncNode).FunctionType == KnownFuncType.Neg;
			var node2neg = node2.Type == MathNodeType.Function && (node2 as FuncNode).FunctionType == KnownFuncType.Neg;
			var node11 = node1neg ? node1.Childs[0] : node1;
			var node21 = node2neg ? node2.Childs[0] : node2;

			MathFuncNode valueNode1 = null;
			if (node11.Type == MathNodeType.Function &&
				(node11 as FuncNode).FunctionType == KnownFuncType.Mult)
					valueNode1 = node11.Childs.Where(child => child.IsValueOrCalculated).FirstOrDefault();
			if (valueNode1 == null)
				valueNode1 = node11.IsValueOrCalculated ? node11 : new ValueNode(new Rational<long>(1, 1));
			var value1 = ((ValueNode)valueNode1).Value;
			if (node1neg)
				value1 *= -1;

			MathFuncNode valueNode2 = null;
			if (node21.Type == MathNodeType.Function &&
				(node21 as FuncNode).FunctionType == KnownFuncType.Mult)
				valueNode2 = node21.Childs.Where(child => child.IsValueOrCalculated).FirstOrDefault();
			if (valueNode2 == null)
				valueNode2 = node21.IsValueOrCalculated ? node21 : new ValueNode(new Rational<long>(1, 1));
			var value2 = ((ValueNode)valueNode2).Value;
			if (node2neg)
				value2 *= -1;

			var notValueNodes1 = node11.Type == MathNodeType.Function &&
				(node11 as FuncNode).FunctionType == KnownFuncType.Mult ?
				node11.Childs.Where(child => !child.IsValueOrCalculated).ToList() :
				node11.IsValueOrCalculated ?
				new List<MathFuncNode>() { } :
				new List<MathFuncNode>() { node11 };
			var notValueNodes2 = node21.Type == MathNodeType.Function &&
				(node21 as FuncNode).FunctionType == KnownFuncType.Mult ?
				node21.Childs.Where(child => !child.IsValueOrCalculated).ToList() :
				node21.IsValueOrCalculated ?
				new List<MathFuncNode>() { } :
				new List<MathFuncNode>() { node21 };

			var mult1 = new FuncNode(KnownFuncType.Mult, notValueNodes1.ToList());
			var mult2 = new FuncNode(KnownFuncType.Mult, notValueNodes2.ToList());
			mult1.Sort();
			mult2.Sort();

			if (mult1.Equals(mult2))
			{
				var resultNodes = new List<MathFuncNode>();
				resultNodes.Add(new ValueNode(value1 + value2));
				resultNodes.AddRange(notValueNodes1);
				return Simplify(new FuncNode(KnownFuncType.Mult, resultNodes));
			}
			else
				return null;
		}
		private MathFuncNode MakeSubstitution(MathFuncNode left, MathFuncNode right, FuncNode currentFunc)
		{
			LeftNode = left;
			RightNode = right;
			_currentFunc = currentFunc;
			return MakeSubstitution(right);
		}
		private FuncNode MultCalculatedFactors(FuncNode mult)
		{
			var result = mult.Childs
				.Where(child => child.Type == MathNodeType.Calculated || child.Type == MathNodeType.Value)
				.Select(factor => factor.DoubleValue)
				.Aggregate(1.0, (t, factor) => t *= factor);

			if (result != 1.0)
			{
				var newChilds = new List<MathFuncNode>() { new CalculatedNode(result) };
				newChilds.AddRange(mult.Childs.Where(c => c.Type != MathNodeType.Calculated && c.Type != MathNodeType.Value));

				return new FuncNode(KnownFuncType.Mult, newChilds);
			}
			else
				return mult;
		}