public static string GetCompressCode(Specification S, G25.FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, string resultName, bool resultIsScalar, string GUstr) { if ((GUstr == null) || (GUstr.Length == 0)) { GUstr = ((1 << S.m_GMV.NbGroups) - 1).ToString(); } StringBuilder SB = new StringBuilder(); if (resultIsScalar) { SB.AppendLine("return c[0];"); } else { string funcName = (S.OutputC()) ? FT.GetMangledName(S, "compress") : FT.GetMangledName(S, S.m_GMV.Name) + "_compress"; if (S.m_outputLanguage != OUTPUT_LANGUAGE.C) SB.Append("return "); SB.Append(funcName + "(c, "); if (S.OutputC()) SB.Append(resultName + "->c, &(" + resultName + "->gu), "); SB.AppendLine(FT.DoubleToString(S, 0.0) + ", " + GUstr + ");"); } return SB.ToString(); }
private static string GetAnyMetricNormCode(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.Metric M, bool squared, G25.CG.Shared.FuncArgInfo[] FAI, G25.SMV returnType, string returnName) { G25.GMV gmv = S.m_GMV; StringBuilder SB = new StringBuilder(); SB.AppendLine(FT.type + " n2 = " + FT.DoubleToString(S, 0.0) + ";"); if (S.OutputCSharpOrJava()) { SB.AppendLine(FT.type + "[] c = new " + FT.type + "[1];"); SB.AppendLine(FT.type + "[][] ac = " + FAI[0].Name + ".to_" + FAI[0].MangledTypeName + "().c();"); } else { bool resultIsScalar = true; bool initResultToZero = true; SB.Append(GetExpandCode(S, cgd, FT, FAI, resultIsScalar, initResultToZero)); } string exaName = "_" + FAI[0].Name; for (int g1 = 0; g1 < gmv.NbGroups; g1++) { bool funcFound = false; for (int g2 = 0; g2 < gmv.NbGroups; g2++) { // get function name string funcName = GetGPpartFunctionName(S, FT, M, g1, g2, 0); // grade 0 part of gp(g, g) // check if funcName (gp part) exists) Tuple<string, string, string> key = new Tuple<string, string, string>(FT.type, M.m_name, funcName); if (cgd.m_gmvGPpartFuncNames.ContainsKey(key) && cgd.m_gmvGPpartFuncNames[key]) { if (!funcFound) { if (S.OutputCSharpOrJava()) SB.Append("if (ac[" + g1 + "] != null) {"); else SB.Append("if (" + exaName + "[" + g1 + "] != NULL) { "); SB.AppendLine(" /* group " + g1 + " (grade " + gmv.Group(g1)[0].Grade() + ") */"); SB.AppendLine("\tc[0] = " + FT.DoubleToString(S, 0.0) + ";"); funcFound = true; } if (g1 != g2) { if (S.OutputCSharpOrJava()) SB.Append("\tif (ac[" + g2 + "] != null) {"); else SB.Append("\tif (" + exaName + "[" + g2 + "] != NULL) {"); SB.AppendLine(" /* group " + g2 + " (grade " + gmv.Group(g2)[0].Grade() + ") */"); } if (S.OutputCSharpOrJava()) SB.AppendLine("\t\t" + funcName + "(ac[" + g1 + "], ac[" + g2 + "], c);"); else SB.AppendLine("\t\t" + funcName + "(" + exaName + "[" + g1 + "], " + exaName + "[" + g2 + "], c);"); if (g1 != g2) SB.AppendLine("\t}"); } } if (funcFound) // only do this if any matching gp function for this group was found { // get multiplier double m = gmv.Group(g1)[0].Reverse().scale / gmv.Group(g1)[0].scale; // must always have the same grade if (m == 1.0) SB.AppendLine("\tn2 += c[0];"); else if (m == -1.0) SB.AppendLine("\tn2 -= c[0];"); else SB.AppendLine("\tn2 += " + FT.DoubleToString(S, m) + " * c[0];"); SB.AppendLine("}"); } } string returnVal; { // get return value if (squared) returnVal = "n2"; else { string sqrtFuncName = G25.CG.Shared.CodeUtil.OpNameToLangString(S, FT, RefGA.Symbolic.UnaryScalarOp.SQRT); if (M.m_metric.IsPositiveDefinite()) // if PD, then negative values are impossible returnVal = sqrtFuncName + "(n2)"; else returnVal = "((n2 < " + FT.DoubleToString(S, 0.0) + ") ? " + sqrtFuncName + "(-n2) : " + sqrtFuncName + "(n2))"; } } // can be shared with other GetNormCode if ((returnType == null) || (returnName == null)) { SB.AppendLine("return " + returnVal + ";"); } else { if (S.OutputC()) { // get assign code, assign it bool mustCast = false; bool dstPtr = true; int nbTabs = 0; bool writeZeros = true; SB.Append(CodeUtil.GenerateSMVassignmentCode(S, FT, mustCast, returnType, returnName, dstPtr, new RefGA.Multivector(returnVal), nbTabs, writeZeros)); } else { bool mustCast = false; int nbTabs = 0; new ReturnInstruction(nbTabs, returnType, FT, mustCast, new RefGA.Multivector(returnVal)).Write(SB, S, cgd); } } return SB.ToString(); }
private static string GetDiagonalMetricNormCode(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.Metric M, bool squared, G25.CG.Shared.FuncArgInfo[] FAI, G25.SMV returnType, string returnName) { G25.GMV gmv = S.m_GMV; StringBuilder SB = new StringBuilder(); if (S.OutputCSharpOrJava()) { SB.AppendLine(FT.type + "[] c = new " + FT.type + "[1];"); SB.AppendLine(FT.type + "[][] ac = " + FAI[0].Name + ".to_" + FAI[0].MangledTypeName + "().c();"); } else SB.AppendLine(FT.type + " c[1];"); SB.AppendLine(FT.type + " n2 = " + FT.DoubleToString(S, 0.0) + ";"); if (S.OutputCppOrC()) SB.AppendLine("int idx = 0;"); string agu = (S.OutputC()) ? FAI[0].Name + "->gu" : FAI[0].Name + ".gu()"; string ac = (S.OutputC()) ? FAI[0].Name + "->c" : FAI[0].Name + ".getC()"; for (int g = 0; g < gmv.NbGroups; g++) { // get function name string funcName = GetGPpartFunctionName(S, FT, M, g, g, 0); // grade 0 part of gp(g, g) // get multiplier double m = gmv.Group(g)[0].Reverse().scale / gmv.Group(g)[0].scale; SB.AppendLine(""); if (S.OutputCSharpOrJava()) SB.Append("if (ac[" + g + "] != null) {"); else SB.Append("if (" + agu + " & " + (1 << g) + ") {"); SB.AppendLine(" /* group " + g + " (grade " + gmv.Group(g)[0].Grade() + ") */"); // check if funcName (gp part) exists) Tuple<string, string, string> key = new Tuple<string, string, string>(FT.type, M.m_name, funcName); if (cgd.m_gmvGPpartFuncNames.ContainsKey(key) && cgd.m_gmvGPpartFuncNames[key]) { SB.AppendLine("\tc[0] = " + FT.DoubleToString(S, 0.0) + ";"); if (S.OutputCSharpOrJava()) SB.AppendLine("\t" + funcName + "(ac[" + g + "], ac[ " + g + "], c);"); else SB.AppendLine("\t" + funcName + "(" + ac + " + idx, " + ac + " + idx, c);"); if (m == 1.0) SB.AppendLine("\tn2 += c[0];"); else if (m == -1.0) SB.AppendLine("\tn2 -= c[0];"); else SB.AppendLine("\tn2 += " + FT.DoubleToString(S, m) + " * c[0];"); } if ((g < (gmv.NbGroups - 1)) && S.OutputCppOrC()) SB.AppendLine("\tidx += " + gmv.Group(g).Length + ";"); SB.AppendLine("}"); } string returnVal; { // get return value if (squared) returnVal = "n2"; else { string sqrtFuncName = G25.CG.Shared.CodeUtil.OpNameToLangString(S, FT, RefGA.Symbolic.UnaryScalarOp.SQRT); if (M.m_metric.IsPositiveDefinite()) // if PD, then negative values are impossible returnVal = sqrtFuncName + "(n2)"; else returnVal = "((n2 < " + FT.DoubleToString(S, 0.0) + ") ? " + sqrtFuncName + "(-n2) : " + sqrtFuncName + "(n2))"; } } if ((returnType == null) || (returnName == null)) { SB.AppendLine("return " + returnVal + ";"); } else { if (S.OutputC()) { // get assign code, assign it bool mustCast = false; bool dstPtr = true; int nbTabs = 0; bool writeZeros = true; SB.Append(CodeUtil.GenerateSMVassignmentCode(S, FT, mustCast, returnType, returnName, dstPtr, new RefGA.Multivector(returnVal), nbTabs, writeZeros)); } else { bool mustCast = false; int nbTabs = 0; new ReturnInstruction(nbTabs, returnType, FT, mustCast, new RefGA.Multivector(returnVal)).Write(SB, S, cgd); } } return SB.ToString(); }
public static void WriteOMtoOMcopy(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, OM srcOm, OM dstOm) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; string srcTypeName = FT.GetMangledName(S, srcOm.Name); string dstTypeName = FT.GetMangledName(S, dstOm.Name); bool writeDecl = S.OutputC(); string funcName = GetFunctionName(S, (S.OutputC() ? "" : dstTypeName), "set", srcTypeName + "_to_" + dstTypeName); // do we inline this func? string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " "); string dstArgStr = (S.OutputC()) ? (dstTypeName + " *dst, ") : ""; string refStr = (S.OutputC()) ? "*" : ((S.OutputCpp()) ? "&" : ""); string CONST = (S.OutputCppOrC()) ? "const " : ""; string funcDecl = inlineStr + "void " + funcName + "(" + dstArgStr + CONST + srcTypeName + " " + refStr + "src)"; // write comment, function declaration Comment comment = new Comment("Copies a " + srcTypeName + " to a " + dstTypeName + "\n" + "Warning 1: coordinates which cannot be represented are silenty lost.\n" + "Warning 2: coordinates which are not present in 'src' are set to zero in 'dst'.\n"); if (writeDecl) { comment.Write(declSB, S, 0); declSB.Append(funcDecl); declSB.AppendLine(";"); } if (S.OutputCSharpOrJava()) comment.Write(defSB, S, 0); defSB.Append(funcDecl); { defSB.AppendLine(" {"); Dictionary<Tuple<int, int, int>, Tuple<int, int, double>> D = dstOm.getMapping(srcOm); StringBuilder copySB = new StringBuilder(); List<string> setToZero = new List<string>(); string matrixStr = (S.OutputC()) ? "m" : "m_m"; string dstMatrixStr = (S.OutputC()) ? "dst->" + matrixStr : matrixStr; string ptrStr = (S.OutputC()) ? "->" : "."; // For all grades of som, for all columns, for all rows, check D, get entry, set; otherwise set to null // Do not use foreach() on D because we want to fill in coordinates in their proper order. for (int gradeIdx = 1; gradeIdx < dstOm.Domain.Length; gradeIdx++) { for (int somRangeIdx = 0; somRangeIdx < dstOm.Range[gradeIdx].Length; somRangeIdx++) { for (int somDomainIdx = 0; somDomainIdx < dstOm.Domain[gradeIdx].Length; somDomainIdx++) { Tuple<int, int, int> key = new Tuple<int, int, int>(gradeIdx, somDomainIdx, somRangeIdx); int somMatrixIdx = dstOm.getCoordinateIndex(gradeIdx, somDomainIdx, somRangeIdx); string dstString = dstMatrixStr + gradeIdx + "[" + somMatrixIdx + "] = "; if (D.ContainsKey(key)) { Tuple<int, int, double> value = D[key]; int gomMatrixIdx = srcOm.getCoordinateIndex(gradeIdx, value.Value1, value.Value2); double multiplier = value.Value3; string multiplierString = (multiplier == 1.0) ? "" : (FT.DoubleToString(S, multiplier) + " * "); copySB.AppendLine("\t" + dstString + multiplierString + " src" + ptrStr + matrixStr + gradeIdx + "[" + gomMatrixIdx + "];"); } else { setToZero.Add(dstString); } } } } // append copy statements defSB.Append(copySB); // append statements to set coordinates to zero if (setToZero.Count > 0) { int cnt = 0; defSB.Append("\t"); foreach (string str in setToZero) { defSB.Append(str); cnt++; if (cnt > 8) { cnt = 0; defSB.AppendLine(""); defSB.Append("\t\t"); } } defSB.AppendLine(FT.DoubleToString(S, 0.0) + ";"); } defSB.AppendLine("}"); } }
private static void WriteCoordExtractFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, string gmvTypeName, int groupIdx, int elementIdx, RefGA.BasisBlade B) { StringBuilder declSB = cgd.m_declSB; StringBuilder defSB = (S.m_inlineSet) ? cgd.m_inlineDefSB : cgd.m_defSB; String bladeName = B.ToLangString(S.m_basisVectorNames); string varName = "A"; // do we inline this func? string inlineStr = G25.CG.Shared.Util.GetInlineString(S, S.m_inlineSet, " "); string funcName = gmvTypeName + "_" + bladeName; string funcDecl = inlineStr + FT.type + " " + funcName + "(const " + gmvTypeName + " *" + varName + ")"; string comment = "/** Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate of '" + varName + "' */"; // declSB.AppendLine("/* group : " + groupIdx + " element: " + elementIdx + "*/"); declSB.AppendLine(comment); declSB.Append(funcDecl); declSB.AppendLine(";"); defSB.AppendLine(""); defSB.Append(funcDecl); defSB.AppendLine(" {"); defSB.AppendLine("\treturn (" + varName + "->gu & " + (1 << groupIdx) + ") ? " + varName + "->c[" + S.m_namespace + "_mvSize[" + varName + "->gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] : " + FT.DoubleToString(S, 0.0) + ";"); defSB.AppendLine("}"); // add extract coord extract function for scalar if (B.Grade() == 0) { string floatFuncName = gmvTypeName + "_" + FT.type; string floatFuncDecl = inlineStr + FT.type + " " + floatFuncName + "(const " + gmvTypeName + " *" + varName + ")"; declSB.AppendLine(comment); declSB.Append(floatFuncDecl); declSB.AppendLine(";"); defSB.Append(floatFuncDecl); defSB.AppendLine(" {"); defSB.AppendLine("\treturn " + funcName + "(" + varName + ");"); defSB.AppendLine("}"); } }
private static void WriteGetCoordFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, StringBuilder SB, string gmvTypeName, int groupIdx, int elementIdx, RefGA.BasisBlade B) { string bladeName = B.ToLangString(S.m_basisVectorNames); // do we inline this func? string inlineStr = "inline "; string funcName = MainGenerator.GETTER_PREFIX + bladeName; string funcDecl = "\t" + inlineStr + FT.type + " " + funcName + "() const"; SB.AppendLine("\t/// Returns the " + bladeName + " coordinate of this " + gmvTypeName + "."); SB.Append(funcDecl); SB.AppendLine(" {"); SB.AppendLine("\t\treturn (m_gu & " + (1 << groupIdx) + ") ? " + "m_c[" + S.m_namespace + "_mvSize[m_gu & " + ((1 << groupIdx) - 1) + "] + " + elementIdx + "] : " + FT.DoubleToString(S, 0.0) + ";"); SB.AppendLine("\t}"); }
private static void WriteGetCoordFunction(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, string gmvTypeName, int groupIdx, int elementIdx, RefGA.BasisBlade B) { string bladeName = B.ToLangString(S.m_basisVectorNames); string funcName = G25.CG.Shared.Main.GETTER_PREFIX + bladeName; string funcDecl = "\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + funcName + "() "; int nbTabs = 1; new G25.CG.Shared.Comment("Returns the " + bladeName + " coordinate of this " + gmvTypeName).Write(SB, S, nbTabs); SB.Append(funcDecl); SB.AppendLine(" {"); SB.AppendLine("\t\treturn (m_c[" + groupIdx + "] == null) ? " + FT.DoubleToString(S, 0.0) + ": " + "m_c[" + groupIdx + "][" + elementIdx + "];"); SB.AppendLine("\t}"); }
/// <summary> /// Writes functions to copy GMVs to SMVs /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteGMVtoSMVcopy(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SMV smv) { StringBuilder defSB = cgd.m_defSB; G25.GMV gmv = S.m_GMV; string srcClassName = FT.GetMangledName(S, gmv.Name); //string dstClassName = FT.GetMangledName(S, smv.Name); bool dstPtr = false; string[] smvAccessStr = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, G25.CG.Shared.SmvUtil.THIS, dstPtr); string funcName = GMV.GetSetFuncName(S); string FINAL = (S.OutputJava()) ? "final " : ""; string funcDecl = "\tpublic " + FINAL + "void " + funcName + "(" + FINAL + srcClassName + " src)"; defSB.Append(funcDecl); { defSB.AppendLine(" {"); // get a dictionary which tells you for each basis blade of 'smv' where it is in 'gmv' // A dictionary from <smv group, smv element> to <gmv group, gmv element> Dictionary<Tuple<int, int>, Tuple<int, int>> D = G25.MV.GetCoordMap(smv, gmv); // what is the highest group of the 'gmv' that must be (partially) copied to the 'smv' int highestGroup = -1; foreach (KeyValuePair<Tuple<int, int>, Tuple<int, int>> KVP in D) if (KVP.Value.Value1 > highestGroup) highestGroup = KVP.Value.Value1; // generate code for each group for (int g = 0; g <= highestGroup; g++) { // determine if group 'g' is to be copied to smv: bool groupIsUsedBySMV = false; foreach (KeyValuePair<Tuple<int, int>, Tuple<int, int>> KVP in D) { // KVP.Key = SMV<group, element> // KVP.Value = GMV<group, element> if (KVP.Value.Value1 == g) { if (!smv.IsCoordinateConstant(KVP.Key.Value2)) { groupIsUsedBySMV = true; break; } } } // if group is present in GMV: if (groupIsUsedBySMV) { defSB.AppendLine("\t\tif (src.c()[" + g + "] != null) {"); defSB.AppendLine("\t\t\t" + FT.type + "[] ptr = src.c()[" + g + "];"); bool mustCast = false; bool srcPtr = true; int nbTabs = 3; RefGA.Multivector[] value = G25.CG.Shared.Symbolic.GMVtoSymbolicMultivector(S, gmv, "ptr", srcPtr, g); bool writeZeros = false; string str = G25.CG.Shared.CodeUtil.GenerateSMVassignmentCode(S, FT, mustCast, smv, G25.CG.Shared.SmvUtil.THIS, dstPtr, value[g], nbTabs, writeZeros); defSB.Append(str); defSB.AppendLine("\t\t}"); defSB.AppendLine("\t\telse {"); foreach (KeyValuePair<Tuple<int, int>, Tuple<int, int>> KVP in D) { if ((KVP.Value.Value1 == g) && (!smv.IsCoordinateConstant(KVP.Key.Value2))) { // translate KVP.Key.Value2 to non-const idx, because the accessStrs are only about non-const blades blades! int bladeIdx = smv.BladeIdxToNonConstBladeIdx(KVP.Key.Value2); defSB.AppendLine("\t\t\t" + smvAccessStr[bladeIdx] + " = " + FT.DoubleToString(S, 0.0) + ";"); } } defSB.AppendLine("\t\t}"); } } defSB.AppendLine("\t}"); } }
/// <summary> /// Writes code for abs largest coordinate /// </summary> /// <param name="S"></param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> public static void WriteLargestCoordinateFunctions(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.SMV smv) { StringBuilder defSB = cgd.m_defSB; defSB.AppendLine(""); const string smvName = G25.CG.Shared.SmvUtil.THIS; const bool ptr = false; string fabsFunc = G25.CG.Shared.CodeUtil.OpNameToLangString(S, FT, RefGA.Symbolic.UnaryScalarOp.ABS); string[] AS = G25.CG.Shared.CodeUtil.GetAccessStr(S, smv, smvName, ptr); RefGA.BasisBlade maxBasisBlade = smv.AbsoluteLargestConstantBasisBlade(); //string className = FT.GetMangledName(S, smv.Name); for (int _returnBitmap = 0; _returnBitmap <= 1; _returnBitmap++) { bool returnBitmap = (_returnBitmap != 0); // write comment int nbTabs = 1; if (returnBitmap) new G25.CG.Shared.Comment("Returns the absolute largest coordinate,\nand the corresponding basis blade bitmap.").Write(defSB, S, nbTabs); else new G25.CG.Shared.Comment("Returns the absolute largest coordinate.").Write(defSB, S, nbTabs); string funcName = Util.GetFunctionName(S, ((returnBitmap) ? "largestBasisBlade" : "largestCoordinate")); string funcDecl; if ((S.OutputCSharp()) && returnBitmap) { funcDecl = FT.type + " " + funcName + "(int bm) "; } else if ((S.OutputJava()) && returnBitmap) { funcDecl = FT.type + "[] " + funcName + "() "; } else { funcDecl = FT.type + " " + funcName + "()"; } string FINAL = (S.OutputJava()) ? "final " : ""; defSB.Append("\tpublic " + FINAL + funcDecl); { defSB.AppendLine(" {"); if ((S.OutputJava()) && returnBitmap) defSB.AppendLine("\t\tint bm;"); int startIdx = 0; if (maxBasisBlade != null) { defSB.AppendLine("\t\t" + FT.type + " maxValue = " + FT.DoubleToString(S, Math.Abs(maxBasisBlade.scale)) + ";"); if (returnBitmap) defSB.AppendLine("\t\tbm = " + maxBasisBlade.bitmap + ";"); } else { defSB.AppendLine("\t\t" + FT.type + " maxValue = " + fabsFunc + "(" + AS[0] + ");"); if (returnBitmap) defSB.AppendLine("\t\tbm = 0;"); startIdx = 1; } for (int c = startIdx; c < smv.NbNonConstBasisBlade; c++) { defSB.Append("\t\tif (" + fabsFunc + "(" + AS[c] + ") > maxValue) { maxValue = " + fabsFunc + "(" + AS[c] + "); "); if (returnBitmap) defSB.Append("bm = " + smv.NonConstBasisBlade(c).bitmap + "; "); defSB.AppendLine("}"); } if ((S.OutputJava()) && returnBitmap) { defSB.AppendLine("\t\treturn new " + FT.type + "[]{maxValue, (" + FT.type + ")bm};"); } else { defSB.AppendLine("\t\treturn maxValue;"); } defSB.AppendLine("\t}"); } } }
/// <summary> /// Returns the code for <c>gmv + scalar</c> /// /// The code is NOT composed of calls to functions generated by <c>WriteCANSparts()</c>. /// /// The returned code is only the body. The function declaration is not included. /// </summary> /// <param name="S">Specification of algebra (used for output language).</param> /// <param name="cgd">Currently not used.</param> /// <param name="FT">Floating point type.</param> /// <param name="FAI">Info about function arguments</param> /// <param name="resultName">Name of variable where the result goes (in the generated code).</param> /// <param name="increment">Whether write increment or decrement function.</param> /// <returns>code for the requested function.</returns> public static string GetIncrementCode(Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, string resultName, bool increment) { G25.GMV gmv = S.m_GMV; StringBuilder SB = new StringBuilder(); if (S.OutputC()) { SB.AppendLine(FT.type + " val" + " = " + FAI[0].MangledTypeName + "_" + gmv.Group(0)[0].ToLangString(S.m_basisVectorNames) + "(" + FAI[0].Name + ")" + ((increment) ? " + " : " - ") + FT.DoubleToString(S, 1.0) + ";"); SB.AppendLine(FAI[0].MangledTypeName + "_copy(" + resultName + ", " + FAI[0].Name + ");"); SB.AppendLine(FAI[0].MangledTypeName + "_set_" + gmv.Group(0)[0].ToLangString(S.m_basisVectorNames) + "(" + resultName + ", val);"); } else { string convertMvIfCode = (S.OutputCSharpOrJava()) ? (".to_" + FAI[0].MangledTypeName + "()") : ""; if (S.OutputCpp()) SB.AppendLine(FAI[0].MangledTypeName + " " + resultName + "(" + FAI[0].Name + ");"); else SB.AppendLine(FAI[0].MangledTypeName + " " + resultName + " = new " + FAI[0].MangledTypeName + "(" + FAI[0].Name + convertMvIfCode + ");"); SB.AppendLine(FT.type + " val" + " = " + resultName + ".get_" + gmv.Group(0)[0].ToLangString(S.m_basisVectorNames) + "()" + ((increment) ? " + " : " - ") + FT.DoubleToString(S, 1.0) + ";"); SB.AppendLine(resultName + ".set_" + gmv.Group(0)[0].ToLangString(S.m_basisVectorNames) + "(val);"); SB.AppendLine("return " + resultName + ";"); } return SB.ToString(); }
/// <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"; }
/// <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> /// 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; } }
/// <summary> /// Writes a function to set an GOM struct to identity, for all floating point types. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Results go here. Also intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="FT">Float point type of 'GOM'.</param> public static void WriteSetIdentity(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, G25.FloatType FT) { SB.AppendLine(""); string omName = "a"; string matrixName = "m_m"; // todo: centralize this name Dictionary<double, List<string>> nonZero = G25.CG.Shared.OMinit.GetGomIdentityInitCode(S, S.m_GOM, omName, matrixName); //string className = FT.GetMangledName(S, S.m_GOM.Name); string funcName = Util.GetFunctionName(S, "setIdentity"); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " void " + funcName + "() {"); for (int g = 1; g < S.m_GOM.Domain.Length; g++) { int s = S.m_GOM.Domain[g].Length * S.m_GOM.Range[g].Length; SB.AppendLine("\t\t" + G25.CG.Shared.Util.GetSetToZeroCode(S, FT, matrixName + g, s)); } // end of loop over all grades of the OM // do the nonZero assignments: foreach (KeyValuePair<double, List<string>> kvp in nonZero) { SB.Append("\t\t"); int cnt = 0; foreach (string coordStr in kvp.Value) { SB.Append(coordStr + " = "); cnt++; if ((cnt % 8) == 0) SB.Append("\n\t\t\t"); } SB.AppendLine(FT.DoubleToString(S, kvp.Key) + ";"); } SB.AppendLine("\t}"); }