/* * (a @ (b @ c)) => (a @@ b @@ c) * (a @@ (b @ c)) => (a @@ b @@ c) * (a @@ (b @@ c)) => (a @@ b @@ c) * Same with flatten function. */ private Node BasicMultiNodeConverter(Node node) { BiNode bin = node.TryToGetAsBiNode; if (bin != null) { if (bin.IsAssociative) { return(BasicMultiNodeConverter(bin.ToMultiNode)); } } MultiNode mul = node.TryToGetAsMultiNode; if (mul != null) { foreach (Node element in mul.Elements.ToArray()) { bin = element.TryToGetAsBiNode; if (bin != null) { if (bin.Signature == mul.Signature) { mul.Elements.Remove(element); mul.Elements.AddRange(new List <Node>() { bin.Left, bin.Right }); } } MultiNode eMul = element.TryToGetAsMultiNode; if (eMul != null) { if (eMul.Signature == mul.Signature) { mul.Elements.Remove(element); mul.Elements.AddRange(eMul.Elements); } } } } return(node); }
/* * (5 * 4 * a * 3) => (60 * a) */ private Node BasicMultiMultiplicationConverter(Node node) { MultiNode mul = node.TryToGetAsMultiNode; if (mul != null) { if (mul.Signature == new MultiMultiplication(null).Signature) { List <Node> elements = new List <Node>(); double multiplier = 1; foreach (Node element in mul.Elements) { Value val = element.TryToGetAsValue; if (val != null) { multiplier *= val.GetValue; } else { elements.Add(element); } } if (multiplier == 0) { return(new Value(0)); } else if (multiplier != 1) { elements.Add(new Value(multiplier)); } return(new MultiMultiplication(elements)); } } return(node); }
/* * ((2 * a) + (3 * a) + (4 * a) + b) => ((9 * a) + b) (for all values and any number of elements) */ private Node BasicMultiplicatorComposeConverter(Node node) { MultiNode mul = node.TryToGetAsMultiNode; // This converter converts only multisums if (mul == null) { return(node); } if (mul.Signature == new MultiSum(null).Signature) { // List of nodes that will appear in returned node as elements List <Node> components = new List <Node>(); // Assistant list to avoid any changes in original list List <Node> elements = new List <Node>(mul.Elements); // As the elements list is changed during loop operation it is problematic to use foreach or for loop // This loop checks for duplicates and multiplied by some value duplicates in the list // The multipliers of the duplicates are sumed so all the duplicates can be replaced by one occurance with sumed multiplier // Every found duplicate and original are removed from the list, so, after checking whole list it should be empty while (elements.Count > 0) { Node element = elements[0]; elements.Remove(element); MultiNode submul = element.TryToGetAsMultiNode; double multiplier = 1; Node value; if (submul != null) { List <Node> submul_elements = new List <Node>(submul.Elements); if (submul.Signature == new MultiMultiplication(null).Signature) { value = submul_elements.Find((x) => x.TryToGetAsValue != null); if (value != null) { submul_elements.Remove(value); multiplier = value.TryToGetAsValue.GetValue; submul = new MultiMultiplication(submul_elements); } } element = submul; } for (int i = 0; i < elements.Count; i++) { Node relement = elements[i]; MultiNode rsubmul = relement.TryToGetAsMultiNode; double mult = 1; if (rsubmul != null) { List <Node> rsubmul_elements = new List <Node>(rsubmul.Elements); if (rsubmul.Signature == new MultiMultiplication(null).Signature) { value = rsubmul_elements.Find((x) => x.TryToGetAsValue != null); if (value != null) { rsubmul_elements.Remove(value); mult = value.TryToGetAsValue.GetValue; rsubmul = new MultiMultiplication(rsubmul_elements); } if (element.Compare(rsubmul)) { multiplier += mult; elements.Remove(relement); i--; } } } else if (element.Compare(relement)) { multiplier += mult; elements.Remove(relement); i--; } } if (multiplier != 1) { if (submul != null) { submul.Elements.Add(new Value(multiplier)); element = submul; } else { element = new MultiMultiplication(new List <Node>() { new Value(multiplier), element }); } } components.Add(element); } return(new MultiSum(components)); } return(node); }