/// <summary> /// Remove a complex assignment /// </summary> /// <param name="a"></param> public void Remove(ComplexAssignment a) { if (Real.Contains(a)) { Real.Remove(a); } if (Imag.Contains(a)) { Imag.Remove(a); } map.Remove(a.Index); nmap[a.Nodes].Remove(a); }
/// <summary> /// Add a complex assignment /// </summary> /// <param name="a"></param> public void Add(ComplexAssignment a) { if (a.Real) { Real.Add(a); } else { Imag.Add(a); } if (!nmap.ContainsKey(a.Nodes)) { nmap.Add(a.Nodes, new HashSet <ComplexAssignment>()); } nmap[a.Nodes].Add(a); map.Add(a.Index, a); }
/// <summary> /// Match assignments /// </summary> private void MatchAssignments(AssignmentGroup group, SortedDictionary <int, ComplexAssignment> insert, SortedDictionary <int, ComplexAssignment> remove) { // Try to match all the statements in the group foreach (var node in group.AllNodes) { ComplexAssignment na = new ComplexAssignment(); na.Nodes = node; na.Op = null; na.Index = int.MaxValue; na.Length = 0; na.Real = true; // Create the real part string rpart = ""; foreach (var a in group.RealByNode(node)) { if (na.Op == null) { na.Op = a.Op; rpart = a.Value; } else { if (a.Op == na.Op) { if (rpart.Length > 0) { rpart += " + "; } rpart += a.Value; } else { if (rpart.Length > 0) { rpart += " - "; } else { rpart += "-"; } if (a.Value.Contains('+') || a.Value.Contains('-')) { rpart += "(" + a.Value + ")"; } else { rpart += a.Value; } } } // Keep the first assignment to insert if (a.Index < na.Index) { na.Index = a.Index; } remove.Add(a.Index, a); } // Create the imaginary part string ipart = ""; foreach (var a in group.ImaginaryByNode(node)) { if (na.Op == null) { na.Op = a.Op; ipart = a.Value; } else { if (a.Op == na.Op) { if (ipart.Length > 0) { ipart += " + "; } ipart += a.Value; } else { if (ipart.Length > 0) { ipart += " - "; } else { ipart += "-"; } if (a.Value.Contains('+') || a.Value.Contains('-')) { ipart += "(" + a.Value + ")"; } else { ipart += a.Value; } } } // Keep the first assignment to insert if (a.Index < na.Index) { na.Index = a.Index; } remove.Add(a.Index, a); } // Build the value if (string.IsNullOrEmpty(ipart)) { na.Value = $"cstate.Matrix[{node.Item1}, {node.Item2}] {na.Op} {rpart};"; } else { if (string.IsNullOrEmpty(rpart)) { rpart = "0.0"; } na.Value = $"cstate.Matrix[{node.Item1}, {node.Item2}] {na.Op} new Complex({rpart}, {ipart});"; } na.Length = na.Value.Length; insert.Add(na.Index, na); } }
/// <summary> /// Group the assignments /// </summary> /// <param name="code"></param> /// <returns></returns> private string ComplexAssignments(string code) { // Find assignments to the imaginary part and try to combine them with the real counterpart // The imaginary assignments are of the form: cstate.Matrix[<node1>, <node2>].Imag +=/-= <expression>; // We need to make sure that conditions are not broken while matching equations... // First clean up some annoying brackets code = Regex.Replace(code, @"\((?<inner>cstate.Matrix\[\w+, \w+\][^;]+)\);", (Match m) => m.Groups["inner"].Value + ";"); SortedDictionary <int, ComplexAssignment> remove = new SortedDictionary <int, ComplexAssignment>(); SortedDictionary <int, ComplexAssignment> insert = new SortedDictionary <int, ComplexAssignment>(); // Find all the statements and their starting positions assignments.Clear(); MatchCollection ms = Regex.Matches(code, @"cstate\.Matrix\[(?<n1>\w+), (?<n2>\w+)\](?<imag>\.Imag)? (?<op>[\+\-]\=) (?<value>[^;]+);"); foreach (Match m in ms) { ComplexAssignment a = new ComplexAssignment(); a.Nodes = new Tuple <string, string>(m.Groups["n1"].Value, m.Groups["n2"].Value); a.Op = m.Groups["op"].Value; a.Value = m.Groups["value"].Value; if (m.Groups["imag"].Success) { a.Real = false; } else { a.Real = true; } a.Index = m.Index; a.Length = m.Length; assignments.Add(a); } // Now match them while keeping track of if-statements, comments and strings Stack <AssignmentGroup> currentgroup = new Stack <AssignmentGroup>(); currentgroup.Push(new AssignmentGroup()); Code.LevelExecute(code, (int i, int lvl) => currentgroup.Push(new AssignmentGroup()), (int i, int lvl) => MatchAssignments(currentgroup.Pop(), insert, remove), (int i, int lvl) => { if (assignments.Contains(i)) { currentgroup.Peek().Add(assignments[i]); } }); MatchAssignments(currentgroup.Pop(), insert, remove); // Remove the old statement assignments and add the new ones int offset = 0; var it_insert = insert.GetEnumerator(); var it_remove = remove.GetEnumerator(); bool ic = it_insert.MoveNext(), rc = it_remove.MoveNext(); while (ic || rc) { if (ic && rc) { // First try to add if (it_insert.Current.Key <= it_remove.Current.Key) { int start = it_insert.Current.Key + offset; code = code.Substring(0, start) + it_insert.Current.Value.Value + code.Substring(start); offset += it_insert.Current.Value.Length; ic = it_insert.MoveNext(); } else { // Only now remove int start = it_remove.Current.Key + offset; code = code.Substring(0, start) + code.Substring(start + it_remove.Current.Value.Length); offset -= it_remove.Current.Value.Length; rc = it_remove.MoveNext(); } } else if (ic) { int start = it_insert.Current.Key + offset; code = code.Substring(0, start) + it_insert.Current.Value.Value + code.Substring(start); offset += it_insert.Current.Value.Length; ic = it_insert.MoveNext(); } else if (rc) { // Only now remove int start = it_remove.Current.Key + offset; code = code.Substring(0, start) + code.Substring(start + it_remove.Current.Value.Length); offset -= it_remove.Current.Value.Length; rc = it_remove.MoveNext(); } } return(code); }