public static void WriteOpenNamespace(StringBuilder SB, G25.Specification S, string namespaceName) { switch (S.m_outputLanguage) { case OUTPUT_LANGUAGE.CPP: case OUTPUT_LANGUAGE.CSHARP: if (S.m_namespace.Length > 0) { SB.Append("namespace "); SB.Append(namespaceName); SB.AppendLine(" {"); } break; case OUTPUT_LANGUAGE.JAVA: if (S.m_namespace.Length > 0) { SB.Append("package "); SB.Append(namespaceName); SB.AppendLine(";"); } break; default: throw new Exception("G25.CG.Shared.Util.WriteOpenNamespace(): output language not supported"); } }
/// <summary> /// Writes the license (as specified in 'S') to 'SB'. Uses opening and closing /// comments. /// </summary> /// <param name="S">Specification (used for license).</param> /// <param name="SB">Where the code goes.</param> public static void WriteLicense(StringBuilder SB, G25.Specification S) { WriteOpenMultilineComment(SB, S); SB.Append(S.GetLicense()); SB.AppendLine(""); WriteCloseMultilineComment(SB, S); }
} // end of WriteParserTest() public static List <string> WriteMetricTests(G25.Specification S, G25.CG.Shared.CGdata cgd, Dictionary <String, String> gpGmvFuncName) // , string gpFuncName { List <string> testFunctionNames = new List <string>(); foreach (FloatType FT in S.m_floatTypes) { //string testStr = FT.DoubleToString(S, FT.PrecisionEpsilon()); foreach (Metric M in S.m_metric) { string gmvName = FT.GetMangledName(S, S.m_GMV.Name); string testFuncName = "test_metric_" + M.m_name + "_" + gmvName; cgd.m_cog.EmitTemplate(cgd.m_defSB, "testMetric", "S=", S, "FT=", FT, "M=", M, "gmv=", S.m_GMV, "gmvName=", gmvName, "testFuncName=", testFuncName, "gpGmvFuncName=", gpGmvFuncName[FT.type + "_" + M.m_name] ); testFunctionNames.Add(testFuncName); } } return(testFunctionNames); } // WriteMetricTests()
/// <summary> /// Converts a <c>RefGA.Symbolic.UnaryScalarOp</c> to code. /// /// Handles special cases (such as inversion) and understands floating point /// types (e.g., <c>fabsf()</c> is used for floats and <c>fabs()</c> is used for doubles in C. /// </summary> /// <param name="S">Used for output language.</param> /// <param name="FT">Floating point type used.</param> /// <param name="Op">The operation to convert to code.</param> /// <returns>Code for implementing <c>Op</c>c>.</returns> public static string UnaryScalarOpToLangString(G25.Specification S, G25.FloatType FT, RefGA.Symbolic.UnaryScalarOp Op) { string valueStr = ScalarOpValueToLangString(S, FT, Op.value); /*{ * if (!Op.value.IsScalar()) throw new Exception("G25.CG.Shared.BasisBlade.ScalarOpToLangString(): value should be scalar, found: " + Op.value.ToString(S.m_basisVectorNames)); * if (Op.value.IsZero()) valueStr = ScalarToLangString(S, FT, RefGA.BasisBlade.ZERO); * else valueStr = ScalarToLangString(S, FT, Op.value.BasisBlades[0]); * }*/ if (Op.opName == UnaryScalarOp.INVERSE) { if (FT.type == "float") { return("1.0f / (" + valueStr + ")"); } else if (FT.type == "double") { return("1.0 / (" + valueStr + ")"); } else { return(FT.castStr + "1.0 / (" + valueStr + ")"); } } else { return(OpNameToLangString(S, FT, Op.opName) + "(" + valueStr + ")"); } } // end of function ScalarOpToLangString()
public static void LoadAndSave(string srcFilename, string dstFilename) { try { Console.WriteLine("Loading algebra specification: " + srcFilename); G25.Specification S = new G25.Specification(srcFilename); Console.WriteLine("Saving algebra specification: " + dstFilename); string str = XML.ToXmlString(S); G25.CG.Shared.Util.WriteFile(dstFilename, str); // write list of generated files if (OptionSaveFileListFile != null) { List <string> L = new List <string>(); L.Add(dstFilename); SaveGenerateFileList(OptionSaveFileListFile, L); } } catch (G25.UserException E) { System.Console.WriteLine("Error:"); System.Console.Write(E.GetErrorReport()); } catch (System.Exception E) { System.Console.WriteLine("Exception:"); System.Console.WriteLine(E.ToString()); System.Console.WriteLine(E.Message); } }
} // WriteMetricTests() public static List <string> WriteGetterSetterTests(G25.Specification S, G25.CG.Shared.CGdata cgd, List <string> randomNumberGeneratorFuncName, Dictionary <string, string> randomVersorFuncName) // , string gpFuncName { List <string> testFunctionNames = new List <string>(); int FTidx = 0; //G25.GMV gmv = S.m_GMV; foreach (FloatType FT in S.m_floatTypes) { //string testStr = FT.DoubleToString(S, FT.PrecisionEpsilon()); string gmvName = FT.GetMangledName(S, S.m_GMV.Name); string testFuncName = "test_getter_setter_" + gmvName; cgd.m_cog.EmitTemplate(cgd.m_defSB, "testGetterSetter", "S=", S, "FT=", FT, "gmv=", S.m_GMV, "gmvName=", gmvName, "testFuncName=", testFuncName, "randomScalarFuncName=", randomNumberGeneratorFuncName[FTidx], "randomVersorFuncName=", randomVersorFuncName[FT.type] ); testFunctionNames.Add(testFuncName); FTidx++; } return(testFunctionNames); } // WriteGetterSetterTests()
/// <param name="S"></param> /// <param name="FT"></param> /// <param name="M"></param> /// <param name="d">1 -> generate dual, d = 0 -> generate undual</param> /// <param name="g1"></param> /// <param name="gd"></param> /// <param name="name1"></param> /// <param name="name2"></param> /// <param name="name3"></param> /// <returns>The code to compute a (un)dual at runtime using the geometric product tables.</returns> public static string GetRuntimeDualCode(G25.Specification S, G25.FloatType FT, G25.Metric M, int d, int g1, int gd, string name1, string name2, string name3) { // get pseudoscalar RefGA.Multivector I = RefGA.Multivector.GetPseudoscalar(S.m_dimension); if (d == 1) // if dual: use inverse I { I = RefGA.Multivector.VersorInverse(I, M.m_metric); } // get grade/group of pseudoscalar in GMV int g2 = S.m_GMV.GetGroupIdx(I.BasisBlades[0]); // get sign of pseudo scalar basis blade in GMV: double IbladeSign = S.m_GMV.Group(g2)[0].scale; string tmpArrayCode; if (S.OutputCppOrC()) { tmpArrayCode = "\t" + FT.type + " " + name2 + "[1] = {" + FT.DoubleToString(S, IbladeSign * I.BasisBlades[0].scale) + "};\n"; } else { tmpArrayCode = "\t\t" + FT.type + "[] " + name2 + " = new " + FT.type + "[]{" + FT.DoubleToString(S, IbladeSign * I.BasisBlades[0].scale) + "};\n\t"; } return (tmpArrayCode + "\t" + GPparts.GetGPpartFunctionName(S, FT, M, g1, g2, gd) + "(" + name1 + ", " + name2 + ", " + name3 + ");\n"); }
} // end of function ScalarOpToLangString() /// <summary> /// Converts a <c>RefGA.Symbolic.BinaryScalarOpToLangString</c> to code. /// /// Handles special cases (such as inversion) and understands floating point /// types (e.g., <c>fabsf()</c> is used for floats and <c>fabs()</c> is used for doubles in C. /// </summary> /// <param name="S">Used for output language.</param> /// <param name="FT">Floating point type used.</param> /// <param name="Op">The operation to convert to code.</param> /// <returns>Code for implementing <c>Op</c>c>.</returns> public static string BinaryScalarOpToLangString(G25.Specification S, G25.FloatType FT, RefGA.Symbolic.BinaryScalarOp Op) { string value1Str = ScalarOpValueToLangString(S, FT, Op.value1); string value2Str = ScalarOpValueToLangString(S, FT, Op.value2); return(OpNameToLangString(S, FT, Op.opName) + "(" + value1Str + ", " + value2Str + ")"); } // end of function BinaryScalarOpToLangString()
public static void Generate(string filename) { try { G25.Specification S = new G25.Specification(filename); // get the code generator and plugins ready CodeGeneratorLoader L = new CodeGeneratorLoader(S.GetOutputLanguageString()); LoadDefaultCodeGenerators(L); // todo: load custom plugins (their location will be in the specification XML?) if (L.GetMainCodeGenerator() == null) throw new G25.UserException("No code generator for language " + S.GetOutputLanguageString()); // generate the code List<string> generatedFiles = L.GetMainCodeGenerator().GenerateCode(S, L.GetCodeGeneratorPlugins()); // insert verbatim code: S.InsertVerbatimCode(generatedFiles); // write list of generated files if (OptionSaveFileListFile != null) SaveGenerateFileList(OptionSaveFileListFile, generatedFiles); } catch (G25.UserException E) { System.Console.WriteLine("Error:"); System.Console.Write(E.GetErrorReport()); } catch (System.Exception E) { System.Console.WriteLine("Exception:"); System.Console.WriteLine(E.ToString()); System.Console.WriteLine(E.Message); } }
/// <summary> /// Writes the copyright notice (as specified in 'S') to 'SB'. /// Uses opening and closing comments. /// </summary> /// <param name="S">Specification (used for license).</param> /// <param name="SB">Where the code goes.</param> public static void WriteCopyright(StringBuilder SB, G25.Specification S) { if (S.m_copyright.Length > 0) { WriteOpenMultilineComment(SB, S); SB.AppendLine(S.m_copyright); WriteCloseMultilineComment(SB, S); } }
/// <summary> /// Constructs an array of func arg info for all arguments of an G25.fgs. /// </summary> /// <param name="S">Used for retrieving the G25.VariableType of 'm_typeName'.</param> /// <param name="F">Function for which you want an array of FuncArgInfo.</param> /// <param name="nbArgs">Default number of arguments. (the user may not specified arguments and then a default is used).</param> /// <param name="FT">Floating point type of arguments.</param> /// <param name="defaultTypeName">When the user does not specify arguments, this is the default type used.</param> /// <param name="computeMultivectorValue">Set to true to expand all multivector values to symbolic RefGA.Multivectors.</param> /// <returns>Array of FuncArgInfo describing the arguments of 'F'.</returns> public static FuncArgInfo[] GetAllFuncArgInfo(G25.Specification S, G25.fgs F, int nbArgs, G25.FloatType FT, string defaultTypeName, bool computeMultivectorValue) { FuncArgInfo[] FAI = new FuncArgInfo[nbArgs]; for (int i = 0; i < nbArgs; i++) { FAI[i] = new FuncArgInfo(S, F, i, FT, defaultTypeName, computeMultivectorValue); } return(FAI); }
/// <summary> /// Returns the code to copy an array of 'nb' floats from 'srcPtrName' to 'dstPtrName'. /// </summary> public static string GetCopyCode(G25.Specification S, G25.FloatType FT, string srcPtrName, string dstPtrName, int nb) { if (nb <= Main.MAX_EXPLICIT_ZERO) { return(GetZeroCodePrefix(S, FT) + GetCopyFuncName(S) + "_" + nb + "(" + dstPtrName + ", " + srcPtrName + ");\n"); } else { return(GetCopyCode(S, FT, srcPtrName, dstPtrName, nb.ToString())); } }
/// <summary> /// Returns the code to set ptrName[0] to ptrName[nb-1] to 0. /// </summary> public static string GetSetToZeroCode(G25.Specification S, G25.FloatType FT, string ptrName, int nb) { if (nb <= Main.MAX_EXPLICIT_ZERO) { return(GetZeroCodePrefix(S, FT) + GetZeroFuncName(S) + "_" + nb + "(" + ptrName + ");\n"); } else { return(GetSetToZeroCode(S, FT, ptrName, nb.ToString())); } }
public static string GetNamespaceName(G25.Specification S) { if (S.OutputJava()) { return(S.m_namespace + "_pkg"); } else if (S.OutputCSharp()) { return(S.m_namespace + "_ns"); } else { return(S.m_namespace); } }
} // 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])); } }
} // end of function BinaryScalarOpToLangString() public static string OpNameToLangString(G25.Specification S, G25.FloatType FT, string opName) { switch (S.m_outputLanguage) { case OUTPUT_LANGUAGE.C: if (FT.type == "float") { return(m_floatOpsC[opName]); } else { return(m_doubleOpsC[opName]); } case OUTPUT_LANGUAGE.CPP: if (FT.type == "float") { return(m_floatOpsCpp[opName]); } else { return(m_doubleOpsCpp[opName]); } case OUTPUT_LANGUAGE.CSHARP: if (FT.type == "float") { return(m_floatOpsCSharp[opName]); } else { return(m_doubleOpsCSharp[opName]); } case OUTPUT_LANGUAGE.JAVA: if (FT.type == "float") { return(m_floatOpsJava[opName]); } else { return(m_doubleOpsJava[opName]); } default: throw new Exception("G25.CG.Shared.BasisBlade.ScalarOpToLangString(): todo: language " + S.GetOutputLanguageString()); } }
/// <summary> /// Converts a symbolic multivector value to a textual description of the specialized multivector /// type that would be required to store that value. This is used for presenting error messages /// to users when a suitable specialized type cannot be found for a specific multivector value. /// </summary> /// <param name="S">Specification, used for basis vector names.</param> /// <param name="value">The value to describe.</param> /// <returns>Textual description of the type that can store 'value'.</returns> public static String MultivectorToTypeDescription(G25.Specification S, RefGA.Multivector value) { StringBuilder SB = new StringBuilder(); bool appendSpace = false; foreach (RefGA.BasisBlade B in value.BasisBlades) { if (appendSpace) SB.Append(" "); SB.Append(new RefGA.BasisBlade(B.bitmap).ToString(S.m_basisVectorNames)); if (B.symScale == null) SB.Append("=" + B.scale); appendSpace = true; } return SB.ToString(); }
private static string GetZeroCodePrefix(G25.Specification S, G25.FloatType FT) { switch (S.m_outputLanguage) { case OUTPUT_LANGUAGE.C: return(S.m_namespace + "_" + FT.type + "_"); case OUTPUT_LANGUAGE.CPP: return(S.m_namespace + "::"); case OUTPUT_LANGUAGE.CSHARP: case OUTPUT_LANGUAGE.JAVA: return(S.m_namespace + "."); default: return("GetZeroCodePrefix(): not implemented yet"); } }
} // end of GenerateCode() /// <summary> /// Writes test code for multivector parser and toString() to <c>cgd.m_defSB</c>. /// </summary> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Code generation data (used for <c>m_cog</c> and <c>m_defSB</c>.</param> /// <param name="randomNumberGeneratorFuncName">Function for random number generator (main float type).</param> /// <param name="randomVersorFuncName">Function for random versor (main float type).</param> /// <param name="subtractGmvFuncName">Function for subtracting general multivectors (main float type).</param> /// <returns></returns> public static string WriteParserTest(G25.Specification S, G25.CG.Shared.CGdata cgd, string randomNumberGeneratorFuncName, string randomVersorFuncName, string subtractGmvFuncName) { string testFuncName = "test_parse_" + S.m_GMV.Name; cgd.m_cog.EmitTemplate(cgd.m_defSB, "testParse", "S=", S, "FT=", S.m_floatTypes[0], "gmvName=", S.m_floatTypes[0].GetMangledName(S, S.m_GMV.Name), "testFuncName=", testFuncName, "targetFuncName=", "Parse", "randomScalarFuncName=", randomNumberGeneratorFuncName, "randomVersorFuncName=", randomVersorFuncName, "subtractGmvFuncName=", subtractGmvFuncName ); return(testFuncName); } // end of WriteParserTest()
/// <summary> /// Returns the name of a converter function. For example, <c>"dualSphere_to_vectorE3GA"</c>. /// </summary> /// <param name="S"></param> /// <param name="F">Used for OutputName. Can be null for default name.</param> /// <param name="mangledSrcTypename">Source type (e.g. <c>"dualSphere"</c>).</param> /// <param name="mangledDstTypename">Destination type (e.g. <c>"vectorE3GA"</c>).</param> /// <returns>the name of a converter function.</returns> public static string GetConverterName(G25.Specification S, G25.fgs F, string mangledSrcTypename, string mangledDstTypename) { if ((F != null) && (F.OutputName != F.Name)) { return(F.OutputName); } switch (S.m_outputLanguage) { case OUTPUT_LANGUAGE.C: return(mangledSrcTypename + "_to_" + mangledDstTypename); case OUTPUT_LANGUAGE.CPP: case OUTPUT_LANGUAGE.CSHARP: case OUTPUT_LANGUAGE.JAVA: return("_" + mangledDstTypename); default: throw new Exception("Not implemented yet"); } }
public static void Generate(string filename) { try { G25.Specification S = new G25.Specification(filename); // get the code generator and plugins ready CodeGeneratorLoader L = new CodeGeneratorLoader(S.GetOutputLanguageString()); LoadDefaultCodeGenerators(L); // todo: load custom plugins (their location will be in the specification XML?) if (L.GetMainCodeGenerator() == null) { throw new G25.UserException("No code generator for language " + S.GetOutputLanguageString()); } // generate the code List <string> generatedFiles = L.GetMainCodeGenerator().GenerateCode(S, L.GetCodeGeneratorPlugins()); // insert verbatim code: S.InsertVerbatimCode(generatedFiles); // write list of generated files if (OptionSaveFileListFile != null) { SaveGenerateFileList(OptionSaveFileListFile, generatedFiles); } } catch (G25.UserException E) { System.Console.WriteLine("Error:"); System.Console.Write(E.GetErrorReport()); } catch (System.Exception E) { System.Console.WriteLine("Exception:"); System.Console.WriteLine(E.ToString()); System.Console.WriteLine(E.Message); } }
/// <summary> /// Writes the appropriate 'close multiline comment' string to <c>SB</c>. /// For example, if <c>S.m_outputLanguage</c> is a C-like language, "*/\n" is written. /// For Python, "\"\"\"\\n" is written. /// </summary> /// <param name="SB">Where the result goes.</param> /// <param name="S">Used for <c>S.m_outputLanguage</c>.</param> public static void WriteCloseMultilineComment(StringBuilder SB, G25.Specification S) { switch (S.m_outputLanguage) { case OUTPUT_LANGUAGE.C: case OUTPUT_LANGUAGE.CPP: case OUTPUT_LANGUAGE.JAVA: case OUTPUT_LANGUAGE.CSHARP: SB.AppendLine("*/"); break; case OUTPUT_LANGUAGE.PYTHON: SB.AppendLine("\"\"\""); break; case OUTPUT_LANGUAGE.MATLAB: SB.AppendLine("%}"); break; default: throw new Exception("G25.CG.Shared.Util.WriteOpenMultilineComment(): output language not supported"); } }
public static void WriteCloseNamespace(StringBuilder SB, G25.Specification S) { WriteCloseNamespace(SB, S, GetNamespaceName(S)); }
public static void LoadAndSave(string srcFilename, string dstFilename) { try { Console.WriteLine("Loading algebra specification: " + srcFilename); G25.Specification S = new G25.Specification(srcFilename); Console.WriteLine("Saving algebra specification: " + dstFilename); string str = XML.ToXmlString(S); G25.CG.Shared.Util.WriteFile(dstFilename, str); // write list of generated files if (OptionSaveFileListFile != null) { List<string> L = new List<string>(); L.Add(dstFilename); SaveGenerateFileList(OptionSaveFileListFile, L); } } catch (G25.UserException E) { System.Console.WriteLine("Error:"); System.Console.Write(E.GetErrorReport()); } catch (System.Exception E) { System.Console.WriteLine("Exception:"); System.Console.WriteLine(E.ToString()); System.Console.WriteLine(E.Message); } }
/// <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()
/// <summary> /// Converts a scalar basis blade (with optional symbolic part) to a string in the output language of <c>S</c>. /// /// Some effort is made to output code which is close to that a human would write. /// </summary> /// <param name="S">Specification of algebra, used for output language, basis vector names, etc.</param> /// <param name="FT">Floating point type of output.</param> /// <param name="B">The basis blade.</param> /// <returns>String code representation of 'B'.</returns> public static string ScalarToLangString(G25.Specification S, G25.FloatType FT, RefGA.BasisBlade B) { string symScaleStr = ""; { // convert symbolic part if (B.symScale != null) { // symbolic scalar string goes in symResult System.Text.StringBuilder symResult = new System.Text.StringBuilder(); int tCnt = 0; for (int t = 0; t < B.symScale.Length; t++) // for each term ...*...*...+ { Object[] T = (Object[])B.symScale[t].Clone(); // clone 'T' because IsolateInverses() might alter it! if (T != null) // if term is not null { // first find all scalarop inverses // turn those into a new term, but without inverses? Object[] TI = IsolateInverses(T); // emit 'T' int pCnt = EmitTerm(S, FT, T, tCnt, symResult); if (TI != null) // do we have to divide by a number of terms? { // emit '/(TI)' symResult.Append("/("); EmitTerm(S, FT, TI, 0, symResult); symResult.Append(")"); } if (pCnt > 0) { tCnt++; // only increment number of terms when T was not empty } } } if (tCnt > 0) { symScaleStr = ((tCnt > 1) ? "(" : "") + symResult + ((tCnt > 1) ? ")" : ""); } } } // end of symbolic part // special cases when numerical scale is exactly +- 1 if (B.scale == 1.0) { if (symScaleStr.Length > 0) { return(symScaleStr); } else { return(FT.DoubleToString(S, 1.0)); } } else if (B.scale == -1.0) { if (symScaleStr.Length > 0) { return("-" + symScaleStr); } else { return(FT.DoubleToString(S, -1.0)); } } else { // get numerical part string numScaleStr = FT.DoubleToString(S, B.scale); // merge symbolic and numerical if (symScaleStr.Length > 0) { numScaleStr = numScaleStr + "*" + symScaleStr; } // done return(numScaleStr); } } // end of function ScalarToLangString
} // end of GetAssignmentStrings() /// <summary> /// Used internally by ScalarToLangString(). /// /// Emits on term (+ ....) of a blade value. Contains some optimizations /// to avoid stuff like <c>+-1.0</c>. /// </summary> protected static int EmitTerm(G25.Specification S, G25.FloatType FT, Object[] T, int tCnt, StringBuilder symResult) { // make stuff below a function bool plusEmitted = false; int pCnt = 0; // number of non-null terms in 'T' for (int p = 0; p < T.Length; p++) // for each product ...* { if (T[p] != null) { if ((!plusEmitted) && (tCnt > 0)) { symResult.Append("+"); plusEmitted = true; } if ((pCnt > 0) && (symResult.Length > 0) && (!((symResult[symResult.Length - 1] == '-') || (symResult[symResult.Length - 1] == '+')))) { symResult.Append("*"); } System.Object O = T[p]; if ((O is System.Double) || (O is System.Single) || (O is System.Int16) || (O is System.Int32) || (O is System.Int64)) // etc . . . (all number types) { double val = (double)O; if ((val == -1.0) && (p == 0) && (T.Length > 1)) { // when multiplying with -1.0, output only a '-', IF the term is the first (p==0) and more terms follow (T.Length > 1) if (symResult.Length > 0) { // when val = -1, output code which is better for humans, instead of -1.0 * ... if (symResult[symResult.Length - 1] == '+') // change '+' to '-' { symResult[symResult.Length - 1] = '-'; } else { symResult.Append("-"); } } else { symResult.Append("-"); } } else if ((val == 1.0) && (p == 0) && (T.Length > 1)) { // when multiplying with 1.0, output nothing IF the term is the first (p==0) and more terms follow (T.Length > 1) // do nothing } else { symResult.Append(FT.DoubleToString(S, (double)O)); } } else if (O is UnaryScalarOp) { UnaryScalarOp USO = (UnaryScalarOp)O; symResult.Append(UnaryScalarOpToLangString(S, FT, USO)); } else if (O is BinaryScalarOp) { BinaryScalarOp BSO = (BinaryScalarOp)O; symResult.Append(BinaryScalarOpToLangString(S, FT, BSO)); } else if (O is RefGA.BasisBlade) { symResult.Append(ScalarToLangString(S, FT, (RefGA.BasisBlade)O)); } else if (O is RefGA.Multivector) { RefGA.Multivector mv = (RefGA.Multivector)O; StringBuilder mvSB = new StringBuilder(); mvSB.Append("("); bool first = true; foreach (RefGA.BasisBlade B in mv.BasisBlades) { if (!first) { mvSB.Append(" + "); } first = false; mvSB.Append(ScalarToLangString(S, FT, B)); } mvSB.Append(")"); symResult.Append(mvSB); } else { symResult.Append(O.ToString()); } pCnt++; } } return(pCnt); }
/// <summary> /// Returns the code to copy an array of 'nb' floats from 'srcPtrName' to 'dstPtrName'. /// </summary> public static string GetCopyCode(G25.Specification S, G25.FloatType FT, string srcPtrName, string dstPtrName, string nb) { return(GetZeroCodePrefix(S, FT) + GetCopyFuncName(S) + "_N(" + dstPtrName + ", " + srcPtrName + ", " + nb + ");\n"); }
/// <summary> /// Write code for conversion to string. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Specification.</param> /// <param name="cgd">Code generation data.</param> /// <param name="def">Whether to generate code for definition or declaration.</param> public static void WriteToString(StringBuilder SB, G25.Specification S, G25.CG.Shared.CGdata cgd, bool def) { string TEMPLATE_NAME = (def) ? "toStringSource" : "toStringHeader"; cgd.m_cog.EmitTemplate(SB, TEMPLATE_NAME, "S=", S, "STRING_PARAMETERS=", STRING_PARAMETERS); }
/// <summary> /// Returns the code to set ptrName[0] to ptrName[nb-1] to 0. /// </summary> public static string GetSetToZeroCode(G25.Specification S, G25.FloatType FT, string ptrName, string nb) { return(GetZeroCodePrefix(S, FT) + GetZeroFuncName(S) + "_N(" + ptrName + ", " + nb + ");\n"); }
/// <summary> /// Constructs a new FuncArgInfo class for a specific argument 'argIdx' of function 'F'. /// </summary> /// <param name="S">Used for retrieving the G25.VariableType of 'm_typeName'.</param> /// <param name="F">Function for which this FuncArgInfo describes an argument.</param> /// <param name="argIdx">Index of argument. Use -1 for artificial 'return argument' used for the C language.</param> /// <param name="FT">Floating point type of the type of the argument.</param> /// <param name="defaultTypeName">Name of the type of the argument.</param> /// <param name="computeMultivectorValue">Set to true to convert the type into symbolic code. Uses 'F' to obtain the actual name of the variable to use inside the symbolic multivector.</param> public FuncArgInfo(G25.Specification S, G25.fgs F, int argIdx, G25.FloatType FT, string defaultTypeName, bool computeMultivectorValue) { m_mvInterface = true; m_name = F.GetArgumentName(argIdx); m_typeName = F.GetArgumentTypeName(argIdx, defaultTypeName); m_type = S.GetType(m_typeName); m_varType = m_type.GetVariableType(); if (m_varType != VARIABLE_TYPE.FLOAT) { m_floatType = FT; } else { m_floatType = S.GetFloatType(m_typeName); } // set mangled type name (depends on whether type is scalar or not) if ((m_varType == VARIABLE_TYPE.FLOAT) || (m_varType == VARIABLE_TYPE.ENUM)) { m_mangledTypeName = m_typeName; } else { m_mangledTypeName = FT.GetMangledName(S, m_typeName); // temp (currently disabled) test for C# and Java // if (S.OutputCSharpOrJava() && (m_varType == VARIABLE_TYPE.GMV)) // m_mangledTypeName = m_mangledTypeName + G25.CG.Shared.Main.IF_SUFFIX; } // set pointer / non pointer flag m_pointer = F.GetArgumentPtr(S, argIdx); // set array flag m_array = F.GetArgumentArr(S, argIdx); m_constant = (argIdx >= 0); if (computeMultivectorValue) { if (m_varType == VARIABLE_TYPE.SMV) { m_multivectorValue = new RefGA.Multivector[1] { Symbolic.SMVtoSymbolicMultivector(S, (G25.SMV)m_type, m_name, m_pointer) }; } else if (m_varType == VARIABLE_TYPE.GMV) { m_multivectorValue = Symbolic.GMVtoSymbolicMultivector(S, (G25.GMV)m_type, m_name, m_pointer, -1); // -1 = sym mv for all groups } else if (m_varType == VARIABLE_TYPE.FLOAT) { m_multivectorValue = new RefGA.Multivector[1] { Symbolic.ScalarToSymbolicMultivector(S, (G25.FloatType)m_type, m_name) } } ; else { // OM: do nothing? m_multivectorValue = null; } } }