protected string SimpleOperator(Context context, InstructionFunction inst, string glue) { int num = context.Node.Children.Count; bool needsparen = false; if (context.Node.Parent != null) { InstructionFunction op = context.Node.Parent.Instruction as InstructionFunction; needsparen = inst == null || (op != null && HasPriority((Cdn.MathFunctionType)op.Id, (Cdn.MathFunctionType)inst.Id)); } if (num == 1) { return(String.Format("{0}{1}", glue, Translate(context, 0)).Trim()); } string[] args = new string[num]; for (int i = 0; i < num; ++i) { args[i] = Translate(context, i); } if (!needsparen) { return(String.Join(glue, args).Trim()); } else { return(String.Format("({0})", String.Join(glue, args).Trim())); } }
/// <summary> /// Transforma las funciones en subprogramas /// </summary> private Program TransformFunctions(Program sourceProgram) { Program program = new Program("Main"); // Añade las funciones originales program.Functions.AddRange(sourceProgram.Functions); // Transforma las funciones foreach (InstructionBase instruction in sourceProgram.Sentences) { if (instruction is InstructionFunction) { InstructionFunction function = instruction as InstructionFunction; if (function != null) { program.Functions.Add(GetFunctionProgram(function, program)); } } else { program.Sentences.Add(instruction); } } // Devuelve el programa return(program); }
protected override string TranslateOperator(InstructionFunction instruction, CLike.Context context) { switch ((Cdn.MathFunctionType)instruction.Id) { case MathFunctionType.Modulo: return(SimpleOperator(context, instruction, " % ")); default: return(base.TranslateOperator(instruction, context)); } }
/// <summary> /// Convierte una instrucción de función en un programa /// </summary> private Program GetFunctionProgram(InstructionFunction function, Program parent) { Program program = new Program(function.Name, parent); // Añade los argumentos a la tabla de símbolos foreach (string argument in function.Arguments) { program.Arguments.Add(argument); } // Añade las instrucciones program.Sentences.AddRange(function.Sentences); // Devuelve el programa return(program); }
/* Translate a builtin function which returns a multidimensional value. */ protected virtual string TranslateV(InstructionFunction instruction, Context context) { Cdn.MathFunctionType type; type = (Cdn.MathFunctionType)instruction.Id; var def = context.MathFunctionV(type, context.Node); string ret = null; if (!context.Node.Dimension.IsOne && !context.SupportsFirstClassArrays) { ret = context.PeekRet(); } var isp = context.Node.Instruction as Instructions.SparseOperator; if (isp != null) { if (!Context.UsedSparseFunctions.ContainsKey(def)) { var sf = new Context.SparseFunction() { Name = def, Type = (Cdn.MathFunctionType)isp.Original.Id, RetSparsity = isp.RetSparsity, ArgSparsity = isp.ArgSparsity }; Context.UsedSparseFunctions[def] = sf; if (sf.Type == MathFunctionType.Pow || sf.Type == MathFunctionType.Power) { Context.UsedMathFunctions.Add("CDN_MATH_POW"); } } } else { Context.UsedMathFunctions.Add(def); } List <string> args = new List <string>(context.Node.Children.Count + 1); int cnt = 0; for (int i = 0; i < context.Node.Children.Count; ++i) { var child = context.Node.Children[i]; args.Add(TranslateChildV(child, context)); var s = child.Dimension.Size(); if (s > cnt) { cnt = s; } } // Provide dimension except for sparse functions since they are generated // for specific static dimensions already if (isp == null) { context.TranslateFunctionDimensionArguments(instruction, args, cnt); } if (ret != null) { return(String.Format("{0}({1}, {2})", def, ret, String.Join(", ", args))); } else { return(String.Format("{0}({1})", def, String.Join(", ", args))); } }
/* * Translates a call to a builtin math function. The InstructionFunction * is used both for operators and functions (they are treated equally). * * If the instruction represents an operator, then we call * TranslateOperator which uses language specific available operators * to translate the instruction. Otherwise a function call is translated * to the language specific builtin math function. */ protected virtual string Translate(InstructionFunction instruction, Context context) { if (instruction.Id < (uint)Cdn.MathFunctionType.NumOperators) { return(TranslateOperator(instruction, context)); } string[] args = new string[context.Node.Children.Count]; // Translate function arguments for (int i = 0; i < context.Node.Children.Count; ++i) { args[i] = Translate(context, i); } string name = context.MathFunction(context.Node); switch ((Cdn.MathFunctionType)instruction.Id) { case MathFunctionType.Transpose: case MathFunctionType.Min: case MathFunctionType.Max: case MathFunctionType.Sum: case MathFunctionType.Product: case MathFunctionType.Hypot: if (args.Length == 1) { // These functions are NOOPs with a single argument return(args[0]); } break; case MathFunctionType.Sqsum: if (args.Length == 1) { Context.UsedMathFunctions.Add(name); return(String.Format("{0}({1})", name, args[0])); } break; } Context.UsedMathFunctions.Add(name); if (Math.FunctionIsVariable((Cdn.MathFunctionType)instruction.Id)) { string ret = ""; // This does not work in the general case, but anyway if (args.Length == 1) { return(args[0]); } for (int i = args.Length - 2; i >= 0; --i) { if (i != args.Length - 2) { ret = String.Format("{0}({1}, {2})", name, args[i], ret); } else { ret = String.Format("{0}({1}, {2})", name, args[i], args[i + 1]); } } return(ret); } return(String.Format("{0}({1})", name, String.Join(", ", args))); }
protected virtual string TranslateOperator(InstructionFunction instruction, Context context) { switch ((Cdn.MathFunctionType)instruction.Id) { case MathFunctionType.And: return(SimpleOperator(context, instruction, " && ")); case MathFunctionType.Divide: return(SimpleOperator(context, instruction, " / ")); case MathFunctionType.Equal: return(SimpleOperator(context, instruction, " == ")); case MathFunctionType.Greater: return(SimpleOperator(context, instruction, " > ")); case MathFunctionType.GreaterOrEqual: return(SimpleOperator(context, instruction, " >= ")); case MathFunctionType.Less: return(SimpleOperator(context, instruction, " < ")); case MathFunctionType.LessOrEqual: return(SimpleOperator(context, instruction, " <= ")); case MathFunctionType.Minus: return(SimpleOperator(context, instruction, " - ")); case MathFunctionType.UnaryMinus: return(String.Format("-({0})", Translate(context, 0))); case MathFunctionType.Multiply: case MathFunctionType.Emultiply: return(SimpleOperator(context, instruction, " * ")); case MathFunctionType.Negate: return(SimpleOperator(context, instruction, " !")); case MathFunctionType.Or: return(SimpleOperator(context, instruction, " || ")); case MathFunctionType.Plus: return(SimpleOperator(context, instruction, " + ")); case MathFunctionType.Modulo: { var def = context.MathFunction(Cdn.MathFunctionType.Modulo, context.Node.Children.Count); Context.UsedMathFunctions.Add(def); return(String.Format("{0}({1}, {2})", def, Translate(context, 0), Translate(context, 1))); } case MathFunctionType.Power: { var def = context.MathFunction(Cdn.MathFunctionType.Pow, context.Node.Children.Count); Context.UsedMathFunctions.Add(def); return(String.Format("{0}({1}, {2})", def, Translate(context, 0), Translate(context, 1))); } case MathFunctionType.Ternary: return(String.Format("(({0}) ? ({1}) : ({2}))", Translate(context, 0), Translate(context, 1), Translate(context, 2))); } throw new NotImplementedException(String.Format("The operator `{0}' is not implemented", instruction.Name)); }
public virtual void TranslateFunctionDimensionArguments(InstructionFunction instruction, List <string> args, int cnt) { var type = (Cdn.MathFunctionType)instruction.Id; switch (type) { case MathFunctionType.Transpose: { var dim = Node.Children[0].Dimension; args.Add(dim.Rows.ToString()); args.Add(dim.Columns.ToString()); } break; case MathFunctionType.Vcat: { var dim1 = Node.Children[0].Dimension; var dim2 = Node.Children[1].Dimension; args.Add(dim1.Rows.ToString()); args.Add(dim2.Rows.ToString()); args.Add(dim1.Columns.ToString()); } break; case MathFunctionType.Diag: { var dim1 = Node.Children[0].Dimension; if (dim1.Rows == 1 || dim1.Columns == 1) { args.Add(dim1.Size().ToString()); } else { args.Add(dim1.Rows.ToString()); } } break; case MathFunctionType.Triu: case MathFunctionType.Tril: { var dim1 = Node.Children[0].Dimension; args.Add(dim1.Rows.ToString()); args.Add(dim1.Columns.ToString()); } break; case MathFunctionType.Multiply: { var d1 = Node.Children[0].Dimension; var d2 = Node.Children[1].Dimension; if (d1.Columns == d2.Rows && !(d1.IsOne || d2.IsOne)) { // Matrix multiply args.Add(d1.Rows.ToString()); args.Add(d1.Columns.ToString()); args.Add(d2.Columns.ToString()); } else { args.Add(cnt.ToString()); } } break; case MathFunctionType.Csum: case MathFunctionType.Rsum: { var d = Node.Children[0].Dimension; args.Add(d.Rows.ToString()); args.Add(d.Columns.ToString()); } break; case MathFunctionType.Index: break; default: if (Node.Children.Count == 2) { var d1 = Node.Children[0].Dimension; var d2 = Node.Children[1].Dimension; if ((d1.Columns == 1 || d2.Columns == 1) && d1.Rows == d2.Rows && d1.Rows != 1 && d1.Columns != d2.Columns) { args.Add(d1.Rows.ToString()); args.Add((d1.Columns == 1 ? d2.Columns : d1.Columns).ToString()); break; } else if ((d1.Rows == 1 || d2.Rows == 1) && d1.Columns == d2.Columns && d1.Columns != 1 && d1.Rows != d2.Rows) { args.Add((d1.Rows == 1 ? d2.Rows : d1.Rows).ToString()); args.Add(d1.Columns.ToString()); break; } } args.Add(cnt.ToString()); break; } }
/// <summary> /// Crea la instrucción de definición de un Mixin /// </summary> private InstructionBase CreateInstructionMixinDefinition() { InstructionFunction instruction = new InstructionFunction(GetToken()); TokenSmallCss token = GetToken(); // Obtiene la función if (token.Row == instruction.Token.Row && token.TypeCss == TokenSmallCss.TokenCssType.Literal) { // Asigna el nombre de la función instruction.Name = token.Value; // Obtiene los argumentos if (ActualToken.Row == instruction.Token.Row) { bool end = false; while (!end && !IsEof) { // Comprueba si es un argumento if (ActualToken.Row == instruction.Token.Row) { if (ActualToken.TypeCss == TokenSmallCss.TokenCssType.Literal || ActualToken.TypeCss == TokenSmallCss.TokenCssType.Variable) { string argument = ActualToken.Value; // Normaliza el argumento if (!argument.StartsWith("$")) { argument = "$" + argument; } // Añade el nombre del argumento instruction.Arguments.Add(argument); // Obtiene el siguiente token GetToken(); } else if (ActualToken.TypeCss == TokenSmallCss.TokenCssType.Comment) { instruction.Sentences.Add(CreateInstructionComment()); } else { instruction.Error = ParseError($"No se reconoce el token entre los argumentos de la función '{instruction.Name}'"); } } else { end = true; } } } if (!instruction.IsError) { if (CheckIsBlock(instruction.Token)) { instruction.Sentences.AddRange(GetBlock(instruction.Token.Indent)); } else { instruction.Error = ParseError("No se han definido las instrucciones de la función"); } } } else { instruction.Error = ParseError("No se encuentra el nombre de la función"); } // Devuelve la instrucción return(instruction); }
private int[] InstructionSparsity(InstructionFunction instr, SparsityInfo[] children, Dictionary <Variable, SparsityInfo> mapping) { switch ((Cdn.MathFunctionType)instr.Id) { case MathFunctionType.Diag: return(DiagSparsity(children)); case MathFunctionType.Divide: case MathFunctionType.Pow: case MathFunctionType.Power: return(DividePowerSparsity(children)); case MathFunctionType.Emultiply: case MathFunctionType.Product: return(UnionSparsity(children)); case MathFunctionType.Minus: case MathFunctionType.Plus: case MathFunctionType.Sqsum: case MathFunctionType.Sum: case MathFunctionType.UnaryMinus: return(IntersectSparsity(children)); case MathFunctionType.Multiply: return(MultiplySparsity(children)); case MathFunctionType.Csum: return(CSumSparsity(children)); case MathFunctionType.Rsum: return(RSumSparsity(children)); case MathFunctionType.Transpose: return(TransposeSparsity(children)); case MathFunctionType.Vcat: return(VcatSparsity(instr.GetStackManipulation().Push.Dimension, children)); case MathFunctionType.Sltdl: // The LTDL factorization has the same sparsity pattern as its // first argument return(CopySparsity(children[0].Sparsity)); case MathFunctionType.SltdlDinv: return(SltdlDinvSparsity(children)); case MathFunctionType.SltdlDinvLinvt: return(SltdlDinvLinvtSparsity(children)); case MathFunctionType.SltdlLinv: return(SltdlLinvSparsity(children)); case MathFunctionType.SltdlLinvt: return(SltdlLinvtSparsity(children)); case MathFunctionType.Slinsolve: return(SlinsolveSparsity(children)); case MathFunctionType.PseudoInverse: return(PseudoInverseSparsity(children)); default: break; } return(new int[0]); }
public override void TranslateFunctionDimensionArguments(InstructionFunction instruction, List <string> args, int cnt) { switch ((Cdn.MathFunctionType)instruction.Id) { case MathFunctionType.Linsolve: { // Add rows of A and columns of B arguments var dim1 = Node.Children[1].Dimension; var dim2 = Node.Children[0].Dimension; // Here we also reorder the arguments A and b. In codyn these // are on the stack in reversed order to make it more efficient // but here we really don't need that and it's more logical // the other way around var tmp = args[0]; args[0] = args[1]; args[1] = tmp; args.Add(dim1.Rows.ToString()); args.Add(dim2.Columns.ToString()); } break; case MathFunctionType.Slinsolve: { // Add columns of B argument // Here we also reorder the arguments. var b = args[0]; var L = args[1]; var A = args[2]; args[0] = A; args[1] = b; args[2] = Node.Children[0].Dimension.Columns.ToString(); args.Add(L); } break; case MathFunctionType.Sltdl: { var A = args[0]; var L = args[1]; args[0] = A; args[1] = Node.Children[1].Dimension.Rows.ToString(); args.Add(L); } break; case MathFunctionType.SltdlDinvLinvt: case MathFunctionType.SltdlLinvt: case MathFunctionType.SltdlLinv: { var b = args[0]; var L = args[1]; var A = args[2]; args[0] = A; args[1] = Node.Children[2].Dimension.Rows.ToString(); args[2] = b; args.Add(Node.Children[0].Dimension.Columns.ToString()); args.Add(L); } break; case MathFunctionType.SltdlDinv: { var b = args[0]; var A = args[1]; args[0] = A; args[1] = Node.Children[1].Dimension.Rows.ToString(); args.Add(b); args.Add(Node.Children[0].Dimension.Columns.ToString()); } break; case MathFunctionType.Inverse: case MathFunctionType.PseudoInverse: case MathFunctionType.Qr: break; default: base.TranslateFunctionDimensionArguments(instruction, args, cnt); break; } }