} // end of ComputeOmInitFromVectorsPlan() /// <summary> /// Computes the signs for the plan as computed by GetOmInitFromVectorsPlan(). /// /// Because the basis blades in the domain of 'om' do not have to be in canonical order, /// there may be some signs required to correctly executed the plan /// </summary> /// <param name="S"></param> /// <param name="om"></param> /// <param name="plan"></param> /// <returns>signs for the plan</returns> public static double[][] ComputeOmInitFromVectorsSigns(Specification S, OM om, uint[][][] plan) { double[][] result = new double[S.m_dimension + 1][]; for (int g = 1; g <= S.m_dimension; g++) { result[g] = new double[om.DomainForGrade(g).Length]; for (int d = 0; d < om.DomainForGrade(g).Length; d++) { // get domain blade we have to construct RefGA.BasisBlade D = om.DomainForGrade(g)[d]; // follow the plan to construct the blade RefGA.BasisBlade P = RefGA.BasisBlade.ONE; for (int p = 0; p < plan[g][d].Length; p++) { G25.Tuple <RefGA.BasisBlade, int, int> info = GetDomainBladeInfo(S, om, plan[g][d][p]); P = RefGA.BasisBlade.op(P, info.Value1); } // compute sign difference & store double s = D.scale / P.scale; result[g][d] = s; } } return(result); } // end of ComputeOmInitFromVectorsSigns()
/// <summary> /// Returns a dictionary (value -> coordinateAccessString) that can be used to initialize a general OM to identity. /// /// Use the dictionary as follows: foreach(string str in dictionary.value) generateCode{str = dictionary.key} /// </summary> public static Dictionary <double, List <string> > GetGomIdentityInitCode(Specification S, G25.GOM gom, string gomName, string matrixName) { Dictionary <double, List <string> > nonZero = new Dictionary <double, List <string> >(); // collect a.m[...] = value in here, by value string refStr = (S.OutputC()) ? gomName + "->" : ""; // figure out which elements need to get something assigned // for all blades in the domain, find matching blade in range, and add it to nonZero for (int g = 1; g < S.m_GOM.Domain.Length; g++) { for (int d = 0; d < S.m_GOM.Domain[g].Length; d++) { RefGA.BasisBlade D = S.m_GOM.Domain[g][d]; for (int r = 0; r < S.m_GOM.Range[g].Length; r++) { RefGA.BasisBlade R = S.m_GOM.Domain[g][r]; if (D.bitmap == R.bitmap) { double val = D.scale / R.scale; string coordStr = refStr + matrixName + g + "[" + (r * S.m_GOM.Domain[g].Length + d) + "]"; if (!nonZero.ContainsKey(val)) { nonZero[val] = new List <string>(); } nonZero[val].Add(coordStr); continue; // no need to search other blades in range } } } } // end of loop over all grades of the OM return(nonZero); }
/// <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); } // end of function GMVtoSymbolicMultivector()
public static G25.VariableType CreateSyntheticSMVtype(Specification S, CGdata cgd, FloatType FT, RefGA.Multivector value) { // make up list of basis blades rsbbp.BasisBlade[] L = new rsbbp.BasisBlade[value.BasisBlades.Length]; for (int i = 0; i < value.BasisBlades.Length; i++) { RefGA.BasisBlade B = value.BasisBlades[i]; if (B.symScale == null) { L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap), B.scale); // constant value } else { L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap)); // non-const value } } // get other required info String name = "nameOfType"; SMV.MULTIVECTOR_TYPE mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR; String comment = "MISSING; PLEASE ADD TO SPECIFICATION"; //String constantName = null; // create the type G25.SMV synSMV = new G25.SMV(name, L, mvType, comment); // throw exception throw new G25.UserException("Missing specialized multivector type.\n" + "Please add the following XML to the specification to fix the dependency:\n" + XML.SMVtoXmlString(S, synSMV)); }
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("};"); }
/// <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 ComputeOmInitFromVectorsSigns() /// <summary> /// Returns info about <c>bitmap</c>. /// /// If bitmap is not in the domain of <c>om</c>, the basis blade in the returned value will be null, /// and the domainIdx will be -1. /// /// If the grade of the bitmap is 1, the domainIdx will be -1 because it is /// assumed to be an input vector. /// </summary> /// <param name="S"></param> /// <param name="om"></param> /// <param name="bitmap"></param> /// <returns><c>BasisBlade, grade, domainIdx</c> for <c>bitmap</c></returns> public static G25.Tuple <RefGA.BasisBlade, int, int> GetDomainBladeInfo(Specification S, OM om, uint bitmap) { int grade = (int)RefGA.Bits.BitCount(bitmap); if (grade == 1) // basis vector { return(new G25.Tuple <RefGA.BasisBlade, int, int>(new RefGA.BasisBlade(bitmap), grade, -1)); } // find the bitmap in the domain RefGA.BasisBlade B = null; int domainIdx = -1; for (int i = 0; i < om.DomainForGrade(grade).Length; i++) { if (bitmap == om.DomainForGrade(grade)[i].bitmap) { domainIdx = i; B = om.DomainForGrade(grade)[i]; break; } } return(new G25.Tuple <RefGA.BasisBlade, int, int>(B, grade, domainIdx)); } // end of GetDomainBladeInfo()
} // end of WriteSet() /// <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) { 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 + "_setArray"; bool mustCast = false; string[] argTypename = new string[1] { FT.type }; string[] argName = new string[1] { "A" }; System.Collections.ArrayList L = new System.Collections.ArrayList(); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(i); //argTypename[i] = FT.type; String coordStr = argName[0] + "[" + i + "]"; //argName[i] = 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); F.SetArgumentPtr(0, true); // first argument is a pointer to array bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue); int nbArgs = 1; // one array of coordinates G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, null, computeMultivectorValue); declSB.AppendLine("/** Sets " + typeName + " to specified coordinates */"); bool staticFunc = false; G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, mvValue); } } } // end of WriteSetArray()
} // end of WriteLargestCoordinateFunctions() /// <summary> /// Writes code to extract the scalar part of an SMV via a non-member function. /// </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 WriteExtractScalarPart(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 = false; RefGA.BasisBlade scalarBlade = RefGA.BasisBlade.ONE; string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineFunctions, " "); foreach (G25.FloatType FT in S.m_floatTypes) { foreach (G25.SMV smv in S.m_SMV) { string[] AS = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, smvName, ptr); string className = FT.GetMangledName(S, smv.Name); string funcName = "_" + FT.type; string altFuncName = "_Float"; string comment = "/// Returns scalar part of " + className; declSB.AppendLine(comment); string funcDecl = FT.type + " " + funcName + "(const " + className + " &" + smvName + ")"; declSB.Append(funcDecl); declSB.AppendLine(";"); declSB.AppendLine(comment); string altFuncDecl = FT.type + " " + altFuncName + "(const " + className + " &" + smvName + ")"; declSB.Append(G25.CG.Shared.Util.GetInlineString(S, true, " ") + altFuncDecl + " {return " + funcName + "(" + smvName + "); }"); declSB.AppendLine(";"); defSB.Append(inlineStr + funcDecl); { defSB.AppendLine(" {"); int elementIdx = smv.GetElementIdx(scalarBlade); double multiplier = (elementIdx >= 0) ? 1.0 / smv.BasisBlade(0, elementIdx).scale : 1.0; if ((elementIdx >= 0) && (!smv.IsCoordinateConstant(elementIdx))) { string multiplerString = (multiplier != 1.0) ? (FT.DoubleToString(S, multiplier) + " * ") : ""; defSB.AppendLine("\treturn " + multiplerString + AS[smv.BladeIdxToNonConstBladeIdx(elementIdx)] + ";"); } else { double constValue = (elementIdx >= 0) ? smv.ConstBasisBladeValue(smv.BladeIdxToConstBladeIdx(elementIdx)) : 0.0; defSB.AppendLine("\treturn " + FT.DoubleToString(S, multiplier * constValue) + ";"); } defSB.AppendLine("}"); } } // end of loop over all smvs } // end of loop over all float types } // end of WriteExtractScalarPart()
/// <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; }
/// <returns>'L' convert to a double array</returns> public static RefGA.BasisBlade[][] ListToDoubleArray(List <List <RefGA.BasisBlade> > L) { RefGA.BasisBlade[][] A = new RefGA.BasisBlade[L.Count][]; for (int i = 0; i < L.Count; i++) { A[i] = L[i].ToArray(); } return(A); }
/// <summary> /// Writes code for m_name = m_value. /// </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.SMV) { G25.SMV dstSmv = m_type as G25.SMV; if (m_declareVariable) { SB.AppendLine("/* cannot yet assign and declare SMV type at the same time */"); } RefGA.BasisBlade[] BL = BasisBlade.GetNonConstBladeList(dstSmv); string[] accessStr = CodeUtil.GetAccessStr(S, dstSmv, m_name, m_ptr); 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.GenerateAssignmentCode(S, accessStr, valueStr, m_nbTabs, writeZeros)); } else if (m_type is G25.FloatType) { // temp hack to override float type. G25.FloatType FT = this.m_floatType; // m_type as G25.FloatType; AppendTabs(SB); if (m_declareVariable) { // also declare the variable right here? // output "/t type " SB.Append(FT.type + " "); } // output name = ....; RefGA.BasisBlade[] BL = new RefGA.BasisBlade[1] { RefGA.BasisBlade.ONE }; String[] accessStr = new String[1] { m_name }; bool writeZeros = true; String[] valueStr = CodeUtil.GetAssignmentStrings(S, FT, m_mustCast, BL, m_value, writeZeros); // apply post operation (like "/ n2") ApplyPostOp(S, cgd, BL, valueStr); SB.AppendLine(CodeUtil.GenerateAssignmentCode(S, accessStr, valueStr, 0, writeZeros)); } else { SB.AppendLine("/* to do: implement " + GetType().ToString() + " for type " + m_type.GetType().ToString() + " */"); } }
} // 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;}"); } }
} // end of WriteSet() /// <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) { 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[] 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.SetArgumentPtr(1, true); // second argument is a pointer to 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 = true; 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 struct 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) { 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; 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 returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue); 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 = true; 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 WriteSet()
/// <returns>'L' convert to a double array</returns> public static RefGA.BasisBlade[][] ListToDoubleArray(List <List <G25.rsbbp.BasisBlade> > L) { RefGA.BasisBlade[][] A = new RefGA.BasisBlade[L.Count][]; for (int i = 0; i < L.Count; i++) { A[i] = new RefGA.BasisBlade[L[i].Count]; for (int j = 0; j < L[i].Count; j++) { A[i][j] = L[i][j].GetBasisBlade; } } return(A); }
} // end of WriteLargestCoordinateFunctions() /// <summary> /// Writes code to extract the scalar part of an SMV via a non-member function. /// </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 WriteExtractScalarPart(Specification S, G25.CG.Shared.CGdata cgd) { G25.GMV gmv = S.m_GMV; StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineFunctions) ? cgd.m_inlineDefSB : cgd.m_defSB; declSB.AppendLine(""); defSB.AppendLine(""); const string gmvName = "x"; RefGA.BasisBlade scalarBlade = RefGA.BasisBlade.ONE; string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineFunctions, " "); foreach (G25.FloatType FT in S.m_floatTypes) { string className = FT.GetMangledName(S, gmv.Name); string funcName = "_" + FT.type; string altFuncName = "_Float"; string comment = "/// Returns scalar part of " + className; declSB.AppendLine(comment); string funcDecl = FT.type + " " + funcName + "(const " + className + " &" + gmvName + ")"; declSB.Append(funcDecl); declSB.AppendLine(";"); declSB.AppendLine(comment); string altFuncDecl = FT.type + " " + altFuncName + "(const " + className + " &" + gmvName + ")"; declSB.Append(G25.CG.Shared.Util.GetInlineString(S, true, " ") + altFuncDecl + " {return " + funcName + "(" + gmvName + "); }"); declSB.AppendLine(";"); defSB.Append(inlineStr + funcDecl); { defSB.AppendLine(" {"); int elementIdx = gmv.GetElementIdx(scalarBlade); double multiplier = 1.0 / gmv.BasisBlade(0, elementIdx).scale; string multiplerString = (multiplier != 1.0) ? (FT.DoubleToString(S, multiplier) + " * ") : ""; // this line assumes that the scalar is the first element of the first group (which is a requirement). defSB.AppendLine("\treturn ((x.gu() & 1) != 0) ? " + multiplerString + "x.getC()[0] : " + FT.DoubleToString(S, 0.0) + ";"); defSB.AppendLine("}"); } } // end of loop over all float types } // end of WriteExtractScalarPart()
} // end of WriteSetZero() /// <summary> /// Writes a function to set an SMV struct to a scalar coordinate, for all floating point types which have a non-constant scalar coordinate. /// </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 WriteSetScalar(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; if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { continue; // if no scalar coordinate, continue } string typeName = FT.GetMangledName(S, smv.Name); string funcName = typeName + "_setScalar"; bool mustCast = false; System.Collections.ArrayList L = new System.Collections.ArrayList(); const int NB_COORDS = 1; string[] argTypename = new string[NB_COORDS]; string[] argName = new string[NB_COORDS]; { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; argTypename[0] = FT.type; argName[0] = "scalarVal"; L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, argName[0])); } 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 = 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); G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_COORDS, FT, null, computeMultivectorValue); declSB.AppendLine("/** Sets " + typeName + " to a scalar value */"); bool staticFunc = false; G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, mvValue); } } }
} // end of WriteLargestCoordinateFunctions() /// <summary> /// Writes code to extract the scalar part of an SMV /// </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 WriteExtractScalarPart(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; RefGA.BasisBlade scalarBlade = new RefGA.BasisBlade(1.0); foreach (G25.FloatType FT in S.m_floatTypes) { foreach (G25.SMV smv in S.m_SMV) { String[] AS = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, smvName, ptr); String typeName = FT.GetMangledName(S, smv.Name); String funcName = typeName + "_" + FT.type; declSB.AppendLine("/** Returns scalar part of " + typeName + " */"); String funcDecl = FT.type + " " + funcName + "(const " + typeName + " *" + smvName + ")"; declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.Append(funcDecl); { defSB.AppendLine(" {"); int scalarCoordIdx = smv.GetElementIdx(scalarBlade); if (scalarCoordIdx >= 0) { double multiplier = 1.0 / smv.BasisBlade(0, scalarCoordIdx).scale; string multiplerString = (multiplier != 1.0) ? (FT.DoubleToString(S, multiplier) + " * "): ""; defSB.AppendLine("\treturn " + multiplerString + AS[scalarCoordIdx] + ";"); } else { defSB.AppendLine("\treturn " + FT.DoubleToString(S, 0.0) + ";"); } defSB.AppendLine("}"); } } // end of loop over all smvs } // end of loop over all float types } // end of WriteExtractScalarPart()
public static void GenerateBasisElementsArray(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { string accessModifierArr = Keywords.ConstArrayAccessModifier(S); G25.GMV gmv = S.m_GMV; // basis vectors in basis elements new G25.CG.Shared.Comment("This array of integers contains the order of basis elements in the general multivector.\n" + "Use it to answer: 'what basis vectors are in the basis element at position [x]?").Write(SB, S, 1); SB.Append("\tpublic " + accessModifierArr + " int[][] BasisElements = "); if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND) { SB.AppendLine("new int[][] {"); { 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\tnew int[] {"); 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("\t};"); } else { SB.AppendLine(G25.CG.CSJ.Util.GetFunctionName(S, "initBasisElementsArray") + "();"); SB.AppendLine(); cgd.m_cog.EmitTemplate(SB, "initBasisElementsArray", "S=", S); } }
/// <summary> /// 'Plans' how to initialize an outermorphism from vector images. /// /// The plan is returned in the form of nested array <c>uint[grade][domain][plan steps]</c>. /// The <c>plan steps</c> are the bitmaps of the basis blades that should be wedged together /// to form the basis blade for <c>grade,domain</c>. /// </summary> /// <param name="S"></param> /// <param name="om"></param> /// <returns>plan for initialization of <c>om</c> from vector images.</returns> public static uint[][][] ComputeOmInitFromVectorsPlan(Specification S, OM om) { // keep track of which basis blades are available (domain vectors are the input, so they are always available) bool[] availableBasisBlades = new bool[1 << S.m_dimension]; for (int i = 0; i < om.DomainVectors.Length; i++) { availableBasisBlades[om.DomainVectors[i].bitmap] = true; } // for each grade, figure out how to construct the basis blades of that grade from basis blades which are already available uint[][][] result = new uint[S.m_dimension + 1][][]; for (int g = 1; g <= S.m_dimension; g++) { result[g] = new uint[om.DomainForGrade(g).Length][]; for (int d = 0; d < om.DomainForGrade(g).Length; d++) { RefGA.BasisBlade D = om.DomainForGrade(g)[d]; // find the largest part of D which is already known List <uint> plan = new List <uint>(); uint bitmap = D.bitmap; while (bitmap != 0) { // find first bit, plan it, see if the rest is available uint lowestBitIdx = (uint)RefGA.Bits.LowestOneBit(bitmap); uint lowestBitmap = (uint)(1 << (int)lowestBitIdx); plan.Add(lowestBitmap); bitmap ^= lowestBitmap; if (availableBasisBlades[bitmap]) // if remaining bitmap has already been computed, use that { plan.Add(bitmap); bitmap ^= bitmap; } } // plan for this basis blade is done: result[g][d] = plan.ToArray(); availableBasisBlades[D.bitmap] = true; } } return(result); } // end of ComputeOmInitFromVectorsPlan()
/// <returns>a list of basis blades in canonical order, sorted by grade. /// Each entry in the outer list contains the basis blades for that grade.</returns> public List <List <G25.rsbbp.BasisBlade> > GetDefaultBasisBlades() { // allocate list for each grade List <List <G25.rsbbp.BasisBlade> > L = new List <List <G25.rsbbp.BasisBlade> >(); for (int i = 0; i < m_spec.m_dimension + 1; i++) { L.Add(new List <G25.rsbbp.BasisBlade>()); } // enumerate over all basis blades, add them to respective lists for (uint b = 0; b < (1 << m_spec.m_dimension); b++) { RefGA.BasisBlade B = new RefGA.BasisBlade(b); L[B.Grade()].Add(new G25.rsbbp.BasisBlade(B)); } return(L); }
/// <summary> /// Generates code to assign <c>value</c> to a variable whose coordinate order is specified by <c>BL</c>. /// /// For example, <c>BL</c> could be <c>[e1, e2, e3]</c> and the multivector value <c>[e1 - 2e3]</c>. /// Then the returned array would be <c>["1", "0", "-2"]</c>. /// /// Parts of <c>value</c> that cannot be assigned to <c>BL</c> are silently ignored. /// /// Possibly, at some point we would like to generate some kind of warning? /// </summary> /// <param name="S">Specification of algebra (not used yet).</param> /// <param name="FT">Floating point type of assigned variable (used for casting strings).</param> /// <param name="mustCast">Set to true if a cast to 'FT' must be performed.</param> /// <param name="BL">Basis blades of assigned variable.</param> /// <param name="value">Multivector value to assign to the list of basis blades. /// Must not contain basis blades inside the symbolic scalars of the RefGA.BasisBlades.</param> /// <param name="writeZeros">When true, <c>"0"</c> will be returned when no value should be assigned /// to some coordinate. <c>null</c> otherwise.</param> /// <returns>An array of strings which tell you what to assign to each coordinate.</returns> public static String[] GetAssignmentStrings(Specification S, FloatType FT, bool mustCast, RefGA.BasisBlade[] BL, RefGA.Multivector value, bool writeZeros) { String[] assignedStr = new String[BL.Length]; int idx = 0; // for each non-const coord, find out what value is (loop through all entries in value) foreach (RefGA.BasisBlade B in BL) { // find same basisblade in 'value' foreach (RefGA.BasisBlade C in value.BasisBlades) { if (C.bitmap == B.bitmap) // match found: get assignment string { // compute D = inverse(B) . C; RefGA.BasisBlade Bi = (new RefGA.BasisBlade(B.bitmap, 1.0 / B.scale)).Reverse(); RefGA.BasisBlade D = RefGA.BasisBlade.scp(Bi, C); if (mustCast) { assignedStr[idx] = FT.castStr + "(" + CodeUtil.ScalarToLangString(S, FT, D) + ")"; } else { assignedStr[idx] = CodeUtil.ScalarToLangString(S, FT, D); } break; } } if (writeZeros && (assignedStr[idx] == null)) // has an assignment string been set? { // no assignment: simply assign "0" assignedStr[idx] = FT.DoubleToString(S, 0.0); } idx++; } return(assignedStr); } // end of GetAssignmentStrings()
/// <returns>'L' convert to a single array</returns> public static RefGA.BasisBlade[] ListToSingleArray(List <List <G25.rsbbp.BasisBlade> > L) { // count total number of basis blades int cnt = 0; for (int i = 0; i < L.Count; i++) { cnt += L[i].Count; } // allocate, copy basis blades RefGA.BasisBlade[] A = new RefGA.BasisBlade[cnt]; int idx = 0; for (int i = 0; i < L.Count; i++) { for (int j = 0; j < L[i].Count; j++) { A[idx++] = L[i][j].GetBasisBlade; } } return(A); }
/// <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 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;}"); } }
} // end of WriteSetZero() /// <summary> /// Writes a function to set an SMV struct to a scalar coordinate, for all floating point types which have a non-constant scalar coordinate. /// </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 WriteSetScalar(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SMV smv) { //if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) return; // if no scalar coordinate, continue 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(); const int NB_COORDS = 1; string[] argTypename = new String[NB_COORDS]; string[] argName = new String[NB_COORDS]; { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; argTypename[0] = FT.type; argName[0] = "scalarVal"; L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, argName[0])); } 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 = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_COORDS, 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); }
/// <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); }
/// <returns>'L' convert to a single array</returns> public static RefGA.BasisBlade[] ListToSingleArray(List<List<G25.rsbbp.BasisBlade>> L) { // count total number of basis blades int cnt = 0; for (int i = 0; i < L.Count; i++) cnt += L[i].Count; // allocate, copy basis blades RefGA.BasisBlade[] A = new RefGA.BasisBlade[cnt]; int idx = 0; for (int i = 0; i < L.Count; i++) { for (int j = 0; j < L[i].Count; j++) A[idx++] = L[i][j].GetBasisBlade; } return A; }
/// <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); }
/// <summary> /// Writes code for m_name = m_value. /// </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.SMV) { G25.SMV dstSmv = m_type as G25.SMV; if (m_declareVariable) SB.AppendLine("/* cannot yet assign and declare SMV type at the same time */"); RefGA.BasisBlade[] BL = BasisBlade.GetNonConstBladeList(dstSmv); string[] accessStr = CodeUtil.GetAccessStr(S, dstSmv, m_name, m_ptr); 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.GenerateAssignmentCode(S, accessStr, valueStr, m_nbTabs, writeZeros)); } else if (m_type is G25.FloatType) { // temp hack to override float type. G25.FloatType FT = this.m_floatType; // m_type as G25.FloatType; AppendTabs(SB); if (m_declareVariable) { // also declare the variable right here? // output "/t type " SB.Append(FT.type + " "); } // output name = ....; RefGA.BasisBlade[] BL = new RefGA.BasisBlade[1] { RefGA.BasisBlade.ONE }; String[] accessStr = new String[1] { m_name }; bool writeZeros = true; String[] valueStr = CodeUtil.GetAssignmentStrings(S, FT, m_mustCast, BL, m_value, writeZeros); // apply post operation (like "/ n2") ApplyPostOp(S, cgd, BL, valueStr); SB.AppendLine(CodeUtil.GenerateAssignmentCode(S, accessStr, valueStr, 0, writeZeros)); } else { SB.AppendLine("/* to do: implement " + GetType().ToString() + " for type " + m_type.GetType().ToString() + " */"); } }
public static void WriteSetMatrix(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som, bool transpose) { int NB_ARGS = 1; string[] argTypes = new string[NB_ARGS]; string[] argNames = new string[NB_ARGS]; argTypes[0] = FT.type; argNames[0] = "M"; // construct image values RefGA.Multivector[] imageValue = new RefGA.Multivector[som.DomainVectors.Length]; for (int d = 0; d < som.DomainVectors.Length; d++) { //imageValue[d] = RefGA.Multivector.ZERO; RefGA.BasisBlade[] IV = new RefGA.BasisBlade[som.RangeVectors.Length]; for (int r = 0; r < som.RangeVectors.Length; r++) { int matrixIdx = (transpose) ? (d * som.RangeVectors.Length + r) : (r * som.DomainVectors.Length + d); string entryName = argNames[0] + "[" + matrixIdx + "]"; IV[r] = new RefGA.BasisBlade(som.RangeVectors[r].bitmap, 1.0, entryName); } imageValue[d] = new RefGA.Multivector(IV); } string typeName = FT.GetMangledName(S, som.Name); string funcName = GetFunctionName(S, typeName, "set", "_setMatrix"); if (transpose) funcName = funcName + "Transpose"; //argNames[0] = "*" + argNames[0]; // quick hack: add pointer to name instead of type! G25.fgs F = new G25.fgs(funcName, funcName, "", argTypes, argNames, new String[] { FT.type }, null, null, null); // null, null = metricName, comment, options F.InitArgumentPtrFromTypeNames(S); if (S.OutputCppOrC()) F.m_argumentPtr[0] = true; else F.m_argumentArr[0] = true; bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, S.m_GMV.Name, computeMultivectorValue); G25.CG.Shared.FuncArgInfo returnArgument = null; if (S.OutputC()) returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, som.Name, computeMultivectorValue); // setup instructions List<G25.CG.Shared.Instruction> I = new List<G25.CG.Shared.Instruction>(); { 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 < som.Domain.Length; g++) { for (int c = 0; c < som.DomainForGrade(g).Length; c++) { G25.SMVOM smvOM = som.DomainSmvForGrade(g)[c]; RefGA.BasisBlade domainBlade = som.DomainForGrade(g)[c]; RefGA.Multivector value = new RefGA.Multivector(new RefGA.BasisBlade(domainBlade, 0)); // copy the scalar part, ditch the basis blade for (uint v = 0; v < som.DomainVectors.Length; v++) { if ((domainBlade.bitmap & som.DomainVectors[v].bitmap) != 0) { value = RefGA.Multivector.op(value, imageValue[v]); } } 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)); } } } Comment comment = new Comment("Sets " + typeName + " from a " + (transpose ? "transposed " : "") + "matrix."); bool writeDecl = (S.OutputC()); bool staticFunc = false; G25.CG.Shared.Functions.WriteFunction(S, cgd, F, S.m_inlineSet, staticFunc, "void", funcName, returnArgument, FAI, I, comment, writeDecl); }
private static void WriteSetCoordFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, StringBuilder SB, string gmvTypeName, int groupIdx, int elementIdx, int groupSize, RefGA.BasisBlade B) { String bladeName = B.ToLangString(S.m_basisVectorNames); // do we inline this func? string inlineStr = "inline "; string funcName = MainGenerator.SETTER_PREFIX + bladeName; string coordName = "val"; string funcDecl = "\t" + inlineStr + "void " + funcName + "(" + FT.type + " " + coordName + ") "; SB.AppendLine("\t/// Sets the " + bladeName + " coordinate of this " + gmvTypeName + "."); SB.Append(funcDecl); SB.AppendLine(" {"); SB.AppendLine("\t\treserveGroup_" + groupIdx + "();"); SB.AppendLine("\t\tm_c[" + S.m_namespace + "_mvSize[m_gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] = " + coordName + ";"); SB.AppendLine("\t}"); }
/// <summary> /// Writes an equality test function for specialized multivectors /// </summary> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> protected void WriteEqualsFunction(FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment) { // setup instructions List<G25.CG.Shared.Instruction> I = new List<G25.CG.Shared.Instruction>(); // get a basis blade list which contains all basis blades (this is used in conjunction with GetAssignmentStrings()) RefGA.BasisBlade[] BL = new RefGA.BasisBlade[1 << m_specification.m_dimension]; for (uint bitmap = 0; bitmap < (uint)BL.Length; bitmap++) BL[bitmap] = new RefGA.BasisBlade(bitmap); // get string to access the coordinates of each basis blade wrt to the basis bool mustCast = false; bool writeZeros = false; string[] assStr1 = G25.CG.Shared.CodeUtil.GetAssignmentStrings(m_specification, FT, mustCast, BL, FAI[0].MultivectorValue[0], writeZeros); string[] assStr2 = G25.CG.Shared.CodeUtil.GetAssignmentStrings(m_specification, FT, mustCast, BL, FAI[1].MultivectorValue[0], writeZeros); string BOOL = CodeUtil.GetBoolType(m_specification); string TRUE = CodeUtil.GetTrueValue(m_specification); string FALSE = CodeUtil.GetFalseValue(m_specification); { // setup instructions // get tmp storage for 'difference' int nbTabs = 1; bool dDeclared = false; // for each assStr, subtract the other, see if difference is within limits for (int i = 0; i < BL.Length; i++) { if ((assStr1[i] == null) && (assStr2[i] == null)) continue; else if (assStr1[i] == null) I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if ((" + assStr2[i] + " < -" + FAI[2].Name + ") || (" + assStr2[i] + " > " + FAI[2].Name + ")) return " + FALSE + "; /* " + BL[i].ToString(m_specification.m_basisVectorNames) + " */")); else if (assStr2[i] == null) I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if ((" + assStr1[i] + " < -" + FAI[2].Name + ") || (" + assStr1[i] + " > " + FAI[2].Name + ")) return " + FALSE + "; /* " + BL[i].ToString(m_specification.m_basisVectorNames) + " */")); else { if (!dDeclared) { // declare a variable 'd', but only if required I.Insert(0, new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " d;")); dDeclared = true; } I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "d = " + assStr1[i] + " - " + assStr2[i] + "; " + "if ((d < -" + FAI[2].Name + ") || (d > " + FAI[2].Name + ")) return " + FALSE + "; /* " + BL[i].ToString(m_specification.m_basisVectorNames) + " */")); } } // finally, return 1 if all check were OK I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return " + TRUE + ";")); } // 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 = BOOL; 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); }
private static void WriteGetCoordFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, StringBuilder SB, string gmvTypeName, int groupIdx, int elementIdx, RefGA.BasisBlade B) { String bladeName = B.ToLangString(S.m_basisVectorNames); // do we inline this func? string inlineStr = "inline "; string funcName = MainGenerator.GETTER_PREFIX + bladeName; string funcDecl = "\t" + inlineStr + FT.type + " " + funcName + "() const"; SB.AppendLine("\t/// Returns the " + bladeName + " coordinate of this " + gmvTypeName + "."); SB.Append(funcDecl); SB.AppendLine(" {"); SB.AppendLine("\t\treturn (m_gu & " + (1 << groupIdx) + ") ? " + "m_c[" + S.m_namespace + "_mvSize[m_gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] : " + FT.DoubleToString(S, 0.0) + ";"); SB.AppendLine("\t}"); }
/// <summary> /// Writes code to extract the scalar part of an SMV /// </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 WriteExtractScalarPart(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; RefGA.BasisBlade scalarBlade = new RefGA.BasisBlade(1.0); foreach (G25.FloatType FT in S.m_floatTypes) { foreach (G25.SMV smv in S.m_SMV) { String[] AS = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, smvName, ptr); String typeName = FT.GetMangledName(S, smv.Name); String funcName = typeName + "_" + FT.type; declSB.AppendLine("/** Returns scalar part of " + typeName + " */"); String funcDecl = FT.type + " " + funcName + "(const " + typeName + " *" + smvName + ")"; declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.Append(funcDecl); { defSB.AppendLine(" {"); int scalarCoordIdx = smv.GetElementIdx(scalarBlade); if (scalarCoordIdx >= 0) { double multiplier = 1.0 / smv.BasisBlade(0, scalarCoordIdx).scale; string multiplerString = (multiplier != 1.0) ? (FT.DoubleToString(S, multiplier) + " * "): ""; defSB.AppendLine("\treturn " + multiplerString + AS[scalarCoordIdx] + ";"); } else defSB.AppendLine("\treturn " + FT.DoubleToString(S, 0.0) + ";"); defSB.AppendLine("}"); } } // end of loop over all smvs } // end of loop over all float types }
/// <summary> /// Constructor for a BasisBlade without a constant coordinate value /// </summary> public BasisBlade(RefGA.BasisBlade B) { m_basisBlade = B; m_isConstant = false; m_constantValue = 0.0; }
/// <returns>a list of basis blades in canonical order, sorted by grade. /// Each entry in the outer list contains the basis blades for that grade.</returns> public List<List<G25.rsbbp.BasisBlade>> GetDefaultBasisBlades() { // allocate list for each grade List<List<G25.rsbbp.BasisBlade>> L = new List<List<G25.rsbbp.BasisBlade>>(); for (int i = 0; i < m_spec.m_dimension + 1; i++) L.Add(new List<G25.rsbbp.BasisBlade>()); // enumerate over all basis blades, add them to respective lists for (uint b = 0; b < (1 << m_spec.m_dimension); b++) { RefGA.BasisBlade B = new RefGA.BasisBlade(b); L[B.Grade()].Add(new G25.rsbbp.BasisBlade(B)); } return L; }
/// <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); } }
/// <summary> /// Constructor for a BasisBlade with a constant coordinate value /// </summary> /// <param name="B"></param> /// <param name="constantValue"></param> public BasisBlade(RefGA.BasisBlade B, double constantValue) { m_basisBlade = B; m_isConstant = true; m_constantValue = constantValue; }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { if (m_specification.m_GOM == null) { throw new G25.UserException("No general outermorphism type defined, while it is required because the type of the first argument was unspecified."); } m_fgs.m_argumentTypeNames = new String[] { m_specification.m_GOM.Name, m_gmv.Name }; } // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_om = (G25.OM)tmpFAI[0].Type; m_mv = (G25.MV)tmpFAI[1].Type; m_gmvFunc = !tmpFAI[1].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // gmv + gmv = gmv } else { RefGA.Multivector inputValue = tmpFAI[1].MultivectorValue[0]; // Compute m_returnValue: // Replace each basis blade in 'inputValue' with its value under the outermorphism. m_returnValue = RefGA.Multivector.ZERO; 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 = m_om.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 = m_specification.OutputC(); RefGA.Multivector omColumnValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(m_specification, m_om.DomainSmvForGrade(inputBlade.Grade())[c], tmpFAI[0].Name, ptr); RefGA.Multivector inputBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(inputBlade, 0)); RefGA.Multivector domainBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(domainBlades[c], 0)); m_returnValue = RefGA.Multivector.Add(m_returnValue, RefGA.Multivector.gp( RefGA.Multivector.gp(omColumnValue, inputBladeScalarMultiplier), domainBladeScalarMultiplier)); break; // no need to search the other domainBlades too } } } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } }
/// <returns>'L' convert to a double array</returns> public static RefGA.BasisBlade[][] ListToDoubleArray(List<List<RefGA.BasisBlade>> L) { RefGA.BasisBlade[][] A = new RefGA.BasisBlade[L.Count][]; for (int i = 0; i < L.Count; i++) A[i] = L[i].ToArray(); return A; }
/// <summary> /// Converts a scalar basis blade (with optional symbolic part) to a string in the output language of <c>S</c>. /// /// Some effort is made to output code which is close to that a human would write. /// </summary> /// <param name="S">Specification of algebra, used for output language, basis vector names, etc.</param> /// <param name="FT">Floating point type of output.</param> /// <param name="B">The basis blade.</param> /// <returns>String code representation of 'B'.</returns> public static string ScalarToLangString(G25.Specification S, G25.FloatType FT, RefGA.BasisBlade B) { string symScaleStr = ""; { // convert symbolic part if (B.symScale != null) { // symbolic scalar string goes in symResult System.Text.StringBuilder symResult = new System.Text.StringBuilder(); int tCnt = 0; for (int t = 0; t < B.symScale.Length; t++) // for each term ...*...*...+ { Object[] T = (Object[])B.symScale[t].Clone(); // clone 'T' because IsolateInverses() might alter it! if (T != null) // if term is not null { // first find all scalarop inverses // turn those into a new term, but without inverses? Object[] TI = IsolateInverses(T); // emit 'T' int pCnt = EmitTerm(S, FT, T, tCnt, symResult); if (TI != null) // do we have to divide by a number of terms? { // emit '/(TI)' symResult.Append("/("); EmitTerm(S, FT, TI, 0, symResult); symResult.Append(")"); } if (pCnt > 0) { tCnt++; // only increment number of terms when T was not empty } } } if (tCnt > 0) { symScaleStr = ((tCnt > 1) ? "(" : "") + symResult + ((tCnt > 1) ? ")" : ""); } } } // end of symbolic part // special cases when numerical scale is exactly +- 1 if (B.scale == 1.0) { if (symScaleStr.Length > 0) { return(symScaleStr); } else { return(FT.DoubleToString(S, 1.0)); } } else if (B.scale == -1.0) { if (symScaleStr.Length > 0) { return("-" + symScaleStr); } else { return(FT.DoubleToString(S, -1.0)); } } else { // get numerical part string numScaleStr = FT.DoubleToString(S, B.scale); // merge symbolic and numerical if (symScaleStr.Length > 0) { numScaleStr = numScaleStr + "*" + symScaleStr; } // done return(numScaleStr); } } // end of function ScalarToLangString
/// <returns>'L' convert to a double array</returns> public static RefGA.BasisBlade[][] ListToDoubleArray(List<List<G25.rsbbp.BasisBlade>> L) { RefGA.BasisBlade[][] A = new RefGA.BasisBlade[L.Count][]; for (int i = 0; i < L.Count; i++) { A[i] = new RefGA.BasisBlade[L[i].Count]; for (int j = 0; j < L[i].Count; j++) A[i][j] = L[i][j].GetBasisBlade; } return A; }