Beispiel #1
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 #2
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 #3
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
        }             // end of function WriteGomParts()
Beispiel #4
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
                RefGA.Multivector value        = tmpFAI[0].MultivectorValue[0];
                RefGA.Multivector reverseValue = RefGA.Multivector.Reverse(value);
                RefGA.Multivector n2Value      = RefGA.Multivector.gp(reverseValue, value, m_M);
                m_nValue = n2Value;
                if (!m_M.IsPositiveDefinite())
                {
                    m_nValue = RefGA.Symbolic.UnaryScalarOp.Abs(m_nValue);
                }
                m_nValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(m_nValue);

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

                try // try to m_nValue = evaluate(m_nValue)
                {
                    m_nValue = m_nValue.SymbolicEval(new RefGA.Symbolic.HashtableSymbolicEvaluator());
                }
                catch (ArgumentException) { }

                if (m_nValue.HasSymbolicScalars() || (!m_nValue.IsScalar()) || m_nValue.IsZero())
                {
                    RefGA.Multivector inverseNValue = RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(normName));
                    m_returnValue = RefGA.Multivector.gp(value, inverseNValue);
                }
                else
                { // no extra step required
                    m_returnValue = RefGA.Multivector.gp(value, new RefGA.Multivector(1.0 / m_nValue.RealScalarPart()));
                    m_nValue      = 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_returnValue).GetName();
                }
            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }
Beispiel #5
0
        /// <summary>
        /// This function contains a function to find a tightly matching specialized multivector.
        /// Given a Multivector 'M', it find the best match which can contain it.
        ///
        /// The function tries each SMV in the specification. It rates them as follows:
        /// -missing variable basis blade: disqualified
        /// -constant coordinate mismatch: disqualified
        /// -constant coordinate match: +1
        /// -excess variable coordinate : -1
        ///
        /// If the symbolic multivector 'M' has a scalar return type, the function will insist on returning
        /// a scalar type! It will not (for example) return a rotor.
        /// </summary>
        /// <param name="S">Specification of algebra, used for the m_SMV</param>
        /// <param name="M">The multivector for which a matching SMV is sought.</param>
        /// <param name="FT">The preferred floating point type (only used when scalar is returned).</param>
        /// <returns>null when no match found; the selected G25.SMV or G25.FloatType otherwise.</returns>
        public static G25.VariableType FindTightestMatch(G25.Specification S, RefGA.Multivector M, FloatType FT)
        {
            G25.SMV   bestSMV       = null;
            const int LOWEST_RATING = -10000000; // rating of good-enough blades _can_ be negative, if they have excess variable coordinates
            int       bestRating    = LOWEST_RATING;

            const double EPSILON = 1e-6; // make this user controllable??

            foreach (G25.SMV smv in S.m_SMV)
            {
                int rating         = 0;
                int nbConstMatched = 0; // number of elements from M.BasisBlades matched with const coordinates
                for (int i = 0; i < M.BasisBlades.Length; i++)
                {
                    // get blade, see if it is constant
                    RefGA.BasisBlade B        = M.BasisBlades[i];
                    bool             constant = (B.symScale == null);

                    // if constant, then try constant blades first
                    bool found = false; // set to true when matching basis blade is found
                    if (constant)
                    {
                        // loop over all constant basis blades
                        for (int j = 0; j < smv.NbConstBasisBlade; j++)
                        {
                            // get basis blade, compare bitmaps
                            RefGA.BasisBlade C = smv.ConstBasisBlade(j);
                            if (C.bitmap == B.bitmap)
                            {
                                if (Math.Abs(C.scale - B.scale) / Math.Abs(C.scale) > EPSILON)
                                {
                                    rating = LOWEST_RATING;
                                    break; // this break the outer loop (over 'i') too
                                }
                                else
                                {
                                    rating++;
                                    nbConstMatched++;
                                    found = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (rating == LOWEST_RATING)
                    {
                        break;
                    }

                    // if no constant basis blade was found, loop over all variable basis blades
                    if (!found)
                    {
                        for (int j = 0; j < smv.NbNonConstBasisBlade; j++)
                        {
                            // get basis blade, compare bitmaps
                            RefGA.BasisBlade C = smv.NonConstBasisBlade(j);
                            if (C.bitmap == B.bitmap)
                            {
                                found = true;
                                break;
                            }
                        }
                    }

                    if (!found)
                    {// if neither constant nor variable basis blade found: no match
                        rating = LOWEST_RATING;
                        break;
                    }
                }

                // disqualify 'smv' when it has const coords not present in 'M'
                if (nbConstMatched < smv.NbConstBasisBlade)
                {
                    rating = LOWEST_RATING;
                }

                if (rating != LOWEST_RATING)
                {
                    // adjust rating for excess variable coordinates:
                    int nbNonConstCoords = M.BasisBlades.Length - nbConstMatched;
                    int nbExcess         = smv.NbNonConstBasisBlade - nbNonConstCoords;
                    if (nbExcess > 0)
                    {
                        rating -= nbExcess;               // subtract 1 for each non-const coordinate that is in 'smv' without actually being useful
                    }
                }

                // keep best SMV so far
                if (rating > bestRating)
                {
                    bestRating = rating;
                    bestSMV    = smv;
                }
            }

            if ((M.IsZero() || M.IsScalar()) && (bestRating < 0))
            {
                return(FT);                                                  // insist on retuning a scalar type
            }
            else
            {
                return(bestSMV);
            }
        } // end of function FindTightestMatch()
Beispiel #6
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
                RefGA.Multivector value = tmpFAI[0].MultivectorValue[0];
                RefGA.Multivector reverseValue = RefGA.Multivector.Reverse(value);
                RefGA.Multivector n2Value = RefGA.Multivector.gp(reverseValue, value, m_M);
                m_nValue = n2Value;
                if (!m_M.IsPositiveDefinite())
                    m_nValue = RefGA.Symbolic.UnaryScalarOp.Abs(m_nValue);
                m_nValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(m_nValue);

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

                try // try to m_nValue = evaluate(m_nValue)
                {
                    m_nValue = m_nValue.SymbolicEval(new RefGA.Symbolic.HashtableSymbolicEvaluator());
                }
                catch (ArgumentException) { }

                if (m_nValue.HasSymbolicScalars() || (!m_nValue.IsScalar()) || m_nValue.IsZero())
                {
                    RefGA.Multivector inverseNValue = RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(normName));
                    m_returnValue = RefGA.Multivector.gp(value, inverseNValue);
                }
                else
                { // no extra step required
                    m_returnValue = RefGA.Multivector.gp(value, new RefGA.Multivector(1.0 / m_nValue.RealScalarPart()));
                    m_nValue = 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_returnValue).GetName();

            }
            m_returnType = m_specification.GetType(m_fgs.m_returnTypeName);
        }