/// <summary> /// Writes code for return m_name. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Not used yet.</param> public override void Write(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { if (m_type is G25.FloatType) { AppendTabs(SB); // Temp hack to override the float type: G25.FloatType FT = m_floatType; //m_type as G25.FloatType; // Should postops still be applied? ApplyPostOp(S, plugins, cog, BL, valueStr); // Not required so far? SB.AppendLine(CodeUtil.GenerateScalarReturnCode(S, FT, m_mustCast, m_value)); } else if (m_type is G25.SMV) { if (S.OutputC()) { bool ptr = true; bool declareVariable = false; new AssignInstruction(m_nbTabs, m_type, m_floatType, m_mustCast, m_value, G25.fgs.RETURN_ARG_NAME, ptr, declareVariable, m_postOp, m_postOpValue).Write(SB, S, cgd); } else { G25.SMV smv = m_type as G25.SMV; RefGA.BasisBlade[] BL = BasisBlade.GetNonConstBladeList(smv); bool writeZeros = true; string[] valueStr = CodeUtil.GetAssignmentStrings(S, m_floatType, m_mustCast, BL, m_value, writeZeros); // apply post operation (like "/ n2") ApplyPostOp(S, cgd, BL, valueStr); SB.AppendLine(CodeUtil.GenerateReturnCode(S, smv, m_floatType, valueStr, m_nbTabs, writeZeros)); } } }
/// <summary> /// Applies 'm_postOp m_postOpValue' to 'valueStr'. /// </summary> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Not used yet.</param> /// <param name="valueStr">The array of value strings to which the postop should be applied</param> /// <param name="BL">Not used yet. May be used later on to known what basis blade each valueStr refers to.</param> public void ApplyPostOp(Specification S, G25.CG.Shared.CGdata cgd, RefGA.BasisBlade[] BL, String[] valueStr) { if (m_postOp == null) { return; } // TODO: currently only for *= and /= // get string of value: string postOpValueStr; RefGA.Multivector sc = m_postOpValue.ScalarPart(); if (sc.IsZero()) { postOpValueStr = CodeUtil.ScalarToLangString(S, m_floatType, RefGA.BasisBlade.ZERO); } else { postOpValueStr = CodeUtil.ScalarToLangString(S, m_floatType, sc.BasisBlades[0]); } // apply "m_postOp postOpValueStr" to all valueStr for (int i = 0; i < valueStr.Length; i++) { valueStr[i] = "(" + valueStr[i] + ")" + m_postOp + ((m_mustCast) ? m_floatType.castStr : "") + "(" + postOpValueStr + ")"; } }
/// <summary> /// Takes a specialized multivector specification (G25.SMV) and converts it into a symbolic multivector. /// The symbolic weights of the multivector are the coordinates of the SMV, labelled according to 'smvName'. /// /// An example is <c>A.c[0]*e1 + A.c[1]*e2 + A.c[2]*e3</c>. /// </summary> /// <param name="S">Specification of the algebra. Used for the access convention (. or ->) and for how to name the coordinates ([0] or e1, e2, e3).</param> /// <param name="smv">The specification of the specialized multivector.</param> /// <param name="smvName">Name the variable should have.</param> /// <param name="ptr">Is 'smvName' a pointer? This changes the way the variable is accessed.</param> /// <returns></returns> public static RefGA.Multivector SMVtoSymbolicMultivector(Specification S, G25.SMV smv, string smvName, bool ptr) { int idx = 0; // index into 'L' RefGA.BasisBlade[] L = new RefGA.BasisBlade[smv.NbConstBasisBlade + smv.NbNonConstBasisBlade]; string[] AL = CodeUtil.GetAccessStr(S, smv, smvName, ptr); // get non-const coords for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { // get basis blade of coordinate RefGA.BasisBlade B = smv.NonConstBasisBlade(i); // merge L[idx++] = new RefGA.BasisBlade(B.bitmap, B.scale, AL[i]); } // get const coords for (int i = 0; i < smv.NbConstBasisBlade; i++) { // get value of coordinate double value = smv.ConstBasisBladeValue(i); // get basis blade of coordinate RefGA.BasisBlade B = smv.ConstBasisBlade(i); // merge L[idx++] = new RefGA.BasisBlade(B.bitmap, B.scale * value); } return(new RefGA.Multivector(L)); } // end of SMVtoSymbolicMultivector()
/// <summary> /// Writes a zero or equality test function for general multivectors, /// based on CASN parts code. /// </summary> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="FT"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> /// <param name="writeZero">When true, a function to test for zero is written.</param> /// <returns>full (mangled) name of generated function</returns> public static string WriteEqualsOrZeroOrGradeBitmapFunction(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment, G25.CG.Shared.CANSparts.EQUALS_ZERO_GRADEBITMAP_TYPE funcType) { // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); int nbTabs = 1; // write this function: string code = ""; if (funcType == G25.CG.Shared.CANSparts.EQUALS_ZERO_GRADEBITMAP_TYPE.EQUALS) { code = G25.CG.Shared.CANSparts.GetEqualsCode(S, cgd, FT, FAI); } else if (funcType == G25.CG.Shared.CANSparts.EQUALS_ZERO_GRADEBITMAP_TYPE.ZERO) { code = G25.CG.Shared.CANSparts.GetZeroCode(S, cgd, FT, FAI); } else if (funcType == G25.CG.Shared.CANSparts.EQUALS_ZERO_GRADEBITMAP_TYPE.GRADE_BITMAP) { code = G25.CG.Shared.CANSparts.GetGradeBitmapCode(S, cgd, FT, FAI); } // add one instruction (verbatim code) I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code)); // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(S, FT, F, FAI); // setup return type and argument: string returnTypeName = null; if (S.OutputC()) { returnTypeName = G25.IntegerType.INTEGER; } else { if (funcType == G25.CG.Shared.CANSparts.EQUALS_ZERO_GRADEBITMAP_TYPE.GRADE_BITMAP) { returnTypeName = G25.IntegerType.INTEGER; } else { returnTypeName = CodeUtil.GetBoolType(S); } } G25.CG.Shared.FuncArgInfo returnArgument = null; // write function bool inline = false; // never inline GMV functions bool staticFunc = Functions.OutputStaticFunctions(S); G25.CG.Shared.Functions.WriteFunction(S, cgd, F, inline, staticFunc, returnTypeName, CF.OutputName, returnArgument, FAI, I, comment); return(CF.OutputName); }
/// <summary> /// Writes code for m_name = m_value. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Not used yet.</param> public override void Write(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd) { if (m_type is G25.SMV) { G25.SMV dstSmv = m_type as G25.SMV; if (m_declareVariable) { SB.AppendLine("/* cannot yet assign and declare SMV type at the same time */"); } RefGA.BasisBlade[] BL = BasisBlade.GetNonConstBladeList(dstSmv); string[] accessStr = CodeUtil.GetAccessStr(S, dstSmv, m_name, m_ptr); bool writeZeros = true; string[] valueStr = CodeUtil.GetAssignmentStrings(S, m_floatType, m_mustCast, BL, m_value, writeZeros); // apply post operation (like "/ n2") ApplyPostOp(S, cgd, BL, valueStr); SB.AppendLine(CodeUtil.GenerateAssignmentCode(S, accessStr, valueStr, m_nbTabs, writeZeros)); } else if (m_type is G25.FloatType) { // temp hack to override float type. G25.FloatType FT = this.m_floatType; // m_type as G25.FloatType; AppendTabs(SB); if (m_declareVariable) { // also declare the variable right here? // output "/t type " SB.Append(FT.type + " "); } // output name = ....; RefGA.BasisBlade[] BL = new RefGA.BasisBlade[1] { RefGA.BasisBlade.ONE }; String[] accessStr = new String[1] { m_name }; bool writeZeros = true; String[] valueStr = CodeUtil.GetAssignmentStrings(S, FT, m_mustCast, BL, m_value, writeZeros); // apply post operation (like "/ n2") ApplyPostOp(S, cgd, BL, valueStr); SB.AppendLine(CodeUtil.GenerateAssignmentCode(S, accessStr, valueStr, 0, writeZeros)); } else { SB.AppendLine("/* to do: implement " + GetType().ToString() + " for type " + m_type.GetType().ToString() + " */"); } }
} // 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()
/// <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()