Beispiel #1
0
        private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C)
        {
            // assume only SMV constants for now
            G25.SMV     smv  = C.Type as G25.SMV;
            ConstantSMV Csmv = C as ConstantSMV;

            string className = FT.GetMangledName(S, smv.Name);

            // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...}
            SB.Append(className);
            SB.Append(" ");
            SB.Append(FT.GetMangledName(S, C.Name));

            if (smv.NbNonConstBasisBlade > 0)
            {
                // MANGLED_TYPENAME MANGLED_CONSTANT_NAME(...)
                SB.Append("(" + className + "::" + G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv));

                for (int c = 0; c < smv.NbNonConstBasisBlade; c++)
                {
                    SB.Append(", ");
                    SB.Append(FT.DoubleToString(S, Csmv.Value[c]));
                }

                SB.Append(")");
            }

            SB.AppendLine(";");
        }
Beispiel #2
0
        private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C)
        {
            // assume only SMV constants for now
            G25.SMV smv = C.Type as G25.SMV;
            ConstantSMV Csmv = C as ConstantSMV;

            string className = FT.GetMangledName(S, smv.Name);

            // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...}
            SB.Append("\tpublic ");
            SB.Append(Keywords.ConstClassInstanceAccessModifier(S));
            SB.Append(" ");
            SB.Append(className);
            SB.Append(" ");
            SB.Append(FT.GetMangledName(S, C.Name));
            SB.Append(" = new ");
            SB.Append(className);
            SB.Append("(");

            if (smv.NbNonConstBasisBlade > 0)
            {
                // MANGLED_TYPENAME MANGLED_CONSTANT_NAME(...)
                SB.Append(className + "." + G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv));

                for (int c = 0; c < smv.NbNonConstBasisBlade; c++)
                {
                    SB.Append(", ");
                    SB.Append(FT.DoubleToString(S, Csmv.Value[c]));
                }

            }
            SB.Append(")");

            SB.AppendLine(";");
        }
Beispiel #3
0
        } // end of GetAccessStr()

        /// <summary>
        /// Generates code for returning a scalar value. The input is a scalar-valued multivector.
        /// </summary>
        /// <param name="S">Specification (used for output language).</param>
        /// <param name="FT">Floating point type which must be returned.</param>
        /// <param name="mustCast">Set to true if the returned value must be cast to <c>FT</c>, that is
        /// if you are not sure that the multivector has the same float type as the return type <c>FT</c>.</param>
        /// <param name="value">The symbolic multivector value to be returned.</param>
        /// <returns>Code for returning a scalar value.</returns>
        public static string GenerateScalarReturnCode(Specification S, FloatType FT, bool mustCast, RefGA.Multivector value)
        {
            if (value.IsZero())
            {
                return("return " + FT.DoubleToString(S, 0.0) + ";");
            }
            else
            {
                return("return " +
                       ((mustCast) ? (FT.castStr + "(") : "") +
                       CodeUtil.ScalarToLangString(S, FT, value.BasisBlades[0]) +
                       ((mustCast) ? ")" : "") +
                       ";");
            }
        } // end of GenerateScalarReturnCode()
Beispiel #4
0
        private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C)
        {
            // assume only SMV constants for now
            G25.SMV     smv  = C.Type as G25.SMV;
            ConstantSMV Csmv = C as ConstantSMV;

            // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...}
            SB.Append(FT.GetMangledName(S, C.Type.GetName()));
            SB.Append(" ");
            SB.Append(FT.GetMangledName(S, C.Name));
            SB.Append(" = {");

            if (smv.NbNonConstBasisBlade == 0)
            {
                // 'C' does not allow empty structs, so there is a filler that must be initialized
                SB.Append("0");
            }
            else
            {
                if (S.m_coordStorage == COORD_STORAGE.ARRAY)
                {
                    SB.Append("{");
                }

                for (int c = 0; c < smv.NbNonConstBasisBlade; c++)
                {
                    if (c > 0)
                    {
                        SB.Append(", ");
                    }
                    SB.Append(FT.DoubleToString(S, Csmv.Value[c]));
                }

                if (S.m_coordStorage == COORD_STORAGE.ARRAY)
                {
                    SB.Append("}");
                }
            }


            SB.AppendLine("};");
        }
Beispiel #5
0
        /// <summary>
        /// Generates code to assign <c>value</c> to a variable whose coordinate order is specified by <c>BL</c>.
        ///
        /// For example, <c>BL</c> could be <c>[e1, e2, e3]</c> and the multivector value <c>[e1 - 2e3]</c>.
        /// Then the returned array would be <c>["1", "0", "-2"]</c>.
        ///
        /// Parts of <c>value</c> that cannot be assigned to <c>BL</c> are silently ignored.
        ///
        /// Possibly, at some point we would like to generate some kind of warning?
        /// </summary>
        /// <param name="S">Specification of algebra (not used yet).</param>
        /// <param name="FT">Floating point type of assigned variable (used for casting strings).</param>
        /// <param name="mustCast">Set to true if a cast to 'FT' must be performed.</param>
        /// <param name="BL">Basis blades of assigned variable.</param>
        /// <param name="value">Multivector value to assign to the list of basis blades.
        /// Must not contain basis blades inside the symbolic scalars of the RefGA.BasisBlades.</param>
        /// <param name="writeZeros">When true, <c>"0"</c> will be returned when no value should be assigned
        /// to some coordinate. <c>null</c> otherwise.</param>
        /// <returns>An array of strings which tell you what to assign to each coordinate.</returns>
        public static String[] GetAssignmentStrings(Specification S, FloatType FT, bool mustCast, RefGA.BasisBlade[] BL,
                                                    RefGA.Multivector value, bool writeZeros)
        {
            String[] assignedStr = new String[BL.Length];
            int      idx         = 0;

            // for each non-const coord, find out what value is (loop through all entries in value)
            foreach (RefGA.BasisBlade B in BL)
            {
                // find same basisblade in 'value'
                foreach (RefGA.BasisBlade C in value.BasisBlades)
                {
                    if (C.bitmap == B.bitmap) // match found: get assignment string
                    {
                        // compute D = inverse(B) . C;
                        RefGA.BasisBlade Bi = (new RefGA.BasisBlade(B.bitmap, 1.0 / B.scale)).Reverse();
                        RefGA.BasisBlade D  = RefGA.BasisBlade.scp(Bi, C);

                        if (mustCast)
                        {
                            assignedStr[idx] = FT.castStr + "(" + CodeUtil.ScalarToLangString(S, FT, D) + ")";
                        }
                        else
                        {
                            assignedStr[idx] = CodeUtil.ScalarToLangString(S, FT, D);
                        }
                        break;
                    }
                }

                if (writeZeros && (assignedStr[idx] == null)) // has an assignment string been set?
                {
                    // no assignment: simply assign "0"
                    assignedStr[idx] = FT.DoubleToString(S, 0.0);
                }

                idx++;
            }
            return(assignedStr);
        } // end of GetAssignmentStrings()
Beispiel #6
0
        /// <summary>
        /// Generates code to assign <c>value</c> to a variable whose coordinate order is specified by <c>BL</c>.
        /// 
        /// For example, <c>BL</c> could be <c>[e1, e2, e3]</c> and the multivector value <c>[e1 - 2e3]</c>.
        /// Then the returned array would be <c>["1", "0", "-2"]</c>.
        /// 
        /// Parts of <c>value</c> that cannot be assigned to <c>BL</c> are silently ignored. 
        /// 
        /// Possibly, at some point we would like to generate some kind of warning?
        /// </summary>
        /// <param name="S">Specification of algebra (not used yet).</param>
        /// <param name="FT">Floating point type of assigned variable (used for casting strings).</param>
        /// <param name="mustCast">Set to true if a cast to 'FT' must be performed.</param>
        /// <param name="BL">Basis blades of assigned variable.</param>
        /// <param name="value">Multivector value to assign to the list of basis blades. 
        /// Must not contain basis blades inside the symbolic scalars of the RefGA.BasisBlades.</param>
        /// <param name="writeZeros">When true, <c>"0"</c> will be returned when no value should be assigned
        /// to some coordinate. <c>null</c> otherwise.</param>
        /// <returns>An array of strings which tell you what to assign to each coordinate.</returns>
        public static String[] GetAssignmentStrings(Specification S, FloatType FT, bool mustCast, RefGA.BasisBlade[] BL, 
            RefGA.Multivector value, bool writeZeros)
        {
            String[] assignedStr = new String[BL.Length];
            int idx = 0;

            // for each non-const coord, find out what value is (loop through all entries in value)
            foreach (RefGA.BasisBlade B in BL)
            {
                // find same basisblade in 'value'
                foreach (RefGA.BasisBlade C in value.BasisBlades)
                {
                    if (C.bitmap == B.bitmap) // match found: get assignment string
                    {
                        // compute D = inverse(B) . C;
                        RefGA.BasisBlade Bi = (new RefGA.BasisBlade(B.bitmap, 1.0 / B.scale)).Reverse();
                        RefGA.BasisBlade D = RefGA.BasisBlade.scp(Bi, C);

                        if (mustCast) assignedStr[idx] = FT.castStr + "(" + CodeUtil.ScalarToLangString(S, FT, D) + ")";
                        else assignedStr[idx] = CodeUtil.ScalarToLangString(S, FT, D);
                        break;
                    }
                }

                if (writeZeros && (assignedStr[idx] == null)) // has an assignment string been set?
                {
                    // no assignment: simply assign "0"
                    assignedStr[idx] = FT.DoubleToString(S, 0.0);
                }

                idx++;
            }
            return assignedStr;
        }
Beispiel #7
0
        /// <summary>
        /// Writes the declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'.
        /// </summary>
        public override void WriteFunction()
        {
            foreach (string floatName in m_fgs.FloatNames)
            {
                FloatType FT = m_specification.GetFloatType(floatName);

                bool computeMultivectorValue    = true;
                G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_gmv.Name, computeMultivectorValue);

                // because of lack of overloading, function names include names of argument types
                G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, m_fgs, FAI);

                // if bivector type: specialize
                if (m_gmvFunc || (!m_scalarSquare))
                {
                    // sin, cos, exp of GMV, or of SMV which does not square to scalar:
                    WriteFunction(FT, CF);
                }
                else
                {
                    // write simple specialized function:
                    int  nbTabs   = 1;
                    bool mustCast = false;

                    // setup instructions
                    List <G25.CG.Shared.Instruction> I = new List <G25.CG.Shared.Instruction>();

                    if (m_signOfSquare == 0)
                    {
                        // assign
                        I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, m_returnType, FT, mustCast, m_returnValue));
                    }
                    else
                    {
                        // alpha
                        bool alphaPtr     = false;
                        bool declareAlpha = true;
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, FT, FT, mustCast, m_alphaValue, m_alphaName, alphaPtr, declareAlpha));

                        // mul
                        if (!(IsCos(m_fgs) || IsCosh(m_fgs)))
                        {
                            I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " " + m_mulName + ";"));
                            {
                                bool mulPtr     = false;
                                bool declareMul = false;

                                List <G25.CG.Shared.Instruction> ifI = new List <G25.CG.Shared.Instruction>();
                                ifI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, m_mulValue, m_mulName, mulPtr, declareMul));

                                List <G25.CG.Shared.Instruction> elseI = new List <G25.CG.Shared.Instruction>();
                                elseI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, RefGA.Multivector.ZERO, m_mulName, mulPtr, declareMul));

                                I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, m_alphaName + " != " + FT.DoubleToString(m_specification, 0.0), ifI, elseI));
                            }
                        }

                        // assign
                        I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, m_returnType, FT, mustCast, m_returnValue));
                    }

                    Comment comment = new Comment(m_fgs.Name + " of " + FAI[0].TypeName + " (uses fast special case)");

                    m_funcName[FT.type] = CF.OutputName;

                    bool staticFunc = Functions.OutputStaticFunctions(m_specification);
                    G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, CF.OutputName, FAI, I, comment);
                } // end of 'if bivector SMV'
            }
        }         // end of WriteFunction
Beispiel #8
0
        private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C)
        {
            // assume only SMV constants for now
            G25.SMV smv = C.Type as G25.SMV;
            ConstantSMV Csmv = C as ConstantSMV;

            // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...}
            SB.Append(FT.GetMangledName(S, C.Type.GetName()));
            SB.Append(" ");
            SB.Append(FT.GetMangledName(S, C.Name));
            SB.Append(" = {");

            if (smv.NbNonConstBasisBlade == 0)
            {
                // 'C' does not allow empty structs, so there is a filler that must be initialized
                SB.Append("0");
            }
            else
            {
                if (S.m_coordStorage == COORD_STORAGE.ARRAY)
                    SB.Append("{");

                for (int c = 0; c < smv.NbNonConstBasisBlade; c++)
                {
                    if (c > 0) SB.Append(", ");
                    SB.Append(FT.DoubleToString(S, Csmv.Value[c]));
                }

                if (S.m_coordStorage == COORD_STORAGE.ARRAY)
                    SB.Append("}");
            }

            SB.AppendLine("};");
        }
Beispiel #9
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 WriteZeroFunction(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>();

            string BOOL  = CodeUtil.GetBoolType(m_specification);
            string TRUE  = CodeUtil.GetTrueValue(m_specification);
            string FALSE = CodeUtil.GetFalseValue(m_specification);

            // write the function:
            {
                int nbTabs = 1;
                // add one instruction (verbatim code)
                //I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code));

                // get largest constant coordinate:
                double largestConstCoord = 0.0;
                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++)
                    {
                        if (Math.Abs(m_smv.ConstBasisBlade(c).scale) > largestConstCoord)
                        {
                            largestConstCoord = Math.Abs(m_smv.ConstBasisBlade(c).scale);
                        }
                    }
                }

                if (largestConstCoord > 0.0) // generate code to check if largest coord > 'eps'
                {
                    I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs,
                                                                    "if (" + FT.DoubleToString(m_specification, largestConstCoord) + " > " + FAI[1].Name + ") return " + FALSE + ";"));
                }

                // 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 + ")) return " + FALSE + ";"));
                }

                // finally, return 1 if all check were OK
                I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return " + TRUE + ";"));
            }

            // because of lack of overloading, function names include names of argument types
            G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, F, FAI);
            m_funcName[FT.type] = CF.OutputName;

            // setup return type and argument:
            string returnTypeName = BOOL;

            G25.CG.Shared.FuncArgInfo returnArgument = null;

            // write function
            bool staticFunc = Functions.OutputStaticFunctions(m_specification);

            G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, F, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment);
        } // end of WriteZeroFunction()
Beispiel #10
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()
Beispiel #11
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 #12
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 = 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 #13
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)
        {
            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 #14
0
        /// <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 WriteZeroFunction(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>();

            string BOOL = CodeUtil.GetBoolType(m_specification);
            string TRUE = CodeUtil.GetTrueValue(m_specification);
            string FALSE = CodeUtil.GetFalseValue(m_specification);

            // write the function:
            {
                int nbTabs = 1;
                // add one instruction (verbatim code)
                //I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code));

                // get largest constant coordinate:
                double largestConstCoord = 0.0;
                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++)
                    {
                        if (Math.Abs(m_smv.ConstBasisBlade(c).scale) > largestConstCoord)
                            largestConstCoord = Math.Abs(m_smv.ConstBasisBlade(c).scale);
                    }
                }

                if (largestConstCoord > 0.0) // generate code to check if largest coord > 'eps'
                {

                    I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs,
                        "if (" + FT.DoubleToString(m_specification, largestConstCoord) + " > " + FAI[1].Name + ") return " + FALSE + ";"));
                }

                // 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 + ")) return " + FALSE + ";"));

                // finally, return 1 if all check were OK
                I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return " + TRUE + ";"));
            }

            // because of lack of overloading, function names include names of argument types
            G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, F, FAI);
            m_funcName[FT.type] = CF.OutputName;

            // setup return type and argument:
            string returnTypeName = BOOL;
            G25.CG.Shared.FuncArgInfo returnArgument = null;

            // write function
            bool staticFunc = Functions.OutputStaticFunctions(m_specification);
            G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, F, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment);
        }
Beispiel #15
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);
        }
Beispiel #16
0
        /// <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);
        }
Beispiel #17
0
        /// <summary>
        /// Generates code for returning a scalar value. The input is a scalar-valued multivector.
        /// </summary>
        /// <param name="S">Specification (used for output language).</param>
        /// <param name="FT">Floating point type which must be returned.</param>
        /// <param name="mustCast">Set to true if the returned value must be cast to <c>FT</c>, that is
        /// if you are not sure that the multivector has the same float type as the return type <c>FT</c>.</param>
        /// <param name="value">The symbolic multivector value to be returned.</param>
        /// <returns>Code for returning a scalar value.</returns>
        public static string GenerateScalarReturnCode(Specification S, FloatType FT, bool mustCast, RefGA.Multivector value)
        {
            if (value.IsZero())
            {
                return "return " + FT.DoubleToString(S, 0.0) + ";";
            }
            else
            {

                return "return " +
                    ((mustCast) ? (FT.castStr + "(") : "") +
                    CodeUtil.ScalarToLangString(S, FT, value.BasisBlades[0]) +
                    ((mustCast) ? ")" : "") +
                    ";";
            }
        }
Beispiel #18
0
        /// <summary>
        /// Should write the declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'.
        /// </summary>
        public override void WriteFunction()
        {
            foreach (string floatName in m_fgs.FloatNames)
            {
                FloatType FT = m_specification.GetFloatType(floatName);

                bool computeMultivectorValue    = true;
                G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_gmv.Name, computeMultivectorValue);

                // generate comment
                Comment comment = new Comment(
                    m_fgs.AddUserComment("Returns logarithm of " + FAI[0].TypeName + " using " + m_G25M.m_name + " metric, assuming a 3D Euclidean rotor."));

                // if scalar or specialized: generate specialized function
                if (m_gmvFunc)
                {
                    StringBuilder declSB = m_cgd.m_declSB;
                    bool          inline = false; // never inline GMV functions
                    StringBuilder defSB  = (inline) ? m_cgd.m_inlineDefSB : m_cgd.m_defSB;

                    // because of lack of overloading, function names include names of argument types
                    G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, m_fgs, FAI);

                    m_funcName[FT.type] = CF.OutputName;

                    // setup hashtable with template arguments:
                    System.Collections.Hashtable argTable = new System.Collections.Hashtable();
                    argTable["S"]                = m_specification;
                    argTable["functionName"]     = m_funcName[FT.type];
                    argTable["FT"]               = FT;
                    argTable["mvType"]           = FT.GetMangledName(m_specification, m_specification.m_GMV.Name);
                    argTable["setPlaneFuncName"] = getSetPlaneFuncName();
                    argTable["scalarGpFuncName"] = m_scalarGpFunc[floatName];
                    argTable["norm2FuncName"]    = m_norm2Func[floatName];
                    argTable["grade2FuncName"]   = m_grade2Func[floatName];

                    if (m_specification.OutputCppOrC())
                    {
                        // header
                        m_cgd.m_cog.EmitTemplate(declSB, "logEuclideanHeader", argTable);
                    }

                    // source
                    m_cgd.m_cog.EmitTemplate(defSB, "logEuclidean", argTable);
                }
                else
                {// write simple specialized function:
                    // setup instructions
                    System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>();
                    {
                        int  nbTabs   = 1;
                        bool mustCast = false;
                        bool nPtr     = false;
                        bool declareN = true;


                        // get grade 2 norm, scalar part
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, FT, FT, mustCast, m_grade2norm2Value, norm2Name, nPtr, declareN));
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, FT, FT, mustCast, m_grade0Value, scalarPartName, nPtr, declareN));

                        // setup checks for grade 2 == 0, grade 0 < 0.0
                        List <G25.CG.Shared.Instruction> specialI = new List <G25.CG.Shared.Instruction>();
                        List <G25.CG.Shared.Instruction> normalI  = new List <G25.CG.Shared.Instruction>();

                        { // special cases
                            // setup checks for grade 0 < 0.0
                            List <G25.CG.Shared.Instruction> ifI   = new List <G25.CG.Shared.Instruction>();
                            List <G25.CG.Shared.Instruction> elseI = new List <G25.CG.Shared.Instruction>();

                            // either return PI * ANY_GRADE2_BLADE or 0
                            RefGA.Multivector arbRot360 = new RefGA.Multivector(new RefGA.BasisBlade(m_grade2Value.BasisBlades[0].bitmap, Math.PI));
                            ifI.Add(new G25.CG.Shared.ReturnInstruction(nbTabs + 2, m_returnType, FT, mustCast, arbRot360));                // return 360 degree rotation in arbitrary plane
                            elseI.Add(new G25.CG.Shared.ReturnInstruction(nbTabs + 2, m_returnType, FT, mustCast, RefGA.Multivector.ZERO)); // return zero if grade2 == 0 and grade0 >= 0

                            specialI.Add(new G25.CG.Shared.IfElseInstruction(nbTabs + 1, scalarPartName + " < " + FT.DoubleToString(m_specification, 0.0), ifI, elseI));
                        }

                        { // normal case
                            // where mulName = atan2(sqrt(grade2norm2), grade0) / sqrt(grade2norm2)
                            RefGA.Multivector normValue   = new RefGA.Multivector(normName);
                            RefGA.Multivector grade0Value = new RefGA.Multivector(scalarPartName);
                            normalI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, RefGA.Symbolic.UnaryScalarOp.Sqrt(new RefGA.Multivector(norm2Name)), normName, nPtr, declareN));
                            normalI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, RefGA.Symbolic.BinaryScalarOp.Atan2(normValue, grade0Value), mulName, nPtr, declareN, "/", normValue));

                            // result = input / n2
                            normalI.Add(new G25.CG.Shared.ReturnInstruction(nbTabs + 1, m_returnType, FT, mustCast, m_returnValue));
                        }

                        I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, norm2Name + " <= " + FT.DoubleToString(m_specification, 0.0), specialI, normalI));
                    }

                    // because of lack of overloading, function names include names of argument types
                    G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, m_fgs, FAI);

                    m_funcName[FT.type] = CF.OutputName;

                    bool staticFunc = Functions.OutputStaticFunctions(m_specification);
                    G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, CF.OutputName, FAI, I, comment);
                }
            }
        } // end of WriteFunction
Beispiel #19
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 #20
0
        } // end of WriteExFunction

        /// <summary>
        /// Writes the declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'.
        /// </summary>
        public override void WriteFunction()
        {
            //G25.SMV smv = m_specification.GetSMV(m_SMVname);

            foreach (string floatName in m_fgs.FloatNames)
            {
                FloatType FT = m_specification.GetFloatType(floatName);

                m_fgs.m_argumentTypeNames[0] = FT.type;
                bool computeMultivectorValue    = false;
                G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, 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, m_fgs, FAI);

                WriteExFunction(FT, CF.OutputName + "_ex");

                System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>();
                int nbTabs = 1;
                I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " " + MINIMUM_NORM + " = " + FT.DoubleToString(m_specification, 0.0001) + ";"));
                I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " " + LARGEST_COORDINATE + " = " + FT.DoubleToString(m_specification, 4.0) + ";"));
                I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs,
                                                                ((m_specification.OutputC()) ? "" : "return ") +
                                                                CF.OutputName + "_ex(" +
                                                                ((m_specification.OutputC()) ? (G25.fgs.RETURN_ARG_NAME + ", ") : "") +
                                                                FAI[0].Name + ", minimumNorm, " + FAI[0].Name + " * largestCoordinate);"));

                // generate comment
                Comment comment = new Comment(m_fgs.AddUserComment("Returns random " + m_SMVname + " with a scale in the interval [0, scale)"));

                G25.CG.Shared.FuncArgInfo returnArgument = null;
                if (m_specification.OutputC())
                {
                    returnArgument = new G25.CG.Shared.FuncArgInfo(m_specification, m_fgs, -1, FT, m_SMVname, false); // false = compute value
                }
                string returnTypeName = FT.GetMangledName(m_specification, m_SMVname);
                bool   staticFunc     = Functions.OutputStaticFunctions(m_specification);
                G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment);
            }
        } // end of WriteFunction
Beispiel #21
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