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)); }
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; }
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 })); }
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()); }
public MathFuncNode VisitParenthesisExpression(ParenthesisExpressionContext context) { var result = Visit(context.expression()); if (context.Quote() != null) { result = new FuncNode(KnownFuncType.Diff, result); } return(result); }
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); }
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); } }
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); } } }
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; } } }
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; }
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; }
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])); } }
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; }
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; }