Exemplo n.º 1
0
Arquivo: gom.cs Projeto: Sciumo/gaigen
        /// <summary>
        /// Writes members variables of a GOM class to 'SB'.
        /// </summary>
        /// <param name="SB">Where the comment goes.</param>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float point type of 'GOM'.</param>
        /// <param name="gom">The general outermorphism for which the class should be written.</param>
        public static void WriteMemberVariables(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom)
        {
            int nbTabs = 1;
            for (int g = 1; g < gom.Domain.Length; g++) // start at '1' in order to skip scalar grade
            {
                string comment = "Matrix for grade " + g + "; the size is " + gom.DomainForGrade(g).Length + " x " + gom.RangeForGrade(g).Length;
                new G25.CG.Shared.Comment(comment).Write(SB, S, nbTabs);

                SB.AppendLine(new string('\t', nbTabs) + Keywords.PackageProtectedAccessModifier(S) + " " + FT.type + "[] m_m" + g + " = new " +
                    FT.type + "[" + gom.DomainForGrade(g).Length * gom.RangeForGrade(g).Length + "];");
            }
        }
Exemplo n.º 2
0
Arquivo: som.cs Projeto: Sciumo/gaigen
        /// <summary>
        /// Writes the definition of an SOM struct to 'SB' (including comments).
        /// </summary>
        /// <param name="SB">Where the code goes.</param>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float point type of 'SMV'.</param>
        /// <param name="som">The general outermorphism for which the struct should be written.</param>
        public static void WriteSOMstruct(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som)
        {
            SB.AppendLine("");

            { // comments for type:
                SB.AppendLine("/**");
                SB.AppendLine(" * This struct can hold a specialized outermorphism.");
                SB.AppendLine(" * ");

                SB.AppendLine(" * The coordinates are stored in type " + FT.type + ".");
                SB.AppendLine(" * ");

                SB.AppendLine(" * There are " + som.Domain.Length + " matrices, one for each grade.");
                SB.AppendLine(" * The columns of these matrices are the range of the outermorphism.");
                SB.AppendLine(" * Matrices are stored in row-major order. So the coordinates of rows are stored contiguously.");
                for (int g = 1; g < som.Domain.Length; g++) // start at '1' in order to skip scalar grade
                {
                    SB.Append(" * Domain grade " + g + ": ");
                    for (int i = 0; i < som.DomainForGrade(g).Length; i++)
                    {
                        if (i > 0) SB.Append(", ");
                        SB.Append(som.DomainForGrade(g)[i].ToString(S.m_basisVectorNames));

                    }

                    SB.AppendLine(".");
                }
                SB.AppendLine(" * ");
                if (!som.DomainAndRangeAreEqual())
                {
                    for (int g = 1; g < som.Range.Length; g++) // start at '1' in order to skip scalar grade
                    {
                        SB.Append(" * Range grade " + g + ": ");
                        for (int i = 0; i < som.RangeForGrade(g).Length; i++)
                        {
                            if (i > 0) SB.Append(", ");
                            SB.Append(som.RangeForGrade(g)[i].ToString(S.m_basisVectorNames));

                        }

                        SB.AppendLine(".");
                    }
                }
                else SB.AppendLine(" * The range and domain are equal.");
                SB.AppendLine(" * ");

                SB.AppendLine(" */");
            } // end of comment

            // typedef
            SB.AppendLine("typedef struct ");
            SB.AppendLine("{");
            for (int g = 1; g < som.Domain.Length; g++) // start at '1' in order to skip scalar grade
            {
                if (!som.EmptyGrade(g))
                {
                    SB.AppendLine("\t/** Matrix for grade " + g + "; the size is " + som.DomainForGrade(g).Length + " x " + som.RangeForGrade(g).Length + " */");
                    SB.AppendLine("\t" + FT.type + " m" + g + "[" +
                        som.DomainForGrade(g).Length * som.RangeForGrade(g).Length + "];");
                }
            }

            SB.AppendLine("} " + FT.GetMangledName(S, som.Name) + ";");
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Writes a function to set an SOM struct/class to identity
        /// </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"></param>
        /// <param name="som"></param>
        public static void WriteSetIdentity(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            if (S.OutputC())
                declSB.AppendLine();
            defSB.AppendLine();

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

            bool mustCast = false;

            G25.fgs F = new G25.fgs(funcName, funcName, "", null, null, 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, som.Name, computeMultivectorValue);

            // setup instructions
            List<G25.CG.Shared.Instruction> I = new List<G25.CG.Shared.Instruction>();
            {
                int nbTabs = 1;
                mustCast = false;
                string valueName = (S.OutputC()) ? G25.fgs.RETURN_ARG_NAME : SmvUtil.THIS;
                bool valuePtr = S.OutputCppOrC();
                bool declareValue = 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];
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smvOM, FT, mustCast, new RefGA.Multivector(som.DomainForGrade(g)[c]), valueName, valuePtr, declareValue));
                    }
                }
            }

            Comment comment = new Comment("Sets " + typeName + " to identity.");
            bool writeDecl = S.OutputC();
            bool staticFunc = false;
            G25.CG.Shared.Functions.WriteFunction(S, cgd, F, S.m_inlineSet, staticFunc, "void", funcName, returnArgument, new G25.CG.Shared.FuncArgInfo[0], I, comment, writeDecl);
        }
Exemplo n.º 6
0
        public static void WriteSetCopy(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            if (S.OutputC())
                declSB.AppendLine();
            defSB.AppendLine();

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

            bool mustCast = false;

            const int NB_ARGS = 1;
            string srcName = "src";
            bool srcPtr = S.OutputC();
            G25.fgs F = new G25.fgs(funcName, funcName, "", new String[] { som.Name }, new String[] { srcName }, 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>();
            {
                int nbTabs = 1;
                mustCast = false;
                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.Multivector srcValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smvOM, srcName, srcPtr);
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smvOM, FT, mustCast, srcValue, dstName, dstPtr, declareDst));
                    }
                }
            }

            Comment comment = new Comment("Copies " + typeName + "."); ;
            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);
        }
Exemplo n.º 7
0
Arquivo: gom.cs Projeto: Sciumo/gaigen
 /// <summary>
 /// Writes members variables of a GOM class to 'SB'.
 /// </summary>
 /// <param name="SB">Where the comment goes.</param>
 /// <param name="S">Used for basis vector names and output language.</param>
 /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
 /// <param name="FT">Float point type of 'GOM'.</param>
 /// <param name="gom">The general outermorphism for which the class should be written.</param>
 public static void WriteMemberVariables(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom)
 {
     SB.AppendLine("public:");
     for (int g = 1; g < gom.Domain.Length; g++) // start at '1' in order to skip scalar grade
     {
         SB.AppendLine("\t/// Matrix for grade " + g + "; the size is " + gom.DomainForGrade(g).Length + " x " + gom.RangeForGrade(g).Length);
         SB.AppendLine("\t" + FT.type + " m_m" + g + "[" +
             gom.DomainForGrade(g).Length * gom.RangeForGrade(g).Length + "];");
     }
 }
Exemplo n.º 8
0
Arquivo: gom.cs Projeto: Sciumo/gaigen
        /// <summary>
        /// Writes comments of a GOM class to 'SB'.
        /// </summary>
        /// <param name="SB">Where the comment goes.</param>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float point type of 'GOM'.</param>
        /// <param name="gom">The general outermorphism for which the class should be written.</param>
        public static void WriteComment(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom)
        {
            SB.AppendLine("/**");
            SB.AppendLine(" * This class can hold a general outermorphism.");
            SB.AppendLine(" * ");

            SB.AppendLine(" * The coordinates are stored in type " + FT.type + ".");
            SB.AppendLine(" * ");

            SB.AppendLine(" * There are " + gom.Domain.Length + " matrices, one for each grade.");
            SB.AppendLine(" * The columns of these matrices are the range of the outermorphism.");
            SB.AppendLine(" * Matrices are stored in row-major order. So the coordinates of rows are stored contiguously.");
            for (int g = 1; g < gom.Domain.Length; g++) // start at '1' in order to skip scalar grade
            {
                SB.Append(" * Domain grade " + g + ": ");
                for (int i = 0; i < gom.DomainForGrade(g).Length; i++)
                {
                    if (i > 0) SB.Append(", ");
                    SB.Append(gom.DomainForGrade(g)[i].ToString(S.m_basisVectorNames));

                }

                SB.AppendLine(".");
            }
            SB.AppendLine(" * ");
            if (!gom.DomainAndRangeAreEqual())
            {
                for (int g = 1; g < gom.Range.Length; g++) // start at '1' in order to skip scalar grade
                {
                    SB.Append(" * Range grade " + g + ": ");
                    for (int i = 0; i < gom.RangeForGrade(g).Length; i++)
                    {
                        if (i > 0) SB.Append(", ");
                        SB.Append(gom.RangeForGrade(g)[i].ToString(S.m_basisVectorNames));

                    }

                    SB.AppendLine(".");
                }
            }
            else SB.AppendLine(" * The range and domain are equal.");
            SB.AppendLine(" * ");

            SB.AppendLine(" */");
        }
Exemplo n.º 9
0
Arquivo: gom.cs Projeto: Sciumo/gaigen
        /// <summary>
        /// Writes 'set()' declarations of a GOM class to '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">Intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float point type of 'GOM'.</param>
        /// <param name="gom">The general outermorphism for which the class should be written.</param>
        /// <param name="className">Mangled name of GOM class.</param>
        /// <param name="rangeVectorSMVname">The name of the SMV which can represent a column of the OM.</param>
        public static void WriteSetDeclarations(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom, string className, string rangeVectorSMVname)
        {
            cgd.m_cog.EmitTemplate(SB, "GOMsetDecl", "S=", S, "FT=", FT, "className=", className, "rangeVectorSMVname=", rangeVectorSMVname);

            { // extra code for per-grade-per-basisblade functions to set OM from vectors
                SB.AppendLine("\tprivate:");
                bool matrixMode = false; // this value is irrelevant at this point
                string typeName = FT.GetMangledName(S, gom.Name);
                string prefix = typeName + "::";
                string[] funcNames = G25.CG.Shared.OMinit.GetSetFromLowerGradeFunctionNames(S, FT, matrixMode);
                for (int g = 1; g < gom.Domain.Length; g++)
                {

                    for (int d = 0; d < gom.DomainForGrade(g).Length; d++)
                    {
                        string funcName = funcNames[g] + "_" + d;
                        if (funcName.IndexOf(prefix) == 0)
                            funcName = funcName.Substring(prefix.Length);
                        SB.AppendLine("\tvoid " + funcName + "();");
                    }
                }
                SB.AppendLine("\tpublic:");
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Returns the comment for the SOM class.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float point type of 'GOM'.</param>
        /// <param name="som">The general outermorphism for which the class should be written.</param>
        public static Comment GetSomComment(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som)
        {
            StringBuilder SB = new StringBuilder();

            SB.AppendLine("This class can hold a specialized outermorphism.");
            SB.AppendLine();

            SB.AppendLine("The coordinates are stored in type " + FT.type + ".");
            SB.AppendLine();

            SB.AppendLine("There are " + som.Domain.Length + " matrices, one for each grade.");
            SB.AppendLine("The columns of these matrices are the range of the outermorphism.");
            SB.AppendLine("Matrices are stored in row-major order. So the coordinates of rows are stored contiguously.");
            for (int g = 1; g < som.Domain.Length; g++) // start at '1' in order to skip scalar grade
            {
                SB.Append("Domain grade " + g + ": ");
                for (int i = 0; i < som.DomainForGrade(g).Length; i++)
                {
                    if (i > 0) SB.Append(", ");
                    SB.Append(som.DomainForGrade(g)[i].ToString(S.m_basisVectorNames));

                }

                SB.AppendLine(".");
            }
            SB.AppendLine();
            if (!som.DomainAndRangeAreEqual())
            {
                for (int g = 1; g < som.Range.Length; g++) // start at '1' in order to skip scalar grade
                {
                    SB.Append("Range grade " + g + ": ");
                    for (int i = 0; i < som.RangeForGrade(g).Length; i++)
                    {
                        if (i > 0) SB.Append(", ");
                        SB.Append(som.RangeForGrade(g)[i].ToString(S.m_basisVectorNames));

                    }

                    SB.AppendLine(".");
                }
            }
            else SB.AppendLine("The range and domain are equal.");

            return new Comment(SB.ToString());
        }