Esempio n. 1
0
 /// <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("");
         }
     }
 }
Esempio n. 2
0
        } // 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;}");
            }
        }
Esempio n. 3
0
        /// <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()
Esempio n. 4
0
        } // 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());
        }
Esempio n. 5
0
        /// <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;
        }
Esempio n. 6
0
 /// <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);
     }
 }
Esempio n. 7
0
        /// <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());
        }
Esempio n. 8
0
        /// <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;");
        }
Esempio n. 9
0
        /// <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;}");
            }
        }
Esempio n. 10
0
        /// <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("");
                }
            }
        }
Esempio n. 11
0
        /// <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 + ";");
            }
        }
Esempio n. 12
0
        /// <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(" */");
        }
Esempio n. 13
0
        } // 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()
Esempio n. 14
0
        /// <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()
Esempio n. 15
0
        } // 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()
Esempio n. 16
0
        } // 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()
Esempio n. 17
0
        } // 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()
Esempio n. 18
0
        /// <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
Esempio n. 19
0
        /// <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) + ";");
        }