} // end of GenerateCode() /// <summary> /// Writes code for all 'set' function and various other function (largest coordinate, coordinate extraction, etc) /// </summary> /// <param name="S"></param> /// <param name="plugins"></param> /// <param name="cgd"></param> protected void GenerateSetFunctions(Specification S, List <CodeGeneratorPlugin> plugins, CG.Shared.CGdata cgd) { const int NB_SET_CODE = 4; // get a temporary cgd for each type of parts code CG.Shared.CGdata[] tmpCgd = new G25.CG.Shared.CGdata[] { new G25.CG.Shared.CGdata(cgd), new G25.CG.Shared.CGdata(cgd), new G25.CG.Shared.CGdata(cgd), new G25.CG.Shared.CGdata(cgd) }; // get parts code generators G25.CG.CPP.GMV p1 = new G25.CG.CPP.GMV(S, tmpCgd[0]); // [0] = GMV G25.CG.CPP.SMV p2 = new G25.CG.CPP.SMV(S, tmpCgd[1]); // [1] = SMV G25.CG.CPP.GOM p3 = new G25.CG.CPP.GOM(S, tmpCgd[2]); // [2] = GOM G25.CG.CPP.SOM p4 = new G25.CG.CPP.SOM(S, tmpCgd[3]); // [3] = SOM // run threads System.Threading.Thread[] T = new System.Threading.Thread[NB_SET_CODE]; T[0] = new Thread(p1.WriteSetFunctions); T[1] = new Thread(p2.WriteSetFunctions); T[2] = new Thread(p3.WriteSetFunctions); T[3] = new Thread(p4.WriteSetFunctions); G25.CG.Shared.Threads.StartThreadArray(T); G25.CG.Shared.Threads.JoinThreadArray(T); // merge declarations and definitions for (int i = 0; i < NB_SET_CODE; i++) { cgd.m_declSB.Append(tmpCgd[i].m_declSB); cgd.m_defSB.Append(tmpCgd[i].m_defSB); cgd.m_inlineDefSB.Append(tmpCgd[i].m_inlineDefSB); } }
} // end of WriteCopyCrossFloat() /// <summary> /// Writes code for abs largest coordinate /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteLargestCoordinateFunctions(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineFunctions) ? cgd.m_inlineDefSB : cgd.m_defSB; declSB.AppendLine(""); defSB.AppendLine(""); const String smvName = "x"; const bool ptr = true; foreach (G25.FloatType FT in S.m_floatTypes) { String fabsFunc = "fabs"; if (FT.type == "float") { fabsFunc = "fabsf"; } foreach (G25.SMV smv in S.m_SMV) { String[] AS = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, smvName, ptr); double maxValue = smv.AbsoluteLargestConstantCoordinate(); String typeName = FT.GetMangledName(S, smv.Name); String funcName = typeName + "_largestCoordinate"; declSB.AppendLine("/** Returns abs largest coordinate of " + typeName + " */"); String funcDecl = FT.type + " " + funcName + "(const " + typeName + " *" + smvName + ")"; declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.Append(funcDecl); { defSB.AppendLine(" {"); int startIdx = 0; if (maxValue != 0.0) { defSB.AppendLine("\t" + FT.type + " maxValue = " + FT.DoubleToString(S, maxValue) + ";"); } else { defSB.AppendLine("\t" + FT.type + " maxValue = " + fabsFunc + "(" + AS[0] + ");"); startIdx = 1; } for (int c = startIdx; c < smv.NbNonConstBasisBlade; c++) { defSB.AppendLine("\tif (" + fabsFunc + "(" + AS[c] + ") > maxValue) maxValue = " + fabsFunc + "(" + AS[c] + ");"); } defSB.AppendLine("\treturn maxValue;"); defSB.AppendLine("}"); } } // end of loop over all smvs } // end of loop over all float types } // end of WriteLargestCoordinateFunctions()
/// <summary> /// Writes 'set()' declarations of a GOM class to 'SB'. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="FT">Float point type of 'GOM'.</param> /// <param name="gom">The general outermorphism for which the class should be written.</param> /// <param name="className">Mangled name of GOM class.</param> /// <param name="rangeVectorSMVname">The name of the SMV which can represent a column of the OM.</param> public static void WriteSetDeclarations(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom, string className, string rangeVectorSMVname) { cgd.m_cog.EmitTemplate(SB, "GOMsetDecl", "S=", S, "FT=", FT, "className=", className, "rangeVectorSMVname=", rangeVectorSMVname); { // extra code for per-grade-per-basisblade functions to set OM from vectors SB.AppendLine("\tprivate:"); bool matrixMode = false; // this value is irrelevant at this point string typeName = FT.GetMangledName(S, gom.Name); string prefix = typeName + "::"; string[] funcNames = G25.CG.Shared.OMinit.GetSetFromLowerGradeFunctionNames(S, FT, matrixMode); for (int g = 1; g < gom.Domain.Length; g++) { for (int d = 0; d < gom.DomainForGrade(g).Length; d++) { string funcName = funcNames[g] + "_" + d; if (funcName.IndexOf(prefix) == 0) { funcName = funcName.Substring(prefix.Length); } SB.AppendLine("\tvoid " + funcName + "();"); } } SB.AppendLine("\tpublic:"); } }
public static void WriteSMVtypeConstants(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { SB.AppendLine(""); SB.AppendLine("/* These constants define a unique number for each specialized multivector type."); SB.AppendLine(" They are used to report usage of non-optimized functions. */"); { int idx = 0; // for each floating point type foreach (G25.FloatType FT in S.m_floatTypes) { // for each smv foreach (G25.SMV smv in S.m_SMV) { String name = (S.m_namespace + "_" + FT.GetMangledName(S, smv.Name)).ToUpper(); SB.AppendLine("#define " + name + " " + idx); idx++; } } } SB.AppendLine(""); SB.AppendLine("/** For each specialized multivector type, the mangled typename."); SB.AppendLine(" * This is used to report usage of non-optimized functions. */"); SB.AppendLine("extern const char *g_" + S.m_namespace + "Typenames[];"); }
/// <summary> /// Writes functions to copy SOMs to GOM. /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="FT">Float type</param> public static void WriteGOMtoSOMcopy(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som) { if (S.m_GOM != null) { G25.CG.Shared.OMinit.WriteOMtoOMcopy(S, cgd, FT, S.m_GOM, som); } } // end of WriteGOMtoSOMcopy()
/// <summary> /// Writes a function to set a GOM struct according to vector images, for all floating point types. /// </summary> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="matrixMode">When true, generates code for setting from matrix instead of vector images.</param> /// <param name="transpose">When this parameter is true and <c>matrixMode</c> is true, generates code for setting from transpose matrix.</param> public static void WriteSetVectorImages(Specification S, G25.CG.Shared.CGdata cgd, bool matrixMode, bool transpose) { foreach (G25.FloatType FT in S.m_floatTypes) { WriteSetVectorImages(S, cgd, FT, matrixMode, transpose); } }
} // end of WriteSetArray() /// <summary> /// Writes a function to copy the value of one SMV struct to another, for all floating point types. /// </summary> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteCopy(Specification S, G25.CG.Shared.CGdata cgd) { //StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; defSB.AppendLine(""); foreach (G25.FloatType FT in S.m_floatTypes) { foreach (G25.SMV smv in S.m_SMV) { // if (smv.NbNonConstBasisBlade == 0) continue; string className = FT.GetMangledName(S, smv.Name); string funcName = className + "::set"; bool mustCast = false; G25.fgs F = new G25.fgs(funcName, funcName, "", new String[] { smv.Name }, null, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); bool computeMultivectorValue = false; int nbArgs = 1; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, null, computeMultivectorValue); RefGA.Multivector value = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smv, FAI[0].Name, FAI[0].Pointer); string dstName = G25.CG.Shared.SmvUtil.THIS; bool dstPtr = true; G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineSet, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, value); } } } // end of WriteCopy()
/// <summary> /// Writes code for return m_name. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Not used yet.</param> public override void Write(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { if (m_type is G25.FloatType) { AppendTabs(SB); // Temp hack to override the float type: G25.FloatType FT = m_floatType; //m_type as G25.FloatType; // Should postops still be applied? ApplyPostOp(S, plugins, cog, BL, valueStr); // Not required so far? SB.AppendLine(CodeUtil.GenerateScalarReturnCode(S, FT, m_mustCast, m_value)); } else if (m_type is G25.SMV) { if (S.OutputC()) { bool ptr = true; bool declareVariable = false; new AssignInstruction(m_nbTabs, m_type, m_floatType, m_mustCast, m_value, G25.fgs.RETURN_ARG_NAME, ptr, declareVariable, m_postOp, m_postOpValue).Write(SB, S, cgd); } else { G25.SMV smv = m_type as G25.SMV; RefGA.BasisBlade[] BL = BasisBlade.GetNonConstBladeList(smv); bool writeZeros = true; string[] valueStr = CodeUtil.GetAssignmentStrings(S, m_floatType, m_mustCast, BL, m_value, writeZeros); // apply post operation (like "/ n2") ApplyPostOp(S, cgd, BL, valueStr); SB.AppendLine(CodeUtil.GenerateReturnCode(S, smv, m_floatType, valueStr, m_nbTabs, writeZeros)); } } }
/// <summary> /// Writes functions to set the GMV types by array value. /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSetArray(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; G25.GMV gmv = S.m_GMV; foreach (G25.FloatType FT in S.m_floatTypes) { string typeName = FT.GetMangledName(S, gmv.Name); string funcName = typeName + "_setArray"; // write comment declSB.AppendLine("/** Sets a " + typeName + " to the value in the array. 'gu' is a group usage bitmap. */"); // do we inline this func? string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " "); string funcDecl = inlineStr + "void " + funcName + "(" + typeName + " *M, int gu, const " + FT.type + " *arr)"; declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.Append(funcDecl); defSB.AppendLine(" {"); defSB.AppendLine("\tM->gu = gu;"); defSB.AppendLine("\t" + G25.CG.Shared.Util.GetCopyCode(S, FT, "arr", "M->c", S.m_namespace + "_mvSize[gu]")); defSB.AppendLine("}"); } }
public static void GenerateBasicInfo(Specification S, G25.CG.Shared.CGdata cgd, StringBuilder SB) { // dimension of space SB.AppendLine("const int " + S.m_namespace + "_spaceDim = " + S.m_dimension + ";"); // number of groups of space SB.AppendLine("const int " + S.m_namespace + "_nbGroups = " + S.m_GMV.NbGroups + ";"); // Euclidean metric? SB.AppendLine("const int " + S.m_namespace + "_metricEuclidean = " + (S.GetMetric("default").m_metric.IsEuclidean() ? "1" : "0") + ";"); // basis vector names SB.AppendLine("const char *" + S.m_namespace + "_basisVectorNames[" + S.m_dimension + "] = {"); SB.Append("\t"); for (int i = 0; i < S.m_dimension; i++) { if (i > 0) { SB.Append(", "); } SB.Append("\"" + S.m_basisVectorNames[i] + "\""); } SB.AppendLine(""); SB.AppendLine("};"); } // end of GenerateBasicInfo()
/// <summary> /// Writes functions to set the GMV types to zero. /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSetZero(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; G25.GMV gmv = S.m_GMV; foreach (G25.FloatType FT in S.m_floatTypes) { string typeName = FT.GetMangledName(S, gmv.Name); string funcName = typeName + "_setZero"; // write comment declSB.AppendLine("/** Sets a " + typeName + " to zero */"); // do we inline this func? string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " "); string funcDecl = inlineStr + "void " + funcName + "(" + typeName + " *M)"; declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.Append(funcDecl); defSB.AppendLine(" {"); defSB.AppendLine("\tM->gu = 0;"); defSB.AppendLine("}"); } }
/// <summary> /// Writes functions to set the GMV types to scalar value. /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSetScalar(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; G25.GMV gmv = S.m_GMV; foreach (G25.FloatType FT in S.m_floatTypes) { String typeName = FT.GetMangledName(S, gmv.Name); String funcName = typeName + "_setScalar"; // write comment declSB.AppendLine("/** Sets a " + typeName + " to a scalar value */"); // do we inline this func? String inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " "); String funcDecl = inlineStr + "void " + funcName + "(" + typeName + " *M, " + FT.type + " val)"; declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.Append(funcDecl); defSB.AppendLine(" {"); defSB.AppendLine("\tM->gu = " + (1 << gmv.GetGroupIdx(RefGA.BasisBlade.ONE)) + ";"); defSB.AppendLine("\tM->c[0] = val;"); defSB.AppendLine("}"); } }
} // end of WriteSetIdentity() /// <summary> /// Writes a function to copy an GOM struct /// </summary> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteCopy(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; declSB.AppendLine(""); defSB.AppendLine(""); string dstName = "dst"; string srcName = "src"; string matrixName = "m"; foreach (G25.FloatType FT in S.m_floatTypes) { String typeName = FT.GetMangledName(S, S.m_GOM.Name); String funcName = typeName + "_copy"; //string comment = "/** Copies " + typeName + " */"; declSB.AppendLine("void " + funcName + "(" + typeName + "*" + dstName + ", const " + typeName + "*" + srcName + ");"); defSB.AppendLine("void " + funcName + "(" + typeName + "*" + dstName + ", const " + typeName + "*" + srcName + ") {"); for (int g = 1; g < S.m_GOM.Domain.Length; g++) { int s = S.m_GOM.Domain[g].Length * S.m_GOM.Range[g].Length; defSB.AppendLine("\t" + G25.CG.Shared.Util.GetCopyCode(S, FT, srcName + "->" + matrixName + g, dstName + "->" + matrixName + g, s)); } // end of loop over all grades of the OM defSB.AppendLine("}"); } } // end of WriteCopy()
public Converter(Specification S, G25.CG.Shared.CGdata cgd, G25.fgs F) { m_specification = S; m_cgd = cgd; m_fgs = F; m_fgs.InitArgumentPtrFromTypeNames(S); }
/// <summary> /// Writes the definition of an GOM struct to 'SB' (including comments). /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="FT">Float point type of 'GOM'.</param> /// <param name="gom">The general outermorphism for which the struct should be written.</param> public static void WriteGOMclass(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom) { SB.AppendLine(""); string className = FT.GetMangledName(S, gom.Name); // get range vector type G25.SMV rangeVectorType = G25.CG.Shared.OMinit.getRangeVectorType(S, FT, cgd, gom); string rangeVectorSMVname = FT.GetMangledName(S, rangeVectorType.Name); WriteComment(SB, S, cgd, FT, gom); // typedef SB.AppendLine("class " + className); SB.AppendLine("{"); // member vars WriteMemberVariables(SB, S, cgd, FT, gom); SB.AppendLine("public:"); // Float type WriteFloatType(SB, S, cgd, FT, gom, className); // constructors WriteConstructors(SB, S, cgd, FT, gom, className, rangeVectorSMVname); // operator= WriteAssignmentOps(SB, S, cgd, FT, gom, className, rangeVectorSMVname); // set(...) WriteSetDeclarations(SB, S, cgd, FT, gom, className, rangeVectorSMVname); SB.AppendLine("}; // end of " + className); }
private static void WriteCoordSetFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, string gmvTypeName, int groupIdx, int elementIdx, int groupSize, RefGA.BasisBlade B) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; String bladeName = B.ToLangString(S.m_basisVectorNames); string varName = "A"; string coordName = bladeName + "_coord"; // do we inline this func? string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " "); string funcName = gmvTypeName + "_set_" + bladeName; string funcDecl = inlineStr + "void " + funcName + "(" + gmvTypeName + " *" + varName + ", " + FT.type + " " + coordName + ")"; declSB.AppendLine("/** Sets the " + B.ToString(S.m_basisVectorNames) + " coordinate of '" + varName + "' */"); declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.AppendLine(""); defSB.Append(funcDecl); defSB.AppendLine(" {"); defSB.AppendLine("\t" + gmvTypeName + "_reserveGroup_" + groupIdx + "(" + varName + ");"); defSB.AppendLine("\t" + varName + "->c[" + S.m_namespace + "_mvSize[" + varName + "->gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] = " + coordName + ";"); defSB.AppendLine("}"); }
public static void GenerateBasisElementsArray(Specification S, G25.CG.Shared.CGdata cgd, StringBuilder SB) { G25.GMV gmv = S.m_GMV; // basis vectors in basis elements SB.AppendLine("const int " + S.m_namespace + "_basisElements[" + (1 << S.m_dimension) + "][" + (S.m_dimension + 1) + "] = {"); { bool comma = false; for (int i = 0; i < gmv.NbGroups; i++) { for (int j = 0; j < gmv.Group(i).Length; j++) { if (comma) { SB.Append(",\n"); } RefGA.BasisBlade B = gmv.Group(i)[j]; SB.Append("\t{"); for (int k = 0; k < S.m_dimension; k++) { if ((B.bitmap & (1 << k)) != 0) { SB.Append(k + ", "); } } SB.Append("-1}"); comma = true; } } } SB.AppendLine(""); SB.AppendLine("};"); }
} // end of WriteSetCopy() /// <summary> /// Writes a function to copy the value of one SMV struct to another with a different floating point type, for all combinations of floating point types. /// </summary> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSetCopyCrossFloat(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType dstFT, G25.SMV smv) { foreach (G25.FloatType srcFT in S.m_floatTypes) { if (srcFT.type == dstFT.type) { continue; } cgd.m_defSB.AppendLine(""); //string srcClassName = srcFT.GetMangledName(smv.Name); //string dstClassName = dstFT.GetMangledName(S, smv.Name); string funcName = GMV.GetSetFuncName(S); bool mustCast = dstFT.MustCastIfAssigned(S, srcFT); G25.fgs F = new G25.fgs(funcName, funcName, "", new String[] { smv.Name }, null, new String[] { srcFT.type }, null, null, null); // null, null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); bool computeMultivectorValue = false; int nbArgs = 1; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, srcFT, null, computeMultivectorValue); RefGA.Multivector value = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smv, FAI[0].Name, FAI[0].Pointer); string dstName = G25.CG.Shared.SmvUtil.THIS; bool dstPtr = false; bool staticFunc = false; G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineSet, staticFunc, "void", null, funcName, null, FAI, dstFT, mustCast, smv, dstName, dstPtr, value); } } // end of WriteSetCopyCrossFloat()
/// <summary> /// Writes a function to set an SMV struct to zero, for all floating point types. /// </summary> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSetZero(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; defSB.AppendLine(""); foreach (G25.FloatType FT in S.m_floatTypes) { foreach (G25.SMV smv in S.m_SMV) { if (smv.NbNonConstBasisBlade == 0) { continue; } string className = FT.GetMangledName(S, smv.Name); string funcName = className + "::set"; bool mustCast = false; string returnVarName = null; string dstName = G25.CG.Shared.SmvUtil.THIS; bool dstPtr = true; G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineSet, "void", returnVarName, funcName, null, null, FT, mustCast, smv, dstName, dstPtr, new RefGA.Multivector(0.0)); } } } // end of WriteSetZero()
} // end of WriteParserTest() public static List <string> WriteMetricTests(G25.Specification S, G25.CG.Shared.CGdata cgd, Dictionary <string, string> gpGmvFuncName) // , string gpFuncName { List <string> testFunctionNames = new List <string>(); foreach (FloatType FT in S.m_floatTypes) { //string testStr = FT.DoubleToString(S, FT.PrecisionEpsilon()); foreach (Metric M in S.m_metric) { string gmvName = FT.GetMangledName(S, S.m_GMV.Name); string testFuncName = "test_metric_" + M.m_name + "_" + gmvName; cgd.m_cog.EmitTemplate(cgd.m_defSB, "testMetric", "S=", S, "FT=", FT, "M=", M, "gmv=", S.m_GMV, "gmvName=", gmvName, "testFuncName=", testFuncName, "gpGmvFuncName=", gpGmvFuncName[FT.type + "_" + M.m_name] ); testFunctionNames.Add(testFuncName); } } return(testFunctionNames); } // WriteMetricTests()
} // end of WriteGOMtoSOMcopy() /// <summary> /// Writes functions to copy SOM to GOMs. /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSOMtoGOMcopy(Specification S, G25.CG.Shared.CGdata cgd) { foreach (G25.FloatType FT in S.m_floatTypes) { WriteSOMtoGOMcopy(S, cgd, FT); } // end of loop over all float types } // end of WriteGOMtoSOMcopy()
} // WriteMetricTests() public static List <string> WriteGetterSetterTests(G25.Specification S, G25.CG.Shared.CGdata cgd, List <string> randomNumberGeneratorFuncName, Dictionary <string, string> randomVersorFuncName) // , string gpFuncName { List <string> testFunctionNames = new List <string>(); int FTidx = 0; //G25.GMV gmv = S.m_GMV; foreach (FloatType FT in S.m_floatTypes) { //string testStr = FT.DoubleToString(S, FT.PrecisionEpsilon()); string gmvName = FT.GetMangledName(S, S.m_GMV.Name); string testFuncName = "test_getter_setter_" + gmvName; cgd.m_cog.EmitTemplate(cgd.m_defSB, "testGetterSetter", "S=", S, "FT=", FT, "gmv=", S.m_GMV, "gmvName=", gmvName, "testFuncName=", testFuncName, "randomScalarFuncName=", randomNumberGeneratorFuncName[FTidx], "randomVersorFuncName=", randomVersorFuncName[FT.type] ); testFunctionNames.Add(testFuncName); FTidx++; } return(testFunctionNames); } // WriteGetterSetterTests()
/// <summary> /// Writes constructors of a SOM class to 'SB'. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="FT">Float point type of 'SOM'.</param> /// <param name="som">The specialized outermorphism for which the class should be written.</param> /// <param name="rangeVectorSMVname">The name of the SMV which can represent a column of the OM.</param> public static void WriteConstructors(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som, string rangeVectorSMVname) { string className = FT.GetMangledName(S, som.Name); string gomClassName = (S.m_GOM == null) ? "" : FT.GetMangledName(S, S.m_GOM.Name); cgd.m_cog.EmitTemplate(SB, "SOMconstructors", "S=", S, "FT=", FT, "som=", som, "className=", className, "gomClassName=", gomClassName, "rangeVectorSMVname=", rangeVectorSMVname); }
/// <summary> /// Writes a increment or decrement function. /// (not based on CASN parts code, but put here anyway). /// </summary> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> /// <param name="increment"></param> public static string WriteIncrementFunction(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment, bool increment) { // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); int nbTabs = 1; // write this function: string code = G25.CG.Shared.CANSparts.GetIncrementCode(S, cgd, FT, FAI, fgs.RETURN_ARG_NAME, increment); // add one instruction (verbatim code) I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code)); // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(S, FT, F, FAI); // setup return type and argument: string returnTypeName = FT.GetMangledName(S, S.m_GMV.Name); G25.CG.Shared.FuncArgInfo returnArgument = null; if (S.OutputC()) { returnArgument = new G25.CG.Shared.FuncArgInfo(S, CF, -1, FT, S.m_GMV.Name, false); // false = compute value } // write function bool inline = false; // never inline GMV functions bool staticFunc = Functions.OutputStaticFunctions(S); G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment); return(CF.OutputName); }
/// <summary> /// Writes a shortcut for 'type', 'fgs'. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Not used yet.</param> /// <param name="FT">Float point type of 'type'.</param> /// <param name="type">The type for which shortcuts should be written.</param> /// <param name="fgs"></param> /// <param name="FAI"></param> public static void WriteFunctionShortcut(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.VariableType type, G25.fgs fgs, FuncArgInfo[] FAI) { int nbTabs = 1; FuncArgInfo[] tailFAI = getTail(FAI); string shortcutCall = getShortcutCall(S, fgs, tailFAI); SB.AppendLine(""); // output comment new Comment("shortcut to " + shortcutCall).Write(SB, S, nbTabs); bool inline = false; bool staticFunc = false; string returnType = FT.GetMangledName(S, fgs.ReturnTypeName); FuncArgInfo returnArgument = null; SB.Append('\t', nbTabs); Functions.WriteDeclaration(SB, S, cgd, inline, staticFunc, returnType, fgs.OutputName, returnArgument, tailFAI); SB.AppendLine(" {"); SB.Append('\t', nbTabs + 1); SB.Append("return "); SB.Append(shortcutCall); SB.AppendLine(";"); SB.Append('\t', nbTabs); SB.AppendLine("}"); }
public static void WriteSMVtypeConstants(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { SB.AppendLine(""); SB.AppendLine("/// <summary>"); SB.AppendLine("/// These constants define a unique number for each specialized multivector type."); SB.AppendLine("/// They are used to report usage of non-optimized functions."); SB.AppendLine("/// </summary>"); Dictionary <string, int> STD = G25.CG.Shared.SmvUtil.GetSpecializedTypeDictionary(S); SB.AppendLine("public enum " + G25.CG.CSJ.GMV.SMV_TYPE + " {"); SB.AppendLine("\t" + G25.CG.Shared.ReportUsage.GetSpecializedConstantName(S, "NONE") + " = -1,"); foreach (KeyValuePair <string, int> kvp in STD) { string name = G25.CG.Shared.ReportUsage.GetSpecializedConstantName(S, kvp.Key); SB.AppendLine("\t" + name + " = " + kvp.Value + ","); } SB.AppendLine("\t" + G25.CG.Shared.ReportUsage.GetSpecializedConstantName(S, G25.CG.Shared.ReportUsage.INVALID)); SB.AppendLine("}"); SB.AppendLine(""); }
/// <summary> /// Generates a source file with the GOM class definition. /// </summary> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="FT"></param> /// <returns></returns> public static string GenerateCode(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT) { G25.GOM gom = S.m_GOM; string className = FT.GetMangledName(S, gom.Name); // get range vector type G25.SMV rangeVectorType = G25.CG.Shared.OMinit.GetRangeVectorType(S, FT, cgd, gom); string rangeVectorSMVname = FT.GetMangledName(S, rangeVectorType.Name); // get filename, list of generated filenames List<string> generatedFiles = new List<string>(); string sourceFilename = MainGenerator.GetClassOutputPath(S, className); generatedFiles.Add(sourceFilename); // get StringBuilder where all generated code goes StringBuilder SB = new StringBuilder(); // get a new 'cgd' where all ouput goes to the one StringBuilder SB cgd = new G25.CG.Shared.CGdata(cgd, SB, SB, SB); // output license, copyright G25.CG.Shared.Util.WriteCopyright(SB, S); G25.CG.Shared.Util.WriteLicense(SB, S); // open namespace G25.CG.Shared.Util.WriteOpenNamespace(SB, S); // write class comment G25.CG.CSJ.GOM.WriteComment(SB, S, cgd, FT, gom); // open class G25.CG.Shared.Util.WriteOpenClass(SB, S, G25.CG.Shared.AccessModifier.AM_public, className, null, null); // write member variables G25.CG.CSJ.GOM.WriteMemberVariables(SB, S, cgd, FT, gom); // write constructors G25.CG.CSJ.GOM.WriteConstructors(SB, S, cgd, FT, gom, className, rangeVectorSMVname); // write set functions G25.CG.CSJ.GOM.WriteSetIdentity(SB, S, cgd, FT); G25.CG.CSJ.GOM.WriteSetCopy(SB, S, cgd, FT); G25.CG.CSJ.GOM.WriteSetVectorImages(S, cgd, FT, false, false); // false, false = matrixMode, transpose G25.CG.CSJ.GOM.WriteSetVectorImages(S, cgd, FT, true, false); // true, false = matrixMode, transpose G25.CG.CSJ.GOM.WriteSOMtoGOMcopy(S, cgd, FT); // write shortcuts for functions G25.CG.Shared.Shortcut.WriteFunctionShortcuts(SB, S, cgd, FT, gom); // close class G25.CG.Shared.Util.WriteCloseClass(SB, S, className); // close namespace G25.CG.Shared.Util.WriteCloseNamespace(SB, S); // write all to file G25.CG.Shared.Util.WriteFile(sourceFilename, SB.ToString()); return sourceFilename; }
public static void WriteSMVtypenames(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { SB.AppendLine(""); SB.AppendLine("const char *g_" + S.m_namespace + "Typenames[] = "); SB.AppendLine("{"); { int idx = 0; // for each floating point type foreach (G25.FloatType FT in S.m_floatTypes) { // for each smv foreach (G25.SMV smv in S.m_SMV) { if (idx > 0) { SB.AppendLine(","); } SB.Append("\t\"" + FT.GetMangledName(S, smv.Name) + "\""); idx++; } } if (idx == 0) { SB.Append("\t\"There are no specialized types defined\""); } } SB.AppendLine(""); SB.AppendLine("};"); }
/// <summary> /// Writes a function to set an SMV struct to zero, for all floating point types. /// </summary> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteSetZero(Specification S, G25.CG.Shared.CGdata cgd) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; declSB.AppendLine(""); defSB.AppendLine(""); foreach (G25.FloatType FT in S.m_floatTypes) { foreach (G25.SMV smv in S.m_SMV) { if (smv.NbNonConstBasisBlade == 0) { continue; } string typeName = FT.GetMangledName(S, smv.Name); string funcName = typeName + "_setZero"; bool mustCast = false; G25.fgs F = new G25.fgs(funcName, funcName, "", null, null, new string[] { FT.type }, null, null, null); // null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue); declSB.AppendLine("/** Sets " + typeName + " to zero */"); string returnVarName = null; bool staticFunc = false; G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineSet, staticFunc, "void", returnVarName, funcName, returnArgument, null, FT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, new RefGA.Multivector(0.0)); } } } // end of WriteSetZero()
public static void GenerateMultivectorSizeArray(Specification S, G25.CG.Shared.CGdata cgd, StringBuilder SB) { G25.GMV gmv = S.m_GMV; // size of multivector based on grade usage bitmap SB.AppendLine("const int " + S.m_namespace + "_mvSize[" + (1 << gmv.NbGroups) + "] = {"); SB.Append("\t"); for (int i = 0; i < (1 << gmv.NbGroups); i++) { int s = 0; for (int j = 0; j < gmv.NbGroups; j++) { if ((i & (1 << j)) != 0) { s += gmv.Group(j).Length; } } SB.Append(s); if (i != ((1 << gmv.NbGroups) - 1)) { SB.Append(", "); } if ((i % 20) == 19) { SB.AppendLine(""); SB.Append("\t"); } } SB.AppendLine("};"); }
/// <summary> /// Applies 'm_postOp m_postOpValue' to 'valueStr'. /// </summary> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Not used yet.</param> /// <param name="valueStr">The array of value strings to which the postop should be applied</param> /// <param name="BL">Not used yet. May be used later on to known what basis blade each valueStr refers to.</param> public void ApplyPostOp(Specification S, G25.CG.Shared.CGdata cgd, RefGA.BasisBlade[] BL, String[] valueStr) { if (m_postOp == null) { return; } // TODO: currently only for *= and /= // get string of value: string postOpValueStr; RefGA.Multivector sc = m_postOpValue.ScalarPart(); if (sc.IsZero()) { postOpValueStr = CodeUtil.ScalarToLangString(S, m_floatType, RefGA.BasisBlade.ZERO); } else { postOpValueStr = CodeUtil.ScalarToLangString(S, m_floatType, sc.BasisBlades[0]); } // apply "m_postOp postOpValueStr" to all valueStr for (int i = 0; i < valueStr.Length; i++) { valueStr[i] = "(" + valueStr[i] + ")" + m_postOp + ((m_mustCast) ? m_floatType.castStr : "") + "(" + postOpValueStr + ")"; } }
/// <summary> /// Should generate the code according to the specification of the algebra. /// </summary> /// <param name="S">The specification of the algebra. The specification also lists the names of the files /// to be generated, or at least the base path.</param> /// <param name="plugins">The plugins which Gaigen found that support the same language as this code generator.</param> /// <returns>a list of filenames; the names of the files that were generated. This may be used /// for post processing.</returns> public List<string> GenerateCode(Specification S, List<CodeGeneratorPlugin> plugins) { // disable all inlining since the Java language does not support this: S.SetInlineNone(); CreatePackageDirectory(S); CoGsharp.CoG cog = InitCog(S); CG.Shared.CGdata cgd = new G25.CG.Shared.CGdata(plugins, cog); cgd.SetDependencyPrefix("missing_function_"); // this makes sure that the user sees the function call is a missing dependency G25.CG.Shared.FunctionGeneratorInfo FGI = (S.m_generateTestSuite) ? new G25.CG.Shared.FunctionGeneratorInfo() : null; // the fields in this variable are set by Functions.WriteFunctions() and reused by TestSuite.GenerateCode() { // pregenerated code that will go into main source // generate code for parts of the geometric product, dual, etc (works in parallel internally) try { bool declOnly = false; G25.CG.Shared.PartsCode.GeneratePartsCode(S, cgd, declOnly); } catch (G25.UserException E) { cgd.AddError(E); } // write function (works in parallel internally) G25.CG.Shared.Functions.WriteFunctions(S, cgd, FGI, Functions.GetFunctionGeneratorPlugins(cgd)); } List<string> generatedFiles = new List<string>(); // generate Doxyfile generatedFiles.Add(G25.CG.Shared.Util.GenerateDoxyfile(S, cgd)); // generate source files / classes for all GMV, SMV, GOM, SOM types generatedFiles.AddRange(GenerateClasses(S, cgd)); // generate source generatedFiles.AddRange(Source.GenerateCode(S, cgd)); // generate smv type enum generatedFiles.AddRange(SmvType.GenerateCode(S, cgd)); // generate GroupBitmap class generatedFiles.AddRange(GroupBitmap.GenerateCode(S, cgd)); // generate multivector interfaces generatedFiles.AddRange(MvInterface.GenerateCode(S, cgd)); // generate parser generatedFiles.AddRange(Parser.GenerateCode(S, cgd)); // generate report usage code generatedFiles.AddRange(ReportUsage.GenerateCode(S, cgd)); // report errors and missing deps to user cgd.PrintErrors(S); cgd.PrintMissingDependencies(S); if ((cgd.GetNbErrors() == 0) && (cgd.GetNbMissingDependencies() == 0) && S.m_generateTestSuite) { // generate test suite generatedFiles.AddRange(TestSuite.GenerateCode(S, cgd, FGI)); } return generatedFiles; }
/// <summary> /// Generates all code for parts of geometric product, substract, add, negate, dual, and so on. /// /// The results go into cgd.m_def and cgd.m_gmvGPpartFuncNames and cgd.m_gmvDualPartFuncNames. /// /// Is also called by TestSuite because the declarations are in the source file by default which /// makes them unavailable to the testing code. /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go into cgd.m_def and cgd.m_gmvGPpartFuncNames and cgd.m_gmvDualPartFuncNames.</param> /// <param name="declOnly">When true, only the declarations are generated and written to <c>cgd.m_defSB</c>.</param> public static void GeneratePartsCode(Specification S, CG.Shared.CGdata cgd, bool declOnly) { // generate all parts of the geometric product (in parallel) const int NB_PARTS_CODE = 4; // get a temporary cgd for each type of parts code CG.Shared.CGdata[] tmpCgd = new G25.CG.Shared.CGdata[NB_PARTS_CODE]; for (int i = 0; i < NB_PARTS_CODE; i++) tmpCgd[i] = new G25.CG.Shared.CGdata(cgd); // get parts code generators G25.CG.Shared.GmvGpParts p1 = new G25.CG.Shared.GmvGpParts(S, tmpCgd[0]); // [0] = GP G25.CG.Shared.GmvCASNparts p2 = new G25.CG.Shared.GmvCASNparts(S, tmpCgd[1]); // [1] = CASN G25.CG.Shared.GmvDualParts p3 = new G25.CG.Shared.GmvDualParts(S, tmpCgd[2]); // [2] = DUAL G25.CG.Shared.GmvGomParts p4 = new G25.CG.Shared.GmvGomParts(S, tmpCgd[3]); // [3] = GOM X GMV // run threads System.Threading.Thread[] T = new System.Threading.Thread[NB_PARTS_CODE]; T[0] = new Thread(p1.WriteGmvGpParts); T[1] = new Thread(p2.WriteGmvCASNparts); T[2] = new Thread(p3.WriteGmvDualParts); T[3] = new Thread(p4.WriteGmvGomParts); G25.CG.Shared.Threads.StartThreadArray(T); G25.CG.Shared.Threads.JoinThreadArray(T); // merge declarations and definitions go into cgd.m_declSB or cgd.m_defSB, depending on the language for (int i = 0; i < NB_PARTS_CODE; i++) { // StringBuilder SB = (S.OutputC()) ? cgd.m_defSB : cgd.m_declSB; StringBuilder SB = cgd.m_defSB; SB.Append(tmpCgd[i].m_declSB); } if (!declOnly) // if only declarations are wanted, don't copy the definitions for (int i = 0; i < NB_PARTS_CODE; i++) cgd.m_defSB.Append(tmpCgd[i].m_defSB); // copy names of part functions from appropriate temporary cgd cgd.m_gmvGPpartFuncNames = tmpCgd[0].m_gmvGPpartFuncNames; // this assumes [0] = GP cgd.m_gmvDualPartFuncNames = tmpCgd[2].m_gmvDualPartFuncNames; // this assumes [2] = DUAL cgd.m_gmvGomPartFuncNames = tmpCgd[3].m_gmvGomPartFuncNames; // this assumes [3] = GOM }
public GmvCASNparts(Specification S, G25.CG.Shared.CGdata cgd) { m_specification = S; m_cgd = cgd; }
protected void writeSmvPassThroughConverter(FloatType FT, string smvTypeName, Comment comment, string funcName, G25.CG.Shared.FuncArgInfo[] FAI) { // verbatim code List<Instruction> instructions = new List<Instruction>(); int nbTabs = 1; instructions.Add(new VerbatimCodeInstruction(nbTabs, "return " + FAI[0].Name + ";")); G25.CG.Shared.CGdata localCGD = new G25.CG.Shared.CGdata(m_cgd, m_declSB, m_defSB, m_inlineDefSB); string returnType = smvTypeName; bool staticFunc = Functions.OutputStaticFunctions(m_specification); FuncArgInfo returnArgument = null; Functions.WriteFunction(m_specification, localCGD, this.m_fgs, m_specification.m_inlineSet, staticFunc, returnType, funcName, returnArgument, FAI, instructions, comment); }
/// <summary> /// Writes any code to extract a grade part. /// </summary> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> /// <param name="gradeIdx">Grade to be selected (use -1 for user-specified).</param> public static string WriteGradeFunction(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment, int gradeIdx) { // setup instructions System.Collections.Generic.List<G25.CG.Shared.Instruction> I = new System.Collections.Generic.List<G25.CG.Shared.Instruction>(); int nbTabs = 1; // write this function: const string GROUP_BITMAP_NAME = "groupBitmap"; string code = G25.CG.Shared.CANSparts.GetGradeCode(S, cgd, FT, gradeIdx, FAI, fgs.RETURN_ARG_NAME, GROUP_BITMAP_NAME); // add one instruction (verbatim code) I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code)); // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(S, FT, F, FAI); string funcName = CF.OutputName; //if (S.OutputC()) // funcName = FT.GetMangledName(S, funcName); // setup return type and argument: string returnTypeName = FT.GetMangledName(S, S.m_GMV.Name); G25.CG.Shared.FuncArgInfo returnArgument = null; if (S.OutputC()) returnArgument = new G25.CG.Shared.FuncArgInfo(S, CF, -1, FT, S.m_GMV.Name, false); // false = compute value //StringBuilder tmpSB = new StringBuilder(); // G25.CG.Shared.Functions.WriteFunction() writes to this SB first so we can add the grade index if required // write function G25.CG.Shared.CGdata tmpCgd = new G25.CG.Shared.CGdata(cgd); bool inline = false; // never inline GMV functions bool staticFunc = Functions.OutputStaticFunctions(S); G25.CG.Shared.Functions.WriteFunction(S, tmpCgd, F, inline, staticFunc, returnTypeName, funcName, returnArgument, FAI, I, comment); if (gradeIdx < 0) // hack: if grade is func arg, then add it: { // add extra argument (int) to select the grade //if (S.OutputCppOrC()) // tmpCgd.m_declSB = AddGradeArg(S, tmpCgd.m_declSB.ToString(), gradeIdx, GROUP_BITMAP_NAME); //tmpCgd.m_defSB = AddGradeArg(S, tmpCgd.m_defSB.ToString(), gradeIdx, GROUP_BITMAP_NAME); //tmpCgd.m_inlineDefSB = AddGradeArg(S, tmpCgd.m_inlineDefSB.ToString(), gradeIdx, GROUP_BITMAP_NAME); } cgd.m_declSB.Append(tmpCgd.m_declSB); cgd.m_defSB.Append(tmpCgd.m_defSB); cgd.m_inlineDefSB.Append(tmpCgd.m_inlineDefSB); return funcName; }
/// <summary> /// Generate all code according to the specification of the algebra. /// </summary> /// <param name="S">The specification of the algebra. The specification also lists the names of the files /// to be generated, or at least the base path.</param> /// <param name="plugins">The plugins which Gaigen found that support the same language as this code generator.</param> /// <returns>a list of filenames; the names of the files that were generated. This may be used /// for post processing.</returns> public List<string> GenerateCode(Specification S, List<CodeGeneratorPlugin> plugins) { // disable all inlining since the C language does not support this: S.SetInlineNone(); CoGsharp.CoG cog = InitCog(S); CG.Shared.CGdata cgd = new G25.CG.Shared.CGdata(plugins, cog); cgd.SetDependencyPrefix("missing_function_"); // this makes sure that the user sees the function call is a missing dependency G25.CG.Shared.FunctionGeneratorInfo FGI = (S.m_generateTestSuite) ? new G25.CG.Shared.FunctionGeneratorInfo() : null; // the fields in this variable are set by Functions.WriteFunctions() and reused by TestSuite.GenerateCode() { // pregenerated code that will go into header, source // generate code for parts of the geometric product, dual, etc (works in parallel internally) try { bool declOnly = false; G25.CG.Shared.PartsCode.GeneratePartsCode(S, cgd, declOnly); } catch (G25.UserException E) {cgd.AddError(E);} // write set zero, set, copy, copy between float types, extract coordinate, largest coordinate, etc (works in parallel internally) try { GenerateSetFunctions(S, plugins, cgd); } catch (G25.UserException E) { cgd.AddError(E); } // write function (works in parallel internally) G25.CG.Shared.Functions.WriteFunctions(S, cgd, FGI, Functions.GetFunctionGeneratorPlugins(cgd)); } List<string> generatedFiles = new List<string>(); // generate Doxyfile generatedFiles.Add(G25.CG.Shared.Util.GenerateDoxyfile(S, cgd)); // generate header generatedFiles.AddRange(Header.GenerateCode(S, cgd)); // generate source generatedFiles.AddRange(Source.GenerateCode(S, cgd)); // generate parser generatedFiles.AddRange(Parser.GenerateCode(S, cgd)); // report errors and missing deps to user cgd.PrintErrors(S); cgd.PrintMissingDependencies(S); if ((cgd.GetNbErrors() == 0) && (cgd.GetNbMissingDependencies() == 0) && S.m_generateTestSuite) { // if no errors, then generate testing code TestSuite.GenerateCode(S, cgd, FGI); } // Generate random number generator source code (Mersenne Twister). // This must be done last since the testing code may require it! if (cgd.GetFeedback(G25.CG.C.MainGenerator.MERSENNE_TWISTER) == "true") generatedFiles.AddRange(RandomMT.GenerateCode(S, cgd)); return generatedFiles; }
/// <summary> /// Writes code for all 'set' function and various other function (largest coordinate, coordinate extraction, etc) /// </summary> /// <param name="S"></param> /// <param name="plugins"></param> /// <param name="cgd"></param> protected void GenerateSetFunctions(Specification S, List<CodeGeneratorPlugin> plugins, CG.Shared.CGdata cgd) { const int NB_SET_CODE = 4; // get a temporary cgd for each type of parts code CG.Shared.CGdata[] tmpCgd = new G25.CG.Shared.CGdata[] {new G25.CG.Shared.CGdata(cgd), new G25.CG.Shared.CGdata(cgd), new G25.CG.Shared.CGdata(cgd), new G25.CG.Shared.CGdata(cgd) }; // get parts code generators G25.CG.C.GMV p1 = new G25.CG.C.GMV(S, tmpCgd[0]); // [0] = GMV G25.CG.C.SMV p2 = new G25.CG.C.SMV(S, tmpCgd[1]); // [1] = SMV G25.CG.C.GOM p3 = new G25.CG.C.GOM(S, tmpCgd[2]); // [2] = GOM G25.CG.C.SOM p4 = new G25.CG.C.SOM(S, tmpCgd[3]); // [3] = SOM // run threads System.Threading.Thread[] T = new System.Threading.Thread[NB_SET_CODE]; T[0] = new Thread(p1.WriteSetFunctions); T[1] = new Thread(p2.WriteSetFunctions); T[2] = new Thread(p3.WriteSetFunctions); T[3] = new Thread(p4.WriteSetFunctions); G25.CG.Shared.Threads.StartThreadArray(T); G25.CG.Shared.Threads.JoinThreadArray(T); // merge declarations and definitions for (int i = 0; i < NB_SET_CODE; i++) { cgd.m_declSB.Append(tmpCgd[i].m_declSB); cgd.m_defSB.Append(tmpCgd[i].m_defSB); cgd.m_inlineDefSB.Append(tmpCgd[i].m_inlineDefSB); } }
/// <summary> /// Generates a source file with the SMV class definition. /// </summary> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="smv"></param> /// <param name="FT"></param> /// <returns></returns> public static string GenerateCode(Specification S, G25.CG.Shared.CGdata cgd, G25.SMV smv, FloatType FT) { string className = FT.GetMangledName(S, smv.Name); // get filename, list of generated filenames List<string> generatedFiles = new List<string>(); string sourceFilename = MainGenerator.GetClassOutputPath(S, className); generatedFiles.Add(sourceFilename); // get StringBuilder where all generated code goes StringBuilder SB = new StringBuilder(); // get a new 'cgd' where all ouput goes to the one StringBuilder SB cgd = new G25.CG.Shared.CGdata(cgd, SB, SB, SB); // output license, copyright G25.CG.Shared.Util.WriteCopyright(SB, S); G25.CG.Shared.Util.WriteLicense(SB, S); // using ... Util.WriteGenericUsing(SB, S); // open namespace G25.CG.Shared.Util.WriteOpenNamespace(SB, S); // write class comment G25.CG.CSJ.SMV.WriteComment(SB, S, cgd, FT, smv); // open class string[] implements = new string[] { MvInterface.GetMvInterfaceName(S, FT) }; G25.CG.Shared.Util.WriteOpenClass(SB, S, G25.CG.Shared.AccessModifier.AM_public, className, null, implements); // member variables G25.CG.CSJ.SMV.WriteMemberVariables(SB, S, cgd, FT, smv); // indices into arrays G25.CG.CSJ.SMV.WriteSMVcoordIndices(SB, S, FT, smv); // special type to safeguard coordinates order in functions G25.CG.CSJ.SMV.WriteCoordinateOrder(SB, S, FT, smv); // write multivector interface implementation G25.CG.CSJ.SMV.WriteMultivectorInterface(SB, S, cgd, FT, smv); // write constructors G25.CG.CSJ.SMV.WriteConstructors(SB, S, cgd, FT, smv); // write set functions G25.CG.CSJ.SMV.WriteSetFunctions(SB, S, cgd, FT, smv); // write largest coordinate functions G25.CG.CSJ.SMV.WriteLargestCoordinateFunctions(S, cgd, FT, smv); // write 'ToString' functions G25.CG.CSJ.GMV.WriteToString(SB, S, cgd, FT, smv); // write get/set coords G25.CG.CSJ.SMV.WriteGetSetCoord(SB, S, cgd, FT, smv); // write shortcuts for functions G25.CG.Shared.Shortcut.WriteFunctionShortcuts(SB, S, cgd, FT, smv); // close class G25.CG.Shared.Util.WriteCloseClass(SB, S, className); // close namespace G25.CG.Shared.Util.WriteCloseNamespace(SB, S); // write all to file G25.CG.Shared.Util.WriteFile(sourceFilename, SB.ToString()); return sourceFilename; }
/// <summary> /// Generates a source file with the GMV class definition. /// </summary> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="FT"></param> /// <returns></returns> public static string GenerateCode(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT) { G25.GMV gmv = S.m_GMV; string className = FT.GetMangledName(S, gmv.Name); // get filename, list of generated filenames List<string> generatedFiles = new List<string>(); string sourceFilename = MainGenerator.GetClassOutputPath(S, className); generatedFiles.Add(sourceFilename); // get StringBuilder where all generated code goes StringBuilder SB = new StringBuilder(); // get a new 'cgd' where all ouput goes to the one StringBuilder SB cgd = new G25.CG.Shared.CGdata(cgd, SB, SB, SB); // output license, copyright G25.CG.Shared.Util.WriteCopyright(SB, S); G25.CG.Shared.Util.WriteLicense(SB, S); // using ... Util.WriteGenericUsing(SB, S); // open namespace G25.CG.Shared.Util.WriteOpenNamespace(SB, S); // write class comment G25.CG.CSJ.GMV.WriteComment(SB, S, cgd, FT, gmv); // open class string[] implements = new string[] { MvInterface.GetMvInterfaceName(S, FT) }; G25.CG.Shared.Util.WriteOpenClass(SB, S, G25.CG.Shared.AccessModifier.AM_public, className, null, implements); // write member vars WriteMemberVariables(SB, S, cgd, FT, gmv); // write constructors WriteConstructors(SB, S, cgd, FT, gmv, className); WriteGetGuC(SB, S, cgd, FT); // write 'set' functions G25.CG.CSJ.GMV.WriteSetZero(SB, S, cgd, FT); G25.CG.CSJ.GMV.WriteSetScalar(SB, S, cgd, FT); G25.CG.CSJ.GMV.WriteSetCompressedArray(SB, S, cgd, FT); G25.CG.CSJ.GMV.WriteSetExpandedArray(SB, S, cgd, FT); G25.CG.CSJ.GMV.WriteGMVtoGMVcopy(SB, S, cgd, FT); G25.CG.CSJ.GMV.WriteSMVtoGMVcopy(SB, S, cgd, FT); // write 'get coordinate' functions G25.CG.CSJ.GMV.WriteGetCoord(SB, S, cgd, FT); // write SetGroupUsage() G25.CG.CSJ.GMV.WriteSetGroupUsage(SB, S, cgd, FT); // write 'reserve group' functions G25.CG.CSJ.GMV.WriteReserveGroup(SB, S, cgd, FT); // write 'set coordinate' functions G25.CG.CSJ.GMV.WriteSetCoord(SB, S, cgd, FT); // write 'largest coordinate' functions G25.CG.CSJ.GMV.WriteLargestCoordinates(SB, S, cgd, FT); // write compress functions G25.CG.CSJ.GMV.WriteCompress(SB, S, cgd, FT); // write 'ToString' functions G25.CG.CSJ.GMV.WriteToString(SB, S, cgd, FT, gmv); // write multivector interface implementation G25.CG.CSJ.GMV.WriteMultivectorInterface(SB, S, cgd, FT); // write shortcuts for functions G25.CG.Shared.Shortcut.WriteFunctionShortcuts(SB, S, cgd, FT, gmv); // close class G25.CG.Shared.Util.WriteCloseClass(SB, S, className); // close namespace G25.CG.Shared.Util.WriteCloseNamespace(SB, S); // write all to file G25.CG.Shared.Util.WriteFile(sourceFilename, SB.ToString()); return sourceFilename; }
/// <summary> /// Writes code for all functions to <c>cgd.m_defSB</c>, <c>cgd.m_inlineDefSB and</c> <c>cgd.m_declSB</c>. /// /// Takes an explicit list of functions (used by <c>TestSuite.GenerateCode()</c>). /// </summary> /// <param name="S"></param> /// <param name="cgd">Generated code goes here</param> /// <param name="FGI">Info about what plugin should implement what function /// The member variables are initialized by this function. <c>FGI</c> can be null when /// no testing code is generated. This allows the memory of the FunctionGenerators to be released /// earlier on.</param> /// <param name="plugins">The available function generators.</param> /// <param name="functions">List of <c>G25.fgs</c> to implement.</param> public static void WriteFunctions( Specification S, G25.CG.Shared.CGdata cgd, G25.CG.Shared.FunctionGeneratorInfo FGI, List<G25.CG.Shared.BaseFunctionGenerator> plugins, List<G25.fgs> functions) { // first split functions into converters and regular functions List<G25.fgs> converterFGS = new List<fgs>(); List<G25.fgs> functionFGS = new List<fgs>(); foreach (G25.fgs F in functions) { if (F.IsConverter(S)) // is 'F' a converter (underscore constructor)? converterFGS.Add(F); else functionFGS.Add(F); } // store converterFGS and functionFGS in FGI, for later use by TestSuite.GenerateCode() if (FGI != null) { FGI.m_converterFGS = converterFGS; FGI.m_functionFGS = functionFGS; } // start threads to generate code for all converters Thread[] converterThreads = new Thread[converterFGS.Count]; Converter[] converters = new Converter[converterFGS.Count]; for (int f = 0; f < converterFGS.Count; f++) { G25.fgs F = converterFGS[f]; converters[f] = new Converter(S, cgd, F); converterThreads[f] = new Thread(converters[f].WriteConverter); } G25.CG.Shared.Threads.StartThreadArray(converterThreads); // find out which plugin can implement which FGS Thread[] functionThreads = new Thread[functionFGS.Count]; G25.CG.Shared.BaseFunctionGenerator[] functionGenerators = new G25.CG.Shared.BaseFunctionGenerator[functionFGS.Count]; G25.CG.Shared.CGdata[] functionCgd = new G25.CG.Shared.CGdata[functionFGS.Count]; for (int f = 0; f < functionFGS.Count; f++) { G25.fgs F = functionFGS[f]; foreach (G25.CG.Shared.BaseFunctionGenerator P in plugins) // check all C plugins { if (P.CanImplement(S, F)) // ask them if they can handle 'F' { // get a clean instance of the code generator and initialize it functionGenerators[f] = System.Activator.CreateInstance(P.GetType()) as BaseFunctionGenerator; functionCgd[f] = new G25.CG.Shared.CGdata(cgd); // m_errors and m_missingDependencies will be shared with main cgd! functionGenerators[f].Init(S, F, functionCgd[f]); F.SetSupportedByPlugin(); break; } } if (!F.GetSupportedByPlugin()) {// no plugin could do 'F': complain about it System.Console.WriteLine("Warning no suitable plugin for function " + F.Name + "; XML specification: "); System.Console.WriteLine(" " + XML.FunctionToXmlString(S, F)); } } // store functionGenerators in FGI, for later use by TestSuite.GenerateCode() if (FGI != null) { FGI.m_functionGenerators = functionGenerators; FGI.m_functionCgd = functionCgd; } // run threads for fill-in of functions for (int f = 0; f < functionFGS.Count; f++) { if (functionGenerators[f] == null) continue; functionThreads[f] = new Thread(functionGenerators[f].CompleteFGSentryPoint); } G25.CG.Shared.Threads.StartThreadArray(functionThreads); G25.CG.Shared.Threads.JoinThreadArray(functionThreads); //G25.CG.Shared.Threads.RunThreadArraySerially(functionThreads); // runs thread for dependency check of functions for (int f = 0; f < functionFGS.Count; f++) { if (functionGenerators[f] == null) continue; functionThreads[f] = new Thread(functionGenerators[f].CheckDepenciesEntryPoint); } G25.CG.Shared.Threads.StartThreadArray(functionThreads); G25.CG.Shared.Threads.JoinThreadArray(functionThreads); //G25.CG.Shared.Threads.RunThreadArraySerially(functionThreads); // runs thread for actual code generation of functions for (int f = 0; f < functionFGS.Count; f++) { if (functionGenerators[f] == null) continue; functionThreads[f] = new Thread(functionGenerators[f].WriteFunctionEntryPoint); } G25.CG.Shared.Threads.StartThreadArray(functionThreads); //G25.CG.Shared.Threads.RunThreadArraySerially(functionThreads); // join all the converter threads: G25.CG.Shared.Threads.JoinThreadArray(converterThreads); // join all function generation threads G25.CG.Shared.Threads.JoinThreadArray(functionThreads); // collect all the results from the threads: for (int f = 0; f < converters.Length; f++) { cgd.m_declSB.Append(converters[f].m_declSB); cgd.m_defSB.Append(converters[f].m_defSB); cgd.m_inlineDefSB.Append(converters[f].m_inlineDefSB); cgd.MergeErrors(converters[f].m_cgd); } // collect all the results from the threads: for (int f = 0; f < functionCgd.Length; f++) { if (functionGenerators[f] == null) continue; cgd.m_declSB.Append(functionCgd[f].m_declSB); cgd.m_defSB.Append(functionCgd[f].m_defSB); cgd.m_inlineDefSB.Append(functionCgd[f].m_inlineDefSB); } }
/// <summary> /// Writes code for all converters (as specified in Function Generation Specification). /// </summary> public void WriteConverter() { try { string rawSrcTypeName = m_fgs.GetArgumentTypeName(0, null); // null = no default name string rawDstTypeName = m_fgs.Name.Substring(1); // dest = function name minus the underscore. bool srcIsGMV = m_specification.m_GMV.GetName().Equals(rawSrcTypeName); const int nbArgs = 1; foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); string srcTypeName = FT.GetMangledName(m_specification, rawSrcTypeName); string dstTypeName = FT.GetMangledName(m_specification, rawDstTypeName); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, nbArgs, FT, m_specification.m_GMV.Name, computeMultivectorValue); // comment: Comment comment = GetComment(m_specification, srcTypeName, dstTypeName, FAI[0].Name, m_fgs.Comment); comment.Write((m_specification.OutputCSharpOrJava()) ? m_defSB : m_declSB, m_specification, 1); string funcName = G25.CG.Shared.Converter.GetConverterName(m_specification, m_fgs, srcTypeName, dstTypeName); if (srcIsGMV) { // convert GMV to SMV writeGmvToSmvConverter(FT, srcTypeName, dstTypeName, comment, funcName, FAI); } else if (srcTypeName == dstTypeName) { // convert to the same type writeSmvPassThroughConverter(FT, srcTypeName, comment, funcName, FAI); } else { // convert SMV/scalar to SMV // if scalar or specialized: generate specialized function: first get symbolic result RefGA.Multivector value = FAI[0].MultivectorValue[0]; G25.CG.Shared.CGdata localCGD = new G25.CG.Shared.CGdata(m_cgd, m_declSB, m_defSB, m_inlineDefSB); G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(m_specification, m_fgs, -1, FT, rawDstTypeName, false); // false = compute value bool staticFunc = Functions.OutputStaticFunctions(m_specification); bool mustCast = false; if (m_specification.OutputC()) { Functions.WriteAssignmentFunction(m_specification, localCGD, m_specification.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, returnArgument.Type as G25.SMV, returnArgument.Name, returnArgument.Pointer, value); } else { Functions.WriteReturnFunction( m_specification, localCGD, m_specification.m_inlineSet, staticFunc, funcName, FAI, FT, mustCast, returnArgument.Type as G25.SMV, value); } } } } catch (G25.UserException E) { if (E.m_XMLerrorSource.Length == 0) { string XMLstring = XML.FunctionToXmlString(m_specification, m_fgs); m_cgd.AddError(new G25.UserException(E.m_message, XMLstring, E.m_filename, E.m_line, E.m_column)); } else m_cgd.AddError(E); } }
/// <summary> /// Must be called before CompleteFGS(), CheckDepencies() or WriteFunction() is called. /// Subclass can override, but if so, must always call superclass version of Init() /// </summary> /// <param name="S"></param> /// <param name="F"></param> /// <param name="cgd">Where the generate code goes.</param> public virtual void Init(Specification S, G25.fgs F, G25.CG.Shared.CGdata cgd) { m_specification = S; m_fgs = F; m_cgd = cgd; m_gmv = m_specification.m_GMV; m_G25M = m_specification.GetMetric(m_fgs.MetricName); m_M = m_G25M.m_metric; m_sane = true; }