/// <summary> /// Returns the comment for a GMV class. /// </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> /// <param name="FT">Float point type of 'GMV'.</param> /// <param name="gmv">The general multivector for which the class should be written.</param> public static Comment GetGmvComment(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GMV gmv) { StringBuilder SB = new StringBuilder(); SB.AppendLine("This class can hold a general multivector."); SB.AppendLine(""); SB.AppendLine("The coordinates are stored in type " + FT.type + "."); SB.AppendLine(""); SB.AppendLine("There are " + gmv.NbGroups + " coordinate groups:"); for (int g = 0; g < gmv.NbGroups; g++) { SB.Append("group " + g + ":"); for (int i = 0; i < gmv.Group(g).Length; i++) { if (i > 0) SB.Append(", "); SB.Append(gmv.Group(g)[i].ToString(S.m_basisVectorNames)); } if (gmv.Group(g).Length > 0) SB.Append(" (grade " + gmv.Group(g)[0].Grade() + ")"); SB.AppendLine("."); } SB.AppendLine(""); switch (S.m_GMV.MemoryAllocationMethod) { case G25.GMV.MEM_ALLOC_METHOD.PARITY_PURE: SB.AppendLine("" + (gmv.NbCoordinates / 2) + " " + FT.type + "s are allocated inside the struct ('parity pure')."); SB.AppendLine("Hence creating a multivector which needs more than that number of coordinates "); SB.AppendLine("will result in unpredictable behaviour (buffer overflow)."); break; case G25.GMV.MEM_ALLOC_METHOD.FULL: SB.AppendLine("" + gmv.NbCoordinates + " " + FT.type + "s are allocated inside the struct."); break; } return new Comment(SB.ToString()); }
/// <summary> /// Takes a general multivector specification (G25.GMV) and converts it into a one symbolic multivector per group/grade part. /// /// The symbolic weights of the multivector are the coordinates of the GMV, labelled according to 'gmvName'. /// Currently, the indices start at zero for each group. /// </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="gmv">The specification of the general multivector.</param> /// <param name="gmvName">Name the variable should have.</param> /// <param name="ptr">Is 'gmvName' a pointer? (not used currently)</param> /// <param name="groupIdx">Index of group/grade to convert (use -1 for all groups)</param> /// <returns></returns> public static RefGA.Multivector[] GMVtoSymbolicMultivector(Specification S, G25.GMV gmv, String gmvName, bool ptr, int groupIdx) { RefGA.Multivector[] R = new RefGA.Multivector[gmv.NbGroups]; //String accessStr = (ptr) ? "->" : "."; for (int g = 0; g < gmv.NbGroups; g++) { if ((groupIdx >= 0) && (g != groupIdx)) continue; // only one group requested? RefGA.BasisBlade[] B = gmv.Group(g); RefGA.BasisBlade[] L = new RefGA.BasisBlade[B.Length]; for (int i = 0; i < B.Length; i++) { RefGA.BasisBlade b = B[i]; String fullCoordName = gmvName + "[" + i + "]"; // merge L[i] = new RefGA.BasisBlade(b.bitmap, b.scale, fullCoordName); } R[g] = new RefGA.Multivector(L); } return R; }
/// <summary> /// Writes the definition of an GMV 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 'SMV'.</param> /// <param name="gmv">The general multivector for which the struct should be written.</param> public static void WriteGMVstruct(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GMV gmv) { SB.AppendLine(""); { // comments for type: SB.AppendLine("/**"); SB.AppendLine(" * This struct can hold a general multivector."); SB.AppendLine(" * "); SB.AppendLine(" * The coordinates are stored in type " + FT.type + "."); SB.AppendLine(" * "); SB.AppendLine(" * There are " + gmv.NbGroups + " coordinate groups:"); for (int g = 0; g < gmv.NbGroups; g++) { SB.Append(" * group " + g + ":"); for (int i = 0; i < gmv.Group(g).Length; i++) { if (i > 0) SB.Append(", "); SB.Append(gmv.Group(g)[i].ToString(S.m_basisVectorNames)); } if (gmv.Group(g).Length > 0) SB.Append(" (grade " + gmv.Group(g)[0].Grade() + ")"); SB.AppendLine("."); } SB.AppendLine(" * "); switch (S.m_GMV.MemoryAllocationMethod) { case G25.GMV.MEM_ALLOC_METHOD.PARITY_PURE: SB.AppendLine(" * " + (gmv.NbCoordinates / 2) + " " + FT.type + "s are allocated inside the struct ('parity pure')."); SB.AppendLine(" * Hence creating a multivector which needs more than that number of coordinates "); SB.AppendLine(" * will result in unpredictable behaviour (buffer overflow)."); break; case G25.GMV.MEM_ALLOC_METHOD.FULL: SB.AppendLine(" * " + gmv.NbCoordinates + " " + FT.type + "s are allocated inside the struct."); break; } SB.AppendLine(" */"); } // end of comment // typedef SB.AppendLine("typedef struct "); SB.AppendLine("{"); // group/grade usage SB.AppendLine("\t/** group/grade usage (a bitmap which specifies which groups/grades are stored in 'c', below). */"); SB.AppendLine("\tint gu;"); // coordinates switch (S.m_GMV.MemoryAllocationMethod) { // case G25.GMV.MEM_ALLOC_METHOD.DYNAMIC: // SB.AppendLine("\t" + FT.type + " *c; ///< the coordinates (array is allocated using realloc())"); // break; case G25.GMV.MEM_ALLOC_METHOD.PARITY_PURE: SB.AppendLine("\t/** The coordinates (note: parity pure). */"); SB.AppendLine("\t" + FT.type + " c[" + (gmv.NbCoordinates / 2) + "];"); break; case G25.GMV.MEM_ALLOC_METHOD.FULL: SB.AppendLine("\t/** The coordinates (full). */"); SB.AppendLine("\t" + FT.type + " c[" + (gmv.NbCoordinates) + "];"); break; } // If we report non-optimized function usage, we need to know original type of GMVs: if (S.m_reportUsage) { SB.AppendLine("\t/** Specialized multivector type. Used to report about non-optimized function usage. */"); SB.AppendLine("\tint t;"); } SB.AppendLine("} " + FT.GetMangledName(S, gmv.Name) + ";"); }
/// <returns>Whether to negate group 'groupIdx' for sign toggle operation 'T'.</returns> private static bool NeedToNegate(G25.GMV gmv, int groupIdx, UnaryToggleSignType T) { switch (T) { case UnaryToggleSignType.NEGATE: return true; case UnaryToggleSignType.REVERSE: return (gmv.Group(groupIdx)[0].Reverse().scale / gmv.Group(groupIdx)[0].scale) < 0; case UnaryToggleSignType.GRADE_INVOLUTION: return (gmv.Group(groupIdx)[0].GradeInvolution().scale / gmv.Group(groupIdx)[0].scale) < 0; case UnaryToggleSignType.CLIFFORD_CONJUGATE: return (gmv.Group(groupIdx)[0].CliffordConjugate().scale / gmv.Group(groupIdx)[0].scale) < 0; default: return false; } }
/// <summary> /// Returns an array of 'access strings' for a specific group of the general multivector. /// Access strings are source code expressions that can be /// used to access the coordinates of one specific group of coordinates of <c>gmv</c>. /// </summary> /// <param name="S">Used for basis blade names, language, COORD_STORAGE , etc.</param> /// <param name="gmv">The specialized multivector for which access strings are generated.</param> /// <param name="gmvName">The variable name of the _array_ of float to be used in the access strings. /// For example, specify <c>"A"</c> to get <c>"A[0]"</c> and so on.</param> /// <param name="groupIdx">Specifies for that group index the access strings should be generated.</param> /// <param name="baseIdx">Index of first coordinate of group (required for C# and Java)</param> /// <returns>Array of strings that can be used to access the coordinates of group <c>groupIdx</c> of the <c>gmv</c>.</returns> public static string[] GetAccessStr(Specification S, G25.GMV gmv, String gmvName, int groupIdx, int baseIdx) { string[] AL = new String[gmv.Group(groupIdx).Length]; for (int i = 0; i < gmv.Group(groupIdx).Length; i++) AL[i] = gmvName + "[" + (baseIdx + i) + "]"; return AL; }
/// <summary> /// Generates the code to assign a multivector value (which may have symbolic coordinates) to one specific coordinate group of a multivector. /// </summary> /// <param name="S">Specification of algebra. Used to known names of basis vector, output language, access strings, etc.</param> /// <param name="FT">Floating point type of destination.</param> /// <param name="mustCast">set to true if a cast to 'FT' must be performed before assigned to 'dstName'.</param> /// <param name="dstGmv">Type of general multivector assigned to.</param> /// <param name="dstName">Name of specialized multivector assigned to.</param> /// <param name="dstGroupIdx">Write to which group in destination type?</param> /// <param name="dstBaseIdx">Base index of coordinate 0 of group (needed for C# and Java)</param> /// <param name="value">Multivector value to assign to the GMV. Must not contain basis blades inside the symbolic scalars.</param> /// <param name="nbTabs">Number of tabs to put before the code.</param> /// <param name="writeZeros">Some callers want to skip "= 0.0" assignments because they would be redundant. So they set this argument to true.</param> /// <returns>String of code for dstName = value;</returns> public static string GenerateGMVassignmentCode(Specification S, FloatType FT, bool mustCast, G25.GMV dstGmv, string dstName, int dstGroupIdx, int dstBaseIdx, RefGA.Multivector value, int nbTabs, bool writeZeros) { RefGA.BasisBlade[] BL = dstGmv.Group(dstGroupIdx); string[] accessStr = GetAccessStr(S, dstGmv, dstName, dstGroupIdx, dstBaseIdx); string[] assignedStr = GetAssignmentStrings(S, FT, mustCast, BL, value, writeZeros); return GenerateAssignmentCode(S, accessStr, assignedStr, nbTabs, writeZeros); }
/// <summary> /// Converts a G25.SMV to an XML string representation. /// </summary> /// <param name="S"></param> /// <param name="smv"></param> /// <returns>XML string representation of 'smv'.</returns> public static string SMVtoXmlString(Specification S, G25.SMV smv) { StringBuilder SB = new StringBuilder(); bool constant = smv.IsConstant() && (S.GetMatchingConstant(smv) != null); string name = smv.Name; // remove the extra constant suffix? if (constant && name.EndsWith(Specification.CONSTANT_TYPE_SUFFIX)) name = name.Substring(0, name.Length - Specification.CONSTANT_TYPE_SUFFIX.Length); SB.Append("<" + XML_SMV); // name SB.Append(" " + XML_NAME + "=\"" + name + "\""); // constant? if (constant) SB.Append(" " + XML_CONST + "=\"" + XML_TRUE + "\""); // type SB.Append(" " + XML_TYPE + "=\"" + smv.MvTypeString + "\""); // end of XML_SMV tag SB.Append(">"); { // emit coordinate order: string[] bvNames = (string[])S.m_basisVectorNames.ToArray(); // loop over all basis blades for (int b = 0; b < smv.Group(0).Length; b++) { if (b > 0) SB.Append(" "); string bbStr = BasisBladeToString(smv.BasisBlade(0, b), bvNames); SB.Append(bbStr); // if constant, add '=....' if (smv.IsCoordinateConstant(b)) SB.Append("=" + smv.ConstBasisBladeValue(smv.BladeIdxToConstBladeIdx(b)).ToString()); } if (smv.Comment.Length > 0) SB.Append(" <" + XML_COMMENT + ">" + smv.Comment + "</" + XML_COMMENT + ">"); } SB.Append("</" + XML_SMV + ">\n"); return SB.ToString(); }