/// <summary> /// Writes the SMV class 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">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteMemberVariables(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { SB.AppendLine("public:"); // individual coordinates or one array? if (S.m_coordStorage == COORD_STORAGE.VARIABLES) { for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine("\t/// The " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\t" + FT.type + " m_" + smv.GetCoordLangID(i, S) + ";"); } } else { if (smv.NbNonConstBasisBlade > 0) { // emit: float c[3]; // e1, e2, e3 SB.AppendLine("\t/// The coordinates (stored in an array)."); SB.Append("\t" + FT.type + " m_c[" + smv.NbNonConstBasisBlade + "]; // "); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { if (i > 0) { SB.Append(", "); } SB.Append(smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames)); } SB.AppendLine(""); } } }
} // end of WriteLargestCoordinateFunctions() /// <summary> /// Writes getters and setters for the SMV coordinates.. /// </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 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteGetSetCoord(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { int nbTabs = 1; string className = FT.GetMangledName(S, smv.Name); // for variable coordinates: for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(i); string name = smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames); string accessName = G25.CG.Shared.SmvUtil.GetCoordAccessString(S, smv, i); // get string getComment = "Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + name + "() { return " + accessName + ";}"); // set string setComment = "Sets the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(setComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " void " + G25.CG.Shared.Main.SETTER_PREFIX + name + "(" + FT.type + " " + name + ") { " + accessName + " = " + name + ";}"); } // for constant coordinates: for (int i = 0; i < smv.NbConstBasisBlade; i++) { RefGA.BasisBlade B = smv.ConstBasisBlade(i); // get string getComment = "Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() { return " + FT.DoubleToString(S, smv.ConstBasisBladeValue(i)) + ";}"); } // write a getter for the scalar which returns 0 if no scalar coordinate is present if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; string getComment = "Returns the scalar coordinate (which is always 0)."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() { return " + FT.DoubleToString(S, 0.0) + ";}"); } // getter for the coordinates (stored in array) if ((S.m_coordStorage == COORD_STORAGE.ARRAY) && (smv.NbNonConstBasisBlade > 0)) { string constantName = G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv); string COORD_ORDER = "coordOrder"; new G25.CG.Shared.Comment("Returns array of coordinates."). SetParamComment(COORD_ORDER, "pass the value '" + className + "." + constantName + "'"). Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + "[] c(" + G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM + " " + COORD_ORDER + ") { return m_c;}"); } }
/// <summary> /// Takes a specialized multivector specification (G25.SMV) and converts it into a symbolic multivector. /// The symbolic weights of the multivector are the coordinates of the SMV, labelled according to 'smvName'. /// /// An example is <c>A.c[0]*e1 + A.c[1]*e2 + A.c[2]*e3</c>. /// </summary> /// <param name="S">Specification of the algebra. Used for the access convention (. or ->) and for how to name the coordinates ([0] or e1, e2, e3).</param> /// <param name="smv">The specification of the specialized multivector.</param> /// <param name="smvName">Name the variable should have.</param> /// <param name="ptr">Is 'smvName' a pointer? This changes the way the variable is accessed.</param> /// <returns></returns> public static RefGA.Multivector SMVtoSymbolicMultivector(Specification S, G25.SMV smv, string smvName, bool ptr) { int idx = 0; // index into 'L' RefGA.BasisBlade[] L = new RefGA.BasisBlade[smv.NbConstBasisBlade + smv.NbNonConstBasisBlade]; string[] AL = CodeUtil.GetAccessStr(S, smv, smvName, ptr); // get non-const coords for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { // get basis blade of coordinate RefGA.BasisBlade B = smv.NonConstBasisBlade(i); // merge L[idx++] = new RefGA.BasisBlade(B.bitmap, B.scale, AL[i]); } // get const coords for (int i = 0; i < smv.NbConstBasisBlade; i++) { // get value of coordinate double value = smv.ConstBasisBladeValue(i); // get basis blade of coordinate RefGA.BasisBlade B = smv.ConstBasisBlade(i); // merge L[idx++] = new RefGA.BasisBlade(B.bitmap, B.scale * value); } return(new RefGA.Multivector(L)); } // end of SMVtoSymbolicMultivector()
} // end of GenerateSMVassignmentCode public static string GenerateReturnCode(Specification S, G25.SMV smv, G25.FloatType FT, String[] valueStr, int nbTabs, bool writeZeros) { StringBuilder SB = new StringBuilder(); string smvName = FT.GetMangledName(S, smv.Name); string STATIC_MEMBER_ACCESS = (S.OutputCpp()) ? "::" : "."; SB.Append('\t', nbTabs); SB.Append("return "); if (S.OutputCSharpOrJava()) { SB.Append("new "); } SB.Append(smvName); SB.Append("("); if (valueStr.Length > 0) { SB.AppendLine(smvName + STATIC_MEMBER_ACCESS + SmvUtil.GetCoordinateOrderConstant(S, smv) + ","); } for (int i = 0; i < valueStr.Length; i++) { SB.Append('\t', nbTabs + 2); SB.Append(valueStr[i]); if (i < (valueStr.Length - 1)) { SB.Append(","); } SB.AppendLine(" // " + smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames)); } SB.Append('\t', nbTabs + 1); SB.Append(");"); return(SB.ToString()); }
/// <summary> /// Utility function which takes a specialized multivector and returns an array of its variable /// RefGA.BasisBlades. I.e., extracts 'smv.NonConstBasisBlade()' /// </summary> /// <param name="smv">Specialized multivector.</param> /// <returns>Array of non-constant basis blades of 'smv'.</returns> public static RefGA.BasisBlade[] GetNonConstBladeList(G25.SMV smv) { RefGA.BasisBlade[] BL = new RefGA.BasisBlade[smv.NbNonConstBasisBlade]; for (int i = 0; i < smv.NbNonConstBasisBlade; i++) BL[i] = smv.NonConstBasisBlade(i); return BL; }
/// <summary> /// Writes the <c>defines</c> for indices of the smv struct to 'SB'. For example, <c>define VECTOR_E1 0</c>. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names.</param> /// <param name="smv">The specialized multivector for which the coordinate indices should be written.</param> public static void WriteSMVcoordIndices(StringBuilder SB, Specification S, G25.SMV smv) { SB.AppendLine(""); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { // write comment about what the #define is SB.AppendLine("/** index of coordinate for " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " in " + smv.Name + ".c */"); SB.AppendLine("#define " + GetCoordIndexDefine(S, smv, i) + " " + i); } }
/// <summary> /// Returns the name of the constant as first argument to functions which have coordinate arguments. /// </summary> /// <param name="S"></param> /// <param name="smv"></param> public static string GetCoordinateOrderConstant(Specification S, G25.SMV smv) { StringBuilder SB = new StringBuilder("coord"); string wedgeSymbol = ""; // no symbol for wedge for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.Append("_"); SB.Append(smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames, wedgeSymbol)); } return(SB.ToString()); }
/// <summary> /// Writes the <c>defines</c> for indices of the smv struct to 'SB'. For example, <c>define VECTOR_E1 0</c>. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names.</param> /// <param name="FT"></param> /// <param name="smv">The specialized multivector for which the coordinate indices should be written.</param> public static void WriteSMVcoordIndices(StringBuilder SB, Specification S, FloatType FT, G25.SMV smv) { string className = FT.GetMangledName(S, smv.Name); SB.AppendLine("\t/// Array indices of " + className + " coordinates."); SB.AppendLine("\ttypedef enum {"); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine("\t\t/// index of coordinate for " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " in " + className); SB.AppendLine("\t\t" + GetCoordIndexDefine(S, FT, smv, i) + " = " + i + ", "); } SB.AppendLine("\t} ArrayIndex;"); }
/// <summary> /// Writes getters and setters for the SMV coordinates.. /// </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 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteGetSetCoord(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { // write variable coordinates for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { string name = smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames); string accessName = G25.CG.Shared.SmvUtil.GetCoordAccessString(S, smv, i); SB.AppendLine("\t/// Returns the " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + name + "() const { return " + accessName + ";}"); SB.AppendLine("\t/// Sets the " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline void " + MainGenerator.SETTER_PREFIX + name + "(" + FT.type + " " + name + ") { " + accessName + " = " + name + ";}"); } // write constant coordinates for (int i = 0; i < smv.NbConstBasisBlade; i++) { RefGA.BasisBlade B = smv.ConstBasisBlade(i); SB.AppendLine("\t/// Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() const { return " + FT.DoubleToString(S, smv.ConstBasisBladeValue(i)) + ";}"); } // write a getter for the scalar which returns 0 if no scalar coordinate is present if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; SB.AppendLine("\t/// Returns the scalar coordinate (which is always 0)."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() const { return " + FT.DoubleToString(S, 0.0) + ";}"); } // getter for the coordinates (stored in array) if ((S.m_coordStorage == COORD_STORAGE.ARRAY) && (smv.NbNonConstBasisBlade > 0)) { SB.AppendLine("\t/// Returns array of coordinates."); SB.AppendLine("\tinline const " + FT.type + " *getC(" + G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM + ") const { return m_c;}"); } }
/// <summary> /// Writes the SMV class 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">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteMemberVariables(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { int nbTabs = 1; string accessModifier = Keywords.PackageProtectedAccessModifier(S); // individual coordinates or one array? if (S.m_coordStorage == COORD_STORAGE.VARIABLES) { for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { string comment = "The " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(comment).Write(SB, S, nbTabs); SB.AppendLine("\t" + accessModifier + " " + FT.type + " m_" + smv.GetCoordLangID(i, S) + ";"); } } else { if (smv.NbNonConstBasisBlade > 0) { // emit: float c[3]; // e1, e2, e3 string comment = " The coordinates (stored in an array)."; new G25.CG.Shared.Comment(comment).Write(SB, S, nbTabs); SB.Append("\t" + accessModifier + " " + FT.type + "[] m_c = new " + FT.type + "[" + smv.NbNonConstBasisBlade + "]; // "); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { if (i > 0) { SB.Append(", "); } SB.Append(smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames)); } SB.AppendLine(""); } } }
/// <summary> /// Writes the <c>defines</c> for indices of the smv struct to 'SB'. For example, <c>define VECTOR_E1 0</c>. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names.</param> /// <param name="FT"></param> /// <param name="smv">The specialized multivector for which the coordinate indices should be written.</param> public static void WriteSMVcoordIndices(StringBuilder SB, Specification S, FloatType FT, G25.SMV smv) { string className = FT.GetMangledName(S, smv.Name); int nbTabs = 1; new G25.CG.Shared.Comment("Array indices of " + className + " coordinates.").Write(SB, S, nbTabs); string AccessModifier = Keywords.ConstAccessModifier(S); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine(); new G25.CG.Shared.Comment("index of coordinate for " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " in " + className).Write(SB, S, nbTabs); SB.AppendLine("\tpublic " + AccessModifier + " int " + GetCoordIndexDefine(S, FT, smv, i) + " = " + i + ";"); } }
/// <summary> /// Writes the SMV class comment '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">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> /// <param name="emitCoordIndices">Whether to emit constants for array indices to coordinates.</param> public static void WriteComment(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv, bool emitCoordIndices) { SB.AppendLine("/**"); SB.AppendLine(" * This class can hold a specialized multivector of type " + FT.GetMangledName(S, smv.Name) + "."); SB.AppendLine(" * "); SB.AppendLine(" * The coordinates are stored in type " + FT.type + "."); SB.AppendLine(" * "); if (smv.NbNonConstBasisBlade > 0) { SB.AppendLine(" * The variable non-zero coordinates are:"); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine(" * - coordinate " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " (array index: " + GetCoordIndexDefine(S, FT, smv, i) + " = " + i + ")"); } } else { SB.AppendLine(" * The type is constant."); } SB.AppendLine(" * "); if (smv.NbConstBasisBlade > 0) { SB.AppendLine(" * The constant non-zero coordinates are:"); for (int i = 0; i < smv.NbConstBasisBlade; i++) { SB.AppendLine(" * - " + smv.ConstBasisBlade(i).ToString(S.m_basisVectorNames) + " = " + smv.ConstBasisBladeValue(i).ToString()); } } else { SB.AppendLine(" * The type has no constant coordinates."); } SB.AppendLine(" * "); if ((smv.Comment != null) && (smv.Comment.Length > 0)) { SB.AppendLine(" * "); SB.AppendLine(" * " + smv.Comment); } SB.AppendLine(" */"); }
} // end of WriteSetCoords() /// <summary> /// Writes a function to set an SMV struct to an array of specified coordinates, 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 WriteSetArray(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SMV smv) { //if (smv.NbNonConstBasisBlade == 0) return; cgd.m_defSB.AppendLine(""); //string className = FT.GetMangledName(S, smv.Name); string funcName = GMV.GetSetFuncName(S); bool mustCast = false; string[] argTypename = new string[2] { G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM, FT.type }; string[] argName = new string[2] { "co", "A" }; System.Collections.ArrayList L = new System.Collections.ArrayList(); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(i); String coordStr = argName[1] + "[" + i + "]"; L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr)); } RefGA.Multivector mvValue = new RefGA.Multivector(L); G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new string[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); F.SetArgumentArr(1, true); // second argument is an array bool computeMultivectorValue = false; int NB_ARGS = 2; // enum + one array of coordinates G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, null, computeMultivectorValue); 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, FT, mustCast, smv, dstName, dstPtr, mvValue); } // end of WriteSetArray()
/// <summary> /// Writes a function to set an SMV class to specified coordinates, 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 WriteSetCoords(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SMV smv) { //if (smv.NbNonConstBasisBlade == 0) return; cgd.m_defSB.AppendLine(""); //string className = FT.GetMangledName(S, smv.Name); string funcName = GMV.GetSetFuncName(S); bool mustCast = false; System.Collections.ArrayList L = new System.Collections.ArrayList(); int NB_ARGS = 1 + smv.NbNonConstBasisBlade; string[] argTypename = new String[NB_ARGS]; string[] argName = new String[NB_ARGS]; argTypename[0] = G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM; argName[0] = "co"; for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(i); argTypename[i + 1] = FT.type; string coordStr = "_" + smv.GetCoordLangID(i, S, COORD_STORAGE.VARIABLES); argName[i + 1] = coordStr; L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr)); } RefGA.Multivector mvValue = new RefGA.Multivector(L); G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, null, computeMultivectorValue); 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, FT, mustCast, smv, dstName, dstPtr, mvValue); } // end of WriteSetCoords()
} // end of GetGmvComment() /// <summary> /// Returns the comment for a SMV class. /// </summary> /// <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 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> /// <param name="emitCoordIndices">Whether to emit constants for array indices to coordinates.</param> public static Comment GetSmvComment(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv, bool emitCoordIndices) { StringBuilder SB = new StringBuilder(); SB.AppendLine("This class can hold a specialized multivector of type " + FT.GetMangledName(S, smv.Name) + "."); SB.AppendLine(""); SB.AppendLine("The coordinates are stored in type " + FT.type + "."); SB.AppendLine(""); if (smv.NbNonConstBasisBlade > 0) { SB.AppendLine("The variable non-zero coordinates are:"); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine(" - coordinate " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " (array index: " + smv.GetCoordLangID(i, S, COORD_STORAGE.VARIABLES).ToUpper() + " = " + i + ")"); } } else SB.AppendLine("The type is constant."); SB.AppendLine(""); if (smv.NbConstBasisBlade > 0) { SB.AppendLine("The constant non-zero coordinates are:"); for (int i = 0; i < smv.NbConstBasisBlade; i++) SB.AppendLine(" - " + smv.ConstBasisBlade(i).ToString(S.m_basisVectorNames) + " = " + smv.ConstBasisBladeValue(i).ToString()); } else SB.AppendLine("The type has no constant coordinates."); SB.AppendLine(""); if ((smv.Comment != null) && (smv.Comment.Length > 0)) { SB.AppendLine(""); SB.AppendLine("" + smv.Comment); } return new Comment(SB.ToString()); } // end of GetSmvComment()
} // end of WriteFunction /// <summary> /// Writes an zero test function for specialized multivectors. /// </summary> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> protected void WriteGradeBitmapFunction(FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment) { // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); // write the function: { int nbTabs = 1; I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "int bitmap = 0;")); // get largest constant coordinate for each grade: Dictionary <int, double> largestConstCoord = new Dictionary <int, double>(); if (m_smv != null) { // first find largest const coord: if any const coord above eps, always return 0 for (int c = 0; c < m_smv.NbConstBasisBlade; c++) { int g = m_smv.ConstBasisBlade(c).Grade(); double absVal = Math.Abs(m_smv.ConstBasisBlade(c).scale); if (!largestConstCoord.ContainsKey(g)) { largestConstCoord[g] = absVal; } else if (absVal > largestConstCoord[g]) { largestConstCoord[g] = absVal; } } } // generate code to check if largest coord of grade > 'eps' foreach (KeyValuePair <int, double> kvp in largestConstCoord) { if (kvp.Value > 0.0) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if (" + FT.DoubleToString(m_specification, kvp.Value) + " > " + FAI[1].Name + ") bitmap |= " + (1 << kvp.Key) + ";")); } } // generate code to check all coordiantes String[] accessStr = G25.CG.Shared.CodeUtil.GetAccessStr(m_specification, m_smv, FAI[0].Name, FAI[0].Pointer); for (int i = 0; i < accessStr.Length; i++) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if ((" + accessStr[i] + " < -" + FAI[1].Name + ") || (" + accessStr[i] + " > " + FAI[1].Name + ")) bitmap |= " + (1 << m_smv.NonConstBasisBlade(i).Grade()) + ";")); } // finally, return 1 if all check were OK I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return bitmap;")); } // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, F, FAI); m_funcName[FT.type] = CF.OutputName; // setup return type and argument: string returnTypeName = G25.IntegerType.INTEGER; G25.CG.Shared.FuncArgInfo returnArgument = null; // write function bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, F, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment); } // end of WriteGradeBitmapFunction()
} // end of WriteGMVtoSMVcopy() /// <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, G25.FloatType FT, G25.SMV smv) { StringBuilder defSB = cgd.m_defSB; defSB.AppendLine(""); const string smvName = G25.CG.Shared.SmvUtil.THIS; const bool ptr = false; string fabsFunc = G25.CG.Shared.CodeUtil.OpNameToLangString(S, FT, RefGA.Symbolic.UnaryScalarOp.ABS); string[] AS = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, smvName, ptr); RefGA.BasisBlade maxBasisBlade = smv.AbsoluteLargestConstantBasisBlade(); //string className = FT.GetMangledName(S, smv.Name); for (int _returnBitmap = 0; _returnBitmap <= 1; _returnBitmap++) { bool returnBitmap = (_returnBitmap != 0); // write comment int nbTabs = 1; if (returnBitmap) { new G25.CG.Shared.Comment("Returns the absolute largest coordinate,\nand the corresponding basis blade bitmap.").Write(defSB, S, nbTabs); } else { new G25.CG.Shared.Comment("Returns the absolute largest coordinate.").Write(defSB, S, nbTabs); } string funcName = Util.GetFunctionName(S, ((returnBitmap) ? "largestBasisBlade" : "largestCoordinate")); string funcDecl; if ((S.OutputCSharp()) && returnBitmap) { funcDecl = FT.type + " " + funcName + "(int bm) "; } else if ((S.OutputJava()) && returnBitmap) { funcDecl = FT.type + "[] " + funcName + "() "; } else { funcDecl = FT.type + " " + funcName + "()"; } string FINAL = (S.OutputJava()) ? "final " : ""; defSB.Append("\tpublic " + FINAL + funcDecl); { defSB.AppendLine(" {"); if ((S.OutputJava()) && returnBitmap) { defSB.AppendLine("\t\tint bm;"); } int startIdx = 0; if (maxBasisBlade != null) { defSB.AppendLine("\t\t" + FT.type + " maxValue = " + FT.DoubleToString(S, Math.Abs(maxBasisBlade.scale)) + ";"); if (returnBitmap) { defSB.AppendLine("\t\tbm = " + maxBasisBlade.bitmap + ";"); } } else { defSB.AppendLine("\t\t" + FT.type + " maxValue = " + fabsFunc + "(" + AS[0] + ");"); if (returnBitmap) { defSB.AppendLine("\t\tbm = 0;"); } startIdx = 1; } for (int c = startIdx; c < smv.NbNonConstBasisBlade; c++) { defSB.Append("\t\tif (" + fabsFunc + "(" + AS[c] + ") > maxValue) { maxValue = " + fabsFunc + "(" + AS[c] + "); "); if (returnBitmap) { defSB.Append("bm = " + smv.NonConstBasisBlade(c).bitmap + "; "); } defSB.AppendLine("}"); } if ((S.OutputJava()) && returnBitmap) { defSB.AppendLine("\t\treturn new " + FT.type + "[]{maxValue, (" + FT.type + ")bm};"); } else { defSB.AppendLine("\t\treturn maxValue;"); } defSB.AppendLine("\t}"); } } } // end of WriteLargestCoordinateFunctions()
/// <summary> /// Writes the 'explicit' declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'. /// /// This function is called by the non-explicit version of the function. /// </summary> public void WriteExFunction(FloatType FT, string exFuncName) { G25.SMV smv = m_specification.GetSMV(m_SMVname); string randFuncCall = FT.DoubleToString(m_specification, -1.0) + " + " + FT.DoubleToString(m_specification, 2.0) + " * " + m_randomScalarFunc[FT.type] + "()"; // construct a explicit FGS string[] exArgumentTypeNames = new string[] { FT.type, FT.type, FT.type }; string[] exVariableNames = { m_fgs.ArgumentVariableNames[0], MINIMUM_NORM, LARGEST_COORDINATE }; fgs exFgs = new fgs(m_fgs.Name, m_fgs.OutputName, m_fgs.ReturnTypeName, exArgumentTypeNames, exVariableNames, m_fgs.FloatNames, m_fgs.MetricName, m_fgs.Comment, m_fgs.Options); exFgs.InitArgumentPtrFromTypeNames(m_specification); bool computeMultivectorValue = false; int nbArgs = 3; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, exFgs, nbArgs, FT, FT.type, computeMultivectorValue); // because of lack of overloading, function names include names of argument types //G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, exFgs, FAI); G25.fgs CF = new G25.fgs(exFgs, exFuncName); //string exFuncName = funcName; // setup code to recursively call exFuncName string exFuncCall = ""; { StringBuilder exFuncCallSB = new StringBuilder(); if (!m_specification.OutputC()) { exFuncCallSB.Append("return "); } exFuncCallSB.Append(exFuncName); exFuncCallSB.Append("("); if (m_specification.OutputC()) { exFuncCallSB.Append(fgs.RETURN_ARG_NAME); exFuncCallSB.Append(", "); } for (int i = 0; i < exVariableNames.Length; i++) { if (i > 0) { exFuncCallSB.Append(", "); } exFuncCallSB.Append(exVariableNames[i]); } exFuncCallSB.AppendLine(");"); if (m_specification.OutputC()) { exFuncCallSB.AppendLine("return;"); } exFuncCall = exFuncCallSB.ToString(); } // generate a random SMV: RefGA.Multivector randomSMV = null; // get highest grade and bitmap of int hg = smv.HighestGrade(); // what is the highest non-zero grade of the type? uint bvBitmap = smv.BasisVectorBitmap(); // which basis vectors are used in the type? // setup random value to be returned if (InitWithRandomCoordinates(m_specification, smv)) { // set all coordinates to random values randomSMV = RefGA.Multivector.ZERO; for (int b = 0; b < smv.NbNonConstBasisBlade; b++) { randomSMV = RefGA.Multivector.Add(randomSMV, RefGA.Multivector.gp(new RefGA.Multivector(smv.NonConstBasisBlade(b)), new RefGA.Multivector("r" + smv.NonConstBasisBlade(b).ToLangString(m_specification.m_basisVectorNames)))); } } else { // set to geometric product of random vectors randomSMV = RefGA.Multivector.ONE; RefGA.Multivector randomVector; RefGA.BasisBlade[] B = new RefGA.BasisBlade[(int)RefGA.Bits.BitCount(bvBitmap)]; for (int g = 0; g < hg; g++) { int cnt = 0; for (int v = 0; v < m_specification.m_dimension; v++) { if ((bvBitmap & (uint)(1 << v)) != 0) { B[cnt] = new RefGA.BasisBlade((uint)(1 << v), 1.0, "r" + g + "_" + m_specification.m_basisVectorNames[v]); cnt++; } } randomVector = new RefGA.Multivector(B); randomSMV = RefGA.Multivector.gp(randomSMV, randomVector, m_G25M.m_metric); } // round value if required by metric if (m_G25M.m_round) { randomSMV = randomSMV.Round(1e-14); } } // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); { int nbTabs = 1; if (!smv.IsConstant()) { string smvTypeName = FT.GetMangledName(m_specification, m_SMVname); // SMV tmp; // double n, mul, lc; if (m_specification.OutputCppOrC()) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, smvTypeName + " tmp;")); } else { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, smvTypeName + " tmp = new " + smvTypeName + "();")); } I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " n, mul, lc;")); I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, CodeUtil.GetBoolType(m_specification) + " nullBlade;")); // double rCoord = randomValue(), ....; StringBuilder randSB = new StringBuilder(); randSB.Append(FT.type); randSB.Append(" "); if (InitWithRandomCoordinates(m_specification, smv)) { // random coordinates for (int b = 0; b < smv.NbNonConstBasisBlade; b++) { if (b > 0) { randSB.Append(", "); } randSB.Append("r" + smv.NonConstBasisBlade(b).ToLangString(m_specification.m_basisVectorNames)); randSB.Append(" = "); randSB.Append(randFuncCall); } } else { // random vectors bool first = true; for (int g = 0; g < hg; g++) { for (int v = 0; v < m_specification.m_dimension; v++) { if (!first) { randSB.Append(", "); } first = false; if ((g > 0) && (v == 0)) { randSB.AppendLine(""); // newline randSB.Append("\t\t"); } randSB.Append("r" + g + "_" + m_specification.m_basisVectorNames[v]); randSB.Append(" = "); randSB.Append(randFuncCall); } } } randSB.Append(";"); I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, randSB.ToString())); // SMV tmp = random; bool mustCast = false; bool randomPtr = false; bool declareRandom = false; I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smv, FT, mustCast, randomSMV, "tmp", randomPtr, declareRandom)); // n = norm_ret_scalar(tmp); string emp = (m_specification.OutputC()) ? "&" : ""; I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "n = " + m_normFunc[FT.type] + "(" + emp + "tmp);")); // lc = largestCoordinate(tmp); if (m_specification.OutputC()) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "lc = " + smvTypeName + "_largestCoordinate(&tmp);")); } else { string lcStr = "largestCoordinate"; if (m_specification.OutputCSharp()) { lcStr = "LargestCoordinate"; } I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "lc = tmp." + lcStr + "();")); } // null = (n == 0) && (lc ! 0) if ((m_smvType.MvType == SMV.MULTIVECTOR_TYPE.ROTOR) || (m_smvType.MvType == SMV.MULTIVECTOR_TYPE.VERSOR)) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "nullBlade = " + (m_specification.OutputC() ? "0" : "false") + ";")); } else { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "nullBlade = ((n == " + FT.DoubleToString(m_specification, 0.0) + ") && (lc != " + FT.DoubleToString(m_specification, 0.0) + "));")); } // test minimumNorm I.Add(new CommentInstruction(nbTabs, "Recurse if generated random value has a norm below user-supplied limit, unless this is a null blade")); I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, "(n < " + exVariableNames[1] + ") && (!nullBlade)", new List <Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, exFuncCall) }, // if instructions new List <Instruction>())); // else instructions // compute multiplier string lcCondition = "(lc * " + CodeUtil.OpNameToLangString(m_specification, FT, "abs") + "(mul)) > largestCoordinate "; I.Add(new CommentInstruction(nbTabs, "Compute multiplier")); I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, "n < " + FT.DoubleToString(m_specification, 0.0001), new List <Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, "mul = " + FT.DoubleToString(m_specification, 1.0) + ";") }, // if instructions new List <Instruction>() // else instructions { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, "mul = " + exFgs.ArgumentVariableNames[0] + " * (" + randFuncCall + ") / n;"), new CommentInstruction(nbTabs + 1, "Test largest coordinate"), new G25.CG.Shared.IfElseInstruction(nbTabs + 1, lcCondition, new List <Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 2, exFuncCall) }, // if instructions new List <Instruction>()) })); // test largest coordinate //I.Add(new CommentInstruction(nbTabs, "Test largest coordinate")); //I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, lcCondition, // new List<Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, exFuncCall) }, // if instructions // new List<Instruction>())); // else instructions // return tmp*mul; I.Add(new CommentInstruction(nbTabs, "Apply multiplier, return")); RefGA.Multivector tmpValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(m_specification, smv, "tmp", false); RefGA.Multivector returnValue = RefGA.Multivector.gp(tmpValue, new RefGA.Multivector("mul")); I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, smv, FT, mustCast, returnValue)); } // end of '!IsConstant()'? else { // the user wants a 'random' constant: simply return the constant itself. RefGA.Multivector returnValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(m_specification, smv, "tmp", false); bool mustCast = false; I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, smv, FT, mustCast, returnValue)); } } // because of lack of overloading, function names include names of argument types //G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, exFgs, FAI); // generate comment Comment comment = new Comment(exFgs.AddUserComment("Returns random " + m_SMVname + " with a scale in the interval [0, scale)")); bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, exFuncName, FAI, I, comment); } // end of WriteExFunction
/// <summary> /// Writes the definition of an SMV 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">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteSMVstruct(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { SB.AppendLine(""); { // comments for type: SB.AppendLine("/**"); SB.AppendLine(" * This struct can hold a specialized multivector of type " + FT.GetMangledName(S, smv.Name) + "."); SB.AppendLine(" * "); SB.AppendLine(" * The coordinates are stored in type " + FT.type + "."); SB.AppendLine(" * "); if (smv.NbNonConstBasisBlade > 0) { SB.AppendLine(" * The variable non-zero coordinates are:"); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine(" * - coordinate " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " (array index: " + GetCoordIndexDefine(S, smv, i) + " = " + i + ")"); } } else { SB.AppendLine(" * The type is constant."); } SB.AppendLine(" * "); if (smv.NbConstBasisBlade > 0) { SB.AppendLine(" * The constant non-zero coordinates are:"); for (int i = 0; i < smv.NbConstBasisBlade; i++) { SB.AppendLine(" * - " + smv.ConstBasisBlade(i).ToString(S.m_basisVectorNames) + " = " + smv.ConstBasisBladeValue(i).ToString()); } } else { SB.AppendLine(" * The type has no constant coordinates."); } SB.AppendLine(" * "); if ((smv.Comment != null) && (smv.Comment.Length > 0)) { SB.AppendLine(" * "); SB.AppendLine(" * " + smv.Comment); } SB.AppendLine(" */"); } // typedef SB.AppendLine("typedef struct "); SB.AppendLine("{"); // individual coordinates or one array? if (smv.NbNonConstBasisBlade > 0) { if (S.m_coordStorage == COORD_STORAGE.VARIABLES) { // emit float e1; float e2; float e3; for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.AppendLine("\t/** The " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate. */"); SB.AppendLine("\t" + FT.type + " " + smv.GetCoordLangID(i, S) + ";"); //G25.CG.Shared.Util.BasisBladeToLangString(smv.NonConstBasisBlade(i), S.m_basisVectorNames) + ";"); } } else { // emit: float c[3]; // e1, e2, e3 SB.AppendLine("\t/** The coordinates (stored in an array). */"); SB.Append("\t" + FT.type + " c[" + smv.NbNonConstBasisBlade + "]; /* "); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { if (i > 0) { SB.Append(", "); } SB.Append(smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames)); } SB.AppendLine("*/"); } } else { SB.AppendLine("\t/** Filler, because C does not allow empty structs. */"); SB.AppendLine("\tint filler;"); } // emit: // no=1 for (int i = 0; i < smv.NbConstBasisBlade; i++) { SB.AppendLine("\t/* " + smv.ConstBasisBlade(i).ToString(S.m_basisVectorNames) + " = " + smv.ConstBasisBladeValue(i).ToString() + "*/"); } SB.AppendLine("} " + FT.GetMangledName(S, smv.Name) + ";"); }