/* * Translators for multidimension values. * * The following methods are called specifically for instructions * which have a multidimensional result. */ protected virtual string TranslateV(Cdn.InstructionMatrix instruction, Context context) { List <string> args = new List <string>(context.Node.Children.Count); if (context.SupportsFirstClassArrays) { bool allone = true; // Simply concatenate the arrays for (int i = 0; i < context.Node.Children.Count; ++i) { args.Add(Translate(context, context.Node.Children[i])); if (!context.Node.Children[i].Dimension.IsOne) { allone = false; } } if (allone) { // Literal array return(String.Format("{0}{1}{2}", context.BeginArray, String.Join(", ", args), context.EndArray)); } else { for (int i = 0; i < context.Node.Children.Count; ++i) { if (context.Node.Children[i].Dimension.IsOne) { args.Add(String.Format("{0}{1}{2}", context.BeginArray, args[i], context.EndArray)); } } return(context.ArrayConcat(args.ToArray())); } } else if (IsZeroMatrix(context.Node, context)) { var tmp = context.PeekRet(); return(context.MemZero(tmp, "0", "ValueType", context.Node.Dimension.Size())); } else { var tmp = context.PeekRet(); int argi = 0; for (int i = 0; i < context.Node.Children.Count; ++i) { var child = context.Node.Children[i]; var inum = child.Instruction as InstructionNumber; if (context.IsMapping(child) || inum == null || inum.Value != 0) { // Translate such that we compute the result of the child // at the tmp + argi location if (argi == 0) { args.Add(TranslateAssign(context, child, tmp)); } else if (context.SupportsPointers) { // TODO: check how this works really, well it doesn't! args.Add(TranslateAssign(context, child, String.Format("{0} + {1}", tmp, argi))); } else { throw new Exception("Matrix instruction without pointers is not yet implemented"); } } argi += child.Dimension.Size(); } return(String.Format("({0}, {1})", String.Join(",\n ", args), tmp)); } }
private void PromoteEdgeSlices() { // This function splits all the edge actions on variables based // on the slice on which the operate on the target variable. var cp = d_actionedVariables; d_actionedVariables = new Dictionary <Variable, EdgeAction[]>(); foreach (var pair in cp) { var variable = pair.Key; var actions = pair.Value; var split = SplitActionsPerSlice(actions); if (split.Count == 1) { // That's ok, no diversity means we can just use the // normal code path d_actionedVariables[pair.Key] = pair.Value; continue; } // Contains a set of instructions for each value in the matrix // representing the final, new equation. Each value in the matrix // is a set of instructions because it can be a sum List <Cdn.Instruction>[] instructions = new List <Instruction> [variable.Dimension.Size()]; // Ai! Cool stuff needs to happen here. Split out new // variables for these equations and setup a new edge action // representing the fully combined set. Complex you say? Indeed! foreach (var elem in split) { // Combine elements with the same indices by simply doing a sum var eqs = Array.ConvertAll <Cdn.EdgeAction, Cdn.Expression>(elem.ToArray(), a => a.Equation); Cdn.Expression sum = Cdn.Expression.Sum(eqs); // Now make a variable for it var nv = new Cdn.Variable(UniqueVariableName(variable.Object, String.Format("__d{0}", variable.Name)), sum, VariableFlags.None); variable.Object.AddVariable(nv); // Add relevant instructions as per slice var slice = elem[0].Indices; if (slice == null || slice.Length == 0) { // Empty slice is just the full range slice = new int[variable.Dimension.Size()]; for (int i = 0; i < slice.Length; ++i) { slice[i] = i; } } for (int i = 0; i < slice.Length; ++i) { if (instructions[slice[i]] == null) { instructions[slice[i]] = new List <Instruction>(); } var vinstr = new Cdn.InstructionVariable(nv); vinstr.SetSlice(new int[] { i }, new Cdn.Dimension { Rows = 1, Columns = 1 }); instructions[slice[i]].Add(vinstr); } } List <Cdn.Instruction> ret = new List <Instruction>(); // Create substitute edge action foreach (var i in instructions) { if (i == null) { ret.Add(new Cdn.InstructionNumber("0")); } else { // Add indexing instructions ret.AddRange(i); // Then add simple plus operators for (int j = 0; j < i.Count - 1; ++j) { ret.Add(new Cdn.InstructionFunction((uint)Cdn.MathFunctionType.Plus, null, 2)); } } } var minstr = new Cdn.InstructionMatrix(new Cdn.StackArgs(instructions.Length), variable.Dimension); ret.Add(minstr); var retex = new Cdn.Expression(""); retex.SetInstructionsTake(ret.ToArray()); var action = new Cdn.EdgeAction(variable.Name, retex); ((Cdn.Node)variable.Object).SelfEdge.AddAction(action); d_actionedVariables[variable] = new EdgeAction[] { action }; } }