Exemplo n.º 1
0
        /// <summary>
        /// Resolves a converter (underscore constructor) dependency.
        /// Searches for a converter from 'fromType' to 'toType'.
        /// 
        /// If the function is not found, this is also enlisted in cgd.m_missingDependencies.
        /// Call cgd.PrintMissingDependencies() should be called to report the missing dependencies
        /// to the end-user.
        /// </summary>
        /// <param name="S">The spec.</param>
        /// <param name="cgd">Missing dependencies go into cgd.m_missingDependencies.</param>
        /// <param name="fromType"></param>
        /// <param name="toType"></param>
        /// <param name="FT"></param>
        /// <returns></returns>
        public static string GetConverterDependency(Specification S, CGdata cgd, string fromType, string toType, G25.FloatType FT)
        {
            // look for 'funcName' in all G25.fgs in the spec
            //                    string funcName = "_" + FT.GetMangledName(S, toType);
            string funcName = "_" + toType;
            foreach (G25.fgs F in S.m_functions)
            {
                if (F.IsConverter(S)) // is 'F' a converter (underscore constructor)?
                {
                    if ((F.Name == funcName) &&
                        (F.ArgumentTypeNames[0] == fromType))
                    {
                        return G25.CG.Shared.Converter.GetConverterName(S, F, FT.GetMangledName(S, fromType), FT.GetMangledName(S, toType));
                    }
                }
            }

            // converter not found: add it to missing deps:
            {
                // add dependency to list of missing deps:
                string outputName = null;
                string[] argumentTypes = new string[] { fromType };
                string[] argVarNames = null;
                string returnTypeName = null;
                string metricName = null;
                string comment = null;
                Dictionary<string, string> options = null;
                G25.fgs F = new G25.fgs(funcName, outputName, returnTypeName, argumentTypes, argVarNames, new string[] { FT.type }, metricName, comment, options);
                cgd.AddMissingDependency(S, F);
            }

            // return fictional name:
            G25.fgs tmpF = null;
            return "missingFunction_" + G25.CG.Shared.Converter.GetConverterName(S, tmpF, FT.GetMangledName(S, fromType), FT.GetMangledName(S, toType));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the name of a generated function (for example <c>gp_mv_mv</c>).
        /// The function is found by looking through all G25.FGS in the Specification.
        ///
        /// If the function is not found, a fictional name is returned, i.e. "missingFunction_" + functionName.
        /// This name will then show up in the generated code, which will not compile as a result.
        ///
        /// If the function is not found, this is also enlisted in cgd.m_missingDependencies.
        /// Call cgd.PrintMissingDependencies() should be called to report the missing dependencies
        /// to the end-user.
        /// </summary>
        /// <param name="S">The spec.</param>
        /// <param name="cgd">Missing dependencies go into cgd.m_missingDependencies.</param>
        /// <param name="functionName">Basic name of the function to be found.</param>
        /// <param name="argumentTypes">Names of the arguments types (not mangled).</param>
        /// <param name="returnTypeName">Name of the return type (can be null or "" for default return type).</param>
        /// <param name="FT">Floating point type.</param>
        /// <param name="metricName">(optional, can be null for don't care)</param>
        /// <returns>The mangled name of the function.</returns>
        public static string GetDependency(Specification S, CGdata cgd, string functionName,
                                           string[] argumentTypes, string returnTypeName, G25.FloatType FT, string metricName)
        {
            // bool returnTrueName = dependent on cgd.mode
            try
            {
                return(GetFunctionName(S, functionName, argumentTypes, returnTypeName, FT, metricName));
            }
            catch (DependencyException)
            { // function not found, return a fictional name, and remember dependency
                G25.fgs F = null;
                {
                    // get name of dep, and make sure it does not get mangled
                    string outputName = functionName + cgd.GetDontMangleUniqueId();
                    if (returnTypeName != null)
                    {
                        outputName = outputName + "_returns_" + returnTypeName;
                    }

                    // add dependency to list of missing deps:
                    string[] argVarNames = null;
                    Dictionary <String, String> options = null;
                    string  comment = null;
                    G25.fgs tmpF    = new G25.fgs(functionName, outputName, returnTypeName, argumentTypes, argVarNames, new String[] { FT.type }, metricName, comment, options);

                    F = cgd.AddMissingDependency(S, tmpF);
                }

                return(cgd.m_dependencyPrefix + F.OutputName);
            }
        } // end of GetDependency()
Exemplo n.º 3
0
        public static G25.VariableType CreateSyntheticSMVtype(Specification S, CGdata cgd, FloatType FT, RefGA.Multivector value)
        {
            // make up list of basis blades
            rsbbp.BasisBlade[] L = new rsbbp.BasisBlade[value.BasisBlades.Length];
            for (int i = 0 ; i < value.BasisBlades.Length; i++)
            {
                RefGA.BasisBlade B = value.BasisBlades[i];
                if (B.symScale == null) L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap), B.scale); // constant value
                else L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap)); // non-const value
            }

            // get other required info
            String name = "nameOfType";
            SMV.MULTIVECTOR_TYPE mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR;
            String comment = "MISSING; PLEASE ADD TO SPECIFICATION";
            //String constantName = null;

            // create the type
            G25.SMV synSMV = new G25.SMV(name, L, mvType, comment);

            // throw exception
            throw new G25.UserException("Missing specialized multivector type.\n" +
                "Please add the following XML to the specification to fix the dependency:\n" +
                XML.SMVtoXmlString(S, synSMV));
        }
Exemplo n.º 4
0
        public static G25.VariableType CreateSyntheticSMVtype(Specification S, CGdata cgd, FloatType FT, RefGA.Multivector value)
        {
            // make up list of basis blades
            rsbbp.BasisBlade[] L = new rsbbp.BasisBlade[value.BasisBlades.Length];
            for (int i = 0; i < value.BasisBlades.Length; i++)
            {
                RefGA.BasisBlade B = value.BasisBlades[i];
                if (B.symScale == null)
                {
                    L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap), B.scale);                     // constant value
                }
                else
                {
                    L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap));  // non-const value
                }
            }

            // get other required info
            String name = "nameOfType";

            SMV.MULTIVECTOR_TYPE mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR;
            String comment = "MISSING; PLEASE ADD TO SPECIFICATION";

            //String constantName = null;

            // create the type
            G25.SMV synSMV = new G25.SMV(name, L, mvType, comment);

            // throw exception
            throw new G25.UserException("Missing specialized multivector type.\n" +
                                        "Please add the following XML to the specification to fix the dependency:\n" +
                                        XML.SMVtoXmlString(S, synSMV));
        }
Exemplo n.º 5
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);
 }
Exemplo n.º 6
0
 /// <summary>
 /// Merges all errors from cgd into this CGdata.
 /// </summary>
 /// <param name="cgd"></param>
 public void MergeErrors(CGdata cgd)
 {
     lock (m_errors)
     {
         if (m_errors != cgd.m_errors)
         {
             m_errors.AddRange(cgd.m_errors);
         }
     }
 }
Exemplo n.º 7
0
 /// <returns>A unique name for the testing function of 'funcName'.</returns>
 public static string GetTestingFunctionName(Specification S, CGdata cgd, string funcName)
 {
     if (S.OutputC())
     {
         return("test_" + funcName);
     }
     else
     {
         return("test_" + funcName + cgd.GetDontMangleUniqueId());
     }
 }
Exemplo n.º 8
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="cgd"></param>
 public CGdata(CGdata cgd)
 {
     // copy all from cgd
     m_plugins = cgd.m_plugins;
     m_cog = cgd.m_cog;
     m_gmvGPpartFuncNames = cgd.m_gmvGPpartFuncNames;
     m_gmvDualPartFuncNames = cgd.m_gmvDualPartFuncNames;
     m_gmvGomPartFuncNames = cgd.m_gmvGomPartFuncNames;
     m_missingDependencies = cgd.m_missingDependencies;
     m_errors = cgd.m_errors;
     m_feedback = cgd.m_feedback;
     m_dependencyId = cgd.m_dependencyId;
     m_dependencyPrefix = cgd.m_dependencyPrefix;
 }
Exemplo n.º 9
0
        } // end of function FindTightestMatch()

        /// <summary>
        /// The user may have requested a return type (F.ReturnTypeName).
        /// In that case, the type with the same name is found, or an exception
        /// is thrown if it does not exists.
        ///
        /// Otherwise, finds the (tightest, best) return type for a function 'F' which
        /// returning the (symbolic) value 'value'.
        /// This  may or may not result in an SMV being found. If no
        /// type is found and the return type is a scalar, then a floating
        /// point type may be returned.
        ///
        /// If no SMV type is found, then a new type is created, and an exception
        /// is thrown which described the missing type.
        /// </summary>
        /// <param name="S">The specification (used to find SMVs)</param>
        /// <param name="cgd">Not used currently.</param>
        /// <param name="F">Function description (used for user-specified return type).</param>
        /// <param name="FT">Floating point type used in function.</param>
        /// <param name="value">The symbolic return value.</param>
        /// <returns>The SMV, FloatType or null if none found.</returns>
        public static G25.VariableType GetReturnType(Specification S, CGdata cgd, G25.fgs F, FloatType FT, RefGA.Multivector value)
        {
            if ((F.ReturnTypeName != null) && (F.ReturnTypeName.Length > 0))
            {
                // The user specified a return type
                G25.SMV returnSmv = S.GetSMV(F.ReturnTypeName); // is it a SMV?
                if (returnSmv != null)
                {
                    return(returnSmv);
                }
                G25.FloatType returnFT = S.GetFloatType(F.ReturnTypeName); // is it a specific float?
                if (returnFT != null)
                {
                    return(FT);                                  //returnFT;
                }
                else if (F.ReturnTypeName == G25.XML.XML_SCALAR) // is it a unspecified float?
                {
                    return(FT);
                }

                // type does not exist: abort (TODO: error message)
                else
                {
                    throw new G25.UserException("Non-existant user-specified return type: " + F.ReturnTypeName,
                                                XML.FunctionToXmlString(S, F)); // non-existant return type
                }
            }
            else
            {
                G25.VariableType RT = FindTightestMatch(S, value, FT);
                if (RT != null)
                {
                    return(RT);
                }
                else
                {
                    return(CreateSyntheticSMVtype(S, cgd, FT, value));
                }
            }
        }
Exemplo n.º 10
0
        } // end of GetDependency()

        /// <summary>
        /// Resolves a converter (underscore constructor) dependency.
        /// Searches for a converter from 'fromType' to 'toType'.
        ///
        /// If the function is not found, this is also enlisted in cgd.m_missingDependencies.
        /// Call cgd.PrintMissingDependencies() should be called to report the missing dependencies
        /// to the end-user.
        /// </summary>
        /// <param name="S">The spec.</param>
        /// <param name="cgd">Missing dependencies go into cgd.m_missingDependencies.</param>
        /// <param name="fromType"></param>
        /// <param name="toType"></param>
        /// <param name="FT"></param>
        /// <returns></returns>
        public static string GetConverterDependency(Specification S, CGdata cgd, string fromType, string toType, G25.FloatType FT)
        {
            // look for 'funcName' in all G25.fgs in the spec
//                    string funcName = "_" + FT.GetMangledName(S, toType);
            string funcName = "_" + toType;

            foreach (G25.fgs F in S.m_functions)
            {
                if (F.IsConverter(S)) // is 'F' a converter (underscore constructor)?
                {
                    if ((F.Name == funcName) &&
                        (F.ArgumentTypeNames[0] == fromType))
                    {
                        return(G25.CG.Shared.Converter.GetConverterName(S, F, FT.GetMangledName(S, fromType), FT.GetMangledName(S, toType)));
                    }
                }
            }

            // converter not found: add it to missing deps:
            {
                // add dependency to list of missing deps:
                string   outputName                 = null;
                string[] argumentTypes              = new string[] { fromType };
                string[] argVarNames                = null;
                string   returnTypeName             = null;
                string   metricName                 = null;
                string   comment                    = null;
                Dictionary <string, string> options = null;
                G25.fgs F = new G25.fgs(funcName, outputName, returnTypeName, argumentTypes, argVarNames, new string[] { FT.type }, metricName, comment, options);
                cgd.AddMissingDependency(S, F);
            }

            // return fictional name:
            G25.fgs tmpF = null;
            return("missingFunction_" + G25.CG.Shared.Converter.GetConverterName(S, tmpF, FT.GetMangledName(S, fromType), FT.GetMangledName(S, toType)));
        }
Exemplo n.º 11
0
 /// <summary>
 /// Merges all errors from cgd into this CGdata.
 /// </summary>
 /// <param name="cgd"></param>
 public void MergeErrors(CGdata cgd)
 {
     lock (m_errors)
     {
         if (m_errors != cgd.m_errors)
         {
             m_errors.AddRange(cgd.m_errors);
         }
     }
 }
Exemplo n.º 12
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
        }
Exemplo n.º 13
0
        /// <summary>
        /// Returns runtime code for check for zero.
        /// </summary>
        /// <param name="S">Specification (used for floating points types, output language, GMV).</param>
        /// <param name="cgd">Output goes here.</param>
        /// <param name="groupIdx">The group to generate code for.</param>
        /// <param name="src">Name of source array .</param>
        /// <param name="epsilon">Name of epsilon variable.</param>
        protected static string GetRuntimeGmvZeroCode(Specification S, CGdata cgd,
            int groupIdx, string src, string epsilon)
        {
            StringBuilder SB = new StringBuilder();

            string TRUE = (S.OutputC()) ? "1" : "true";
            string FALSE = (S.OutputC()) ? "0" : "false";

            SB.Append("\tint i;\n");
            SB.Append("\tfor (i = 0; i < " + (S.m_GMV.Group(groupIdx).Length).ToString() + "; i++)\n");
            SB.Append("\t\tif ((" + src + "[i] < -" + epsilon + ") || (" + src + "[i] > " + epsilon + ")) return " + FALSE + ";\n");
            SB.Append("\treturn " + TRUE + ";\n");

            return SB.ToString();
        }
Exemplo n.º 14
0
        /// <summary>
        /// Returns code for run-time copying-and-scalar-multiplying/dividing of GMV parts.
        /// </summary>
        /// <param name="S">Specification (used for floating points types, output language, GMV).</param>
        /// <param name="cgd">Output goes here.</param>
        /// <param name="groupIdx">The group to generate code for.</param>
        /// <param name="src">Name of source array.</param>
        /// <param name="dst">Name of destination array.</param>
        /// <param name="scale">Name of scalar variable.</param>
        /// <param name="symbol">Symbol to use ("*" or "/").</param>
        protected static string GetRuntimeGmvCopyMulDivCode(Specification S, CGdata cgd, 
            int groupIdx, string src, string dst, string scale, string symbol)
        {
            StringBuilder SB = new StringBuilder();

            SB.Append("\tint i;\n");
            SB.Append("\tfor (i = 0; i < " + (S.m_GMV.Group(groupIdx).Length).ToString() + "; i++)\n");
            SB.Append("\t\t" + dst + "[i] = " + src + "[i] " + symbol + " " + scale + ";\n");

            return SB.ToString();
        }
Exemplo n.º 15
0
        /// <summary>
        /// Returns code for expand-code equality check of two GMV parts.
        /// </summary>
        /// <param name="S">Specification (used for floating points types, output language, GMV).</param>
        /// <param name="cgd">Output goes here.</param>
        /// <param name="groupIdx">The group to generate code for.</param>
        /// <param name="src1">Name of source array 1.</param>
        /// <param name="src2">Name of source array 2.</param>
        /// <param name="epsilon">Name of epsilon variable.</param>
        protected static string GetExpandGmvEqualsCode(Specification S, CGdata cgd,
            int groupIdx, string src1, string src2, string epsilon)
        {
            StringBuilder SB = new StringBuilder();

            string TRUE = CodeUtil.GetTrueValue(S);
            string FALSE = CodeUtil.GetFalseValue(S);

            for (int i = 0; i < S.m_GMV.Group(groupIdx).Length; i++)
                SB.Append("\t\tif (((" + src1 + "[" + i + "] - " + src2 + "[" + i + "]) < -" + epsilon + ") || ((" + src1 + "[" + i + "] - " + src2 + "[" + i + "]) > " + epsilon + ")) return " + FALSE + ";\n");
            SB.Append("\treturn " + TRUE + ";\n");

            return SB.ToString();
        }
Exemplo n.º 16
0
        } // end of GetFunctionName()

        /// <summary>
        /// Returns the name of a generated function (for example <c>gp_mv_mv</c>).
        /// The function is found by looking through all G25.FGS in the Specification.
        ///
        /// If the function is not found, a fictional name is returned, i.e. "missingFunction_" + functionName.
        /// This name will then show up in the generated code, which will not compile as a result.
        ///
        /// If the function is not found, this is also enlisted in cgd.m_missingDependencies.
        /// Call cgd.PrintMissingDependencies() should be called to report the missing dependencies
        /// to the end-user.
        /// </summary>
        /// <param name="S">The spec.</param>
        /// <param name="cgd">Missing dependencies go into cgd.m_missingDependencies.</param>
        /// <param name="functionName">Basic name of the function to be found.</param>
        /// <param name="argumentTypes">Names of the arguments types (not mangled).</param>
        /// <param name="FT">Floating point type.</param>
        /// <param name="metricName">(optional, can be null for don't care)</param>
        /// <returns>The mangled name of the function.</returns>
        public static string GetDependency(Specification S, CGdata cgd, string functionName, string[] argumentTypes, G25.FloatType FT, string metricName)
        {
            string returnTypeName = null;

            return(GetDependency(S, cgd, functionName, argumentTypes, returnTypeName, FT, metricName));
        }
Exemplo n.º 17
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="cgd"></param>
 public CGdata(CGdata cgd)
 {
     // copy all from cgd
     m_plugins = cgd.m_plugins;
     m_cog = cgd.m_cog;
     m_gmvGPpartFuncNames = cgd.m_gmvGPpartFuncNames;
     m_gmvDualPartFuncNames = cgd.m_gmvDualPartFuncNames;
     m_gmvGomPartFuncNames = cgd.m_gmvGomPartFuncNames;
     m_missingDependencies = cgd.m_missingDependencies;
     m_errors = cgd.m_errors;
     m_feedback = cgd.m_feedback;
     m_dependencyId = cgd.m_dependencyId;
     m_dependencyPrefix = cgd.m_dependencyPrefix;
 }
Exemplo n.º 18
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()
Exemplo n.º 19
0
        /// <summary>
        /// Returns the name of a generated function (for example <c>gp_mv_mv</c>).
        /// The function is found by looking through all G25.FGS in the Specification.
        /// 
        /// If the function is not found, a fictional name is returned, i.e. "missingFunction_" + functionName.
        /// This name will then show up in the generated code, which will not compile as a result.
        /// 
        /// If the function is not found, this is also enlisted in cgd.m_missingDependencies.
        /// Call cgd.PrintMissingDependencies() should be called to report the missing dependencies
        /// to the end-user.
        /// </summary>
        /// <param name="S">The spec.</param>
        /// <param name="cgd">Missing dependencies go into cgd.m_missingDependencies.</param>
        /// <param name="functionName">Basic name of the function to be found.</param>
        /// <param name="argumentTypes">Names of the arguments types (not mangled).</param>
        /// <param name="returnTypeName">Name of the return type (can be null or "" for default return type).</param>
        /// <param name="FT">Floating point type.</param>
        /// <param name="metricName">(optional, can be null for don't care)</param>
        /// <returns>The mangled name of the function.</returns>
        public static string GetDependency(Specification S, CGdata cgd, string functionName, 
            string[] argumentTypes, string returnTypeName, G25.FloatType FT, string metricName)
        {
            // bool returnTrueName = dependent on cgd.mode
            try
            {
                return GetFunctionName(S, functionName, argumentTypes, returnTypeName, FT, metricName);
            }
            catch (DependencyException)
            { // function not found, return a fictional name, and remember dependency
                G25.fgs F = null;
                {
                    // get name of dep, and make sure it does not get mangled
                    string outputName = functionName + cgd.GetDontMangleUniqueId();
                    if (returnTypeName != null) outputName = outputName + "_returns_" + returnTypeName;

                    // add dependency to list of missing deps:
                    string[] argVarNames = null;
                    Dictionary<String, String> options = null;
                    string comment = null;
                    G25.fgs tmpF = new G25.fgs(functionName, outputName, returnTypeName, argumentTypes, argVarNames, new String[] { FT.type }, metricName, comment, options);

                    F = cgd.AddMissingDependency(S, tmpF);
                }

                return cgd.m_dependencyPrefix + F.OutputName;
            }
        }
Exemplo n.º 20
0
 /// <summary>
 /// Constructor that allows you to set StringBuilders for each possible destination
 /// of the generated code (decl, def, inline def).
 /// </summary>
 /// <param name="cgd"></param>
 /// <param name="declSB"></param>
 /// <param name="defSB"></param>
 /// <param name="inlineDefSB"></param>
 public CGdata(CGdata cgd, StringBuilder declSB, StringBuilder defSB, StringBuilder inlineDefSB) : this(cgd)
 {
     m_declSB = declSB;
     m_defSB = defSB;
     m_inlineDefSB = inlineDefSB;
 }
Exemplo n.º 21
0
        /// <summary>
        /// The user may have requested a return type (F.ReturnTypeName). 
        /// In that case, the type with the same name is found, or an exception 
        /// is thrown if it does not exists.
        /// 
        /// Otherwise, finds the (tightest, best) return type for a function 'F' which 
        /// returning the (symbolic) value 'value'. 
        /// This  may or may not result in an SMV being found. If no 
        /// type is found and the return type is a scalar, then a floating
        /// point type may be returned.
        /// 
        /// If no SMV type is found, then a new type is created, and an exception
        /// is thrown which described the missing type.
        /// </summary>
        /// <param name="S">The specification (used to find SMVs)</param>
        /// <param name="cgd">Not used currently.</param>
        /// <param name="F">Function description (used for user-specified return type).</param>
        /// <param name="FT">Floating point type used in function.</param>
        /// <param name="value">The symbolic return value.</param>
        /// <returns>The SMV, FloatType or null if none found.</returns>
        public static G25.VariableType GetReturnType(Specification S, CGdata cgd, G25.fgs F, FloatType FT, RefGA.Multivector value)
        {
            if ((F.ReturnTypeName != null) && (F.ReturnTypeName.Length > 0))
            {
                // The user specified a return type
                G25.SMV returnSmv = S.GetSMV(F.ReturnTypeName); // is it a SMV?
                if (returnSmv != null) return returnSmv;
                G25.FloatType returnFT = S.GetFloatType(F.ReturnTypeName); // is it a specific float?
                if (returnFT != null) return FT; //returnFT;
                else if (F.ReturnTypeName == G25.XML.XML_SCALAR) // is it a unspecified float?
                    return FT;

                // type does not exist: abort (TODO: error message)
                else throw new G25.UserException("Non-existant user-specified return type: " + F.ReturnTypeName,
                    XML.FunctionToXmlString(S, F)); // non-existant return type
            }
            else
            {
                G25.VariableType RT = FindTightestMatch(S, value, FT);
                if (RT != null) return RT;
                else return CreateSyntheticSMVtype(S, cgd, FT, value);
            }
        }
Exemplo n.º 22
0
 /// <summary>
 /// Constructor that allows you to set StringBuilders for each possible destination
 /// of the generated code (decl, def, inline def).
 /// </summary>
 /// <param name="cgd"></param>
 /// <param name="declSB"></param>
 /// <param name="defSB"></param>
 /// <param name="inlineDefSB"></param>
 public CGdata(CGdata cgd, StringBuilder declSB, StringBuilder defSB, StringBuilder inlineDefSB)
     : this(cgd)
 {
     m_declSB = declSB;
     m_defSB = defSB;
     m_inlineDefSB = inlineDefSB;
 }
Exemplo n.º 23
0
        /// <summary>
        /// Generates functions which compute the dual or undual of general multivectors, on a group by group basis.
        /// 
        /// This function should be called early on in the code generation process, at least
        /// before any of the <c>GetDualCode()</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 WriteDualParts(Specification S, CGdata cgd)
        {
            G25.GMV gmv = S.m_GMV;

            string name1 = "A";
            string name2 = "B";
            string name3 = "C";
            bool ptr = true;
            int allGroups = -1;
            bool mustCast = false;
            int nbBaseTabs = (S.OutputCSharpOrJava()) ? 1 : 0;
            int nbCodeTabs = nbBaseTabs + 1;
            bool writeZeros = false;

            // get symbolic multivectors
            RefGA.Multivector[] M1 = null;
            if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                M1 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, name1, 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>();

                foreach (G25.Metric M in S.m_metric)
                {
                    if (M.m_metric.IsDegenerate()) continue; // do not generate code for degenerate metrics

                    for (int g1 = 0; g1 < gmv.NbGroups; g1++)
                    {
                        for (int d = 1; d >= 0; d--) // d = 1 -> generate dual, d = 0 -> generate undual
                        {
                            // get value of operation, name of function:
                            RefGA.Multivector value = null;
                            if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                            {
                                try
                                {
                                    value = (d == 0) ? RefGA.Multivector.Undual(M1[g1], M.m_metric) : RefGA.Multivector.Dual(M1[g1], M.m_metric);
                                }
                                catch (Exception)
                                {
                                    cgd.AddError(new G25.UserException("Non-invertable pseudoscalar. Do not generate (un)dual functions for degenerate metrics."));
                                    return;
                                }
                                if (M.m_round) value = value.Round(1e-14);
                            }

                            int grade = gmv.Group(g1)[0].Grade();
                            int dualGrade = S.m_dimension - grade;
                            for (int g3 = 0; g3 < gmv.NbGroups; g3++)
                            {
                                if (gmv.Group(g3)[0].Grade() == dualGrade)
                                {
                                    string funcName = (d == 0) ? GetUndualPartFunctionName(S, FT, M, g1, g3) : GetDualPartFunctionName(S, FT, M, g1, g3);

                                    // get assignment code
                                    string code = "";

                                    if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    { // full code expansion
                                        int dstBaseIdx = 0;
                                        code = G25.CG.Shared.CodeUtil.GenerateGMVassignmentCode(S, FT, mustCast, gmv, name3, g3, dstBaseIdx, value, nbCodeTabs, writeZeros);
                                    }
                                    else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    { // runtime code
                                        code = GetRuntimeDualCode(S, FT, M, d, g1, g3, name1, name2, name3);
                                    }

                                    cgd.m_gmvDualPartFuncNames[new Tuple<string, string, string>(FT.type, M.m_name, funcName)] = (code.Length > 0);

                                    if (code.Length == 0) continue; // only if code is non-empty

                                    // is the following ever required: (i.e. the dual of a basis blade wrt to the full space is not a single basis blade?)
                                    //if (!M.m_metric.IsDiagonal())
                                    //    code = code.Replace("=", "+=");

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

                                    // write comment
                                    string comment = "Computes the partial " + ((d == 0) ? "un" : "") + "dual (w.r.t. full space) of a multivector.";

                                    string ACCESS = "";
                                    if (S.OutputJava()) ACCESS = "protected final 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.type + ARR + name1 + ", " + FT.type + ARR + name3 + ")";

                                    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 output groups
                        } // end of loop over undual (0) and dual(1)
                    } // end of loop over all input groups
                } // end of loop over all metric
            } // end of loop over all float types
        }
Exemplo n.º 24
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;
 }
Exemplo n.º 25
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
        }
Exemplo n.º 26
0
 /// <returns>A unique name for the testing function of 'funcName'.</returns>
 public static string GetTestingFunctionName(Specification S, CGdata cgd, string funcName)
 {
     if (S.OutputC())
         return "test_" + funcName;
     else return "test_" + funcName + cgd.GetDontMangleUniqueId();
 }
Exemplo n.º 27
0
        /// <summary>
        /// Generates functions which compute the dual or undual of general multivectors, on a group by group basis.
        ///
        /// This function should be called early on in the code generation process, at least
        /// before any of the <c>GetDualCode()</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 WriteDualParts(Specification S, CGdata cgd)
        {
            G25.GMV gmv = S.m_GMV;

            string name1      = "A";
            string name2      = "B";
            string name3      = "C";
            bool   ptr        = true;
            int    allGroups  = -1;
            bool   mustCast   = false;
            int    nbBaseTabs = (S.OutputCSharpOrJava()) ? 1 : 0;
            int    nbCodeTabs = nbBaseTabs + 1;
            bool   writeZeros = false;

            // get symbolic multivectors
            RefGA.Multivector[] M1 = null;
            if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
            {
                M1 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, name1, 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>();

                foreach (G25.Metric M in S.m_metric)
                {
                    if (M.m_metric.IsDegenerate())
                    {
                        continue;                            // do not generate code for degenerate metrics
                    }
                    for (int g1 = 0; g1 < gmv.NbGroups; g1++)
                    {
                        for (int d = 1; d >= 0; d--) // d = 1 -> generate dual, d = 0 -> generate undual
                        {
                            // get value of operation, name of function:
                            RefGA.Multivector value = null;
                            if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                            {
                                try
                                {
                                    value = (d == 0) ? RefGA.Multivector.Undual(M1[g1], M.m_metric) : RefGA.Multivector.Dual(M1[g1], M.m_metric);
                                }
                                catch (Exception)
                                {
                                    cgd.AddError(new G25.UserException("Non-invertable pseudoscalar. Do not generate (un)dual functions for degenerate metrics."));
                                    return;
                                }
                                if (M.m_round)
                                {
                                    value = value.Round(1e-14);
                                }
                            }


                            int grade     = gmv.Group(g1)[0].Grade();
                            int dualGrade = S.m_dimension - grade;
                            for (int g3 = 0; g3 < gmv.NbGroups; g3++)
                            {
                                if (gmv.Group(g3)[0].Grade() == dualGrade)
                                {
                                    string funcName = (d == 0) ? GetUndualPartFunctionName(S, FT, M, g1, g3) : GetDualPartFunctionName(S, FT, M, g1, g3);

                                    // get assignment code
                                    string code = "";

                                    if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                    { // full code expansion
                                        int dstBaseIdx = 0;
                                        code = G25.CG.Shared.CodeUtil.GenerateGMVassignmentCode(S, FT, mustCast, gmv, name3, g3, dstBaseIdx, value, nbCodeTabs, writeZeros);
                                    }
                                    else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                    { // runtime code
                                        code = GetRuntimeDualCode(S, FT, M, d, g1, g3, name1, name2, name3);
                                    }

                                    cgd.m_gmvDualPartFuncNames[new Tuple <string, string, string>(FT.type, M.m_name, funcName)] = (code.Length > 0);

                                    if (code.Length == 0)
                                    {
                                        continue;                   // only if code is non-empty
                                    }
                                    // is the following ever required: (i.e. the dual of a basis blade wrt to the full space is not a single basis blade?)
                                    //if (!M.m_metric.IsDiagonal())
                                    //    code = code.Replace("=", "+=");

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

                                    // write comment
                                    string comment = "Computes the partial " + ((d == 0) ? "un" : "") + "dual (w.r.t. full space) of a multivector.";

                                    string ACCESS = "";
                                    if (S.OutputJava())
                                    {
                                        ACCESS = "protected final 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.type + ARR + name1 + ", " + FT.type + ARR + name3 + ")";

                                    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 output groups
                        }     // end of loop over undual (0) and dual(1)
                    }         // end of loop over all input groups
                }             // end of loop over all metric
            }                 // end of loop over all float types
        }                     // end of function WriteDualParts()
Exemplo n.º 28
0
        /// <summary>
        /// Writes pieces of code to <c>cgd</c> which compute the geometric product of general multivectors,
        /// on a group by group basis. The function is output language aware.
        /// </summary>
        /// <param name="S">Specification (used for output language, GMV).</param>
        /// <param name="cgd">Result goes here, and <c>cgd.m_gmvGPpartFuncNames</c> is set.</param>
        public static void WriteGmvGpParts(Specification S, CGdata cgd)
        {
            G25.GMV gmv = S.m_GMV;

            string name1 = "A";
            string name2 = "B";
            string name3 = "C";
            bool ptr = true;
            int allGroups = -1;
            bool mustCast = false;
            int nbBaseTabs = (S.OutputCSharpOrJava()) ? 1 : 0;
            int nbCodeTabs = 1 + nbBaseTabs;
            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 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, name1, ptr, allGroups);
                M2 = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, name2, ptr, allGroups);
            }

            foreach (G25.FloatType FT in S.m_floatTypes)
            {
                bool fromOutsideRuntimeNamespace = true;
                string runtimeComputeGpFuncName = GetRuntimeComputeGpFuncName(S, FT, fromOutsideRuntimeNamespace);

                int metricId = 0;
                foreach (G25.Metric M in S.m_metric)
                {
                    // map from code fragment to name of function
                    Dictionary<string, string> generatedCode = new Dictionary<string, string>();

                    for (int g1 = 0; g1 < gmv.NbGroups; g1++)
                    {
                        for (int g2 = 0; g2 < gmv.NbGroups; g2++)
                        {
                            RefGA.Multivector M3 = null;
                            if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                            {
                                M3 = RefGA.Multivector.gp(M1[g1], M2[g2], M.m_metric);
                                // round value if required by metric
                                if (M.m_round) M3 = M3.Round(1e-14);
                            }

                            for (int gd = 0; gd < gmv.NbGroups; gd++)
                            {
                                // get function name
                                string funcName = GetGPpartFunctionName(S, FT, M, g1, g2, gd);

                                // get assignment code
                                string code = ""; // empty string means 'no code for this combo of g1, g2, gd and metric'.

                                if (S.m_gmvCodeGeneration == GMV_CODE.EXPAND)
                                { // code for full expansion
                                    int dstBaseIdx = 0;
                                    code = G25.CG.Shared.CodeUtil.GenerateGMVassignmentCode(S, FT, mustCast, gmv, name3, gd, dstBaseIdx, M3, nbCodeTabs, writeZeros);
                                    // replace '=' with '+='
                                    code = code.Replace("=", "+=");
                                }
                                else if (S.m_gmvCodeGeneration == GMV_CODE.RUNTIME)
                                { // code for runtime geometric product
                                    string EMP = (S.OutputCppOrC()) ? "&" : "";

                                    if (!S.m_GMV.IsZeroGP(g1, g2, gd))
                                    {
                                        fromOutsideRuntimeNamespace = true;
                                        string runtimeGpTableName = GetRuntimeGpTableName(S, M, g1, g2, gd, fromOutsideRuntimeNamespace);
                                        if (S.OutputCSharpOrJava())
                                        {
                                            string initFunc = S.OutputJava() ? "initRuntimeGpTable" : "InitRuntimeGpTable";

                                            code = "\t\tif(" + runtimeGpTableName + " == null) " +
                                              runtimeGpTableName + " = " + initFunc + "(" + metricId + ", " + g1 + ", " + g2 + ", " + gd + ");\n\t";
                                        }
                                        code += "\t" + runtimeComputeGpFuncName + "(" + name1 + ", " + name2 + ", " + name3 +
                                            ", " + EMP + runtimeGpTableName + ", " + metricId + ", " + g1 + ", " + g2 + ", " + gd + ");\n";
                                    }
                                }

                                // set the function names of parts of the geometric product
                                cgd.m_gmvGPpartFuncNames[new Tuple<string, string, string>(FT.type, M.m_name, funcName)] = (code.Length > 0);

                                if (code.Length > 0)
                                {
                                    // check if code was already generated, and, if so, reuse it
                                    if ((S.m_gmvCodeGeneration == GMV_CODE.EXPAND) && generatedCode.ContainsKey(code))
                                    {
                                        // ready generated: call that function
                                        code = new string('\t', nbCodeTabs) + generatedCode[code] + "(" + name1 + ", " + name2 + ", " + name3 + ");\n";
                                    }
                                    else
                                    {
                                        // not generated yet: remember code -> function
                                        generatedCode[code] = funcName;
                                    }

                                    string comment = "Computes the partial geometric product of two multivectors (group " + g1 + "  x  group " + g2 + " -> group " + gd + ")";
                                    string funcDecl;

                                    if (S.OutputCppOrC())
                                    {
                                        funcDecl = "void " + funcName + "(const " + FT.type + " *" + name1 + ", const " + FT.type + " *" + name2 + ", " + FT.type + " *" + name3 + ")";

                                        // write comment
                                        int nbCommentTabs = nbBaseTabs;
                                        new Comment(comment).Write(cgd.m_declSB, S, nbCommentTabs);
                                        // emit decl
                                        cgd.m_declSB.Append(funcDecl);
                                        cgd.m_declSB.AppendLine(";");
                                    }
                                    else
                                    {
                                        string ACCESS = (S.OutputJava()) ? "protected final static " : "protected internal static ";
                                        funcDecl = ACCESS + "void " + funcName + "(" + FT.type + "[] " + name1 + ", " + FT.type + "[] " + name2 + ", " + FT.type + "[] " + name3 + ")";

                                        // write comment
                                        int nbCommentTabs = nbBaseTabs;
                                        new Comment(comment).Write(cgd.m_defSB, S, nbCommentTabs);
                                    }

                                    // 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 'if code not empty'
                            } // end of loop over the grade of 'C'
                        } // end of loop over the grade of 'B'
                    } // end of loop over the grade of 'A'
                    metricId++;
                } // end of loop over all metrics
            } // end of loop over all float types
        }
Exemplo n.º 29
0
 /// <summary>
 /// Returns the name of a generated function (for example <c>gp_mv_mv</c>).
 /// The function is found by looking through all G25.FGS in the Specification.
 /// 
 /// If the function is not found, a fictional name is returned, i.e. "missingFunction_" + functionName.
 /// This name will then show up in the generated code, which will not compile as a result.
 /// 
 /// If the function is not found, this is also enlisted in cgd.m_missingDependencies.
 /// Call cgd.PrintMissingDependencies() should be called to report the missing dependencies
 /// to the end-user.
 /// </summary>
 /// <param name="S">The spec.</param>
 /// <param name="cgd">Missing dependencies go into cgd.m_missingDependencies.</param>
 /// <param name="functionName">Basic name of the function to be found.</param>
 /// <param name="argumentTypes">Names of the arguments types (not mangled).</param>
 /// <param name="FT">Floating point type.</param>
 /// <param name="metricName">(optional, can be null for don't care)</param>
 /// <returns>The mangled name of the function.</returns>
 public static string GetDependency(Specification S, CGdata cgd, string functionName, string[] argumentTypes, G25.FloatType FT, string metricName)
 {
     string returnTypeName = null;
     return GetDependency(S, cgd, functionName, argumentTypes, returnTypeName, FT, metricName);
 }