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 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;
		}