/// <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="FT">Float type.</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, FloatType FT, bool matrixMode, bool transpose) { G25.GOM gom = S.m_GOM; // get the 'plan' on how to initialize all domain basis blades efficiently: uint[][][] plan = G25.CG.Shared.OMinit.ComputeOmInitFromVectorsPlan(S, gom); double[][] signs = G25.CG.Shared.OMinit.ComputeOmInitFromVectorsSigns(S, gom, plan); // get range vector type G25.SMV rangeVectorType = G25.CG.Shared.OMinit.GetRangeVectorType(S, FT, cgd, gom); // setup array of arguments, function specification, etc int NB_ARGS = (matrixMode) ? 1 : gom.DomainVectors.Length; string[] argTypes = new string[NB_ARGS], argNames = new string[NB_ARGS]; RefGA.Multivector[] symbolicBBvalues = new RefGA.Multivector[1 << S.m_dimension]; // symbolic basis blade values go here if (matrixMode) { argTypes[0] = FT.type; argNames[0] = "M"; // convert matrix columns to symbolic Multivector values for (int d = 0; d < gom.DomainVectors.Length; d++) { RefGA.BasisBlade[] IV = new RefGA.BasisBlade[gom.RangeVectors.Length]; for (int r = 0; r < gom.RangeVectors.Length; r++) { int matrixIdx = (transpose) ? (d * gom.RangeVectors.Length + r) : (r * gom.DomainVectors.Length + d); string entryName = argNames[0] + "[" + matrixIdx + "]"; IV[r] = new RefGA.BasisBlade(gom.RangeVectors[r].bitmap, 1.0, entryName); } symbolicBBvalues[gom.DomainVectors[d].bitmap] = new RefGA.Multivector(IV); } } else { for (int d = 0; d < NB_ARGS; d++) { argTypes[d] = rangeVectorType.Name; argNames[d] = "i" + gom.DomainVectors[d].ToLangString(S.m_basisVectorNames); bool ptr = S.OutputC(); symbolicBBvalues[gom.DomainVectors[d].bitmap] = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, rangeVectorType, argNames[d], ptr); } } // generate function names for all grades (basis blade names not included) string typeName = FT.GetMangledName(S, gom.Name); string[] funcNames = GetSetFromLowerGradeFunctionNames(S, FT, matrixMode); // setup instructions (for main function, and subfunctions for grades) List <G25.CG.Shared.Instruction> mainI = new List <G25.CG.Shared.Instruction>(); List <G25.CG.Shared.Instruction>[] bladeI = new List <G25.CG.Shared.Instruction> [1 << S.m_dimension]; { bool mustCast = false; int nbTabs = 1; string dstName = (S.OutputC()) ? G25.fgs.RETURN_ARG_NAME : SmvUtil.THIS; bool dstPtr = S.OutputCppOrC(); bool declareDst = false; for (int g = 1; g < gom.Domain.Length; g++) { for (int d = 0; d < gom.DomainForGrade(g).Length; d++) { G25.SMVOM smvOM = gom.DomainSmvForGrade(g)[d]; RefGA.BasisBlade domainBlade = gom.DomainForGrade(g)[d]; if (g > 1) { bladeI[domainBlade.bitmap] = new List <G25.CG.Shared.Instruction>(); string funcCallCode = funcNames[g] + "_" + d + "("; if (S.OutputC()) { funcCallCode += G25.fgs.RETURN_ARG_NAME; } funcCallCode += ");"; mainI.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, funcCallCode)); } // follow the plan RefGA.Multivector value = new RefGA.Multivector(signs[g][d]); uint[] P = plan[g][d]; for (int p = 0; p < P.Length; p++) { value = RefGA.Multivector.op(value, symbolicBBvalues[P[p]]); } // add instructions List <G25.CG.Shared.Instruction> I = (g == 1) ? mainI : bladeI[domainBlade.bitmap]; I.Add(new G25.CG.Shared.CommentInstruction(nbTabs, "Set image of " + domainBlade.ToString(S.m_basisVectorNames))); I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smvOM, FT, mustCast, value, dstName, dstPtr, declareDst)); // store symbolic value symbolicBBvalues[domainBlade.bitmap] = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smvOM, dstName, dstPtr); } } } // output grade > 1 functions if (cgd.generateOmInitCode(FT.type)) { for (int g = 2; g < gom.Domain.Length; g++) { for (int d = 0; d < gom.DomainForGrade(g).Length; d++) { RefGA.BasisBlade domainBlade = gom.DomainForGrade(g)[d]; string funcName = funcNames[g] + "_" + d; G25.fgs F = new G25.fgs(funcName, funcName, "", new string[0], new string[0], new string[] { FT.type }, null, null, null); // null, null = metricName, comment, options //F.InitArgumentPtrFromTypeNames(S); bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo returnArgument = null; if (S.OutputC()) { returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, gom.Name, computeMultivectorValue); } int nbArgs = 0; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, S.m_GMV.Name, computeMultivectorValue); Comment comment; comment = new Comment("Sets grade " + g + " part of outermorphism matrix based on lower grade parts."); bool inline = false; // do not inline this potentially huge function bool staticFunc = false; bool writeDecl = S.OutputC(); G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, "void", funcName, returnArgument, FAI, bladeI[domainBlade.bitmap], comment, writeDecl); } } } { // output grade 1 function G25.fgs F = new G25.fgs(funcNames[1], funcNames[1], "", argTypes, argNames, new string[] { FT.type }, null, null, null); // null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); if (matrixMode) { F.m_argumentPtr[0] = S.OutputCppOrC(); F.m_argumentArr[0] = S.OutputCSharpOrJava(); } bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo returnArgument = null; if (S.OutputC()) { returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, gom.Name, computeMultivectorValue); } G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, S.m_GMV.Name, computeMultivectorValue); Comment comment; if (!matrixMode) { comment = new Comment("Sets " + typeName + " from images of the domain vectors."); } else { comment = new Comment("Sets " + typeName + " from a " + (transpose ? "transposed " : "") + "matrix"); } bool inline = false; // do not inline this potentially huge function bool staticFunc = false; bool writeDecl = S.OutputC(); G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, "void", funcNames[1], returnArgument, FAI, mainI, comment, writeDecl); } } // end of WriteSetVectorImages()
/// <summary> /// Generates functions which compute parts of the application of a general outermorphism to a general multivector. /// /// This function should be called early on in the code generation process, at least /// before any of the <c>???()</c> functions is called. /// </summary> /// <param name="S">Specification (used for output language, GMV).</param> /// <param name="cgd">Where the result goes.</param> public static void WriteGomParts(Specification S, CGdata cgd) { if (S.m_GOM == null) { return; // nothing to do if GOM not defiend } int nbBaseTabs = (S.OutputCSharpOrJava()) ? 1 : 0; int nbCodeTabs = nbBaseTabs + 1; G25.GMV gmv = S.m_GMV; G25.GOM gom = S.m_GOM; string nameGOM = "O"; string nameSrcGMV = "A"; string nameDstGMV = "C"; // get symbolic multivector value RefGA.Multivector[] M1 = null; { bool ptr = (S.OutputC()); int allGroups = -1; M1 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, nameSrcGMV, ptr, allGroups); } foreach (G25.FloatType FT in S.m_floatTypes) { // map from code fragment to name of function Dictionary <string, string> generatedCode = new Dictionary <string, string>(); // loop over all groups of the GMV, multiply with GOM, and assign the result for (int srcGroup = 0; srcGroup < gmv.NbGroups; srcGroup++) { RefGA.Multivector inputValue = M1[srcGroup]; if (inputValue.IsScalar()) { continue; } // Replace each basis blade in 'inputValue' with its value under the outermorphism. RefGA.Multivector returnValue = RefGA.Multivector.ZERO; // returnValue = gom * gmv[srcGroup] for (int i = 0; i < inputValue.BasisBlades.Length; i++) { // get input blade and domain for that grade RefGA.BasisBlade inputBlade = inputValue.BasisBlades[i]; RefGA.BasisBlade[] domainBlades = gom.DomainForGrade(inputBlade.Grade()); for (int c = 0; c < domainBlades.Length; c++) { // if a match is found in the domain, add range vector to m_returnValue if (domainBlades[c].bitmap == inputBlade.bitmap) { bool ptr = (S.OutputC()); RefGA.Multivector omColumnValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, gom.DomainSmvForGrade(inputBlade.Grade())[c], nameGOM, ptr); RefGA.Multivector inputBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(inputBlade, 0)); RefGA.Multivector domainBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(domainBlades[c], 0)); returnValue = RefGA.Multivector.Add(returnValue, RefGA.Multivector.gp( RefGA.Multivector.gp(omColumnValue, inputBladeScalarMultiplier), domainBladeScalarMultiplier)); break; // no need to search the other domainBlades too } } } // end of 'compute return value' // assign returnValue to various groups of the gmv for (int dstGroup = 0; dstGroup < gmv.NbGroups; dstGroup++) { bool mustCast = false; bool writeZeros = false; // no need to generate "+= 0.0;" int dstBaseIdx = 0; string code = G25.CG.Shared.CodeUtil.GenerateGMVassignmentCode(S, FT, mustCast, gmv, nameDstGMV, dstGroup, dstBaseIdx, returnValue, nbCodeTabs, writeZeros); string funcName = GetGomPartFunctionName(S, FT, srcGroup, dstGroup); cgd.m_gmvGomPartFuncNames[new Tuple <string, string>(FT.type, funcName)] = (code.Length > 0); if (code.Length == 0) { continue; } if (!S.m_GMV.IsGroupedByGrade(S.m_dimension)) { code = code.Replace("=", "+="); } // check if code was already generated, and, if so, reuse it if (generatedCode.ContainsKey(code)) { // ready generated: call that function code = "\t" + generatedCode[code] + "(" + nameGOM + ", " + nameSrcGMV + ", " + nameDstGMV + ");\n"; } else { // not generated yet: remember code -> function generatedCode[code] = funcName; } // write comment string comment = "Computes the partial application of a general outermorphism to a general multivector"; string OM_PTR = ""; if (S.OutputC()) { OM_PTR = "*"; } else if (S.OutputCpp()) { OM_PTR = "&"; } string ACCESS = ""; if (S.OutputJava()) { ACCESS = "protected static "; } else if (S.OutputCSharp()) { ACCESS = "protected internal static "; } string ARR = (S.OutputCSharpOrJava()) ? "[] " : " *"; string CONST = (S.OutputCSharpOrJava()) ? "" : "const "; string funcDecl = ACCESS + "void " + funcName + "(" + CONST + FT.GetMangledName(S, gom.Name) + " " + OM_PTR + nameGOM + ", " + CONST + FT.type + ARR + nameSrcGMV + ", " + FT.type + ARR + nameDstGMV + ")"; if (S.OutputCppOrC()) { new Comment(comment).Write(cgd.m_declSB, S, nbBaseTabs); cgd.m_declSB.Append(funcDecl); cgd.m_declSB.AppendLine(";"); } else { new Comment(comment).Write(cgd.m_defSB, S, nbBaseTabs); } // emit def cgd.m_defSB.Append('\t', nbBaseTabs); cgd.m_defSB.Append(funcDecl); cgd.m_defSB.AppendLine(" {"); cgd.m_defSB.Append(code); cgd.m_defSB.Append('\t', nbBaseTabs); cgd.m_defSB.AppendLine("}"); } // end of loop over all dest GMV groups } // end of loop over all source GMV groups } // end of loop over all float types } // end of function WriteGomParts()