/*
         * 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));
            }
        }
Exemple #2
0
        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 };
            }
        }