Beispiel #1
0
        /// <param name="S"></param>
        /// <param name="FT"></param>
        /// <param name="M"></param>
        /// <param name="d">1 -> generate dual, d = 0 -> generate undual</param>
        /// <param name="g1"></param>
        /// <param name="gd"></param>
        /// <param name="name1"></param>
        /// <param name="name2"></param>
        /// <param name="name3"></param>
        /// <returns>The code to compute a (un)dual at runtime using the geometric product tables.</returns>
        public static string GetRuntimeDualCode(G25.Specification S, G25.FloatType FT, G25.Metric M,
                                                int d, int g1, int gd,
                                                string name1, string name2, string name3)
        {
            // get pseudoscalar
            RefGA.Multivector I = RefGA.Multivector.GetPseudoscalar(S.m_dimension);
            if (d == 1) // if dual: use inverse I
            {
                I = RefGA.Multivector.VersorInverse(I, M.m_metric);
            }

            // get grade/group of pseudoscalar in GMV
            int g2 = S.m_GMV.GetGroupIdx(I.BasisBlades[0]);

            // get sign of pseudo scalar basis blade in GMV:
            double IbladeSign = S.m_GMV.Group(g2)[0].scale;

            string tmpArrayCode;

            if (S.OutputCppOrC())
            {
                tmpArrayCode = "\t" + FT.type + " " + name2 + "[1] = {" + FT.DoubleToString(S, IbladeSign * I.BasisBlades[0].scale) + "};\n";
            }
            else
            {
                tmpArrayCode = "\t\t" + FT.type + "[] " + name2 + " = new " + FT.type + "[]{" + FT.DoubleToString(S, IbladeSign * I.BasisBlades[0].scale) + "};\n\t";
            }

            return
                (tmpArrayCode +
                 "\t" + GPparts.GetGPpartFunctionName(S, FT, M, g1, g2, gd) + "(" + name1 + ", " + name2 + ", " + name3 + ");\n");
        }
Beispiel #2
0
        /// <summary>
        /// Applies 'm_postOp m_postOpValue' to 'valueStr'.
        /// </summary>
        /// <param name="S">Specification of algebra.</param>
        /// <param name="cgd">Not used yet.</param>
        /// <param name="valueStr">The array of value strings to which the postop should be applied</param>
        /// <param name="BL">Not used yet. May be used later on to known what basis blade each valueStr refers to.</param>
        public void ApplyPostOp(Specification S, G25.CG.Shared.CGdata cgd, RefGA.BasisBlade[] BL, String[] valueStr)
        {
            if (m_postOp == null)
            {
                return;
            }

            // TODO: currently only for *= and /=

            // get string of value:
            string postOpValueStr;

            RefGA.Multivector sc = m_postOpValue.ScalarPart();
            if (sc.IsZero())
            {
                postOpValueStr = CodeUtil.ScalarToLangString(S, m_floatType, RefGA.BasisBlade.ZERO);
            }
            else
            {
                postOpValueStr = CodeUtil.ScalarToLangString(S, m_floatType, sc.BasisBlades[0]);
            }

            // apply "m_postOp postOpValueStr" to all valueStr
            for (int i = 0; i < valueStr.Length; i++)
            {
                valueStr[i] = "(" + valueStr[i] + ")" + m_postOp + ((m_mustCast) ? m_floatType.castStr : "") + "(" + postOpValueStr + ")";
            }
        }
Beispiel #3
0
        } // end of WriteSetCopy()

        /// <summary>
        /// Writes a function to copy the value of one SMV struct to another with a different floating point type, for all combinations of floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetCopyCrossFloat(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType dstFT, G25.SMV smv)
        {
            foreach (G25.FloatType srcFT in S.m_floatTypes)
            {
                if (srcFT.type == dstFT.type)
                {
                    continue;
                }

                cgd.m_defSB.AppendLine("");

                //string srcClassName = srcFT.GetMangledName(smv.Name);
                //string dstClassName = dstFT.GetMangledName(S, smv.Name);
                string funcName = GMV.GetSetFuncName(S);
                bool   mustCast = dstFT.MustCastIfAssigned(S, srcFT);

                G25.fgs F = new G25.fgs(funcName, funcName, "", new String[] { smv.Name }, null, new String[] { srcFT.type }, null, null, null); // null, null, null = metricName, comment, options
                F.InitArgumentPtrFromTypeNames(S);
                bool computeMultivectorValue = false;
                int  nbArgs = 1;
                G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, srcFT, null, computeMultivectorValue);

                RefGA.Multivector value = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smv, FAI[0].Name, FAI[0].Pointer);

                string dstName = G25.CG.Shared.SmvUtil.THIS;
                bool   dstPtr  = false;

                bool staticFunc = false;
                G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                S.m_inlineSet, staticFunc, "void", null, funcName, null, FAI, dstFT, mustCast, smv, dstName, dstPtr, value);
            }
        } // end of WriteSetCopyCrossFloat()
Beispiel #4
0
        } // end of WriteSetArray()

        /// <summary>
        /// Writes a function to copy the value of one SMV struct to another, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteCopy(Specification S, G25.CG.Shared.CGdata cgd)
        {
            //StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
//                            if (smv.NbNonConstBasisBlade == 0) continue;

                    string className = FT.GetMangledName(S, smv.Name);
                    string funcName  = className + "::set";
                    bool   mustCast  = false;

                    G25.fgs F = new G25.fgs(funcName, funcName, "", new String[] { smv.Name }, null, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    bool computeMultivectorValue = false;
                    int  nbArgs = 1;
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, null, computeMultivectorValue);


                    RefGA.Multivector value = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smv, FAI[0].Name, FAI[0].Pointer);

                    string dstName = G25.CG.Shared.SmvUtil.THIS;
                    bool   dstPtr  = true;

                    bool staticFunc = false;
                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                    S.m_inlineSet, staticFunc, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, value);
                }
            }
        } // end of WriteCopy()
Beispiel #5
0
        /// <summary>
        /// Takes a general multivector specification (G25.GMV) and converts it into a one symbolic multivector per group/grade part.
        ///
        /// The symbolic weights of the multivector are the coordinates of the GMV, labelled according to 'gmvName'.
        /// Currently, the indices start at zero for each group.
        /// </summary>
        /// <param name="S">Specification of the algebra. Used for the access convention (. or ->) and for how to name the coordinates ([0] or e1, e2, e3).</param>
        /// <param name="gmv">The specification of the general multivector.</param>
        /// <param name="gmvName">Name the variable should have.</param>
        /// <param name="ptr">Is 'gmvName' a pointer? (not used currently)</param>
        /// <param name="groupIdx">Index of group/grade to convert (use -1 for all groups)</param>
        /// <returns></returns>
        public static RefGA.Multivector[] GMVtoSymbolicMultivector(Specification S, G25.GMV gmv, String gmvName, bool ptr, int groupIdx)
        {
            RefGA.Multivector[] R = new RefGA.Multivector[gmv.NbGroups];

            //String accessStr = (ptr) ? "->" : ".";

            for (int g = 0; g < gmv.NbGroups; g++)
            {
                if ((groupIdx >= 0) && (g != groupIdx))
                {
                    continue;                                     // only one group requested?
                }
                RefGA.BasisBlade[] B = gmv.Group(g);
                RefGA.BasisBlade[] L = new RefGA.BasisBlade[B.Length];
                for (int i = 0; i < B.Length; i++)
                {
                    RefGA.BasisBlade b             = B[i];
                    String           fullCoordName = gmvName + "[" + i + "]";
                    // merge
                    L[i] = new RefGA.BasisBlade(b.bitmap, b.scale, fullCoordName);
                }
                R[g] = new RefGA.Multivector(L);
            }

            return(R);
        } // end of function GMVtoSymbolicMultivector()
Beispiel #6
0
 /// <summary>
 /// Instruction for generating code for an assignment to or a return of a variable.
 /// </summary>
 /// <param name="nbTabs">How many tabs to put in front of code.</param>
 /// <param name="T">Type of assigned variable.</param>
 /// <param name="FT">Floating point type of coordinates of assigned variable.</param>
 /// <param name="mustCast">When assigning to variable, should the coordinates be cast to FT?</param>
 /// <param name="value">The assigned value.</param>
 public AssignOrReturnInstruction(int nbTabs, G25.VariableType T, G25.FloatType FT, bool mustCast, RefGA.Multivector value)
     : base(nbTabs)
 {
     m_type      = T;
     m_floatType = FT;
     m_mustCast  = mustCast;
     m_value     = value;
 }
Beispiel #7
0
        } // end of WriteSet()

        /// <summary>
        /// Writes a function to set an SMV struct to an array of specified coordinates, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetArray(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB  = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            declSB.AppendLine("");
            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.NbNonConstBasisBlade == 0)
                    {
                        continue;
                    }

                    string typeName = FT.GetMangledName(S, smv.Name);
                    string funcName = typeName + "_setArray";
                    bool   mustCast = false;

                    string[] argTypename = new string[1] {
                        FT.type
                    };
                    string[] argName = new string[1] {
                        "A"
                    };

                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    for (int i = 0; i < smv.NbNonConstBasisBlade; i++)
                    {
                        RefGA.BasisBlade B = smv.NonConstBasisBlade(i);
                        //argTypename[i] = FT.type;
                        String coordStr = argName[0] + "[" + i + "]";
                        //argName[i] = coordStr;
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);


                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    F.SetArgumentPtr(0, true);                                                                                         // first argument is a pointer to array

                    bool computeMultivectorValue             = false;
                    G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue);
                    int nbArgs = 1; // one array of coordinates
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, null, computeMultivectorValue);


                    declSB.AppendLine("/** Sets " + typeName + " to specified coordinates */");

                    bool staticFunc = false;
                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                    S.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, mvValue);
                }
            }
        } // end of WriteSetArray()
Beispiel #8
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            m_ipType = GetIpType(m_specification, m_fgs);

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_smv1    = tmpFAI[0].Type as G25.SMV;
            m_smv2    = tmpFAI[1].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                if (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT)
                {
                    m_fgs.m_returnTypeName = m_gmv.Name;// gmv * gmv = gmv
                }
                else
                {
                    m_fgs.ReturnTypeName = FT.type;
                }
            }
            else
            {
                // compute return value
                m_returnValue = RefGA.Multivector.ip(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M, m_ipType);

                // round value if required by metric
                if (m_G25M.m_round)
                {
                    m_returnValue = m_returnValue.Round(1e-14);
                }

                // get name of return type
                if ((m_fgs.ReturnTypeName.Length == 0) && (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT))
                {
                    m_fgs.ReturnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
                else
                {
                    m_fgs.ReturnTypeName = FT.type;
                }
            }
        }
Beispiel #9
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);
        }
Beispiel #10
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc     = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_trueGmvFunc = (!tmpFAI[0].IsScalarOrSMV()) && (!tmpFAI[1].IsScalarOrSMV());
            m_arg1isGmv   = !tmpFAI[0].IsScalarOrSMV();
            m_arg2isGmv   = !tmpFAI[1].IsScalarOrSMV();
            m_smv1        = tmpFAI[0].Type as G25.SMV;
            m_smv2        = tmpFAI[1].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;           // gmv * gmv = gmv
            }
            else
            {
                // compute return value
                m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[1].MultivectorValue[0]);
                m_n2Value      = RefGA.Multivector.gp(m_reverseValue, tmpFAI[1].MultivectorValue[0], m_M);
                if (m_G25M.m_round)
                {
                    m_n2Value = m_n2Value.Round(1e-14);
                }

                //m_returnValue = RefGA.Multivector.gp(RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M),
                //  RefGA.Symbolic.ScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName))));
                m_returnValue = RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M);

                // round value if required by metric
                if (m_G25M.m_round)
                {
                    m_returnValue = m_returnValue.Round(1e-14);
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            if (m_G25M.m_metric.IsDegenerate())
            {
                throw new G25.UserException("Cannot generate dual functions for degenerate metrics.");
            }

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;            // dual(gmv) = gmv
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // compute return value
                if (IsDual(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.Dual(tmpFAI[0].MultivectorValue[0], m_M);
                }
                else if (IsUndual(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.Undual(tmpFAI[0].MultivectorValue[0], m_M);
                }

                // round value if required by metric
                if (m_G25M.m_round)
                {
                    m_returnValue = m_returnValue.Round(1e-14);
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            m_isNorm2 = IsNorm2(m_fgs);

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, new RefGA.Multivector("x")).GetName();            // norm(gmv) = scalar
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // compute return value
                if (m_isNorm2)
                {
                    m_returnValue = tmpFAI[0].MultivectorValue[0].Norm_r2(m_M);
                }
                else
                {
                    m_returnValue = RefGA.Symbolic.UnaryScalarOp.Abs(tmpFAI[0].MultivectorValue[0].Norm_r(m_M));
                }

                // round value if required by metric
                if (m_G25M.m_round)
                {
                    m_returnValue = m_returnValue.Round(1e-14);
                }

                // avoid null return value because that might return in getting the wrong return type
                RefGA.Multivector nonZeroReturnValue = (m_returnValue.IsZero()) ? RefGA.Multivector.ONE : m_returnValue;

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, nonZeroReturnValue).GetName();
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;            // dual(gmv) = gmv
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // get symbolic result
                m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[0].MultivectorValue[0]);
                m_n2Value      = RefGA.Multivector.gp(m_reverseValue, tmpFAI[0].MultivectorValue[0], m_M);
                if (m_G25M.m_round)
                {
                    m_n2Value = m_n2Value.Round(1e-14);
                }

                if (m_n2Value.HasSymbolicScalars() || (!m_n2Value.IsScalar()) || m_n2Value.IsZero())
                {
                    m_inverseValue = RefGA.Multivector.gp(m_reverseValue,
                                                          RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName))));
                }
                else
                {
                    m_inverseValue = RefGA.Multivector.gp(m_reverseValue, new RefGA.Multivector(1.0 / m_n2Value.RealScalarPart()));
                    m_n2Value      = null;
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_inverseValue).GetName();
                }
            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }
Beispiel #14
0
 /// <summary>
 /// Returns the SMV type that can hold an image of a basis vector.
 /// </summary>
 public static G25.SMV GetRangeVectorType(Specification S, G25.FloatType FT, CGdata cgd, G25.SOM som)
 {
     RefGA.Multivector rangeVectorValue = new RefGA.Multivector(som.RangeVectors);
     G25.SMV           rangeVectorType  = (G25.SMV)G25.CG.Shared.SpecializedReturnType.FindTightestMatch(S, rangeVectorValue, FT);
     if (rangeVectorType == null) // type is missing, add it and tell user to add it to XML
     {
         rangeVectorType = (G25.SMV)G25.CG.Shared.SpecializedReturnType.CreateSyntheticSMVtype(S, cgd, FT, rangeVectorValue);
     }
     return(rangeVectorType);
 }
Beispiel #15
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;            // toggle_sign(gmv) = gmv
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // compute return value
                if (IsNegate(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.Negate(tmpFAI[0].MultivectorValue[0]);
                }
                else if (IsReverse(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.Reverse(tmpFAI[0].MultivectorValue[0]);
                }
                else if (IsCliffordConjugate(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.CliffordConjugate(tmpFAI[0].MultivectorValue[0]);
                }
                else if (IsGradeInvolution(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.GradeInvolution(tmpFAI[0].MultivectorValue[0]);
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
        }
Beispiel #16
0
        } // end of WriteSet()

        /// <summary>
        /// Writes a function to set an SMV struct to an array of specified coordinates, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetArray(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.NbNonConstBasisBlade == 0)
                    {
                        continue;
                    }

                    string className = FT.GetMangledName(S, smv.Name);
                    string funcName  = className + "::set";
                    bool   mustCast  = false;

                    string[] argTypename = new string[2] {
                        G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM, FT.type
                    };
                    string[] argName = new string[2] {
                        "co", "A"
                    };

                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    for (int i = 0; i < smv.NbNonConstBasisBlade; i++)
                    {
                        RefGA.BasisBlade B        = smv.NonConstBasisBlade(i);
                        String           coordStr = argName[1] + "[" + i + "]";
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);

                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    F.SetArgumentPtr(1, true);                                                                                         // second argument is a pointer to array

                    bool computeMultivectorValue = false;
                    int  NB_ARGS = 2; // enum + one array of coordinates
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, null, computeMultivectorValue);

                    string dstName = G25.CG.Shared.SmvUtil.THIS;
                    bool   dstPtr  = true;

                    bool staticFunc = false;
                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                    S.m_inlineSet, staticFunc, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, mvValue);
                }
            }
        } // end of WriteSetArray()
Beispiel #17
0
        /// <summary>
        /// Writes a function to set an SMV struct to specified coordinates, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetCoords(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.NbNonConstBasisBlade == 0)
                    {
                        continue;
                    }

                    string className = FT.GetMangledName(S, smv.Name);
                    string funcName  = className + "::set";
                    bool   mustCast  = false;


                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    int      NB_ARGS     = 1 + smv.NbNonConstBasisBlade;
                    string[] argTypename = new String[NB_ARGS];
                    string[] argName     = new String[NB_ARGS];
                    argTypename[0] = G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM;
                    argName[0]     = "co";
                    for (int i = 0; i < smv.NbNonConstBasisBlade; i++)
                    {
                        RefGA.BasisBlade B = smv.NonConstBasisBlade(i);
                        argTypename[i + 1] = FT.type;
                        string coordStr = "_" + smv.GetCoordLangID(i, S, COORD_STORAGE.VARIABLES);
                        argName[i + 1] = coordStr;
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);


                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    bool computeMultivectorValue = false;
                    //G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue);
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, null, computeMultivectorValue);

                    string dstName = G25.CG.Shared.SmvUtil.THIS;
                    bool   dstPtr  = true;

                    bool staticFunc = false;
                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                    S.m_inlineSet, staticFunc, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, mvValue);
                }
            }
        } // end of WriteSet()
Beispiel #18
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        ///  - Optionally fill in F.m_argumentPtr
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc     = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_trueGmvFunc = (!tmpFAI[0].IsScalarOrSMV()) && (!tmpFAI[1].IsScalarOrSMV());
            m_smv1        = tmpFAI[0].Type as G25.SMV;
            m_smv2        = tmpFAI[1].Type as G25.SMV;


            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;           // gmv + gmv = gmv
            }
            else
            {
                // compute return value
                if (IsAdd(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.Add(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]);
                }
                else if (IsSubtract(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.Subtract(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]);
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
        }
Beispiel #19
0
        } // end of WriteSetZero()

        /// <summary>
        /// Writes a function to set an SMV struct to a scalar coordinate, for all floating point types which have a non-constant scalar coordinate.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetScalar(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB  = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            declSB.AppendLine("");
            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    // if (smv.NbNonConstBasisBlade == 0) continue;
                    if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0)
                    {
                        continue;                                              // if no scalar coordinate, continue
                    }
                    string typeName = FT.GetMangledName(S, smv.Name);
                    string funcName = typeName + "_setScalar";
                    bool   mustCast = false;


                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    const int NB_COORDS            = 1;
                    string[]  argTypename          = new string[NB_COORDS];
                    string[]  argName = new string[NB_COORDS];
                    {
                        RefGA.BasisBlade B = RefGA.BasisBlade.ONE;
                        argTypename[0] = FT.type;
                        argName[0]     = "scalarVal";
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, argName[0]));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);

                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    bool computeMultivectorValue = false;
                    G25.CG.Shared.FuncArgInfo   returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue);
                    G25.CG.Shared.FuncArgInfo[] FAI            = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_COORDS, FT, null, computeMultivectorValue);

                    declSB.AppendLine("/** Sets " + typeName + " to a scalar value */");

                    bool staticFunc = false;
                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                    S.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, mvValue);
                }
            }
        }
Beispiel #20
0
        } // end of WriteCopy()

        /// <summary>
        /// Writes a function to copy the value of one SMV struct to another with a different floating point type, for all combinations of floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteCopyCrossFloat(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB  = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;

            declSB.AppendLine("");
            defSB.AppendLine("");

            foreach (G25.FloatType srcFT in S.m_floatTypes)
            {
                foreach (G25.FloatType dstFT in S.m_floatTypes)
                {
                    if (srcFT.type == dstFT.type)
                    {
                        continue;
                    }
                    foreach (G25.SMV smv in S.m_SMV)
                    {
                        if (smv.NbNonConstBasisBlade == 0)
                        {
                            continue;
                        }

                        String  srcTypeName = srcFT.GetMangledName(S, smv.Name);
                        String  dstTypeName = dstFT.GetMangledName(S, smv.Name);
                        G25.fgs tmpFgs      = null;
                        String  funcName    = G25.CG.Shared.Converter.GetConverterName(S, tmpFgs, srcTypeName, dstTypeName);
                        bool    mustCast    = dstFT.MustCastIfAssigned(S, srcFT);

                        G25.fgs F = new G25.fgs(funcName, funcName, "", new String[] { smv.Name }, null, new String[] { srcFT.type }, null, null, null); // null, null, null = metricName, comment, options
                        F.InitArgumentPtrFromTypeNames(S);
                        bool computeMultivectorValue             = false;
                        G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, dstFT, smv.Name, computeMultivectorValue);
                        int nbArgs = 1;
                        G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, srcFT, null, computeMultivectorValue);

                        declSB.AppendLine("/** Copies " + srcTypeName + " to " + dstTypeName + ": " + returnArgument.Name + " = " + FAI[0].Name + " */");

                        RefGA.Multivector value = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, smv, FAI[0].Name, FAI[0].Pointer);

                        bool staticFunc = false;
                        G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                                        S.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, dstFT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, value);
                    }
                }
            }
        } // end of WriteCopyCrossFloat()
Beispiel #21
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            m_gradeIdx = GetGradeIdx(m_fgs.Name);

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name }
            }
            ;

            // supplement the extra 'int' argument
            if ((m_gradeIdx < 0) && (m_fgs.ArgumentTypeNames.Length == 1))
            {
                m_fgs.m_argumentTypeNames     = new string[] { m_fgs.ArgumentTypeNames[0], G25.GroupBitmapType.GROUP_BITMAP };
                m_fgs.m_argumentVariableNames = new string[] { m_fgs.m_argumentVariableNames[0], "groupBitmap" };
            }

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();
            m_smv     = tmpFAI[0].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;            // grade(gmv) = gmv
            }
            else
            { // compute return value
                m_returnValue = tmpFAI[0].MultivectorValue[0].ExtractGrade(m_gradeIdx);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
        }
Beispiel #22
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        ///
        /// As the return type is required, many functions will also compute the return value and other info
        /// needed for generating the code inside this function. These intermediate values are then
        /// stored in class variables so they can be reused in WriteFunction()
        /// </summary>
        public override void CompleteFGS()
        {
            NB_ARGS = m_fgs.NbArguments; // all arguments must be explicitly listed

            // in C language, all arguments are pointers
            if (m_fgs.ArgumentPtr.Length == 0)
            {
                bool ptr = m_specification.OutputC();
                m_fgs.m_argumentPtr = new bool[] { ptr, ptr };
                m_fgs.m_argumentArr = new bool[] { false, false };
            }

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_smv1 = tmpFAI[0].Type as G25.SMV;
            m_smv2 = tmpFAI[1].Type as G25.SMV;

            { // compute return value
                // compute symbolic distance squared value
                m_returnValue = RefGA.Multivector.gp(
                    RefGA.Multivector.ScalarProduct(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M),
                    -2.0);

                // apply sqrt(fabs()) if distance should not be squared:
                if (IsDistance(m_fgs))
                {
                    m_returnValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(RefGA.Symbolic.UnaryScalarOp.Abs(m_returnValue));
                }

                // round value if required by metric
                if (m_G25M.m_round)
                {
                    m_returnValue = m_returnValue.Round(1e-14);
                }
            }

            // get name of return type
            if (m_fgs.m_returnTypeName.Length == 0)
            {
                m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        } // end of CompleteFGS()
Beispiel #23
0
        /// <summary>
        /// Converts a symbolic multivector value to a textual description of the specialized multivector 
        /// type that would be required to store that value. This is used for presenting error messages 
        /// to users when a suitable specialized type cannot be found for a specific multivector value.
        /// </summary>
        /// <param name="S">Specification, used for basis vector names.</param>
        /// <param name="value">The value to describe.</param>
        /// <returns>Textual description of the type that can store 'value'.</returns>
        public static String MultivectorToTypeDescription(G25.Specification S, RefGA.Multivector value)
        {
            StringBuilder SB = new StringBuilder();

            bool appendSpace = false;
            foreach (RefGA.BasisBlade B in value.BasisBlades)
            {
                if (appendSpace) SB.Append(" ");

                SB.Append(new RefGA.BasisBlade(B.bitmap).ToString(S.m_basisVectorNames));
                if (B.symScale == null)
                    SB.Append("=" + B.scale);

                appendSpace = true;
            }
            return SB.ToString();
        }
Beispiel #24
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool      computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;            // unit(gmv) = gmv
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // get symbolic result
                m_grade0Value = tmpFAI[0].MultivectorValue[0].ExtractGrade(0);
                m_grade2Value = tmpFAI[0].MultivectorValue[0].ExtractGrade(2);
                RefGA.Multivector reverseGrade2Value = RefGA.Multivector.Reverse(m_grade2Value);
                m_grade2norm2Value = RefGA.Multivector.gp(reverseGrade2Value, m_grade2Value, m_M);

                m_returnValue = RefGA.Multivector.gp(m_grade2Value, new RefGA.Multivector(mulName)); // where mulName = atan2(sqrt(grade2norm2), grade0) / sqrt(grade2norm2)

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }
Beispiel #25
0
        } // end of WriteAssignmentFunction()

        /// <summary>
        ///
        /// </summary>
        /// <param name="S">Used for all kinds of stuff.</param>
        /// <param name="cgd">Results go into cgd.m_defSB, and so on</param>
        /// <param name="inline">Should the function we inline?</param>
        /// <param name="staticFunc">Static function?</param>
        /// <param name="functionName">The name of the function which is to be generated.</param>
        /// <param name="arguments">Array of FuncArg which describes the arguments of the function.</param>
        /// <param name="returnFT">Floating point type of return variable.</param>
        /// <param name="mustCastDst">set to true if coordinates of 'value' must be cast to 'dstFT'.</param>
        /// <param name="returnType">The type to be returned.</param>
        /// <param name="value">Value to be written to the returned.</param>
        public static void WriteReturnFunction(
            Specification S, G25.CG.Shared.CGdata cgd,
            bool inline, bool staticFunc, string functionName,
            FuncArgInfo[] arguments,
            FloatType returnFT, bool mustCastDst, G25.VariableType returnType, RefGA.Multivector value)
        {
            string returnTypeName;
            bool   returnSMV = returnType is G25.SMV;

            if (returnSMV)
            {
                returnTypeName = returnFT.GetMangledName(S, (returnType as G25.SMV).Name);
            }
            else
            {
                returnTypeName = (returnType as G25.FloatType).type;
            }

            // where the definition goes:
            StringBuilder defSB = (inline) ? cgd.m_inlineDefSB : cgd.m_defSB;

            // declaration:
            if (S.OutputCppOrC())
            {
                WriteDeclaration(cgd.m_declSB, S, cgd, false, staticFunc, returnTypeName, functionName, null, arguments);
                cgd.m_declSB.AppendLine(";");
            }

            WriteDeclaration(defSB, S, cgd, inline, staticFunc, returnTypeName, functionName, null, arguments);


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

            int nbTabs           = 1;
            ReturnInstruction RI = new ReturnInstruction(nbTabs, returnType, returnFT, mustCastDst, value);

            RI.Write(defSB, S, cgd);

            defSB.Append("\n");

            defSB.AppendLine("}");
        } // end of WriteReturnFunction()
Beispiel #26
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, FT.type }
            }
            ;

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            bool computeMultivectorValue = true;

            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name;            // div(gmv, scalar) = gmv
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                RefGA.Multivector inputValue = tmpFAI[0].MultivectorValue[0];
                RefGA.Multivector divValue   = RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(tmpFAI[1].Name));
                m_returnValue = RefGA.Multivector.gp(inputValue, divValue);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                {
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
            }
        }
Beispiel #27
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 #28
0
        /// <summary>
        /// Takes a general multivector specification (G25.GMV) and converts it into a one symbolic multivector per group/grade part.
        /// 
        /// The symbolic weights of the multivector are the coordinates of the GMV, labelled according to 'gmvName'.
        /// Currently, the indices start at zero for each group.
        /// </summary>
        /// <param name="S">Specification of the algebra. Used for the access convention (. or ->) and for how to name the coordinates ([0] or e1, e2, e3).</param>
        /// <param name="gmv">The specification of the general multivector.</param>
        /// <param name="gmvName">Name the variable should have.</param>
        /// <param name="ptr">Is 'gmvName' a pointer? (not used currently)</param>
        /// <param name="groupIdx">Index of group/grade to convert (use -1 for all groups)</param>
        /// <returns></returns>
        public static RefGA.Multivector[] GMVtoSymbolicMultivector(Specification S, G25.GMV gmv, String gmvName, bool ptr, int groupIdx)
        {
            RefGA.Multivector[] R = new RefGA.Multivector[gmv.NbGroups];

            //String accessStr = (ptr) ? "->" : ".";

            for (int g = 0; g < gmv.NbGroups; g++) {
                if ((groupIdx >= 0) && (g != groupIdx)) continue; // only one group requested?

                RefGA.BasisBlade[] B = gmv.Group(g);
                RefGA.BasisBlade[] L = new RefGA.BasisBlade[B.Length];
                for (int i = 0; i < B.Length; i++)
                {
                    RefGA.BasisBlade b = B[i];
                    String fullCoordName = gmvName + "[" + i + "]";
                    // merge
                    L[i] = new RefGA.BasisBlade(b.bitmap, b.scale, fullCoordName);
                }
                R[g] = new RefGA.Multivector(L);
            }

            return R;
        }
Beispiel #29
0
        } // end of WriteSetZero()

        /// <summary>
        /// Writes a function to set an SMV struct to a scalar coordinate, for all floating point types which have a non-constant scalar coordinate.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetScalar(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SMV smv)
        {
            //if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) return; // if no scalar coordinate, continue

            cgd.m_defSB.AppendLine("");

            //string className = FT.GetMangledName(S, smv.Name);
            string funcName = GMV.GetSetFuncName(S);
            bool   mustCast = false;

            System.Collections.ArrayList L = new System.Collections.ArrayList();
            const int NB_COORDS            = 1;

            string[] argTypename = new String[NB_COORDS];
            string[] argName     = new String[NB_COORDS];
            {
                RefGA.BasisBlade B = RefGA.BasisBlade.ONE;
                argTypename[0] = FT.type;
                argName[0]     = "scalarVal";
                L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, argName[0]));
            }
            RefGA.Multivector mvValue = new RefGA.Multivector(L);

            G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null = metricName, comment, options
            F.InitArgumentPtrFromTypeNames(S);
            bool computeMultivectorValue = false;

            G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_COORDS, FT, null, computeMultivectorValue);

            string dstName = G25.CG.Shared.SmvUtil.THIS;
            bool   dstPtr  = false;

            bool staticFunc = false;

            G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                                                            S.m_inlineSet, staticFunc, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, mvValue);
        }
Beispiel #30
0
        private static void WriteConvertingConstructor(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.fgs fgs, SMV srcSmv, SMV dstSmv)
        {
            string  srcTypeName = FT.GetMangledName(S, srcSmv.GetName());
            string  dstTypeName = FT.GetMangledName(S, dstSmv.GetName());
            string  argName     = "x";
            Comment comment     = new Comment("Converting constructor, from " + srcTypeName + " to " + dstTypeName);

            comment.Write(SB, S, 1);

            SB.AppendLine("\tpublic " + dstTypeName + "(" + srcTypeName + " " + argName + ") {");

            int  nbTabs          = 2;
            bool declareVariable = false;
            bool cast            = false;
            bool srcPtr          = false;
            bool dstPtr          = false;

            RefGA.Multivector value = Symbolic.SMVtoSymbolicMultivector(S, srcSmv, argName, srcPtr);
            AssignInstruction AI    = new AssignInstruction(nbTabs, dstSmv, FT, cast, value, SmvUtil.THIS, dstPtr, declareVariable);

            AI.Write(SB, S, cgd);

            SB.AppendLine("\t}");
        }
Beispiel #31
0
        /// <summary>
        /// Writes a function to set an SMV struct to specified coordinates, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSet(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;
            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.NbNonConstBasisBlade == 0) continue;

                    string className = FT.GetMangledName(S, smv.Name);
                    string funcName = className + "::set";
                    bool mustCast = false;

                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    int NB_ARGS = 1 + smv.NbNonConstBasisBlade;
                    string[] argTypename = new String[NB_ARGS];
                    string[] argName = new String[NB_ARGS];
                    argTypename[0] = G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM;
                    argName[0] = "co";
                    for (int i = 0; i < smv.NbNonConstBasisBlade; i++)
                    {
                        RefGA.BasisBlade B = smv.NonConstBasisBlade(i);
                        argTypename[i + 1] = FT.type;
                        string coordStr = "_" + smv.GetCoordLangID(i, S, COORD_STORAGE.VARIABLES);
                        argName[i + 1] = coordStr;
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);

                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    bool computeMultivectorValue = false;
                    //G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue);
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, null, computeMultivectorValue);

                    string dstName = G25.CG.Shared.SmvUtil.THIS;
                    bool dstPtr = true;

                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                        S.m_inlineSet, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, mvValue);
                }
            }
        }
Beispiel #32
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                m_fgs.m_returnTypeName = m_gmv.Name; // sin/cos/sinh/cosh/exp(gmv) = gmv
                m_returnType = m_gmv;
                m_inputTypeName = m_gmv.Name;
                m_returnTypeName = m_gmv.Name;
            }
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                try  // exceptions are caught below -> in that case, do a series for the SMV
                { // sin/cos/sinh/cosh/exp(smv bivector)
                    RefGA.Multivector value = tmpFAI[0].MultivectorValue[0];
                    RefGA.Multivector squareValue = RefGA.Multivector.gp(value, value, m_M);

                    String userSetSquare = m_fgs.GetOption("square");
                    if (userSetSquare != null) m_signOfSquare = (int)Math.Sign(Double.Parse(userSetSquare));
                    else
                    {
                        // the following line can throw an exception, which is caught below
                        double sqEval = RefGA.Symbolic.SymbolicUtil.EvaluateRandomSymbolicToScalar(squareValue);
                        m_signOfSquare = (int)Math.Sign(sqEval);
                    }
                    m_scalarSquare = true;

                    // compute alpha = sqrt(fabs(value^2))
                    m_alphaValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(RefGA.Symbolic.UnaryScalarOp.Abs(squareValue));

                    // use hyperbolic sin / cos or regular sin / cos for shortcuts?
                    bool hyperbolic =
                            (((IsExp(m_fgs) || IsCosh(m_fgs) || IsSinh(m_fgs)) && (m_signOfSquare > 0)) ||
                            ((IsCos(m_fgs) || IsSin(m_fgs)) && (m_signOfSquare < 0)));

                    // compute mul for SIN and EXP (assuming alpha is not zero)
                    if (IsCos(m_fgs) || m_alphaValue.IsZero()) m_mulValue = RefGA.Multivector.ONE;
                    else if (m_signOfSquare == 0) m_mulValue = RefGA.Multivector.ZERO;
                    else
                    {
                        if (hyperbolic)
                            m_mulValue = RefGA.Multivector.gp(
                                                            RefGA.Symbolic.UnaryScalarOp.Sinh(new RefGA.Multivector(m_alphaName)),
                                                            RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(m_alphaName)));
                        else m_mulValue = RefGA.Multivector.gp(
                                                            RefGA.Symbolic.UnaryScalarOp.Sin(new RefGA.Multivector(m_alphaName)),
                                                            RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(m_alphaName)));
                    }

                    // compute sin, cos part
                    RefGA.Multivector cosValue = null, sinValue = null;

                    if (m_signOfSquare == 0)
                    {
                        cosValue = RefGA.Multivector.ONE;
                        sinValue = value;
                    }
                    else
                    {
                        sinValue = RefGA.Multivector.gp(value, new RefGA.Multivector(m_mulName));
                        if (hyperbolic) cosValue = RefGA.Symbolic.UnaryScalarOp.Cosh(new RefGA.Multivector(m_alphaName));
                        else cosValue = RefGA.Symbolic.UnaryScalarOp.Cos(new RefGA.Multivector(m_alphaName));
                    }

                    // compute return value
                    if (IsExp(m_fgs)) m_returnValue = RefGA.Multivector.Add(cosValue, sinValue);
                    else if (IsCos(m_fgs) || IsCosh(m_fgs)) m_returnValue = cosValue;
                    else if (IsSin(m_fgs) || IsSinh(m_fgs)) m_returnValue = sinValue;

                    // get name of return type
                    if (m_fgs.m_returnTypeName.Length == 0)
                    {
                        m_returnType = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue);
                        m_fgs.m_returnTypeName = m_returnType.GetName();
                    }
                    else
                    {
                        m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
                    }

                }
                catch (System.Exception)
                { // sin/cos/sinh/cosh/exp(any SMV)
                    // determine return type
                    ComputeReturnTypeExpSmv(tmpFAI, FT);
                    m_inputTypeName = tmpFAI[0].TypeName;
                    m_fgs.m_returnTypeName = m_returnTypeName;
                }

            }
        }
Beispiel #33
0
        /// <summary>
        /// Computes the return type for exp(smv).
        /// Sets m_returnTypeName and m_returnType.
        /// </summary>
        protected void ComputeReturnTypeExpSmv(G25.CG.Shared.FuncArgInfo[] FAI, G25.FloatType FT)
        {
            m_returnTypeName = m_fgs.ReturnTypeName;
            if (m_returnTypeName.Length == 0)
            {
                // find out returntype
                G25.SMV inputType = FAI[0].Type as G25.SMV;
                { // determine tight return type (i.e., keep repeating the geometric product of the input type until no more new basis blades are found)
                    // We want to known which basis blades are present in inputType-to-the-power-of-infinity
                    // So which bases blades will be present in the return type?
                    bool[] present = new bool[1 << m_specification.m_dimension];
                    {
                        bool[] tried = new bool[(1 << m_specification.m_dimension) * (1 << m_specification.m_dimension)];

                        // init 'present' with the inputType
                        for (int i = 0; i < inputType.NbCoordinates; i++)
                        {
                            present[inputType.Group(0)[i].bitmap] = true;
                        }

                        // combine bitmaps (gp) until no more new bitmaps found
                        bool newBBfound = true;
                        while (newBBfound)
                        {
                            newBBfound = false;
                            for (uint i = 0; i < present.Length; i++)
                            {
                                if (!present[i]) continue;
                                for (uint j = 0; j < present.Length; j++)
                                {
                                    if (!present[j]) continue;
                                    if (tried[j * (1 << m_specification.m_dimension) + i]) continue;

                                    // remember that we tried this combo of input blades:
                                    tried[j * (1 << m_specification.m_dimension) + i] = true;

                                    RefGA.Multivector M = RefGA.Multivector.gp(new RefGA.Multivector(new RefGA.BasisBlade(i)),
                                        new RefGA.Multivector(new RefGA.BasisBlade(j)), m_G25M.m_metric);

                                    for (int k = 0; k < M.BasisBlades.Length; k++)
                                    {
                                        uint b = M.BasisBlades[k].bitmap;
                                        if (!present[b])
                                        { // this bitmap wasn't found yet, so mark it as present
                                            newBBfound = true;
                                            present[b] = true;
                                        }
                                    }
                                }
                            }
                        } // end of combine bitmaps (gp) until no more new bitmaps found
                    }

                    // construct multivector of return type, get return type
                    {
                        System.Collections.ArrayList L = new System.Collections.ArrayList();
                        for (uint i = 0; i < present.Length; i++)
                        {
                            if (!present[i]) continue;
                            else L.Add(new RefGA.BasisBlade(i, 1.0, "c" + i));
                        }
                        RefGA.Multivector RTMV = new RefGA.Multivector(L);
                        m_returnType = CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, RTMV) as G25.SMV;
                        m_returnTypeName = m_returnType.GetName();
                    }
                }
            } // end of 'find out return type name'
            else
            {
                m_returnType = m_specification.GetType(m_returnTypeName);
            }
        }
Beispiel #34
0
 /// <summary>
 /// Instruction for generating code for an assignment to or a return of a variable.
 /// 
 /// This version of the constructor allows for a 'post operation' to be applied to the 'value'.
 /// Because Gaigen 2.5 cannot (yet) find common subexpressions, it is hard to generate code like
 ///     <code>
 ///     A.c[0] = (expr) / n2;
 ///     A.c[1] = (expr) / n2;
 ///     etc
 ///     </code>
 /// because the division will distribute to all terms of expr. So instead you'd get:
 ///     <code>
 ///     A.c[0] = (expr1 / n2) + (expr2 / n2) + ... +  (exprn / n2);
 ///     A.c[1] = (expr1 / n2) + (expr2 / n2) + ... +  (exprn / n2);
 ///     etc
 ///     </code>
 /// So this hack allows one to specify a post
 /// operator (currently multiplier (<c>"*"</c>) or divisor (<c>"/"</c>) and a value to use for that purpose.
 /// </summary>
 /// <param name="nbTabs">How many tabs to put in front of code.</param>
 /// <param name="T">Type of assigned variable.</param>
 /// <param name="FT">Floating point type of coordinates of assigned variable.</param>
 /// <param name="mustCast">When assigning to variable, should the coordinates be cast to FT?</param>
 /// <param name="value">The assigned value.</param>
 /// <param name="postOp">'post operation'. Currently allows for global multiplier (<c>"*"</c>) or divisor (<c>"/"</c>).</param>
 /// <param name="postOpValue">Value to use with 'post operation' (currently must be scalar).</param>
 public AssignOrReturnInstruction(int nbTabs, G25.VariableType T, G25.FloatType FT, bool mustCast, RefGA.Multivector value, string postOp, RefGA.Multivector postOpValue)
     : base(nbTabs)
 {
     m_type = T;
     m_floatType = FT;
     m_mustCast = mustCast;
     m_value = value;
     m_postOp = postOp;
     m_postOpValue = postOpValue;
 }
Beispiel #35
0
        /// <summary>
        /// Writes a function to set a GOM struct according to vector images, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param>
        /// <param name="FT">Float type.</param>
        /// <param name="matrixMode">When true, generates code for setting from matrix instead of vector images.</param>
        /// <param name="transpose">When this parameter is true and <c>matrixMode</c> is true, generates code for setting from transpose matrix.</param>
        public static void WriteSetVectorImages(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, bool matrixMode, bool transpose)
        {
            G25.GOM gom = S.m_GOM;

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

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

            // setup array of arguments, function specification, etc
            int NB_ARGS = (matrixMode) ? 1 : gom.DomainVectors.Length;
            string[] argTypes = new string[NB_ARGS], argNames = new string[NB_ARGS];
            RefGA.Multivector[] symbolicBBvalues = new RefGA.Multivector[1 << S.m_dimension]; // symbolic basis blade values go here
            if (matrixMode)
            {
                argTypes[0] = FT.type;
                argNames[0] = "M";

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

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

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

            // setup instructions (for main function, and subfunctions for grades)
            List<G25.CG.Shared.Instruction> mainI = new List<G25.CG.Shared.Instruction>();
            List<G25.CG.Shared.Instruction>[] bladeI = new List<G25.CG.Shared.Instruction>[1 << S.m_dimension];
            {
                bool mustCast = false;
                int nbTabs = 1;
                string dstName = (S.OutputC()) ? G25.fgs.RETURN_ARG_NAME : SmvUtil.THIS;
                bool dstPtr = S.OutputCppOrC();
                bool declareDst = false;
                for (int g = 1; g < gom.Domain.Length; g++)
                {

                    for (int d = 0; d < gom.DomainForGrade(g).Length; d++)
                    {
                        G25.SMVOM smvOM = gom.DomainSmvForGrade(g)[d];
                        RefGA.BasisBlade domainBlade = gom.DomainForGrade(g)[d];

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

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

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

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

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

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

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

                        bool computeMultivectorValue = false;

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

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

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

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

                bool computeMultivectorValue = false;

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

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

                Comment comment;
                if (!matrixMode) comment = new Comment("Sets " + typeName + " from images of the domain vectors.");
                else comment = new Comment("Sets " + typeName + " from a " + (transpose ? "transposed " : "") + "matrix");
                bool inline = false; // do not inline this potentially huge function
                bool staticFunc = false;
                bool writeDecl = S.OutputC();
                G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, "void", funcNames[1], returnArgument, FAI, mainI, comment, writeDecl);
            }
        }
Beispiel #36
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // unit(gmv) = gmv
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // get symbolic result
                m_grade0Value = tmpFAI[0].MultivectorValue[0].ExtractGrade(0);
                m_grade2Value = tmpFAI[0].MultivectorValue[0].ExtractGrade(2);
                RefGA.Multivector reverseGrade2Value = RefGA.Multivector.Reverse(m_grade2Value);
                m_grade2norm2Value = RefGA.Multivector.gp(reverseGrade2Value, m_grade2Value, m_M);

                m_returnValue = RefGA.Multivector.gp(m_grade2Value, new RefGA.Multivector(mulName)); // where mulName = atan2(sqrt(grade2norm2), grade0) / sqrt(grade2norm2)

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();

            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }
Beispiel #37
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_trueGmvFunc = (!tmpFAI[0].IsScalarOrSMV()) && (!tmpFAI[1].IsScalarOrSMV());
            m_arg1isGmv = !tmpFAI[0].IsScalarOrSMV();
            m_arg2isGmv = !tmpFAI[1].IsScalarOrSMV();
            m_smv1 = tmpFAI[0].Type as G25.SMV;
            m_smv2 = tmpFAI[1].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name;// gmv * gmv = gmv
            else
            {
                // compute return value
                m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[1].MultivectorValue[0]);
                m_n2Value = RefGA.Multivector.gp(m_reverseValue, tmpFAI[1].MultivectorValue[0], m_M);
                if (m_G25M.m_round) m_n2Value = m_n2Value.Round(1e-14);

                //m_returnValue = RefGA.Multivector.gp(RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M),
                  //  RefGA.Symbolic.ScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName))));
                m_returnValue = RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M);

                // round value if required by metric
                if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        }
Beispiel #38
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // dual(gmv) = gmv
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // get symbolic result
                m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[0].MultivectorValue[0]);
                m_n2Value = RefGA.Multivector.gp(m_reverseValue, tmpFAI[0].MultivectorValue[0], m_M);
                if (m_G25M.m_round) m_n2Value = m_n2Value.Round(1e-14);

                if (m_n2Value.HasSymbolicScalars() || (!m_n2Value.IsScalar()) || m_n2Value.IsZero())
                {
                    m_inverseValue = RefGA.Multivector.gp(m_reverseValue,
                        RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName))));
                }
                else
                {
                    m_inverseValue = RefGA.Multivector.gp(m_reverseValue, new RefGA.Multivector(1.0 / m_n2Value.RealScalarPart()));
                    m_n2Value = null;
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_inverseValue).GetName();
            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }
Beispiel #39
0
 /// <summary>
 /// Returns the SMV type that can hold an image of a basis vector.
 /// </summary>
 public static G25.SMV GetRangeVectorType(Specification S, G25.FloatType FT, CGdata cgd, G25.SOM som)
 {
     RefGA.Multivector rangeVectorValue = new RefGA.Multivector(som.RangeVectors);
     G25.SMV rangeVectorType = (G25.SMV)G25.CG.Shared.SpecializedReturnType.FindTightestMatch(S, rangeVectorValue, FT);
     if (rangeVectorType == null) // type is missing, add it and tell user to add it to XML
     {
         rangeVectorType = (G25.SMV)G25.CG.Shared.SpecializedReturnType.CreateSyntheticSMVtype(S, cgd, FT, rangeVectorValue);
     }
     return rangeVectorType;
 }
Beispiel #40
0
        /// <summary>
        /// Writes functions for the copying, adding, subtracting, negating, scaling
        /// inverse scaling and Hadamard product of general multivectors, on a group by group basis.
        /// 
        /// Internally the function loops over all float types, and over all operations (8 in total)
        /// to generate all code.
        /// 
        /// This function should be called early on in the code generation process, at least
        /// before any of the <c>Get....Code()</c> functions is called.
        /// </summary>
        /// <param name="S">Specification (used for floating points types, output language, GMV).</param>
        /// <param name="cgd">Output goes here.</param>
        public static void WriteCANSparts(Specification S, CGdata cgd)
        {
            G25.GMV gmv = S.m_GMV;

            string srcName1 = "A";
            string srcName2 = "B";
            string dstName = "C";
            string epsilonName = "eps";
            string scaleName = "s";
            bool ptr = true;
            int allGroups = -1;
            bool mustCast = false;
            int nbBaseTabs = (S.OutputCSharpOrJava()) ? 1 : 0;
            int nbCodeTabs = nbBaseTabs + 1;
            bool writeZeros = false;

            // get two symbolic multivectors (with different symbolic names):
            RefGA.Multivector[] M1 = null, M2 = null;
            if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
            { // M1 and M2 and only required for full code expansion
                M1 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, srcName1, ptr, allGroups);
                M2 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, srcName2, ptr, allGroups);
            }
            RefGA.Multivector scaleM = new RefGA.Multivector(scaleName);

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                // map from code fragment to name of function
                Dictionary<string, string> generatedCode = new Dictionary<string, string>();

                for (int g1 = 0; g1 < gmv.NbGroups; g1++)
                {
                    int g2 = g1;

                    const int COPY = 0;
                    const int COPY_MUL = 1;
                    const int COPY_DIV = 2;
                    const int ADD = 3;
                    const int SUB = 4;
                    const int NEG = 5;
                    const int ADD2 = 6;
                    const int SUB2 = 7;
                    const int HP = 8;
                    const int IHP = 9;
                    const int EQUALS = 10;
                    const int ZERO = 11;
                    const int NB_OPS = 12;

                    for (int op = 0; op < NB_OPS; op++)
                    {
                        // get value of operation, name of function:
                        RefGA.Multivector value = null;
                        String funcName = null;
                        String comment = null;
                        String code = null; // code depends on code generation mode (expand or run-time)
                        switch (op)
                        {
                            case COPY:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = M1[g1];
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvCopyCode(S, cgd, g1, srcName1, dstName);
                                funcName = GetCopyPartFunctionName(S, FT, g1);
                                comment = "copies coordinates of group " + g1;
                                break;
                            case COPY_MUL:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = RefGA.Multivector.gp(scaleM, M1[g1]);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvCopyMulDivCode(S, cgd, g1, srcName1, dstName, scaleName, "*");
                                funcName = GetCopyMulPartFunctionName(S, FT, g1);
                                comment = "copies and multiplies (by " + scaleName + ") coordinates of group " + g1;
                                break;
                            case COPY_DIV:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = RefGA.Multivector.gp(M1[g1], scaleM);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvCopyMulDivCode(S, cgd, g1, srcName1, dstName, scaleName, "/");
                                funcName = GetCopyDivPartFunctionName(S, FT, g1);
                                comment = "copies and divides (by " + scaleName + ") coordinates of group " + g1;
                                break;
                            case ADD:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = M1[g1];
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAddSubNegCode(S, cgd, g1, srcName1, dstName, "+= ");
                                funcName = GetAddPartFunctionName(S, FT, g1);
                                comment = "adds coordinates of group " + g1 + " from variable " + srcName1 + " to " + dstName;
                                break;
                            case SUB:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = M1[g1];
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAddSubNegCode(S, cgd, g1, srcName1, dstName, "-= ");
                                funcName = GetSubPartFunctionName(S, FT, g1);
                                comment = "subtracts coordinates of group " + g1 + " in variable " + srcName1 + " from " + dstName;
                                break;
                            case NEG:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = RefGA.Multivector.Negate(M1[g1]);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAddSubNegCode(S, cgd, g1, srcName1, dstName, "= -");
                                funcName = GetNegPartFunctionName(S, FT, g1);
                                comment = "negate coordinates of group " + g1 + " of variable " + srcName1;
                                break;
                            case ADD2:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = RefGA.Multivector.Add(M1[g1], M2[g2]);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAdd2Sub2HpCode(S, cgd, g1, srcName1, srcName2, dstName, "+");
                                funcName = GetAdd2PartFunctionName(S, FT, g1);
                                comment = "adds coordinates of group " + g1 + " of variables " + srcName1 + " and " + srcName2;
                                break;
                            case SUB2:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    value = RefGA.Multivector.Subtract(M1[g1], M2[g2]);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAdd2Sub2HpCode(S, cgd, g1, srcName1, srcName2, dstName, "-");
                                funcName = GetSub2PartFunctionName(S, FT, g1);
                                comment = "subtracts coordinates of group " + g1 + " of variables " + srcName1 + " from " + srcName2;
                                break;
                            case HP:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                {
                                    value = RefGA.Multivector.HadamardProduct(M1[g1], M2[g2]);
                                    RefGA.Multivector correctedValue = RefGA.Multivector.InverseHadamardProduct(value, S.m_GMV.ToMultivectorValue());
                                    value = correctedValue;
                                }
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAdd2Sub2HpCode(S, cgd, g1, srcName1, srcName2, dstName, "*");
                                funcName = GetHadamardProductPartFunctionName(S, FT, g1);
                                comment = "performs coordinate-wise multiplication of coordinates of group " + g1 + " of variables " + srcName1 + " and " + srcName2;
                                break;
                            case IHP:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                {
                                    value = RefGA.Multivector.InverseHadamardProduct(M1[g1], M2[g2]);
                                    RefGA.Multivector correctedValue = RefGA.Multivector.InverseHadamardProduct(value, S.m_GMV.ToMultivectorValue());
                                    value = correctedValue;
                                }
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvAdd2Sub2HpCode(S, cgd, g1, srcName1, srcName2, dstName, "/");
                                funcName = GetInverseHadamardProductPartFunctionName(S, FT, g1);
                                comment = "performs coordinate-wise division of coordinates of group " + g1 + " of variables " + srcName1 + " and " + srcName2 + "\n(no checks for divide by zero are made)";
                                break;
                            case EQUALS:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    code = GetExpandGmvEqualsCode(S, cgd, g1, srcName1, srcName2, epsilonName);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvEqualsCode(S, cgd, g1, srcName1, srcName2, epsilonName);
                                funcName = GetEqualsPartFunctionName(S, FT, g1);
                                comment = "check for equality up to " + epsilonName + " of coordinates of group " + g1 + " of variables " + srcName1 + " and " + srcName2;
                                break;
                            case ZERO:
                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    code = GetExpandGmvZeroCode(S, cgd, g1, srcName1, epsilonName);
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    code = GetRuntimeGmvZeroCode(S, cgd, g1, srcName1, epsilonName);
                                funcName = GetZeroPartFunctionName(S, FT, g1);
                                comment = "checks if coordinates of group " + g1 + " of variable " + srcName1 + " are zero up to "  + epsilonName;
                                break;

                        }

                        // code generation for full code expansion
                        if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                        {
                            if (!((op == EQUALS) || (op == ZERO))) { // EQUALS and ZERO are different: they generate their own code
                                // get assignment code
                                int dstBaseIdx = 0;
                                code = G25.CG.Shared.CodeUtil.GenerateGMVassignmentCode(S, FT, mustCast, gmv, dstName, g1, dstBaseIdx, value, nbCodeTabs, writeZeros);

                                // replace assignment symbols if required
                                if (op == ADD) code = code.Replace("=", "+=");
                                else if (op == SUB) code = code.Replace("=", "-=");
                                else if (op == COPY_DIV) code = code.Replace("*" + scaleName, "/" + scaleName);
                            }
                        }

                        // check if code was already generated, and, if so, reuse it
                        if (generatedCode.ContainsKey(code))
                        {
                            // already generated: call that function
                            if ((op == ADD2) || (op == SUB2) || (op == HP) || (op == IHP))
                                code = new string('\t', nbCodeTabs) + generatedCode[code] + "(" + srcName1 + ", " + srcName2 + ", " + dstName + ");\n";
                            else if ((op == COPY_MUL) || (op == COPY_DIV))
                                code = new string('\t', nbCodeTabs) + generatedCode[code] + "(" + srcName1 + ", " + dstName + ", " + scaleName + ");\n";
                            else if (op == ZERO)
                                code = new string('\t', nbCodeTabs) + "return " + generatedCode[code] + "(" + srcName1 + ", " + epsilonName + ");\n";
                            else if (op == EQUALS)
                                code = new string('\t', nbCodeTabs) + "return " + generatedCode[code] + "(" + srcName1 + ", " + srcName2 + ", " + epsilonName + ");\n";
                            else code = new string('\t', nbCodeTabs) + generatedCode[code] + "(" + srcName1 + ", " + dstName + ");\n";
                        }
                        else
                        {
                            // not generated yet: remember code -> function
                            generatedCode[code] = funcName;
                        }

                        string ACCESS = "";
                        if (S.OutputJava()) ACCESS = "protected final static ";
                        else if (S.OutputCSharp()) ACCESS  = "protected internal static ";

                        string BOOL = CodeUtil.GetBoolType(S);
                        string ARR = (S.OutputCSharpOrJava()) ? "[] " : " *";
                        string CONST = (S.OutputCSharpOrJava()) ? "" : "const ";
                        string funcDecl;

                        // one or two input args, scale or not?
                        if ((op == ADD2) || (op == SUB2) || (op == HP) || (op == IHP))
                            funcDecl = ACCESS + "void " + funcName + "(" + CONST + FT.type + ARR + srcName1 + ", " + CONST + FT.type + ARR + srcName2 + ", " + FT.type + ARR + dstName + ")";
                        else if ((op == COPY_MUL) || (op == COPY_DIV))
                            funcDecl = ACCESS + "void " + funcName + "(" + CONST + FT.type + ARR + srcName1 + ", " + FT.type + ARR + dstName + ", " + FT.type + " " + scaleName + ")";
                        else if (op == ZERO)
                            funcDecl = ACCESS + BOOL + " " + funcName + "(" + CONST + FT.type + ARR + srcName1 + ", " + FT.type + " " + epsilonName + ")";
                        else if (op == EQUALS)
                            funcDecl = ACCESS + BOOL + " " + funcName + "(" + CONST + FT.type + ARR + srcName1 + ", " + CONST + FT.type + ARR + srcName2 + ", " + FT.type + " " + epsilonName + ")";
                        else funcDecl = ACCESS + "void " + funcName + "(" + CONST + FT.type + ARR + srcName1 + ", " + FT.type + ARR + dstName + ")";

                        if (S.OutputCppOrC())
                        {
                            new Comment(comment).Write(cgd.m_declSB, S, nbBaseTabs);
                            cgd.m_declSB.Append(funcDecl); cgd.m_declSB.AppendLine(";");
                        }
                        else
                        {
                            new Comment(comment).Write(cgd.m_defSB, S, nbBaseTabs);
                        }

                        // append func body:
                        cgd.m_defSB.Append('\t', nbBaseTabs);
                        cgd.m_defSB.Append(funcDecl);
                        cgd.m_defSB.AppendLine(" {");
                        cgd.m_defSB.Append(code);
                        cgd.m_defSB.Append('\t', nbBaseTabs);
                        cgd.m_defSB.AppendLine("}");
                    }
                } // end of loop over the grade of 'A'
            } // end of loop over all float types
        }
Beispiel #41
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            m_gradeIdx = GetGradeIdx(m_fgs.Name);

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name };

            // supplement the extra 'int' argument
            if ((m_gradeIdx < 0) && (m_fgs.ArgumentTypeNames.Length == 1))
            {
                m_fgs.m_argumentTypeNames = new string[] { m_fgs.ArgumentTypeNames[0], G25.GroupBitmapType.GROUP_BITMAP };
                m_fgs.m_argumentVariableNames = new string[] { m_fgs.m_argumentVariableNames[0], "groupBitmap" };
            }

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();
            m_smv = tmpFAI[0].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // grade(gmv) = gmv
            else
            { // compute return value
                m_returnValue = tmpFAI[0].MultivectorValue[0].ExtractGrade(m_gradeIdx);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        }
Beispiel #42
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 #43
0
        /// <summary>
        /// Writes a function to set an SMV struct to an array of specified coordinates, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetArray(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;
            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.NbNonConstBasisBlade == 0) continue;

                    String className = FT.GetMangledName(S, smv.Name);
                    String funcName = className + "::set";
                    bool mustCast = false;

                    String[] argTypename = new String[2] { G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM, FT.type };
                    String[] argName = new String[2]{"co", "A"};

                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    for (int i = 0; i < smv.NbNonConstBasisBlade; i++)
                    {
                        RefGA.BasisBlade B = smv.NonConstBasisBlade(i);
                        String coordStr = argName[1] + "[" + i + "]";
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);

                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    F.SetArgumentPtr(1, true); // second argument is a pointer to array

                    bool computeMultivectorValue = false;
                    int NB_ARGS = 2; // enum + one array of coordinates
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, null, computeMultivectorValue);

                    string dstName = G25.CG.Shared.SmvUtil.THIS;
                    bool dstPtr = true;

                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                        S.m_inlineSet, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, mvValue);
                }
            }
        }
Beispiel #44
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // get info on # arguments
            m_isUnit = IsApplyUnitVersor(m_fgs) || IsApplyVersorWI(m_fgs); // unit or inverse provided?
            NB_ARGS = GetNbArgs(m_fgs); // number of arguments (2 or 3)

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                m_fgs.m_argumentTypeNames = new String[NB_ARGS];
                for (int i = 0; i < NB_ARGS; i++)
                    m_fgs.m_argumentTypeNames[i] = m_gmv.Name;
            }

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);
            m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());

            m_versorMv = (G25.MV)tmpFAI[0].Type;
            m_subjectMv = (G25.MV)tmpFAI[1].Type;
            if (tmpFAI.Length > 2)
                m_inverseVersorMv = (G25.MV)tmpFAI[2].Type;

            { // get symbolic result
                // get grade of input blade:
                m_inputGradeUsage = tmpFAI[1].MultivectorValue[0].GradeUsage();

                // get basic transformed value
                m_versorValue = tmpFAI[0].MultivectorValue[0];
                m_reverseVersorValue = (IsApplyVersorWI(m_fgs)) ? tmpFAI[2].MultivectorValue[0] : RefGA.Multivector.Reverse(m_versorValue);
                m_transformedValue =
                    RefGA.Multivector.gp(
                    RefGA.Multivector.gp(m_versorValue, tmpFAI[1].MultivectorValue[0], m_M),
                    m_reverseVersorValue, m_M);

                // apply grade part selection
                m_transformedValue = m_transformedValue.ExtractGrade(RefGA.Multivector.GradeBitmapToArray(m_inputGradeUsage));

                // if rotor is not guaranteed by the user to be unit, compute norm squared
                if (!m_isUnit)
                    m_n2Value = RefGA.Multivector.ip(m_reverseVersorValue, m_versorValue, m_M, RefGA.BasisBlade.InnerProductType.LEFT_CONTRACTION);

                // round value if required by metric
                if (m_G25M.m_round)
                {
                    m_transformedValue = m_transformedValue.Round(1e-14);
                    if (m_n2Value != null)
                        m_n2Value = m_n2Value.Round(1e-14);
                }
            }

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // gmv * gmv / gmv = gmv
            else
            {
                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_transformedValue).GetName();
            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }
Beispiel #45
0
        /// <summary>
        /// Writes a function to set an SMV struct to a scalar coordinate, for all floating point types which have a non-constant scalar coordinate.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetScalar(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;
            declSB.AppendLine("");
            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) continue; // if no scalar coordinate, continue

                    string className = FT.GetMangledName(S, smv.Name);
                    string funcName = className + "::set";
                    bool mustCast = false;

                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    const int NB_COORDS = 1;
                    string[] argTypename = new String[NB_COORDS];
                    string[] argName = new String[NB_COORDS];
                    {
                        RefGA.BasisBlade B = RefGA.BasisBlade.ONE;
                        argTypename[0] = FT.type;
                        argName[0] = "scalarVal";
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, argName[0]));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);

                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    bool computeMultivectorValue = false;
                    //G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue);
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_COORDS, FT, null, computeMultivectorValue);

                    string dstName = G25.CG.Shared.SmvUtil.THIS;
                    bool dstPtr = true;

                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                        S.m_inlineSet, "void", null, funcName, null, FAI, FT, mustCast, smv, dstName, dstPtr, mvValue);
                }
            }
        }
Beispiel #46
0
        /// <summary>
        /// Writes a function to set an SMV struct to an array of specified coordinates, for all floating point types.
        /// </summary>
        /// <param name="S">Used for basis vector names and output language.</param>
        /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param>
        public static void WriteSetArray(Specification S, G25.CG.Shared.CGdata cgd)
        {
            StringBuilder declSB = cgd.m_declSB;
            StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB;
            declSB.AppendLine("");
            defSB.AppendLine("");

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                foreach (G25.SMV smv in S.m_SMV)
                {
                    if (smv.NbNonConstBasisBlade == 0) continue;

                    string typeName = FT.GetMangledName(S, smv.Name);
                    string funcName = typeName + "_setArray";
                    bool mustCast = false;

                    string[] argTypename = new string[1] { FT.type };
                    string[] argName = new string[1] { "A" };

                    System.Collections.ArrayList L = new System.Collections.ArrayList();
                    for (int i = 0; i < smv.NbNonConstBasisBlade; i++)
                    {
                        RefGA.BasisBlade B = smv.NonConstBasisBlade(i);
                        //argTypename[i] = FT.type;
                        String coordStr = argName[0] + "[" + i + "]";
                        //argName[i] = coordStr;
                        L.Add(new RefGA.BasisBlade(B.bitmap, B.scale, coordStr));
                    }
                    RefGA.Multivector mvValue = new RefGA.Multivector(L);

                    G25.fgs F = new G25.fgs(funcName, funcName, "", argTypename, argName, new String[] { FT.type }, null, null, null); // null, null, null = metricName, comment, options
                    F.InitArgumentPtrFromTypeNames(S);
                    F.SetArgumentPtr(0, true); // first argument is a pointer to array

                    bool computeMultivectorValue = false;
                    G25.CG.Shared.FuncArgInfo returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, smv.Name, computeMultivectorValue);
                    int nbArgs = 1; // one array of coordinates
                    G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, nbArgs, FT, null, computeMultivectorValue);

                    declSB.AppendLine("/** Sets " + typeName + " to specified coordinates */");

                    bool staticFunc = false;
                    G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd,
                        S.m_inlineSet, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, smv, returnArgument.Name, returnArgument.Pointer, mvValue);
                }
            }
        }
Beispiel #47
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// 
        /// As the return type is required, many functions will also compute the return value and other info 
        /// needed for generating the code inside this function. These intermediate values are then
        /// stored in class variables so they can be reused in WriteFunction()
        /// </summary>
        public override void CompleteFGS()
        {
            NB_ARGS = m_fgs.NbArguments; // all arguments must be explicitly listed

            // in C language, all arguments are pointers
            if (m_fgs.ArgumentPtr.Length == 0)
            {
                bool ptr = m_specification.OutputC();
                m_fgs.m_argumentPtr = new bool[] { ptr, ptr };
                m_fgs.m_argumentArr = new bool[] { false, false };
            }

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_smv1 = tmpFAI[0].Type as G25.SMV;
            m_smv2 = tmpFAI[1].Type as G25.SMV;

            { // compute return value
                // compute symbolic distance squared value
                m_returnValue = RefGA.Multivector.gp(
                    RefGA.Multivector.ScalarProduct(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M),
                    -2.0);

                // apply sqrt(fabs()) if distance should not be squared:
                if (IsDistance(m_fgs))
                    m_returnValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(RefGA.Symbolic.UnaryScalarOp.Abs(m_returnValue));

                // round value if required by metric
                if (m_G25M.m_round)
                    m_returnValue = m_returnValue.Round(1e-14);
            }

            // get name of return type
            if (m_fgs.m_returnTypeName.Length == 0)
                m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
        }
Beispiel #48
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
            {
                if (m_specification.m_GOM == null)
                    throw new G25.UserException("No general outermorphism type defined, while it is required because the type of the first argument was unspecified.");
                m_fgs.m_argumentTypeNames = new String[] { m_specification.m_GOM.Name, m_gmv.Name };
            }

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_om = (G25.OM)tmpFAI[0].Type;
            m_mv = (G25.MV)tmpFAI[1].Type;
            m_gmvFunc = !tmpFAI[1].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name;// gmv + gmv = gmv
            else
            {
                RefGA.Multivector inputValue = tmpFAI[1].MultivectorValue[0];

                // Compute m_returnValue:
                // Replace each basis blade in 'inputValue' with its value under the outermorphism.
                m_returnValue = RefGA.Multivector.ZERO;
                for (int i = 0; i < inputValue.BasisBlades.Length; i++)
                {
                    // get input blade and domain for that grade
                    RefGA.BasisBlade inputBlade = inputValue.BasisBlades[i];
                    RefGA.BasisBlade[] domainBlades = m_om.DomainForGrade(inputBlade.Grade());
                    for (int c = 0; c < domainBlades.Length; c++)
                    {
                        // if a match is found in the domain, add range vector to m_returnValue
                        if (domainBlades[c].bitmap == inputBlade.bitmap)
                        {
                            bool ptr = m_specification.OutputC();
                            RefGA.Multivector omColumnValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(m_specification, m_om.DomainSmvForGrade(inputBlade.Grade())[c], tmpFAI[0].Name, ptr);
                            RefGA.Multivector inputBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(inputBlade, 0));
                            RefGA.Multivector domainBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(domainBlades[c], 0));
                            m_returnValue = RefGA.Multivector.Add(m_returnValue,
                                RefGA.Multivector.gp(
                                RefGA.Multivector.gp(omColumnValue, inputBladeScalarMultiplier),
                                domainBladeScalarMultiplier));
                            break; // no need to search the other domainBlades too
                        }
                    }
                }

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        }
Beispiel #49
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);
                }
            }
        }
Beispiel #50
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_smv1 = tmpFAI[0].Type as G25.SMV;
            m_smv2 = tmpFAI[1].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // gmv ^ gmv = gmv
            else
            {
                // compute return value
                m_returnValue = RefGA.Multivector.op(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        }
Beispiel #51
0
        public static void WriteSetMatrix(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SOM som, bool transpose)
        {
            int NB_ARGS = 1;
            string[] argTypes = new string[NB_ARGS];
            string[] argNames = new string[NB_ARGS];
            argTypes[0] = FT.type;
            argNames[0] = "M";

            // construct image values
            RefGA.Multivector[] imageValue = new RefGA.Multivector[som.DomainVectors.Length];
            for (int d = 0; d < som.DomainVectors.Length; d++)
            {
                //imageValue[d] = RefGA.Multivector.ZERO;
                RefGA.BasisBlade[] IV = new RefGA.BasisBlade[som.RangeVectors.Length];
                for (int r = 0; r < som.RangeVectors.Length; r++)
                {
                    int matrixIdx = (transpose) ? (d * som.RangeVectors.Length + r) : (r * som.DomainVectors.Length + d);
                    string entryName = argNames[0] + "[" + matrixIdx + "]";
                    IV[r] = new RefGA.BasisBlade(som.RangeVectors[r].bitmap, 1.0, entryName);
                }
                imageValue[d] = new RefGA.Multivector(IV);
            }

            string typeName = FT.GetMangledName(S, som.Name);
            string funcName = GetFunctionName(S, typeName, "set", "_setMatrix");
            if (transpose) funcName = funcName + "Transpose";

            //argNames[0] = "*" + argNames[0]; // quick hack: add pointer to name instead of type!
            G25.fgs F = new G25.fgs(funcName, funcName, "", argTypes, argNames, new String[] { FT.type }, null, null, null); // null, null = metricName, comment, options
            F.InitArgumentPtrFromTypeNames(S);
            if (S.OutputCppOrC())
                F.m_argumentPtr[0] = true;
            else F.m_argumentArr[0] = true;
            bool computeMultivectorValue = false;
            G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, S.m_GMV.Name, computeMultivectorValue);

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

            // setup instructions
            List<G25.CG.Shared.Instruction> I = new List<G25.CG.Shared.Instruction>();
            {
                bool mustCast = false;
                int nbTabs = 1;
                string dstName = (S.OutputC()) ? G25.fgs.RETURN_ARG_NAME : SmvUtil.THIS;
                bool dstPtr = S.OutputCppOrC();
                bool declareDst = false;
                for (int g = 1; g < som.Domain.Length; g++)
                {
                    for (int c = 0; c < som.DomainForGrade(g).Length; c++)
                    {
                        G25.SMVOM smvOM = som.DomainSmvForGrade(g)[c];
                        RefGA.BasisBlade domainBlade = som.DomainForGrade(g)[c];
                        RefGA.Multivector value = new RefGA.Multivector(new RefGA.BasisBlade(domainBlade, 0)); // copy the scalar part, ditch the basis blade
                        for (uint v = 0; v < som.DomainVectors.Length; v++)
                        {
                            if ((domainBlade.bitmap & som.DomainVectors[v].bitmap) != 0)
                            {
                                value = RefGA.Multivector.op(value, imageValue[v]);
                            }
                        }

                        I.Add(new G25.CG.Shared.CommentInstruction(nbTabs, "Set image of " + domainBlade.ToString(S.m_basisVectorNames)));
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smvOM, FT, mustCast, value, dstName, dstPtr, declareDst));
                    }
                }

            }

            Comment comment = new Comment("Sets " + typeName + " from a " + (transpose ? "transposed " : "") + "matrix.");
            bool writeDecl = (S.OutputC());
            bool staticFunc = false;
            G25.CG.Shared.Functions.WriteFunction(S, cgd, F, S.m_inlineSet, staticFunc, "void", funcName, returnArgument, FAI, I, comment, writeDecl);
        }
Beispiel #52
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_smv1 = tmpFAI[0].Type as G25.SMV;
            m_smv2 = tmpFAI[1].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // gmv * gmv = gmv
            else
            {
                // compute return value
                if (IsInverse(m_fgs))
                {
                    m_returnValue = RefGA.Multivector.ihp(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]);
                }
                else
                {
                    m_returnValue = RefGA.Multivector.hp(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]);
                }

                bool getReturnType = (m_fgs.m_returnTypeName.Length == 0);

                // get name of return type
                if (getReturnType)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();

                // This code corrects the result for the signs of the basis blade, and loops until the return type converges.
                // The reason for this code is that the hadamard product is not well-defined when the basis blades of the operands and the result do not match.
                while (true) {
                    G25.VariableType returnType = m_specification.GetType(m_fgs.m_returnTypeName);
                    if (returnType is G25.SMV)
                    {
                        G25.SMV returnSMV = returnType as G25.SMV;
                        RefGA.Multivector unitReturnSmv = returnSMV.ToMultivectorValue();
                        RefGA.Multivector correctedReturnValue = RefGA.Multivector.ihp(m_returnValue, unitReturnSmv);
                        if (getReturnType)
                        {
                            string newReturnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                            if (newReturnTypeName == m_fgs.m_returnTypeName)
                            {
                                m_returnValue = correctedReturnValue;
                                break;
                            }
                            else m_fgs.m_returnTypeName = newReturnTypeName;
                        }
                        else {
                            m_returnValue = correctedReturnValue;
                            break;
                        }
                    }
                    else break;
                }
            }
        }
Beispiel #53
0
        public static void WriteSetVectorImages(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SOM som)
        {
            G25.SMV rangeVectorType = G25.CG.Shared.OMinit.GetRangeVectorType(S, FT, cgd, som);

            // loop over som.DomainVectors
            // setup array of arguments, function specification, etc
            int NB_ARGS = som.DomainVectors.Length;
            string[] argTypes = new string[NB_ARGS];
            string[] argNames = new string[NB_ARGS];
            RefGA.Multivector[] argValue = new RefGA.Multivector[NB_ARGS];
            for (int d = 0; d < NB_ARGS; d++)
            {
                argTypes[d] = rangeVectorType.Name;
                argNames[d] = "i" + som.DomainVectors[d].ToLangString(S.m_basisVectorNames);
                bool ptr = (S.OutputC());
                argValue[d] = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, rangeVectorType, argNames[d], ptr);
            }

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

            G25.fgs F = new G25.fgs(funcName, funcName, "", argTypes, argNames, new String[] { FT.type }, null, null, null); // null, null = metricName, comment, options
            F.InitArgumentPtrFromTypeNames(S);
            bool computeMultivectorValue = false;
            G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, F, NB_ARGS, FT, S.m_GMV.Name, computeMultivectorValue);

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

            // setup instructions
            List<G25.CG.Shared.Instruction> I = new List<G25.CG.Shared.Instruction>();
            {
                bool mustCast = false;
                int nbTabs = 1;
                string dstName = (S.OutputC()) ? G25.fgs.RETURN_ARG_NAME : SmvUtil.THIS;
                bool dstPtr = S.OutputCppOrC();
                bool declareDst = false;
                for (int g = 1; g < som.Domain.Length; g++)
                {
                    for (int c = 0; c < som.DomainForGrade(g).Length; c++)
                    {
                        G25.SMVOM smvOM = som.DomainSmvForGrade(g)[c];
                        RefGA.BasisBlade domainBlade = som.DomainForGrade(g)[c];
                        RefGA.Multivector value = new RefGA.Multivector(new RefGA.BasisBlade(domainBlade, 0)); // copy the scalar part, ditch the basis blade
                        for (uint v = 0; v < som.DomainVectors.Length; v++)
                        {
                            if ((domainBlade.bitmap & som.DomainVectors[v].bitmap) != 0)
                            {
                                value = RefGA.Multivector.op(value, argValue[v]);
                            }
                        }

                        I.Add(new G25.CG.Shared.CommentInstruction(nbTabs, "Set image of " + domainBlade.ToString(S.m_basisVectorNames)));
                        I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smvOM, FT, mustCast, value, dstName, dstPtr, declareDst));
                    }
                }

            }

            Comment comment = new Comment("Sets " + typeName + " from images of the domain vectors.");
            bool writeDecl = false;
            bool staticFunc = false;
            G25.CG.Shared.Functions.WriteFunction(S, cgd, F, S.m_inlineSet, staticFunc, "void", funcName, returnArgument, FAI, I, comment, writeDecl);
        }
Beispiel #54
0
        /// <summary>
        /// Generates functions which compute parts of the application of a general outermorphism to a general multivector.
        /// 
        /// This function should be called early on in the code generation process, at least
        /// before any of the <c>???()</c> functions is called.
        /// </summary>
        /// <param name="S">Specification (used for output language, GMV).</param>
        /// <param name="cgd">Where the result goes.</param>
        public static void WriteGomParts(Specification S, CGdata cgd)
        {
            if (S.m_GOM == null) return; // nothing to do if GOM not defiend

            int nbBaseTabs = (S.OutputCSharpOrJava()) ? 1 : 0;
            int nbCodeTabs = nbBaseTabs + 1;

            G25.GMV gmv = S.m_GMV;
            G25.GOM gom = S.m_GOM;

            string nameGOM = "O";
            string nameSrcGMV = "A";
            string nameDstGMV = "C";

            // get symbolic multivector value
            RefGA.Multivector[] M1 = null;
            {
                bool ptr = (S.OutputC());
                int allGroups = -1;
                M1 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, nameSrcGMV, ptr, allGroups);
            }

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                // map from code fragment to name of function
                Dictionary<string, string> generatedCode = new Dictionary<string, string>();

                // loop over all groups of the GMV, multiply with GOM, and assign the result
                for (int srcGroup = 0; srcGroup < gmv.NbGroups; srcGroup++)
                {
                    RefGA.Multivector inputValue = M1[srcGroup];
                    if (inputValue.IsScalar()) continue;

                    // Replace each basis blade in 'inputValue' with its value under the outermorphism.
                    RefGA.Multivector returnValue = RefGA.Multivector.ZERO; // returnValue = gom * gmv[srcGroup]
                    for (int i = 0; i < inputValue.BasisBlades.Length; i++)
                    {
                        // get input blade and domain for that grade
                        RefGA.BasisBlade inputBlade = inputValue.BasisBlades[i];
                        RefGA.BasisBlade[] domainBlades = gom.DomainForGrade(inputBlade.Grade());
                        for (int c = 0; c < domainBlades.Length; c++)
                        {
                            // if a match is found in the domain, add range vector to m_returnValue
                            if (domainBlades[c].bitmap == inputBlade.bitmap)
                            {
                                bool ptr = (S.OutputC());
                                RefGA.Multivector omColumnValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(S, gom.DomainSmvForGrade(inputBlade.Grade())[c], nameGOM, ptr);
                                RefGA.Multivector inputBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(inputBlade, 0));
                                RefGA.Multivector domainBladeScalarMultiplier = new RefGA.Multivector(new RefGA.BasisBlade(domainBlades[c], 0));
                                returnValue = RefGA.Multivector.Add(returnValue,
                                    RefGA.Multivector.gp(
                                    RefGA.Multivector.gp(omColumnValue, inputBladeScalarMultiplier),
                                    domainBladeScalarMultiplier));
                                break; // no need to search the other domainBlades too
                            }
                        }
                    } // end of 'compute return value'

                    // assign returnValue to various groups of the gmv
                    for (int dstGroup = 0; dstGroup < gmv.NbGroups; dstGroup++)
                    {
                        bool mustCast = false;
                        bool writeZeros = false; // no need to generate "+= 0.0;"
                        int dstBaseIdx = 0;
                        string code = G25.CG.Shared.CodeUtil.GenerateGMVassignmentCode(S, FT, mustCast, gmv, nameDstGMV, dstGroup, dstBaseIdx, returnValue, nbCodeTabs, writeZeros);

                        string funcName = GetGomPartFunctionName(S, FT, srcGroup, dstGroup);
                        cgd.m_gmvGomPartFuncNames[new Tuple<string, string>(FT.type, funcName)] = (code.Length > 0);

                        if (code.Length == 0) continue;

                        if (!S.m_GMV.IsGroupedByGrade(S.m_dimension))
                            code = code.Replace("=", "+=");

                        // check if code was already generated, and, if so, reuse it
                        if (generatedCode.ContainsKey(code))
                        {
                            // ready generated: call that function
                            code = "\t" + generatedCode[code] + "(" + nameGOM + ", " + nameSrcGMV + ", " + nameDstGMV + ");\n";
                        }
                        else
                        {
                            // not generated yet: remember code -> function
                            generatedCode[code] = funcName;
                        }

                        // write comment
                        string comment = "Computes the partial application of a general outermorphism to a general multivector";

                        string OM_PTR = "";
                        if (S.OutputC()) OM_PTR = "*";
                        else if (S.OutputCpp()) OM_PTR = "&";

                        string ACCESS = "";
                        if (S.OutputJava()) ACCESS = "protected static ";
                        else if (S.OutputCSharp()) ACCESS = "protected internal static ";

                        string ARR = (S.OutputCSharpOrJava()) ? "[] " : " *";
                        string CONST = (S.OutputCSharpOrJava()) ? "" : "const ";

                        string funcDecl = ACCESS + "void " + funcName + "(" + CONST + FT.GetMangledName(S, gom.Name) + " " + OM_PTR + nameGOM + ", " + CONST + FT.type + ARR + nameSrcGMV + ", " + FT.type + ARR + nameDstGMV + ")";

                        if (S.OutputCppOrC())
                        {
                            new Comment(comment).Write(cgd.m_declSB, S, nbBaseTabs);
                            cgd.m_declSB.Append(funcDecl); cgd.m_declSB.AppendLine(";");
                        }
                        else
                        {
                            new Comment(comment).Write(cgd.m_defSB, S, nbBaseTabs);
                        }

                        // emit def
                        cgd.m_defSB.Append('\t', nbBaseTabs);
                        cgd.m_defSB.Append(funcDecl);
                        cgd.m_defSB.AppendLine(" {");
                        cgd.m_defSB.Append(code);
                        cgd.m_defSB.Append('\t', nbBaseTabs);
                        cgd.m_defSB.AppendLine("}");

                    } // end of loop over all dest GMV groups
                } // end of loop over all source GMV groups
            } // end of loop over all float types
        }
Beispiel #55
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// 
        /// As the return type is required, many functions will also compute the return value and other info 
        /// needed for generating the code inside this function. These intermediate values are then
        /// stored in class variables so they can be reused in WriteFunction()
        /// </summary>
        public override void CompleteFGS()
        {
            NB_ARGS = m_fgs.NbArguments; // all arguments must be explicitly listed

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            { // compute return value
                RefGA.Multivector no = GetOrigin(m_specification, m_fgs);
                RefGA.Multivector ni = GetInfinity(m_specification, m_fgs);

                // compose a vector value (the Euclidean part)
                RefGA.Multivector vectorValue = RefGA.Multivector.ZERO;
                if ((IsRandom(m_specification, m_fgs)) || (IsCoordBased(m_specification, m_fgs, FT)))
                {
                    m_returnValue = no;
                    for (int i = 0; i < m_specification.m_dimension - 2; i++)
                    {
                        string bvName = "e" + (i + 1).ToString(); // todo: this assumes a fixed name for the basis vectors. Make these names options?
                        int bvIdx = m_specification.GetBasisVectorIndex(bvName);
                        if (bvIdx < 0)
                            throw new G25.UserException("Cannot find basis vector " + bvName, XML.FunctionToXmlString(m_specification, m_fgs));

                        RefGA.Multivector basisVector = RefGA.Multivector.GetBasisVector(bvIdx);

                        if (IsRandom(m_specification, m_fgs))
                            vectorValue = RefGA.Multivector.Add(vectorValue, RefGA.Multivector.gp(new RefGA.Multivector("ce" + (i + 1).ToString()), basisVector));
                        else vectorValue = RefGA.Multivector.Add(vectorValue, RefGA.Multivector.gp(tmpFAI[i].MultivectorValue[0], basisVector));
                    }
                }
                else if (IsVectorBased(m_specification, m_fgs, FT))
                {
                    vectorValue = tmpFAI[0].MultivectorValue[0];
                    m_vectorType = tmpFAI[0].Type;
                }
                else if (IsFlatPointBased(m_specification, m_fgs, FT))
                {
                    m_flatPointType = tmpFAI[0].Type as G25.SMV;
                    RefGA.BasisBlade.InnerProductType lc = RefGA.BasisBlade.InnerProductType.LEFT_CONTRACTION;
                    RefGA.Multivector noni = RefGA.Multivector.OuterProduct(no, ni);
                    // scale = no^ni . pointPair
                    RefGA.Multivector scale =
                        RefGA.Multivector.InnerProduct(noni, tmpFAI[0].MultivectorValue[0], m_M, lc).ScalarPart();
                    if (m_G25M.m_round) scale = scale.Round(1e-14);

                    // sphere = no . pointPair
                    RefGA.Multivector sphere = RefGA.Multivector.InnerProduct(no, tmpFAI[0].MultivectorValue[0], m_M, lc);
                    // normalizedSphere = sphere / scale

                    bool needToNormalize = (scale.HasSymbolicScalars() || (scale.RealScalarPart() != 1.0));
                    RefGA.Multivector normalizedSphere = (needToNormalize) ? RefGA.Multivector.gp(sphere, RefGA.Symbolic.UnaryScalarOp.Inverse(scale)) : sphere;

                    // keep only euclidean vectors
                    RefGA.Multivector euclMultivector = getSumOfUnitEuclideanBasisVectors();
                    // vector = sphere-noni
                    m_pointPairVectorValue = RefGA.Multivector.hp(normalizedSphere, euclMultivector);
                    // round vector
                    if (m_G25M.m_round) m_pointPairVectorValue = m_pointPairVectorValue.Round(1e-14);

                    // get type
                    m_vectorType = (G25.SMV)G25.CG.Shared.SpecializedReturnType.FindTightestMatch(m_specification, m_pointPairVectorValue, FT);
                    if (m_vectorType == null)
                    {
                        throw new G25.UserException("Missing Euclidean vector type; cannot construct conformal point from " + m_fgs.ArgumentTypeNames[0], XML.FunctionToXmlString(m_specification, m_fgs));
                    }

                    // get 'value' (just a reference to the name of the variable where m_pointPairVectorValue will be stored.
                    bool pointer = false;
                    vectorValue = Symbolic.SMVtoSymbolicMultivector(m_specification, (G25.SMV)m_vectorType, VECTOR_NAME, pointer);
                }
                else
                {
                    throw new G25.UserException("Invalid arguments specified.", XML.FunctionToXmlString(m_specification, m_fgs));
                }

                { // add no and 0.5 vectorValue^2 ni
                    RefGA.Multivector vectorValueSquared = RefGA.Multivector.scp(vectorValue, vectorValue);
                    RefGA.Multivector niPart = RefGA.Multivector.gp(
                        RefGA.Multivector.gp(vectorValueSquared, ni), 0.5);
                    m_returnValue = RefGA.Multivector.Add(RefGA.Multivector.Add(no, vectorValue), niPart);
                }
            } // end of compute return value

            // get name of return type
            if (m_fgs.m_returnTypeName.Length == 0)
                m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
        }
Beispiel #56
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            m_ipType = GetIpType(m_specification, m_fgs);

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV());
            m_smv1 = tmpFAI[0].Type as G25.SMV;
            m_smv2 = tmpFAI[1].Type as G25.SMV;

            // compute intermediate results, set return type
            if (m_gmvFunc)
            {
                if (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT)
                {
                    m_fgs.m_returnTypeName = m_gmv.Name;// gmv * gmv = gmv
                }
                else
                {
                    m_fgs.ReturnTypeName = FT.type;
                }
            }
            else
            {
                // compute return value
                m_returnValue = RefGA.Multivector.ip(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M, m_ipType);

                // round value if required by metric
                if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14);

                // get name of return type
                if ((m_fgs.ReturnTypeName.Length == 0) && (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT))
                {
                    m_fgs.ReturnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
                }
                else
                {
                    m_fgs.ReturnTypeName = FT.type;
                }
            }
        }
Beispiel #57
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            m_isNorm2 = IsNorm2(m_fgs);

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, new RefGA.Multivector("x")).GetName(); // norm(gmv) = scalar
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // compute return value
                if (m_isNorm2) m_returnValue = tmpFAI[0].MultivectorValue[0].Norm_r2(m_M);
                else m_returnValue = RefGA.Symbolic.UnaryScalarOp.Abs(tmpFAI[0].MultivectorValue[0].Norm_r(m_M));

                // round value if required by metric
                if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14);

                // avoid null return value because that might return in getting the wrong return type
                RefGA.Multivector nonZeroReturnValue = (m_returnValue.IsZero()) ? RefGA.Multivector.ONE : m_returnValue;

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, nonZeroReturnValue).GetName();
            }
        }
Beispiel #58
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            if (m_G25M.m_metric.IsDegenerate())
                throw new G25.UserException("Cannot generate dual functions for degenerate metrics.");

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // dual(gmv) = gmv
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                // compute return value
                if (IsDual(m_fgs)) m_returnValue = RefGA.Multivector.Dual(tmpFAI[0].MultivectorValue[0], m_M);
                else if (IsUndual(m_fgs)) m_returnValue = RefGA.Multivector.Undual(tmpFAI[0].MultivectorValue[0], m_M);

                // round value if required by metric
                if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        }
Beispiel #59
0
        } // end of function ScalarToLangString

        /// <summary>
        /// Converts scalar part of 'value' to ouput language dependent string.
        /// </summary>
        private static string ScalarOpValueToLangString(G25.Specification S, G25.FloatType FT, RefGA.Multivector value)
        {
            if (!value.IsScalar())
            {
                throw new Exception("G25.CG.Shared.BasisBlade.ScalarOpValueToLangString(): value should be scalar, found: " + value.ToString(S.m_basisVectorNames));
            }
            if (value.IsZero())
            {
                return(ScalarToLangString(S, FT, RefGA.BasisBlade.ZERO));
            }
            else
            {
                return(ScalarToLangString(S, FT, value.BasisBlades[0]));
            }
        }
Beispiel #60
0
        /// <summary>
        /// If this FunctionGenerator can implement 'F', then this function should complete the (possible)
        /// blanks in 'F'. This means:
        ///  - Fill in F.m_returnTypeName if it is empty
        ///  - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty.
        /// </summary>
        public override void CompleteFGS()
        {
            FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]);

            // fill in ArgumentTypeNames
            if (m_fgs.ArgumentTypeNames.Length == 0)
                m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, FT.type };

            // init argument pointers from the completed typenames (language sensitive);
            m_fgs.InitArgumentPtrFromTypeNames(m_specification);

            // get all function info
            bool computeMultivectorValue = true;
            G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue);

            m_gmvFunc = !tmpFAI[0].IsScalarOrSMV();

            // compute intermediate results, set return type
            if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // div(gmv, scalar) = gmv
            else
            {
                m_smv = tmpFAI[0].Type as G25.SMV;

                RefGA.Multivector inputValue = tmpFAI[0].MultivectorValue[0];
                RefGA.Multivector divValue = RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(tmpFAI[1].Name));
                m_returnValue = RefGA.Multivector.gp(inputValue, divValue);

                // get name of return type
                if (m_fgs.m_returnTypeName.Length == 0)
                    m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName();
            }
        }