/// <summary> /// Writes the 'explicit' declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'. /// /// This function is called by the non-explicit version of the function. /// </summary> public void WriteExFunction(FloatType FT, string exFuncName) { G25.SMV smv = m_specification.GetSMV(m_SMVname); string randFuncCall = FT.DoubleToString(m_specification, -1.0) + " + " + FT.DoubleToString(m_specification, 2.0) + " * " + m_randomScalarFunc[FT.type] + "()"; // construct a explicit FGS string[] exArgumentTypeNames = new string[] { FT.type, FT.type, FT.type }; string[] exVariableNames = { m_fgs.ArgumentVariableNames[0], MINIMUM_NORM, LARGEST_COORDINATE }; fgs exFgs = new fgs(m_fgs.Name, m_fgs.OutputName, m_fgs.ReturnTypeName, exArgumentTypeNames, exVariableNames, m_fgs.FloatNames, m_fgs.MetricName, m_fgs.Comment, m_fgs.Options); exFgs.InitArgumentPtrFromTypeNames(m_specification); bool computeMultivectorValue = false; int nbArgs = 3; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, exFgs, nbArgs, FT, FT.type, computeMultivectorValue); // because of lack of overloading, function names include names of argument types //G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, exFgs, FAI); G25.fgs CF = new G25.fgs(exFgs, exFuncName); //string exFuncName = funcName; // setup code to recursively call exFuncName string exFuncCall = ""; { StringBuilder exFuncCallSB = new StringBuilder(); if (!m_specification.OutputC()) { exFuncCallSB.Append("return "); } exFuncCallSB.Append(exFuncName); exFuncCallSB.Append("("); if (m_specification.OutputC()) { exFuncCallSB.Append(fgs.RETURN_ARG_NAME); exFuncCallSB.Append(", "); } for (int i = 0; i < exVariableNames.Length; i++) { if (i > 0) { exFuncCallSB.Append(", "); } exFuncCallSB.Append(exVariableNames[i]); } exFuncCallSB.AppendLine(");"); if (m_specification.OutputC()) { exFuncCallSB.AppendLine("return;"); } exFuncCall = exFuncCallSB.ToString(); } // generate a random SMV: RefGA.Multivector randomSMV = null; // get highest grade and bitmap of int hg = smv.HighestGrade(); // what is the highest non-zero grade of the type? uint bvBitmap = smv.BasisVectorBitmap(); // which basis vectors are used in the type? // setup random value to be returned if (InitWithRandomCoordinates(m_specification, smv)) { // set all coordinates to random values randomSMV = RefGA.Multivector.ZERO; for (int b = 0; b < smv.NbNonConstBasisBlade; b++) { randomSMV = RefGA.Multivector.Add(randomSMV, RefGA.Multivector.gp(new RefGA.Multivector(smv.NonConstBasisBlade(b)), new RefGA.Multivector("r" + smv.NonConstBasisBlade(b).ToLangString(m_specification.m_basisVectorNames)))); } } else { // set to geometric product of random vectors randomSMV = RefGA.Multivector.ONE; RefGA.Multivector randomVector; RefGA.BasisBlade[] B = new RefGA.BasisBlade[(int)RefGA.Bits.BitCount(bvBitmap)]; for (int g = 0; g < hg; g++) { int cnt = 0; for (int v = 0; v < m_specification.m_dimension; v++) { if ((bvBitmap & (uint)(1 << v)) != 0) { B[cnt] = new RefGA.BasisBlade((uint)(1 << v), 1.0, "r" + g + "_" + m_specification.m_basisVectorNames[v]); cnt++; } } randomVector = new RefGA.Multivector(B); randomSMV = RefGA.Multivector.gp(randomSMV, randomVector, m_G25M.m_metric); } // round value if required by metric if (m_G25M.m_round) { randomSMV = randomSMV.Round(1e-14); } } // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); { int nbTabs = 1; if (!smv.IsConstant()) { string smvTypeName = FT.GetMangledName(m_specification, m_SMVname); // SMV tmp; // double n, mul, lc; if (m_specification.OutputCppOrC()) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, smvTypeName + " tmp;")); } else { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, smvTypeName + " tmp = new " + smvTypeName + "();")); } I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " n, mul, lc;")); I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, CodeUtil.GetBoolType(m_specification) + " nullBlade;")); // double rCoord = randomValue(), ....; StringBuilder randSB = new StringBuilder(); randSB.Append(FT.type); randSB.Append(" "); if (InitWithRandomCoordinates(m_specification, smv)) { // random coordinates for (int b = 0; b < smv.NbNonConstBasisBlade; b++) { if (b > 0) { randSB.Append(", "); } randSB.Append("r" + smv.NonConstBasisBlade(b).ToLangString(m_specification.m_basisVectorNames)); randSB.Append(" = "); randSB.Append(randFuncCall); } } else { // random vectors bool first = true; for (int g = 0; g < hg; g++) { for (int v = 0; v < m_specification.m_dimension; v++) { if (!first) { randSB.Append(", "); } first = false; if ((g > 0) && (v == 0)) { randSB.AppendLine(""); // newline randSB.Append("\t\t"); } randSB.Append("r" + g + "_" + m_specification.m_basisVectorNames[v]); randSB.Append(" = "); randSB.Append(randFuncCall); } } } randSB.Append(";"); I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, randSB.ToString())); // SMV tmp = random; bool mustCast = false; bool randomPtr = false; bool declareRandom = false; I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, smv, FT, mustCast, randomSMV, "tmp", randomPtr, declareRandom)); // n = norm_ret_scalar(tmp); string emp = (m_specification.OutputC()) ? "&" : ""; I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "n = " + m_normFunc[FT.type] + "(" + emp + "tmp);")); // lc = largestCoordinate(tmp); if (m_specification.OutputC()) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "lc = " + smvTypeName + "_largestCoordinate(&tmp);")); } else { string lcStr = "largestCoordinate"; if (m_specification.OutputCSharp()) { lcStr = "LargestCoordinate"; } I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "lc = tmp." + lcStr + "();")); } // null = (n == 0) && (lc ! 0) if ((m_smvType.MvType == SMV.MULTIVECTOR_TYPE.ROTOR) || (m_smvType.MvType == SMV.MULTIVECTOR_TYPE.VERSOR)) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "nullBlade = " + (m_specification.OutputC() ? "0" : "false") + ";")); } else { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "nullBlade = ((n == " + FT.DoubleToString(m_specification, 0.0) + ") && (lc != " + FT.DoubleToString(m_specification, 0.0) + "));")); } // test minimumNorm I.Add(new CommentInstruction(nbTabs, "Recurse if generated random value has a norm below user-supplied limit, unless this is a null blade")); I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, "(n < " + exVariableNames[1] + ") && (!nullBlade)", new List <Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, exFuncCall) }, // if instructions new List <Instruction>())); // else instructions // compute multiplier string lcCondition = "(lc * " + CodeUtil.OpNameToLangString(m_specification, FT, "abs") + "(mul)) > largestCoordinate "; I.Add(new CommentInstruction(nbTabs, "Compute multiplier")); I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, "n < " + FT.DoubleToString(m_specification, 0.0001), new List <Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, "mul = " + FT.DoubleToString(m_specification, 1.0) + ";") }, // if instructions new List <Instruction>() // else instructions { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, "mul = " + exFgs.ArgumentVariableNames[0] + " * (" + randFuncCall + ") / n;"), new CommentInstruction(nbTabs + 1, "Test largest coordinate"), new G25.CG.Shared.IfElseInstruction(nbTabs + 1, lcCondition, new List <Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 2, exFuncCall) }, // if instructions new List <Instruction>()) })); // test largest coordinate //I.Add(new CommentInstruction(nbTabs, "Test largest coordinate")); //I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, lcCondition, // new List<Instruction>() { new G25.CG.Shared.VerbatimCodeInstruction(nbTabs + 1, exFuncCall) }, // if instructions // new List<Instruction>())); // else instructions // return tmp*mul; I.Add(new CommentInstruction(nbTabs, "Apply multiplier, return")); RefGA.Multivector tmpValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(m_specification, smv, "tmp", false); RefGA.Multivector returnValue = RefGA.Multivector.gp(tmpValue, new RefGA.Multivector("mul")); I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, smv, FT, mustCast, returnValue)); } // end of '!IsConstant()'? else { // the user wants a 'random' constant: simply return the constant itself. RefGA.Multivector returnValue = G25.CG.Shared.Symbolic.SMVtoSymbolicMultivector(m_specification, smv, "tmp", false); bool mustCast = false; I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, smv, FT, mustCast, returnValue)); } } // because of lack of overloading, function names include names of argument types //G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, exFgs, FAI); // generate comment Comment comment = new Comment(exFgs.AddUserComment("Returns random " + m_SMVname + " with a scale in the interval [0, scale)")); bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, exFuncName, FAI, I, comment); } // end of WriteExFunction
} // end of WriteFunction /// <summary> /// Writes an zero test function for specialized multivectors. /// </summary> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> protected void WriteZeroFunction(FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment) { // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); string BOOL = CodeUtil.GetBoolType(m_specification); string TRUE = CodeUtil.GetTrueValue(m_specification); string FALSE = CodeUtil.GetFalseValue(m_specification); // write the function: { int nbTabs = 1; // add one instruction (verbatim code) //I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code)); // get largest constant coordinate: double largestConstCoord = 0.0; if (m_smv != null) { // first find largest const coord: if any const coord above eps, always return 0 for (int c = 0; c < m_smv.NbConstBasisBlade; c++) { if (Math.Abs(m_smv.ConstBasisBlade(c).scale) > largestConstCoord) { largestConstCoord = Math.Abs(m_smv.ConstBasisBlade(c).scale); } } } if (largestConstCoord > 0.0) // generate code to check if largest coord > 'eps' { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if (" + FT.DoubleToString(m_specification, largestConstCoord) + " > " + FAI[1].Name + ") return " + FALSE + ";")); } // generate code to check all coordiantes string[] accessStr = G25.CG.Shared.CodeUtil.GetAccessStr(m_specification, m_smv, FAI[0].Name, FAI[0].Pointer); for (int i = 0; i < accessStr.Length; i++) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if ((" + accessStr[i] + " < -" + FAI[1].Name + ") || (" + accessStr[i] + " > " + FAI[1].Name + ")) return " + FALSE + ";")); } // finally, return 1 if all check were OK I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return " + TRUE + ";")); } // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, F, FAI); m_funcName[FT.type] = CF.OutputName; // setup return type and argument: string returnTypeName = BOOL; G25.CG.Shared.FuncArgInfo returnArgument = null; // write function bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, F, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment); } // end of WriteZeroFunction()
} // end of WriteFunction /// <summary> /// Writes an equality test function for specialized multivectors /// </summary> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> protected void WriteEqualsFunction(FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment) { // setup instructions List <G25.CG.Shared.Instruction> I = new List <G25.CG.Shared.Instruction>(); // get a basis blade list which contains all basis blades (this is used in conjunction with GetAssignmentStrings()) RefGA.BasisBlade[] BL = new RefGA.BasisBlade[1 << m_specification.m_dimension]; for (uint bitmap = 0; bitmap < (uint)BL.Length; bitmap++) { BL[bitmap] = new RefGA.BasisBlade(bitmap); } // get string to access the coordinates of each basis blade wrt to the basis bool mustCast = false; bool writeZeros = false; string[] assStr1 = G25.CG.Shared.CodeUtil.GetAssignmentStrings(m_specification, FT, mustCast, BL, FAI[0].MultivectorValue[0], writeZeros); string[] assStr2 = G25.CG.Shared.CodeUtil.GetAssignmentStrings(m_specification, FT, mustCast, BL, FAI[1].MultivectorValue[0], writeZeros); string BOOL = CodeUtil.GetBoolType(m_specification); string TRUE = CodeUtil.GetTrueValue(m_specification); string FALSE = CodeUtil.GetFalseValue(m_specification); { // setup instructions // get tmp storage for 'difference' int nbTabs = 1; bool dDeclared = false; // for each assStr, subtract the other, see if difference is within limits for (int i = 0; i < BL.Length; i++) { if ((assStr1[i] == null) && (assStr2[i] == null)) { continue; } else if (assStr1[i] == null) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if ((" + assStr2[i] + " < -" + FAI[2].Name + ") || (" + assStr2[i] + " > " + FAI[2].Name + ")) return " + FALSE + "; /* " + BL[i].ToString(m_specification.m_basisVectorNames) + " */")); } else if (assStr2[i] == null) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if ((" + assStr1[i] + " < -" + FAI[2].Name + ") || (" + assStr1[i] + " > " + FAI[2].Name + ")) return " + FALSE + "; /* " + BL[i].ToString(m_specification.m_basisVectorNames) + " */")); } else { if (!dDeclared) { // declare a variable 'd', but only if required I.Insert(0, new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " d;")); dDeclared = true; } I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "d = " + assStr1[i] + " - " + assStr2[i] + "; " + "if ((d < -" + FAI[2].Name + ") || (d > " + FAI[2].Name + ")) return " + FALSE + "; /* " + BL[i].ToString(m_specification.m_basisVectorNames) + " */")); } } // finally, return 1 if all check were OK I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return " + TRUE + ";")); } // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, F, FAI); m_funcName[FT.type] = CF.OutputName; // setup return type and argument: string returnTypeName = BOOL; G25.CG.Shared.FuncArgInfo returnArgument = null; // write function bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, F, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment); }