private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C) { // assume only SMV constants for now G25.SMV smv = C.Type as G25.SMV; ConstantSMV Csmv = C as ConstantSMV; string className = FT.GetMangledName(S, smv.Name); // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...} SB.Append(className); SB.Append(" "); SB.Append(FT.GetMangledName(S, C.Name)); if (smv.NbNonConstBasisBlade > 0) { // MANGLED_TYPENAME MANGLED_CONSTANT_NAME(...) SB.Append("(" + className + "::" + G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv)); for (int c = 0; c < smv.NbNonConstBasisBlade; c++) { SB.Append(", "); SB.Append(FT.DoubleToString(S, Csmv.Value[c])); } SB.Append(")"); } SB.AppendLine(";"); }
private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C) { // assume only SMV constants for now G25.SMV smv = C.Type as G25.SMV; ConstantSMV Csmv = C as ConstantSMV; string className = FT.GetMangledName(S, smv.Name); // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...} SB.Append("\tpublic "); SB.Append(Keywords.ConstClassInstanceAccessModifier(S)); SB.Append(" "); SB.Append(className); SB.Append(" "); SB.Append(FT.GetMangledName(S, C.Name)); SB.Append(" = new "); SB.Append(className); SB.Append("("); if (smv.NbNonConstBasisBlade > 0) { // MANGLED_TYPENAME MANGLED_CONSTANT_NAME(...) SB.Append(className + "." + G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv)); for (int c = 0; c < smv.NbNonConstBasisBlade; c++) { SB.Append(", "); SB.Append(FT.DoubleToString(S, Csmv.Value[c])); } } SB.Append(")"); SB.AppendLine(";"); }
} // end of GetAccessStr() /// <summary> /// Generates code for returning a scalar value. The input is a scalar-valued multivector. /// </summary> /// <param name="S">Specification (used for output language).</param> /// <param name="FT">Floating point type which must be returned.</param> /// <param name="mustCast">Set to true if the returned value must be cast to <c>FT</c>, that is /// if you are not sure that the multivector has the same float type as the return type <c>FT</c>.</param> /// <param name="value">The symbolic multivector value to be returned.</param> /// <returns>Code for returning a scalar value.</returns> public static string GenerateScalarReturnCode(Specification S, FloatType FT, bool mustCast, RefGA.Multivector value) { if (value.IsZero()) { return("return " + FT.DoubleToString(S, 0.0) + ";"); } else { return("return " + ((mustCast) ? (FT.castStr + "(") : "") + CodeUtil.ScalarToLangString(S, FT, value.BasisBlades[0]) + ((mustCast) ? ")" : "") + ";"); } } // end of GenerateScalarReturnCode()
private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C) { // assume only SMV constants for now G25.SMV smv = C.Type as G25.SMV; ConstantSMV Csmv = C as ConstantSMV; // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...} SB.Append(FT.GetMangledName(S, C.Type.GetName())); SB.Append(" "); SB.Append(FT.GetMangledName(S, C.Name)); SB.Append(" = {"); if (smv.NbNonConstBasisBlade == 0) { // 'C' does not allow empty structs, so there is a filler that must be initialized SB.Append("0"); } else { if (S.m_coordStorage == COORD_STORAGE.ARRAY) { SB.Append("{"); } for (int c = 0; c < smv.NbNonConstBasisBlade; c++) { if (c > 0) { SB.Append(", "); } SB.Append(FT.DoubleToString(S, Csmv.Value[c])); } if (S.m_coordStorage == COORD_STORAGE.ARRAY) { SB.Append("}"); } } SB.AppendLine("};"); }
/// <summary> /// Generates code to assign <c>value</c> to a variable whose coordinate order is specified by <c>BL</c>. /// /// For example, <c>BL</c> could be <c>[e1, e2, e3]</c> and the multivector value <c>[e1 - 2e3]</c>. /// Then the returned array would be <c>["1", "0", "-2"]</c>. /// /// Parts of <c>value</c> that cannot be assigned to <c>BL</c> are silently ignored. /// /// Possibly, at some point we would like to generate some kind of warning? /// </summary> /// <param name="S">Specification of algebra (not used yet).</param> /// <param name="FT">Floating point type of assigned variable (used for casting strings).</param> /// <param name="mustCast">Set to true if a cast to 'FT' must be performed.</param> /// <param name="BL">Basis blades of assigned variable.</param> /// <param name="value">Multivector value to assign to the list of basis blades. /// Must not contain basis blades inside the symbolic scalars of the RefGA.BasisBlades.</param> /// <param name="writeZeros">When true, <c>"0"</c> will be returned when no value should be assigned /// to some coordinate. <c>null</c> otherwise.</param> /// <returns>An array of strings which tell you what to assign to each coordinate.</returns> public static String[] GetAssignmentStrings(Specification S, FloatType FT, bool mustCast, RefGA.BasisBlade[] BL, RefGA.Multivector value, bool writeZeros) { String[] assignedStr = new String[BL.Length]; int idx = 0; // for each non-const coord, find out what value is (loop through all entries in value) foreach (RefGA.BasisBlade B in BL) { // find same basisblade in 'value' foreach (RefGA.BasisBlade C in value.BasisBlades) { if (C.bitmap == B.bitmap) // match found: get assignment string { // compute D = inverse(B) . C; RefGA.BasisBlade Bi = (new RefGA.BasisBlade(B.bitmap, 1.0 / B.scale)).Reverse(); RefGA.BasisBlade D = RefGA.BasisBlade.scp(Bi, C); if (mustCast) { assignedStr[idx] = FT.castStr + "(" + CodeUtil.ScalarToLangString(S, FT, D) + ")"; } else { assignedStr[idx] = CodeUtil.ScalarToLangString(S, FT, D); } break; } } if (writeZeros && (assignedStr[idx] == null)) // has an assignment string been set? { // no assignment: simply assign "0" assignedStr[idx] = FT.DoubleToString(S, 0.0); } idx++; } return(assignedStr); } // end of GetAssignmentStrings()
/// <summary> /// Generates code to assign <c>value</c> to a variable whose coordinate order is specified by <c>BL</c>. /// /// For example, <c>BL</c> could be <c>[e1, e2, e3]</c> and the multivector value <c>[e1 - 2e3]</c>. /// Then the returned array would be <c>["1", "0", "-2"]</c>. /// /// Parts of <c>value</c> that cannot be assigned to <c>BL</c> are silently ignored. /// /// Possibly, at some point we would like to generate some kind of warning? /// </summary> /// <param name="S">Specification of algebra (not used yet).</param> /// <param name="FT">Floating point type of assigned variable (used for casting strings).</param> /// <param name="mustCast">Set to true if a cast to 'FT' must be performed.</param> /// <param name="BL">Basis blades of assigned variable.</param> /// <param name="value">Multivector value to assign to the list of basis blades. /// Must not contain basis blades inside the symbolic scalars of the RefGA.BasisBlades.</param> /// <param name="writeZeros">When true, <c>"0"</c> will be returned when no value should be assigned /// to some coordinate. <c>null</c> otherwise.</param> /// <returns>An array of strings which tell you what to assign to each coordinate.</returns> public static String[] GetAssignmentStrings(Specification S, FloatType FT, bool mustCast, RefGA.BasisBlade[] BL, RefGA.Multivector value, bool writeZeros) { String[] assignedStr = new String[BL.Length]; int idx = 0; // for each non-const coord, find out what value is (loop through all entries in value) foreach (RefGA.BasisBlade B in BL) { // find same basisblade in 'value' foreach (RefGA.BasisBlade C in value.BasisBlades) { if (C.bitmap == B.bitmap) // match found: get assignment string { // compute D = inverse(B) . C; RefGA.BasisBlade Bi = (new RefGA.BasisBlade(B.bitmap, 1.0 / B.scale)).Reverse(); RefGA.BasisBlade D = RefGA.BasisBlade.scp(Bi, C); if (mustCast) assignedStr[idx] = FT.castStr + "(" + CodeUtil.ScalarToLangString(S, FT, D) + ")"; else assignedStr[idx] = CodeUtil.ScalarToLangString(S, FT, D); break; } } if (writeZeros && (assignedStr[idx] == null)) // has an assignment string been set? { // no assignment: simply assign "0" assignedStr[idx] = FT.DoubleToString(S, 0.0); } idx++; } return assignedStr; }
/// <summary> /// Writes the declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'. /// </summary> public override void WriteFunction() { foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_gmv.Name, computeMultivectorValue); // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, m_fgs, FAI); // if bivector type: specialize if (m_gmvFunc || (!m_scalarSquare)) { // sin, cos, exp of GMV, or of SMV which does not square to scalar: WriteFunction(FT, CF); } else { // write simple specialized function: int nbTabs = 1; bool mustCast = false; // setup instructions List <G25.CG.Shared.Instruction> I = new List <G25.CG.Shared.Instruction>(); if (m_signOfSquare == 0) { // assign I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, m_returnType, FT, mustCast, m_returnValue)); } else { // alpha bool alphaPtr = false; bool declareAlpha = true; I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, FT, FT, mustCast, m_alphaValue, m_alphaName, alphaPtr, declareAlpha)); // mul if (!(IsCos(m_fgs) || IsCosh(m_fgs))) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " " + m_mulName + ";")); { bool mulPtr = false; bool declareMul = false; List <G25.CG.Shared.Instruction> ifI = new List <G25.CG.Shared.Instruction>(); ifI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, m_mulValue, m_mulName, mulPtr, declareMul)); List <G25.CG.Shared.Instruction> elseI = new List <G25.CG.Shared.Instruction>(); elseI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, RefGA.Multivector.ZERO, m_mulName, mulPtr, declareMul)); I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, m_alphaName + " != " + FT.DoubleToString(m_specification, 0.0), ifI, elseI)); } } // assign I.Add(new G25.CG.Shared.ReturnInstruction(nbTabs, m_returnType, FT, mustCast, m_returnValue)); } Comment comment = new Comment(m_fgs.Name + " of " + FAI[0].TypeName + " (uses fast special case)"); m_funcName[FT.type] = CF.OutputName; bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, CF.OutputName, FAI, I, comment); } // end of 'if bivector SMV' } } // end of WriteFunction
private static void WriteDefinition(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Constant C) { // assume only SMV constants for now G25.SMV smv = C.Type as G25.SMV; ConstantSMV Csmv = C as ConstantSMV; // MANGLED_TYPENAME MANGLED_CONSTANT_NAME = {...} SB.Append(FT.GetMangledName(S, C.Type.GetName())); SB.Append(" "); SB.Append(FT.GetMangledName(S, C.Name)); SB.Append(" = {"); if (smv.NbNonConstBasisBlade == 0) { // 'C' does not allow empty structs, so there is a filler that must be initialized SB.Append("0"); } else { if (S.m_coordStorage == COORD_STORAGE.ARRAY) SB.Append("{"); for (int c = 0; c < smv.NbNonConstBasisBlade; c++) { if (c > 0) SB.Append(", "); SB.Append(FT.DoubleToString(S, Csmv.Value[c])); } if (S.m_coordStorage == COORD_STORAGE.ARRAY) SB.Append("}"); } SB.AppendLine("};"); }
} // 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 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 WriteGradeBitmapFunction(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>(); // write the function: { int nbTabs = 1; I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "int bitmap = 0;")); // get largest constant coordinate for each grade: Dictionary <int, double> largestConstCoord = new Dictionary <int, double>(); 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++) { int g = m_smv.ConstBasisBlade(c).Grade(); double absVal = Math.Abs(m_smv.ConstBasisBlade(c).scale); if (!largestConstCoord.ContainsKey(g)) { largestConstCoord[g] = absVal; } else if (absVal > largestConstCoord[g]) { largestConstCoord[g] = absVal; } } } // generate code to check if largest coord of grade > 'eps' foreach (KeyValuePair <int, double> kvp in largestConstCoord) { if (kvp.Value > 0.0) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if (" + FT.DoubleToString(m_specification, kvp.Value) + " > " + FAI[1].Name + ") bitmap |= " + (1 << kvp.Key) + ";")); } } // 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 + ")) bitmap |= " + (1 << m_smv.NonConstBasisBlade(i).Grade()) + ";")); } // finally, return 1 if all check were OK I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return bitmap;")); } // 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 = G25.IntegerType.INTEGER; 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 WriteGradeBitmapFunction()
/// <summary> /// Writes getters and setters for the SMV coordinates.. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteGetSetCoord(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { // write variable coordinates for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { string name = smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames); string accessName = G25.CG.Shared.SmvUtil.GetCoordAccessString(S, smv, i); SB.AppendLine("\t/// Returns the " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + name + "() const { return " + accessName + ";}"); SB.AppendLine("\t/// Sets the " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline void " + MainGenerator.SETTER_PREFIX + name + "(" + FT.type + " " + name + ") { " + accessName + " = " + name + ";}"); } // write constant coordinates for (int i = 0; i < smv.NbConstBasisBlade; i++) { RefGA.BasisBlade B = smv.ConstBasisBlade(i); SB.AppendLine("\t/// Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() const { return " + FT.DoubleToString(S, smv.ConstBasisBladeValue(i)) + ";}"); } // write a getter for the scalar which returns 0 if no scalar coordinate is present if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; SB.AppendLine("\t/// Returns the scalar coordinate (which is always 0)."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() const { return " + FT.DoubleToString(S, 0.0) + ";}"); } // getter for the coordinates (stored in array) if ((S.m_coordStorage == COORD_STORAGE.ARRAY) && (smv.NbNonConstBasisBlade > 0)) { SB.AppendLine("\t/// Returns array of coordinates."); SB.AppendLine("\tinline const " + FT.type + " *getC(" + G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM + ") const { return m_c;}"); } }
/// <summary> /// Writes getters and setters for the SMV coordinates.. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteGetSetCoord(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { // write variable coordinates for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { string name = smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames); string accessName = GetCoordAccessString(S, smv, i); SB.AppendLine("\t/// Returns the " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + name + "() const { return " + accessName + ";}"); SB.AppendLine("\t/// Sets the " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline void " + MainGenerator.SETTER_PREFIX + name + "(" + FT.type + " " + name + ") { " + accessName + " = " + name + ";}"); } // write constant coordinates for (int i = 0; i < smv.NbConstBasisBlade; i++) { RefGA.BasisBlade B = smv.ConstBasisBlade(i); SB.AppendLine("\t/// Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() const { return " + FT.DoubleToString(S, smv.ConstBasisBladeValue(i)) + ";}"); } // write a getter for the scalar which returns 0 if no scalar coordinate is present if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; SB.AppendLine("\t/// Returns the scalar coordinate (which is always 0)."); SB.AppendLine("\tinline " + FT.type + " " + MainGenerator.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() const { return " + FT.DoubleToString(S, 0.0) + ";}"); } // getter for the coordinates (stored in array) if ((S.m_coordStorage == COORD_STORAGE.ARRAY) && (smv.NbNonConstBasisBlade > 0)) { SB.AppendLine("\t/// Returns array of coordinates."); SB.AppendLine("\tinline const " + FT.type + " *getC(" + G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM + ") const { return m_c;}"); } }
/// <summary> /// Writes getters and setters for the SMV coordinates.. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteGetSetCoord(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { int nbTabs = 1; string className = FT.GetMangledName(S, smv.Name); // for variable coordinates: for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(i); string name = smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames); string accessName = G25.CG.Shared.SmvUtil.GetCoordAccessString(S, smv, i); // get string getComment = "Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + name + "() { return " + accessName + ";}"); // set string setComment = "Sets the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(setComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " void " + G25.CG.Shared.Main.SETTER_PREFIX + name + "(" + FT.type + " " + name + ") { " + accessName + " = " + name + ";}"); } // for constant coordinates: for (int i = 0; i < smv.NbConstBasisBlade; i++) { RefGA.BasisBlade B = smv.ConstBasisBlade(i); // get string getComment = "Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() { return " + FT.DoubleToString(S, smv.ConstBasisBladeValue(i)) + ";}"); } // write a getter for the scalar which returns 0 if no scalar coordinate is present if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; string getComment = "Returns the scalar coordinate (which is always 0)."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() { return " + FT.DoubleToString(S, 0.0) + ";}"); } // getter for the coordinates (stored in array) if ((S.m_coordStorage == COORD_STORAGE.ARRAY) && (smv.NbNonConstBasisBlade > 0)) { string constantName = G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv); string COORD_ORDER = "coordOrder"; new G25.CG.Shared.Comment("Returns array of coordinates."). SetParamComment(COORD_ORDER, "pass the value '" + className + "." + constantName + "'"). Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + "[] c(" + G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM + " " + COORD_ORDER + ") { return m_c;}"); } }
/// <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); }
/// <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); }
/// <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 WriteGradeBitmapFunction(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>(); // write the function: { int nbTabs = 1; I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "int bitmap = 0;")); // get largest constant coordinate for each grade: Dictionary<int, double> largestConstCoord = new Dictionary<int, double>(); 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++) { int g = m_smv.ConstBasisBlade(c).Grade(); double absVal = Math.Abs(m_smv.ConstBasisBlade(c).scale); if (!largestConstCoord.ContainsKey(g)) largestConstCoord[g] = absVal; else if (absVal > largestConstCoord[g]) largestConstCoord[g] = absVal; } } // generate code to check if largest coord of grade > 'eps' foreach (KeyValuePair<int, double> kvp in largestConstCoord) { if (kvp.Value > 0.0) { I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "if (" + FT.DoubleToString(m_specification, kvp.Value) + " > " + FAI[1].Name + ") bitmap |= " + (1 << kvp.Key) + ";")); } } // 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 + ")) bitmap |= " + (1 << m_smv.NonConstBasisBlade(i).Grade()) + ";")); // finally, return 1 if all check were OK I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, "return bitmap;")); } // 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 = G25.IntegerType.INTEGER; 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); }
/// <summary> /// Generates code for returning a scalar value. The input is a scalar-valued multivector. /// </summary> /// <param name="S">Specification (used for output language).</param> /// <param name="FT">Floating point type which must be returned.</param> /// <param name="mustCast">Set to true if the returned value must be cast to <c>FT</c>, that is /// if you are not sure that the multivector has the same float type as the return type <c>FT</c>.</param> /// <param name="value">The symbolic multivector value to be returned.</param> /// <returns>Code for returning a scalar value.</returns> public static string GenerateScalarReturnCode(Specification S, FloatType FT, bool mustCast, RefGA.Multivector value) { if (value.IsZero()) { return "return " + FT.DoubleToString(S, 0.0) + ";"; } else { return "return " + ((mustCast) ? (FT.castStr + "(") : "") + CodeUtil.ScalarToLangString(S, FT, value.BasisBlades[0]) + ((mustCast) ? ")" : "") + ";"; } }
/// <summary> /// Should write the declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'. /// </summary> public override void WriteFunction() { foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_gmv.Name, computeMultivectorValue); // generate comment Comment comment = new Comment( m_fgs.AddUserComment("Returns logarithm of " + FAI[0].TypeName + " using " + m_G25M.m_name + " metric, assuming a 3D Euclidean rotor.")); // if scalar or specialized: generate specialized function if (m_gmvFunc) { StringBuilder declSB = m_cgd.m_declSB; bool inline = false; // never inline GMV functions StringBuilder defSB = (inline) ? m_cgd.m_inlineDefSB : m_cgd.m_defSB; // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, m_fgs, FAI); m_funcName[FT.type] = CF.OutputName; // setup hashtable with template arguments: System.Collections.Hashtable argTable = new System.Collections.Hashtable(); argTable["S"] = m_specification; argTable["functionName"] = m_funcName[FT.type]; argTable["FT"] = FT; argTable["mvType"] = FT.GetMangledName(m_specification, m_specification.m_GMV.Name); argTable["setPlaneFuncName"] = getSetPlaneFuncName(); argTable["scalarGpFuncName"] = m_scalarGpFunc[floatName]; argTable["norm2FuncName"] = m_norm2Func[floatName]; argTable["grade2FuncName"] = m_grade2Func[floatName]; if (m_specification.OutputCppOrC()) { // header m_cgd.m_cog.EmitTemplate(declSB, "logEuclideanHeader", argTable); } // source m_cgd.m_cog.EmitTemplate(defSB, "logEuclidean", argTable); } else {// write simple specialized function: // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); { int nbTabs = 1; bool mustCast = false; bool nPtr = false; bool declareN = true; // get grade 2 norm, scalar part I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, FT, FT, mustCast, m_grade2norm2Value, norm2Name, nPtr, declareN)); I.Add(new G25.CG.Shared.AssignInstruction(nbTabs, FT, FT, mustCast, m_grade0Value, scalarPartName, nPtr, declareN)); // setup checks for grade 2 == 0, grade 0 < 0.0 List <G25.CG.Shared.Instruction> specialI = new List <G25.CG.Shared.Instruction>(); List <G25.CG.Shared.Instruction> normalI = new List <G25.CG.Shared.Instruction>(); { // special cases // setup checks for grade 0 < 0.0 List <G25.CG.Shared.Instruction> ifI = new List <G25.CG.Shared.Instruction>(); List <G25.CG.Shared.Instruction> elseI = new List <G25.CG.Shared.Instruction>(); // either return PI * ANY_GRADE2_BLADE or 0 RefGA.Multivector arbRot360 = new RefGA.Multivector(new RefGA.BasisBlade(m_grade2Value.BasisBlades[0].bitmap, Math.PI)); ifI.Add(new G25.CG.Shared.ReturnInstruction(nbTabs + 2, m_returnType, FT, mustCast, arbRot360)); // return 360 degree rotation in arbitrary plane elseI.Add(new G25.CG.Shared.ReturnInstruction(nbTabs + 2, m_returnType, FT, mustCast, RefGA.Multivector.ZERO)); // return zero if grade2 == 0 and grade0 >= 0 specialI.Add(new G25.CG.Shared.IfElseInstruction(nbTabs + 1, scalarPartName + " < " + FT.DoubleToString(m_specification, 0.0), ifI, elseI)); } { // normal case // where mulName = atan2(sqrt(grade2norm2), grade0) / sqrt(grade2norm2) RefGA.Multivector normValue = new RefGA.Multivector(normName); RefGA.Multivector grade0Value = new RefGA.Multivector(scalarPartName); normalI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, RefGA.Symbolic.UnaryScalarOp.Sqrt(new RefGA.Multivector(norm2Name)), normName, nPtr, declareN)); normalI.Add(new G25.CG.Shared.AssignInstruction(nbTabs + 1, FT, FT, mustCast, RefGA.Symbolic.BinaryScalarOp.Atan2(normValue, grade0Value), mulName, nPtr, declareN, "/", normValue)); // result = input / n2 normalI.Add(new G25.CG.Shared.ReturnInstruction(nbTabs + 1, m_returnType, FT, mustCast, m_returnValue)); } I.Add(new G25.CG.Shared.IfElseInstruction(nbTabs, norm2Name + " <= " + FT.DoubleToString(m_specification, 0.0), specialI, normalI)); } // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(m_specification, FT, m_fgs, FAI); m_funcName[FT.type] = CF.OutputName; bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, CF.OutputName, FAI, I, comment); } } } // end of WriteFunction
} // end of WriteLargestCoordinateFunctions() /// <summary> /// Writes getters and setters for the SMV coordinates.. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Not used yet.</param> /// <param name="FT">Float point type of 'SMV'.</param> /// <param name="smv">The specialized multivector for which the struct should be written.</param> public static void WriteGetSetCoord(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.SMV smv) { int nbTabs = 1; string className = FT.GetMangledName(S, smv.Name); // for variable coordinates: for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(i); string name = smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames); string accessName = G25.CG.Shared.SmvUtil.GetCoordAccessString(S, smv, i); // get string getComment = "Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + name + "() { return " + accessName + ";}"); // set string setComment = "Sets the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(setComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " void " + G25.CG.Shared.Main.SETTER_PREFIX + name + "(" + FT.type + " " + name + ") { " + accessName + " = " + name + ";}"); } // for constant coordinates: for (int i = 0; i < smv.NbConstBasisBlade; i++) { RefGA.BasisBlade B = smv.ConstBasisBlade(i); // get string getComment = "Returns the " + B.ToString(S.m_basisVectorNames) + " coordinate."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() { return " + FT.DoubleToString(S, smv.ConstBasisBladeValue(i)) + ";}"); } // write a getter for the scalar which returns 0 if no scalar coordinate is present if (smv.GetElementIdx(RefGA.BasisBlade.ONE) < 0) { RefGA.BasisBlade B = RefGA.BasisBlade.ONE; string getComment = "Returns the scalar coordinate (which is always 0)."; new G25.CG.Shared.Comment(getComment).Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + " " + G25.CG.Shared.Main.GETTER_PREFIX + B.ToLangString(S.m_basisVectorNames) + "() { return " + FT.DoubleToString(S, 0.0) + ";}"); } // getter for the coordinates (stored in array) if ((S.m_coordStorage == COORD_STORAGE.ARRAY) && (smv.NbNonConstBasisBlade > 0)) { string constantName = G25.CG.Shared.SmvUtil.GetCoordinateOrderConstant(S, smv); string COORD_ORDER = "coordOrder"; new G25.CG.Shared.Comment("Returns array of coordinates."). SetParamComment(COORD_ORDER, "pass the value '" + className + "." + constantName + "'"). Write(SB, S, nbTabs); SB.AppendLine("\t" + Keywords.PublicAccessModifier(S) + " " + FT.type + "[] c(" + G25.CG.Shared.SmvUtil.COORDINATE_ORDER_ENUM + " " + COORD_ORDER + ") { return m_c;}"); } }
} // end of WriteExFunction /// <summary> /// Writes the declaration/definitions of 'F' to StringBuffer 'SB', taking into account parameters specified in specification 'S'. /// </summary> public override void WriteFunction() { //G25.SMV smv = m_specification.GetSMV(m_SMVname); foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); m_fgs.m_argumentTypeNames[0] = FT.type; bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo[] FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, 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, m_fgs, FAI); WriteExFunction(FT, CF.OutputName + "_ex"); System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); int nbTabs = 1; I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " " + MINIMUM_NORM + " = " + FT.DoubleToString(m_specification, 0.0001) + ";")); I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, FT.type + " " + LARGEST_COORDINATE + " = " + FT.DoubleToString(m_specification, 4.0) + ";")); I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, ((m_specification.OutputC()) ? "" : "return ") + CF.OutputName + "_ex(" + ((m_specification.OutputC()) ? (G25.fgs.RETURN_ARG_NAME + ", ") : "") + FAI[0].Name + ", minimumNorm, " + FAI[0].Name + " * largestCoordinate);")); // generate comment Comment comment = new Comment(m_fgs.AddUserComment("Returns random " + m_SMVname + " with a scale in the interval [0, scale)")); G25.CG.Shared.FuncArgInfo returnArgument = null; if (m_specification.OutputC()) { returnArgument = new G25.CG.Shared.FuncArgInfo(m_specification, m_fgs, -1, FT, m_SMVname, false); // false = compute value } string returnTypeName = FT.GetMangledName(m_specification, m_SMVname); bool staticFunc = Functions.OutputStaticFunctions(m_specification); G25.CG.Shared.Functions.WriteFunction(m_specification, m_cgd, CF, m_specification.m_inlineFunctions, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment); } } // end of WriteFunction
/// <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