Beispiel #1
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;}");
            }
        }
Beispiel #2
0
        private static void WriteCoordSetFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, string gmvTypeName, int groupIdx, int elementIdx, int groupSize, RefGA.BasisBlade B)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB  = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            String bladeName = B.ToLangString(S.m_basisVectorNames);

            string varName   = "A";
            string coordName = bladeName + "_coord";

            // do we inline this func?
            string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " ");

            string funcName = gmvTypeName + "_set_" + bladeName;

            string funcDecl = inlineStr + "void " + funcName + "(" + gmvTypeName + " *" + varName + ", " + FT.type + " " + coordName + ")";

            declSB.AppendLine("/** Sets the " + B.ToString(S.m_basisVectorNames) + " coordinate of '" + varName + "' */");
            declSB.Append(funcDecl);
            declSB.AppendLine(";");

            defSB.AppendLine("");
            defSB.Append(funcDecl);
            defSB.AppendLine(" {");

            defSB.AppendLine("\t" + gmvTypeName + "_reserveGroup_" + groupIdx + "(" + varName + ");");
            defSB.AppendLine("\t" + varName + "->c[" + S.m_namespace + "_mvSize[" + varName + "->gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] = " + coordName + ";");
            defSB.AppendLine("}");
        }
Beispiel #3
0
        }         // end of WriteGMVtoSMVcopy()

        private static void WriteCoordExtractFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, string gmvTypeName, int groupIdx, int elementIdx, RefGA.BasisBlade B)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB  = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            String bladeName = B.ToLangString(S.m_basisVectorNames);

            string varName = "A";

            // do we inline this func?
            string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " ");

            string funcName = gmvTypeName + "_" + bladeName;

            string funcDecl = inlineStr + FT.type + " " + funcName + "(const " + gmvTypeName + " *" + varName + ")";

            string comment = "/** Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate of '" + varName + "' */";

//                    declSB.AppendLine("/* group : " + groupIdx + " element: " + elementIdx + "*/");
            declSB.AppendLine(comment);
            declSB.Append(funcDecl);
            declSB.AppendLine(";");

            defSB.AppendLine("");
            defSB.Append(funcDecl);
            defSB.AppendLine(" {");
            defSB.AppendLine("\treturn (" + varName + "->gu & " + (1 << groupIdx) + ") ? " +
                             varName + "->c[" + S.m_namespace + "_mvSize[" + varName + "->gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] : " +
                             FT.DoubleToString(S, 0.0) + ";");
            defSB.AppendLine("}");

            // add extract coord extract function for scalar
            if (B.Grade() == 0)
            {
                string floatFuncName = gmvTypeName + "_" + FT.type;
                string floatFuncDecl = inlineStr + FT.type + " " + floatFuncName + "(const " + gmvTypeName + " *" + varName + ")";

                declSB.AppendLine(comment);
                declSB.Append(floatFuncDecl);
                declSB.AppendLine(";");

                defSB.Append(floatFuncDecl);
                defSB.AppendLine(" {");
                defSB.AppendLine("\treturn " + funcName + "(" + varName + ");");
                defSB.AppendLine("}");
            }
        }
Beispiel #4
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;}");
            }
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        public static void WriteSetVectorImages(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SOM som)
        {
            G25.SMV rangeVectorType = G25.CG.Shared.OMinit.GetRangeVectorType(S, FT, cgd, som);

            // loop over som.DomainVectors
            // setup array of arguments, function specification, etc
            int NB_ARGS = som.DomainVectors.Length;

            string[]            argTypes = new string[NB_ARGS];
            string[]            argNames = new string[NB_ARGS];
            RefGA.Multivector[] argValue = new RefGA.Multivector[NB_ARGS];
            for (int d = 0; d < NB_ARGS; d++)
            {
                argTypes[d] = rangeVectorType.Name;
                argNames[d] = "i" + som.DomainVectors[d].ToLangString(S.m_basisVectorNames);
                bool ptr = (S.OutputC());
                argValue[d] = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, rangeVectorType, argNames[d], ptr);
            }


            string typeName = FT.GetMangledName(S, som.Name);
            string funcName = GetFunctionName(S, typeName, "set", "_setVectorImages");


            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);
            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, argValue[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 images of the domain vectors.");
            bool    writeDecl  = false;
            bool    staticFunc = false;

            G25.CG.Shared.Functions.WriteFunction(S, cgd, F, S.m_inlineSet, staticFunc, "void", funcName, returnArgument, FAI, I, comment, writeDecl);
        }
Beispiel #7
0
        /// <summary>
        /// Writes a function to set a GOM struct according to vector images, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float type.</param>
        /// <param name="matrixMode">When true, generates code for setting from matrix instead of vector images.</param>
        /// <param name="transpose">When this parameter is true and <c>matrixMode</c> is true, generates code for setting from transpose matrix.</param>
        public static void WriteSetVectorImages(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, bool matrixMode, bool transpose)
        {
            G25.GOM gom = S.m_GOM;

            // get the 'plan' on how to initialize all domain basis blades efficiently:
            uint[][][] plan  = G25.CG.Shared.OMinit.ComputeOmInitFromVectorsPlan(S, gom);
            double[][] signs = G25.CG.Shared.OMinit.ComputeOmInitFromVectorsSigns(S, gom, plan);

            // get range vector type
            G25.SMV rangeVectorType = G25.CG.Shared.OMinit.GetRangeVectorType(S, FT, cgd, gom);

            // setup array of arguments, function specification, etc
            int NB_ARGS = (matrixMode) ? 1 : gom.DomainVectors.Length;

            string[]            argTypes         = new string[NB_ARGS], argNames = new string[NB_ARGS];
            RefGA.Multivector[] symbolicBBvalues = new RefGA.Multivector[1 << S.m_dimension]; // symbolic basis blade values go here
            if (matrixMode)
            {
                argTypes[0] = FT.type;
                argNames[0] = "M";

                // convert matrix columns to symbolic Multivector values
                for (int d = 0; d < gom.DomainVectors.Length; d++)
                {
                    RefGA.BasisBlade[] IV = new RefGA.BasisBlade[gom.RangeVectors.Length];
                    for (int r = 0; r < gom.RangeVectors.Length; r++)
                    {
                        int    matrixIdx = (transpose) ? (d * gom.RangeVectors.Length + r) : (r * gom.DomainVectors.Length + d);
                        string entryName = argNames[0] + "[" + matrixIdx + "]";
                        IV[r] = new RefGA.BasisBlade(gom.RangeVectors[r].bitmap, 1.0, entryName);
                    }
                    symbolicBBvalues[gom.DomainVectors[d].bitmap] = new RefGA.Multivector(IV);
                }
            }
            else
            {
                for (int d = 0; d < NB_ARGS; d++)
                {
                    argTypes[d] = rangeVectorType.Name;
                    argNames[d] = "i" + gom.DomainVectors[d].ToLangString(S.m_basisVectorNames);
                    bool ptr = S.OutputC();

                    symbolicBBvalues[gom.DomainVectors[d].bitmap] = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, rangeVectorType, argNames[d], ptr);
                }
            }

            // generate function names for all grades (basis blade names not included)
            string typeName = FT.GetMangledName(S, gom.Name);

            string[] funcNames = GetSetFromLowerGradeFunctionNames(S, FT, matrixMode);


            // setup instructions (for main function, and subfunctions for grades)
            List <G25.CG.Shared.Instruction> mainI = new List <G25.CG.Shared.Instruction>();

            List <G25.CG.Shared.Instruction>[] bladeI = new List <G25.CG.Shared.Instruction> [1 << S.m_dimension];
            {
                bool   mustCast   = false;
                int    nbTabs     = 1;
                string dstName    = (S.OutputC()) ? G25.fgs.RETURN_ARG_NAME : SmvUtil.THIS;
                bool   dstPtr     = S.OutputCppOrC();
                bool   declareDst = false;
                for (int g = 1; g < gom.Domain.Length; g++)
                {
                    for (int d = 0; d < gom.DomainForGrade(g).Length; d++)
                    {
                        G25.SMVOM        smvOM       = gom.DomainSmvForGrade(g)[d];
                        RefGA.BasisBlade domainBlade = gom.DomainForGrade(g)[d];


                        if (g > 1)
                        {
                            bladeI[domainBlade.bitmap] = new List <G25.CG.Shared.Instruction>();

                            string funcCallCode = funcNames[g] + "_" + d + "(";
                            if (S.OutputC())
                            {
                                funcCallCode += G25.fgs.RETURN_ARG_NAME;
                            }
                            funcCallCode += ");";
                            mainI.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, funcCallCode));
                        }

                        // follow the plan
                        RefGA.Multivector value = new RefGA.Multivector(signs[g][d]);
                        uint[]            P     = plan[g][d];
                        for (int p = 0; p < P.Length; p++)
                        {
                            value = RefGA.Multivector.op(value, symbolicBBvalues[P[p]]);
                        }

                        // add instructions
                        List <G25.CG.Shared.Instruction> I = (g == 1) ? mainI : bladeI[domainBlade.bitmap];
                        I.Add(new G25.CG.Shared.CommentInstruction(nbTabs, "Set image of " + domainBlade.ToString(S.m_basisVectorNames)));
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smvOM, FT, mustCast, value, dstName, dstPtr, declareDst));

                        // store symbolic value
                        symbolicBBvalues[domainBlade.bitmap] = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smvOM, dstName, dstPtr);
                    }
                }
            }

            // output grade > 1 functions
            if (cgd.generateOmInitCode(FT.type))
            {
                for (int g = 2; g < gom.Domain.Length; g++)
                {
                    for (int d = 0; d < gom.DomainForGrade(g).Length; d++)
                    {
                        RefGA.BasisBlade domainBlade = gom.DomainForGrade(g)[d];

                        string  funcName = funcNames[g] + "_" + d;
                        G25.fgs F        = new G25.fgs(funcName, funcName, "", new string[0], new string[0], new string[] { FT.type }, null, null, null); // null, null = metricName, comment, options
                        //F.InitArgumentPtrFromTypeNames(S);

                        bool computeMultivectorValue = false;

                        G25.CG.Shared.FuncArgInfo returnArgument = null;
                        if (S.OutputC())
                        {
                            returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, gom.Name, computeMultivectorValue);
                        }

                        int nbArgs = 0;
                        G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, S.m_GMV.Name, computeMultivectorValue);

                        Comment comment;
                        comment = new Comment("Sets grade " + g + " part of outermorphism matrix based on lower grade parts.");
                        bool inline     = false; // do not inline this potentially huge function
                        bool staticFunc = false;
                        bool writeDecl  = S.OutputC();
                        G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, "void", funcName, returnArgument, FAI, bladeI[domainBlade.bitmap], comment, writeDecl);
                    }
                }
            }


            {                                                                                                                            // output grade 1 function
                G25.fgs F = new G25.fgs(funcNames[1], funcNames[1], "", argTypes, argNames, new string[] { FT.type }, null, null, null); // null, null = metricName, comment, options
                F.InitArgumentPtrFromTypeNames(S);
                if (matrixMode)
                {
                    F.m_argumentPtr[0] = S.OutputCppOrC();
                    F.m_argumentArr[0] = S.OutputCSharpOrJava();
                }

                bool computeMultivectorValue = false;

                G25.CG.Shared.FuncArgInfo returnArgument = null;
                if (S.OutputC())
                {
                    returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, gom.Name, computeMultivectorValue);
                }

                G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, S.m_GMV.Name, computeMultivectorValue);

                Comment comment;
                if (!matrixMode)
                {
                    comment = new Comment("Sets " + typeName + " from images of the domain vectors.");
                }
                else
                {
                    comment = new Comment("Sets " + typeName + " from a " + (transpose ? "transposed " : "") + "matrix");
                }
                bool inline     = false; // do not inline this potentially huge function
                bool staticFunc = false;
                bool writeDecl  = S.OutputC();
                G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, "void", funcNames[1], returnArgument, FAI, mainI, comment, writeDecl);
            }
        } // end of WriteSetVectorImages()