} // end of WriteFunctions() /// <summary> /// Writes a simple function which assigns some value based on specialized multivectors or scalars to some variable. /// /// Used by a lot of simple C functions, like gp, op, lc. /// /// Somewhat obsolete (preferably, use the more generic, instruction based WriteFunction()). /// /// </summary> /// <param name="S">Specification of algebra.</param> /// <param name="cgd">Results go into cgd.m_defSB, and so on</param> /// <param name="F">The function generation specification.</param> /// <param name="FT">Default float pointer type.</param> /// <param name="FAI">Info on the arguments of the function.</param> /// <param name="value">The value to assign.</param> /// <param name="comment">Optional comment for function (can be null).</param> public static void WriteSpecializedFunction(Specification S, G25.CG.Shared.CGdata cgd, G25.fgs F, FloatType FT, G25.CG.Shared.FuncArgInfo[] FAI, RefGA.Multivector value, Comment comment) { // get return type (may be a G25.SMV or a G25.FloatType) G25.VariableType returnType = G25.CG.Shared.SpecializedReturnType.GetReturnType(S, cgd, F, FT, value); if (returnType == null) { throw new G25.UserException("Missing return type: " + G25.CG.Shared.BasisBlade.MultivectorToTypeDescription(S, value), XML.FunctionToXmlString(S, F)); } bool ptr = true; string dstName = G25.fgs.RETURN_ARG_NAME; //string dstTypeName = (returnType is G25.SMV) ? FT.GetMangledName((returnType as G25.SMV).Name) : (returnType as G25.FloatType).type; string funcName = F.OutputName; // write comment to declaration if (comment != null) { if (S.OutputCppOrC()) { comment.Write(cgd.m_declSB, S, 0); } else { comment.Write(cgd.m_defSB, S, 0); } } if ((returnType is G25.SMV) && (S.OutputC())) { bool mustCast = false; G25.SMV dstSmv = returnType as G25.SMV; G25.CG.Shared.FuncArgInfo returnArgument = null; returnArgument = new G25.CG.Shared.FuncArgInfo(S, F, -1, FT, dstSmv.Name, false); // false = compute value bool staticFunc = S.OutputCSharpOrJava(); G25.CG.Shared.Functions.WriteAssignmentFunction(S, cgd, S.m_inlineFunctions, staticFunc, "void", null, funcName, returnArgument, FAI, FT, mustCast, dstSmv, dstName, ptr, value); } else { G25.FloatType returnFT = ((returnType as G25.FloatType) == null) ? FT : (returnType as G25.FloatType); bool mustCast = false; for (int i = 0; i < FAI.Length; i++) { mustCast |= returnFT.MustCastIfAssigned(S, FAI[i].FloatType); } bool staticFunc = S.OutputCSharpOrJava(); G25.CG.Shared.Functions.WriteReturnFunction(S, cgd, S.m_inlineSet, staticFunc, funcName, FAI, FT, mustCast, returnType, value); } } // end of WriteSpecializedFunction()
} // end of GenerateSMVassignmentCode public static string GenerateReturnCode(Specification S, G25.SMV smv, G25.FloatType FT, String[] valueStr, int nbTabs, bool writeZeros) { StringBuilder SB = new StringBuilder(); string smvName = FT.GetMangledName(S, smv.Name); string STATIC_MEMBER_ACCESS = (S.OutputCpp()) ? "::" : "."; SB.Append('\t', nbTabs); SB.Append("return "); if (S.OutputCSharpOrJava()) { SB.Append("new "); } SB.Append(smvName); SB.Append("("); if (valueStr.Length > 0) { SB.AppendLine(smvName + STATIC_MEMBER_ACCESS + SmvUtil.GetCoordinateOrderConstant(S, smv) + ","); } for (int i = 0; i < valueStr.Length; i++) { SB.Append('\t', nbTabs + 2); SB.Append(valueStr[i]); if (i < (valueStr.Length - 1)) { SB.Append(","); } SB.AppendLine(" // " + smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames)); } SB.Append('\t', nbTabs + 1); SB.Append(");"); return(SB.ToString()); }
/// <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 the definition of an GOM struct to 'SB' (including comments). /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names and output language.</param> /// <param name="cgd">Intermediate data for code generation. Also contains plugins and cog.</param> /// <param name="FT">Float point type of 'GOM'.</param> /// <param name="gom">The general outermorphism for which the struct should be written.</param> public static void WriteGOMclass(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.GOM gom) { SB.AppendLine(""); string className = FT.GetMangledName(S, gom.Name); // get range vector type G25.SMV rangeVectorType = G25.CG.Shared.OMinit.getRangeVectorType(S, FT, cgd, gom); string rangeVectorSMVname = FT.GetMangledName(S, rangeVectorType.Name); WriteComment(SB, S, cgd, FT, gom); // typedef SB.AppendLine("class " + className); SB.AppendLine("{"); // member vars WriteMemberVariables(SB, S, cgd, FT, gom); SB.AppendLine("public:"); // Float type WriteFloatType(SB, S, cgd, FT, gom, className); // constructors WriteConstructors(SB, S, cgd, FT, gom, className, rangeVectorSMVname); // operator= WriteAssignmentOps(SB, S, cgd, FT, gom, className, rangeVectorSMVname); // set(...) WriteSetDeclarations(SB, S, cgd, FT, gom, className, rangeVectorSMVname); SB.AppendLine("}; // end of " + className); }
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(";"); }
/// <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)); } } }
public static G25.VariableType CreateSyntheticSMVtype(Specification S, CGdata cgd, FloatType FT, RefGA.Multivector value) { // make up list of basis blades rsbbp.BasisBlade[] L = new rsbbp.BasisBlade[value.BasisBlades.Length]; for (int i = 0 ; i < value.BasisBlades.Length; i++) { RefGA.BasisBlade B = value.BasisBlades[i]; if (B.symScale == null) L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap), B.scale); // constant value else L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap)); // non-const value } // get other required info String name = "nameOfType"; SMV.MULTIVECTOR_TYPE mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR; String comment = "MISSING; PLEASE ADD TO SPECIFICATION"; //String constantName = null; // create the type G25.SMV synSMV = new G25.SMV(name, L, mvType, comment); // throw exception throw new G25.UserException("Missing specialized multivector type.\n" + "Please add the following XML to the specification to fix the dependency:\n" + XML.SMVtoXmlString(S, synSMV)); }
/// <summary> /// This function checks the dependencies for the _testing_ code of this function. If dependencies are /// missing, the function adds the required functions (this is done simply by asking for them . . .). /// </summary> public override void CheckTestingDepencies() { //bool returnTrueName = true; foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); m_randomScalarFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "random_" + FT.type, new String[0], FT.type, FT, null); // actual requirements: if (m_gmvFunc) { m_randomBladeFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "random_blade", new String[0], m_specification.m_GMV.Name, FT, null); m_subtractGmvFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "subtract", new String[] { m_specification.m_GMV.Name, m_specification.m_GMV.Name }, m_specification.m_GMV.Name, FT, null); m_opGmvFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "op", new String[] { m_specification.m_GMV.Name, m_specification.m_GMV.Name }, m_specification.m_GMV.Name, FT, null); } else if (m_specification.m_GOM != null) // test for applyOM(SMV) can only be performed when GOM exists { string defaultReturnTypeName = null; G25.SMV gomRangeVectorType = getGomRangeVectorType(FT); m_randomRangeVectorFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "random_" + gomRangeVectorType.Name, new String[0], defaultReturnTypeName, FT, null); m_randomDomainSmvFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "random_" + m_mv.Name, new String[0], defaultReturnTypeName, FT, null); m_subtractGmvFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "subtract", new String[] { m_specification.m_GMV.Name, m_specification.m_GMV.Name }, defaultReturnTypeName, FT, null); m_gmvApplyOmFuncName[FT.type] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "applyOM", new String[] { m_specification.m_GOM.Name, m_specification.m_GMV.Name }, defaultReturnTypeName, FT, null); } } }
public static G25.VariableType CreateSyntheticSMVtype(Specification S, CGdata cgd, FloatType FT, RefGA.Multivector value) { // make up list of basis blades rsbbp.BasisBlade[] L = new rsbbp.BasisBlade[value.BasisBlades.Length]; for (int i = 0; i < value.BasisBlades.Length; i++) { RefGA.BasisBlade B = value.BasisBlades[i]; if (B.symScale == null) { L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap), B.scale); // constant value } else { L[i] = new rsbbp.BasisBlade(new RefGA.BasisBlade(B.bitmap)); // non-const value } } // get other required info String name = "nameOfType"; SMV.MULTIVECTOR_TYPE mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR; String comment = "MISSING; PLEASE ADD TO SPECIFICATION"; //String constantName = null; // create the type G25.SMV synSMV = new G25.SMV(name, L, mvType, comment); // throw exception throw new G25.UserException("Missing specialized multivector type.\n" + "Please add the following XML to the specification to fix the dependency:\n" + XML.SMVtoXmlString(S, synSMV)); }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { m_ipType = GetIpType(m_specification, m_fgs); // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) { if (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT) { m_fgs.m_returnTypeName = m_gmv.Name;// gmv * gmv = gmv } else { m_fgs.ReturnTypeName = FT.type; } } else { // compute return value m_returnValue = RefGA.Multivector.ip(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M, m_ipType); // round value if required by metric if (m_G25M.m_round) { m_returnValue = m_returnValue.Round(1e-14); } // get name of return type if ((m_fgs.ReturnTypeName.Length == 0) && (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT)) { m_fgs.ReturnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } else { m_fgs.ReturnTypeName = FT.type; } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_trueGmvFunc = (!tmpFAI[0].IsScalarOrSMV()) && (!tmpFAI[1].IsScalarOrSMV()); m_arg1isGmv = !tmpFAI[0].IsScalarOrSMV(); m_arg2isGmv = !tmpFAI[1].IsScalarOrSMV(); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // gmv * gmv = gmv } else { // compute return value m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[1].MultivectorValue[0]); m_n2Value = RefGA.Multivector.gp(m_reverseValue, tmpFAI[1].MultivectorValue[0], m_M); if (m_G25M.m_round) { m_n2Value = m_n2Value.Round(1e-14); } //m_returnValue = RefGA.Multivector.gp(RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M), // RefGA.Symbolic.ScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName)))); m_returnValue = RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M); // round value if required by metric if (m_G25M.m_round) { m_returnValue = m_returnValue.Round(1e-14); } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } }
/// <summary> /// Utility function which takes a specialized multivector and returns an array of its variable /// RefGA.BasisBlades. I.e., extracts 'smv.NonConstBasisBlade()' /// </summary> /// <param name="smv">Specialized multivector.</param> /// <returns>Array of non-constant basis blades of 'smv'.</returns> public static RefGA.BasisBlade[] GetNonConstBladeList(G25.SMV smv) { RefGA.BasisBlade[] BL = new RefGA.BasisBlade[smv.NbNonConstBasisBlade]; for (int i = 0; i < smv.NbNonConstBasisBlade; i++) BL[i] = smv.NonConstBasisBlade(i); return BL; }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); m_isNorm2 = IsNorm2(m_fgs); // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, new RefGA.Multivector("x")).GetName(); // norm(gmv) = scalar } else { m_smv = tmpFAI[0].Type as G25.SMV; // compute return value if (m_isNorm2) { m_returnValue = tmpFAI[0].MultivectorValue[0].Norm_r2(m_M); } else { m_returnValue = RefGA.Symbolic.UnaryScalarOp.Abs(tmpFAI[0].MultivectorValue[0].Norm_r(m_M)); } // round value if required by metric if (m_G25M.m_round) { m_returnValue = m_returnValue.Round(1e-14); } // avoid null return value because that might return in getting the wrong return type RefGA.Multivector nonZeroReturnValue = (m_returnValue.IsZero()) ? RefGA.Multivector.ONE : m_returnValue; // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, nonZeroReturnValue).GetName(); } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { if (m_G25M.m_metric.IsDegenerate()) { throw new G25.UserException("Cannot generate dual functions for degenerate metrics."); } // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // dual(gmv) = gmv } else { m_smv = tmpFAI[0].Type as G25.SMV; // compute return value if (IsDual(m_fgs)) { m_returnValue = RefGA.Multivector.Dual(tmpFAI[0].MultivectorValue[0], m_M); } else if (IsUndual(m_fgs)) { m_returnValue = RefGA.Multivector.Undual(tmpFAI[0].MultivectorValue[0], m_M); } // round value if required by metric if (m_G25M.m_round) { m_returnValue = m_returnValue.Round(1e-14); } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // dual(gmv) = gmv } else { m_smv = tmpFAI[0].Type as G25.SMV; // get symbolic result m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[0].MultivectorValue[0]); m_n2Value = RefGA.Multivector.gp(m_reverseValue, tmpFAI[0].MultivectorValue[0], m_M); if (m_G25M.m_round) { m_n2Value = m_n2Value.Round(1e-14); } if (m_n2Value.HasSymbolicScalars() || (!m_n2Value.IsScalar()) || m_n2Value.IsZero()) { m_inverseValue = RefGA.Multivector.gp(m_reverseValue, RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName)))); } else { m_inverseValue = RefGA.Multivector.gp(m_reverseValue, new RefGA.Multivector(1.0 / m_n2Value.RealScalarPart())); m_n2Value = null; } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_inverseValue).GetName(); } } m_returnType = m_specification.GetType(m_fgs.m_returnTypeName); }
} // end of GenerateScalarReturnCode() /// <summary> /// Generates the code to assign a multivector value (which may have symbolic coordinates) to a specialized multivector. /// </summary> /// <param name="S">Specification of algebra. Used to known names of basis vector, output language, access strings, etc.</param> /// <param name="FT">Floating point type of destination.</param> /// <param name="mustCast">Set to true if a cast to 'FT' must be performed before assigned to 'dstName'.</param> /// <param name="dstSmv">Type of specialized multivector assigned to.</param> /// <param name="dstName">Name of specialized multivector assigned to.</param> /// <param name="dstPtr">Is the destination of pointer?</param> /// <param name="value">Multivector value to assign to the SMV. Must not contain basis blades inside the symbolic scalars.</param> /// <param name="nbTabs">Number of tabs to put before the code.</param> /// <param name="writeZeros">Some callers want to skip <c>"= 0.0"</c> assignments because they would be redundant. For /// example the caller may know that the destination is already set to zero. If so, set this argument to false and /// code for setting coordinates to 0 will not be generated.</param> /// <returns>String of code for dstName = value;</returns> public static string GenerateSMVassignmentCode(Specification S, FloatType FT, bool mustCast, G25.SMV dstSmv, String dstName, bool dstPtr, RefGA.Multivector value, int nbTabs, bool writeZeros) { RefGA.BasisBlade[] BL = BasisBlade.GetNonConstBladeList(dstSmv); string[] accessStr = GetAccessStr(S, dstSmv, dstName, dstPtr); string[] assignedStr = GetAssignmentStrings(S, FT, mustCast, BL, value, writeZeros); //int nbTabs = 1; return(GenerateAssignmentCode(S, accessStr, assignedStr, nbTabs, writeZeros)); } // end of GenerateSMVassignmentCode
/// <summary> /// Writes the <c>defines</c> for indices of the smv struct to 'SB'. For example, <c>define VECTOR_E1 0</c>. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for basis vector names.</param> /// <param name="smv">The specialized multivector for which the coordinate indices should be written.</param> public static void WriteSMVcoordIndices(StringBuilder SB, Specification S, G25.SMV smv) { SB.AppendLine(""); for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { // write comment about what the #define is SB.AppendLine("/** index of coordinate for " + smv.NonConstBasisBlade(i).ToString(S.m_basisVectorNames) + " in " + smv.Name + ".c */"); SB.AppendLine("#define " + GetCoordIndexDefine(S, smv, i) + " " + i); } }
/// <summary> /// Returns the SMV type that can hold an image of a basis vector. /// </summary> public static G25.SMV GetRangeVectorType(Specification S, G25.FloatType FT, CGdata cgd, G25.SOM som) { RefGA.Multivector rangeVectorValue = new RefGA.Multivector(som.RangeVectors); G25.SMV rangeVectorType = (G25.SMV)G25.CG.Shared.SpecializedReturnType.FindTightestMatch(S, rangeVectorValue, FT); if (rangeVectorType == null) // type is missing, add it and tell user to add it to XML { rangeVectorType = (G25.SMV)G25.CG.Shared.SpecializedReturnType.CreateSyntheticSMVtype(S, cgd, FT, rangeVectorValue); } return(rangeVectorType); }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // toggle_sign(gmv) = gmv } else { m_smv = tmpFAI[0].Type as G25.SMV; // compute return value if (IsNegate(m_fgs)) { m_returnValue = RefGA.Multivector.Negate(tmpFAI[0].MultivectorValue[0]); } else if (IsReverse(m_fgs)) { m_returnValue = RefGA.Multivector.Reverse(tmpFAI[0].MultivectorValue[0]); } else if (IsCliffordConjugate(m_fgs)) { m_returnValue = RefGA.Multivector.CliffordConjugate(tmpFAI[0].MultivectorValue[0]); } else if (IsGradeInvolution(m_fgs)) { m_returnValue = RefGA.Multivector.GradeInvolution(tmpFAI[0].MultivectorValue[0]); } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } }
/// <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() + " */"); } }
/// <summary> /// Returns string to access coordinates number 'coordIdx'. /// </summary> /// <param name="S"></param> /// <param name="smv"></param> /// <param name="coordIdx"></param> /// <returns></returns> public static string GetCoordAccessString(Specification S, G25.SMV smv, int coordIdx) { if (S.m_coordStorage == COORD_STORAGE.VARIABLES) { return("m_" + smv.GetCoordLangID(coordIdx, S)); } else { return("m_c[" + coordIdx + "]"); } }
/// <summary> /// Returns the name of the constant as first argument to functions which have coordinate arguments. /// </summary> /// <param name="S"></param> /// <param name="smv"></param> public static string GetCoordinateOrderConstant(Specification S, G25.SMV smv) { StringBuilder SB = new StringBuilder("coord"); string wedgeSymbol = ""; // no symbol for wedge for (int i = 0; i < smv.NbNonConstBasisBlade; i++) { SB.Append("_"); SB.Append(smv.NonConstBasisBlade(i).ToLangString(S.m_basisVectorNames, wedgeSymbol)); } return(SB.ToString()); }
/// <summary> /// Writes all shortcuts for 'type'. /// </summary> /// <param name="SB">Where the code goes.</param> /// <param name="S">Used for namespace.</param> /// <param name="cgd">Not used yet.</param> /// <param name="FT">Float point type of 'type'.</param> /// <param name="type">The type for which the function should be written.</param> public static void WriteFunctionShortcuts(StringBuilder SB, Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.VariableType type) { Dictionary <string, List <G25.Operator> > operatorMap = S.GetOperatorMap(); Dictionary <string, bool> boundOperators = new Dictionary <string, bool>(); foreach (G25.fgs fgs in S.m_functions) { if ((type is G25.SMV) && fgs.IsConverter(S)) { G25.SMV smv = (G25.SMV)type; if (fgs.IsConverterSource(S, (G25.SMV)type, FT)) { // write converter here . . . //SB.AppendLine("// converter source here!"); } else if (fgs.IsConverterDestination(S, smv, FT)) { // write converter here . . . Converter.WriteMemberConverter(SB, S, cgd, FT, fgs, (G25.SMV)S.GetType(fgs.ArgumentTypeNames[0]), smv); } } else if (fgs.GetSupportedByPlugin() && (fgs.NbArguments >= 1) && (Array.IndexOf(fgs.FloatNames, FT.type) >= 0)) { // get function arguments bool computeMultivectorValue = false; G25.CG.Shared.FuncArgInfo[] FAI = null; try { FAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(S, fgs, fgs.NbArguments, FT, "not set", computeMultivectorValue); } catch (Exception ex) { if ((type is G25.GMV) && (FT == S.m_floatTypes[0])) // only warn once { Console.WriteLine("Warning: cannot generate shortcut to " + fgs.ToString()); } continue; } // if type matches, write the shortcut, and possibly an operator if (FAI[0].TypeName.Equals(type.GetName())) { WriteFunctionShortcut(SB, S, cgd, FT, type, fgs, FAI); if (S.OutputCSharpOrJava()) { removeMvInterfaces(FAI); // arguments to operators need to be of the multivector type, not the multivector interface type } WriteOperatorShortcut(SB, S, cgd, FT, type, fgs, FAI, operatorMap, boundOperators); } } } } // end of function WriteFunctionShortcuts()
/// <returns>true when input to function has one argument which is a SMV of grade 2.</returns> public bool IsFlatPointBased(Specification S, G25.fgs F, FloatType FT) { if (!(F.ArgumentTypeNames.Length == 1) && (!IsCoordBased(S, F, FT))) { return(false); } G25.SMV smv = S.GetSMV(F.ArgumentTypeNames[0]); if (smv == null) { return(false); } return((smv.LowestGrade() == 2) && (smv.HighestGrade() == 2)); }
/// <summary> /// This function should check the dependencies of this function. If dependencies are /// missing, the function can complain (throw exception) or fix it (add the required functions). /// /// If changes are made to the specification then it must be locked first because /// multiple threads run in parallel which may all modify the specification! /// </summary> public override void CheckDepencies() { m_SMVname = getSMVnameFromFGS(m_fgs); m_smvType = m_specification.GetSMV(m_SMVname); // check dependencies for all float types foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); //bool returnTrueName = false; m_randomScalarFunc[floatName] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, RandomScalar.RANDOM + floatName, new string[0], floatName, FT, null); m_normFunc[floatName] = G25.CG.Shared.Dependencies.GetDependency(m_specification, m_cgd, "norm", new string[] { m_SMVname }, FT, m_G25M.m_name) + G25.CG.Shared.CANSparts.RETURNS_SCALAR; } }
/// <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 scalarSMV = m_specification.GetScalarSMV(); bool scalarTypePresent = scalarSMV != null; foreach (string floatName in m_fgs.FloatNames) { FloatType FT = m_specification.GetFloatType(floatName); // hack to override floating point return type if (m_specification.IsFloatType(m_fgs.ReturnTypeName)) { m_fgs.ReturnTypeName = FT.type; } 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 " + m_fgs.Name + " of " + FAI[0].TypeName + " using " + m_G25M.m_name + " metric.")); // 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 scalar or specialized: generate specialized function if (m_gmvFunc) { m_funcName[FT.type] = G25.CG.Shared.GmvGpParts.WriteGMVnormFunction(m_specification, m_cgd, FT, m_G25M, FAI, m_fgs, comment, m_isNorm2); } else { m_funcName[FT.type] = CF.OutputName; // write out the function: G25.CG.Shared.Functions.WriteSpecializedFunction(m_specification, m_cgd, CF, FT, FAI, m_returnValue, comment); } // write 'returns float' versions of norm if (scalarTypePresent) { WriteNormReturnsScalar(FT, FAI, CF.OutputName, scalarSMV); } else { WriteNormReturnsScalarPassThrough(m_specification, FT, FAI, CF.OutputName); } } } // end of WriteFunction
/// <summary> /// Return true if <c>smv</c> can be initialized with random values for each coordinate: /// - scalar types /// - vector types /// - dual vector types /// - pseudoscalar types /// - G25.SMV.MULTIVECTOR_TYPE.MULTIVECTOR types /// </summary> /// <param name="S"></param> /// <param name="smv"></param> /// <returns>true if <c>smv</c> can be initialized with random values for each coordinate.</returns> public static bool InitWithRandomCoordinates(Specification S, G25.SMV smv) { if (smv.MvType == G25.SMV.MULTIVECTOR_TYPE.MULTIVECTOR) { return(true); } int lg = smv.LowestGrade(); int hg = smv.HighestGrade(); if (lg != hg) { return(false); } return((lg == 0) || (lg == 1) || (lg == (S.m_dimension - 1)) || (lg == S.m_dimension)); }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// - Optionally fill in F.m_argumentPtr /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name } } ; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_trueGmvFunc = (!tmpFAI[0].IsScalarOrSMV()) && (!tmpFAI[1].IsScalarOrSMV()); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // gmv + gmv = gmv } else { // compute return value if (IsAdd(m_fgs)) { m_returnValue = RefGA.Multivector.Add(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]); } else if (IsSubtract(m_fgs)) { m_returnValue = RefGA.Multivector.Subtract(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]); } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } }
} // end of WriteGMVigpFunction /// <summary> /// Writes any norm function for general multivectors, based on gp parts code. /// </summary> /// <param name="SB"></param> /// <param name="S"></param> /// <param name="cgd"></param> /// <param name="FT"></param> /// <param name="M"></param> /// <param name="FAI"></param> /// <param name="F"></param> /// <param name="comment"></param> /// <param name="declOnly"></param> /// <param name="squared"></param> /// <returns>name of generated function.</returns> public static string WriteGMVnormFunction(Specification S, G25.CG.Shared.CGdata cgd, FloatType FT, G25.Metric M, G25.CG.Shared.FuncArgInfo[] FAI, G25.fgs F, Comment comment, bool squared) { // setup instructions System.Collections.Generic.List <G25.CG.Shared.Instruction> I = new System.Collections.Generic.List <G25.CG.Shared.Instruction>(); int nbTabs = 1; // because of lack of overloading, function names include names of argument types G25.fgs CF = G25.CG.Shared.Util.AppendTypenameToFuncName(S, FT, F, FAI); string funcName = CF.OutputName; // get return info G25.SMV returnType = null; string returnTypeName = null; G25.CG.Shared.FuncArgInfo returnArgument = null; { // try to get scalar type returnType = S.GetScalarSMV(); if (returnType == null) { returnTypeName = FT.type; } else { if (S.OutputC()) { returnArgument = new G25.CG.Shared.FuncArgInfo(S, CF, -1, FT, returnType.Name, false); // false = compute value } returnTypeName = FT.GetMangledName(S, returnType.GetName()); } } // write this function: string code = G25.CG.Shared.GPparts.GetNormCode(S, cgd, FT, M, squared, FAI, returnType, G25.fgs.RETURN_ARG_NAME); // add the verbatim code I.Add(new G25.CG.Shared.VerbatimCodeInstruction(nbTabs, code)); // 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, funcName, returnArgument, FAI, I, comment); return(funcName); } // end of WriteGMVnormFunction
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { m_gradeIdx = GetGradeIdx(m_fgs.Name); // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) { m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name } } ; // supplement the extra 'int' argument if ((m_gradeIdx < 0) && (m_fgs.ArgumentTypeNames.Length == 1)) { m_fgs.m_argumentTypeNames = new string[] { m_fgs.ArgumentTypeNames[0], G25.GroupBitmapType.GROUP_BITMAP }; m_fgs.m_argumentVariableNames = new string[] { m_fgs.m_argumentVariableNames[0], "groupBitmap" }; } // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); m_smv = tmpFAI[0].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // grade(gmv) = gmv } else { // compute return value m_returnValue = tmpFAI[0].MultivectorValue[0].ExtractGrade(m_gradeIdx); // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// /// As the return type is required, many functions will also compute the return value and other info /// needed for generating the code inside this function. These intermediate values are then /// stored in class variables so they can be reused in WriteFunction() /// </summary> public override void CompleteFGS() { NB_ARGS = m_fgs.NbArguments; // all arguments must be explicitly listed // in C language, all arguments are pointers if (m_fgs.ArgumentPtr.Length == 0) { bool ptr = m_specification.OutputC(); m_fgs.m_argumentPtr = new bool[] { ptr, ptr }; m_fgs.m_argumentArr = new bool[] { false, false }; } // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; { // compute return value // compute symbolic distance squared value m_returnValue = RefGA.Multivector.gp( RefGA.Multivector.ScalarProduct(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M), -2.0); // apply sqrt(fabs()) if distance should not be squared: if (IsDistance(m_fgs)) { m_returnValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(RefGA.Symbolic.UnaryScalarOp.Abs(m_returnValue)); } // round value if required by metric if (m_G25M.m_round) { m_returnValue = m_returnValue.Round(1e-14); } } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } } // end of CompleteFGS()
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); m_isNorm2 = IsNorm2(m_fgs); // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, new RefGA.Multivector("x")).GetName(); // norm(gmv) = scalar else { m_smv = tmpFAI[0].Type as G25.SMV; // compute return value if (m_isNorm2) m_returnValue = tmpFAI[0].MultivectorValue[0].Norm_r2(m_M); else m_returnValue = RefGA.Symbolic.UnaryScalarOp.Abs(tmpFAI[0].MultivectorValue[0].Norm_r(m_M)); // round value if required by metric if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14); // avoid null return value because that might return in getting the wrong return type RefGA.Multivector nonZeroReturnValue = (m_returnValue.IsZero()) ? RefGA.Multivector.ONE : m_returnValue; // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, nonZeroReturnValue).GetName(); } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // gmv ^ gmv = gmv else { // compute return value m_returnValue = RefGA.Multivector.op(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]); // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) { m_fgs.m_returnTypeName = m_gmv.Name; // sin/cos/sinh/cosh/exp(gmv) = gmv m_returnType = m_gmv; m_inputTypeName = m_gmv.Name; m_returnTypeName = m_gmv.Name; } else { m_smv = tmpFAI[0].Type as G25.SMV; try // exceptions are caught below -> in that case, do a series for the SMV { // sin/cos/sinh/cosh/exp(smv bivector) RefGA.Multivector value = tmpFAI[0].MultivectorValue[0]; RefGA.Multivector squareValue = RefGA.Multivector.gp(value, value, m_M); String userSetSquare = m_fgs.GetOption("square"); if (userSetSquare != null) m_signOfSquare = (int)Math.Sign(Double.Parse(userSetSquare)); else { // the following line can throw an exception, which is caught below double sqEval = RefGA.Symbolic.SymbolicUtil.EvaluateRandomSymbolicToScalar(squareValue); m_signOfSquare = (int)Math.Sign(sqEval); } m_scalarSquare = true; // compute alpha = sqrt(fabs(value^2)) m_alphaValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(RefGA.Symbolic.UnaryScalarOp.Abs(squareValue)); // use hyperbolic sin / cos or regular sin / cos for shortcuts? bool hyperbolic = (((IsExp(m_fgs) || IsCosh(m_fgs) || IsSinh(m_fgs)) && (m_signOfSquare > 0)) || ((IsCos(m_fgs) || IsSin(m_fgs)) && (m_signOfSquare < 0))); // compute mul for SIN and EXP (assuming alpha is not zero) if (IsCos(m_fgs) || m_alphaValue.IsZero()) m_mulValue = RefGA.Multivector.ONE; else if (m_signOfSquare == 0) m_mulValue = RefGA.Multivector.ZERO; else { if (hyperbolic) m_mulValue = RefGA.Multivector.gp( RefGA.Symbolic.UnaryScalarOp.Sinh(new RefGA.Multivector(m_alphaName)), RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(m_alphaName))); else m_mulValue = RefGA.Multivector.gp( RefGA.Symbolic.UnaryScalarOp.Sin(new RefGA.Multivector(m_alphaName)), RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(m_alphaName))); } // compute sin, cos part RefGA.Multivector cosValue = null, sinValue = null; if (m_signOfSquare == 0) { cosValue = RefGA.Multivector.ONE; sinValue = value; } else { sinValue = RefGA.Multivector.gp(value, new RefGA.Multivector(m_mulName)); if (hyperbolic) cosValue = RefGA.Symbolic.UnaryScalarOp.Cosh(new RefGA.Multivector(m_alphaName)); else cosValue = RefGA.Symbolic.UnaryScalarOp.Cos(new RefGA.Multivector(m_alphaName)); } // compute return value if (IsExp(m_fgs)) m_returnValue = RefGA.Multivector.Add(cosValue, sinValue); else if (IsCos(m_fgs) || IsCosh(m_fgs)) m_returnValue = cosValue; else if (IsSin(m_fgs) || IsSinh(m_fgs)) m_returnValue = sinValue; // get name of return type if (m_fgs.m_returnTypeName.Length == 0) { m_returnType = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue); m_fgs.m_returnTypeName = m_returnType.GetName(); } else { m_returnType = m_specification.GetType(m_fgs.m_returnTypeName); } } catch (System.Exception) { // sin/cos/sinh/cosh/exp(any SMV) // determine return type ComputeReturnTypeExpSmv(tmpFAI, FT); m_inputTypeName = tmpFAI[0].TypeName; m_fgs.m_returnTypeName = m_returnTypeName; } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { if (m_G25M.m_metric.IsDegenerate()) throw new G25.UserException("Cannot generate dual functions for degenerate metrics."); // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // dual(gmv) = gmv else { m_smv = tmpFAI[0].Type as G25.SMV; // compute return value if (IsDual(m_fgs)) m_returnValue = RefGA.Multivector.Dual(tmpFAI[0].MultivectorValue[0], m_M); else if (IsUndual(m_fgs)) m_returnValue = RefGA.Multivector.Undual(tmpFAI[0].MultivectorValue[0], m_M); // round value if required by metric if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14); // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // unit(gmv) = gmv else { m_smv = tmpFAI[0].Type as G25.SMV; // get symbolic result m_grade0Value = tmpFAI[0].MultivectorValue[0].ExtractGrade(0); m_grade2Value = tmpFAI[0].MultivectorValue[0].ExtractGrade(2); RefGA.Multivector reverseGrade2Value = RefGA.Multivector.Reverse(m_grade2Value); m_grade2norm2Value = RefGA.Multivector.gp(reverseGrade2Value, m_grade2Value, m_M); m_returnValue = RefGA.Multivector.gp(m_grade2Value, new RefGA.Multivector(mulName)); // where mulName = atan2(sqrt(grade2norm2), grade0) / sqrt(grade2norm2) // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } m_returnType = m_specification.GetType(m_fgs.m_returnTypeName); }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { m_gradeIdx = GetGradeIdx(m_fgs.Name); // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new string[] { m_gmv.Name }; // supplement the extra 'int' argument if ((m_gradeIdx < 0) && (m_fgs.ArgumentTypeNames.Length == 1)) { m_fgs.m_argumentTypeNames = new string[] { m_fgs.ArgumentTypeNames[0], G25.GroupBitmapType.GROUP_BITMAP }; m_fgs.m_argumentVariableNames = new string[] { m_fgs.m_argumentVariableNames[0], "groupBitmap" }; } // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); m_smv = tmpFAI[0].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // grade(gmv) = gmv else { // compute return value m_returnValue = tmpFAI[0].MultivectorValue[0].ExtractGrade(m_gradeIdx); // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_trueGmvFunc = (!tmpFAI[0].IsScalarOrSMV()) && (!tmpFAI[1].IsScalarOrSMV()); m_arg1isGmv = !tmpFAI[0].IsScalarOrSMV(); m_arg2isGmv = !tmpFAI[1].IsScalarOrSMV(); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name;// gmv * gmv = gmv else { // compute return value m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[1].MultivectorValue[0]); m_n2Value = RefGA.Multivector.gp(m_reverseValue, tmpFAI[1].MultivectorValue[0], m_M); if (m_G25M.m_round) m_n2Value = m_n2Value.Round(1e-14); //m_returnValue = RefGA.Multivector.gp(RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M), // RefGA.Symbolic.ScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName)))); m_returnValue = RefGA.Multivector.gp(tmpFAI[0].MultivectorValue[0], m_reverseValue, m_M); // round value if required by metric if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14); // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { m_ipType = GetIpType(m_specification, m_fgs); // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) { if (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT) { m_fgs.m_returnTypeName = m_gmv.Name;// gmv * gmv = gmv } else { m_fgs.ReturnTypeName = FT.type; } } else { // compute return value m_returnValue = RefGA.Multivector.ip(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M, m_ipType); // round value if required by metric if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14); // get name of return type if ((m_fgs.ReturnTypeName.Length == 0) && (m_ipType != RefGA.BasisBlade.InnerProductType.SCALAR_PRODUCT)) { m_fgs.ReturnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } else { m_fgs.ReturnTypeName = FT.type; } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, FT.type }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // div(gmv, scalar) = gmv else { m_smv = tmpFAI[0].Type as G25.SMV; RefGA.Multivector inputValue = tmpFAI[0].MultivectorValue[0]; RefGA.Multivector divValue = RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(tmpFAI[1].Name)); m_returnValue = RefGA.Multivector.gp(inputValue, divValue); // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !(tmpFAI[0].IsScalarOrSMV() && tmpFAI[1].IsScalarOrSMV()); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // gmv * gmv = gmv else { // compute return value if (IsInverse(m_fgs)) { m_returnValue = RefGA.Multivector.ihp(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]); } else { m_returnValue = RefGA.Multivector.hp(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0]); } bool getReturnType = (m_fgs.m_returnTypeName.Length == 0); // get name of return type if (getReturnType) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); // This code corrects the result for the signs of the basis blade, and loops until the return type converges. // The reason for this code is that the hadamard product is not well-defined when the basis blades of the operands and the result do not match. while (true) { G25.VariableType returnType = m_specification.GetType(m_fgs.m_returnTypeName); if (returnType is G25.SMV) { G25.SMV returnSMV = returnType as G25.SMV; RefGA.Multivector unitReturnSmv = returnSMV.ToMultivectorValue(); RefGA.Multivector correctedReturnValue = RefGA.Multivector.ihp(m_returnValue, unitReturnSmv); if (getReturnType) { string newReturnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); if (newReturnTypeName == m_fgs.m_returnTypeName) { m_returnValue = correctedReturnValue; break; } else m_fgs.m_returnTypeName = newReturnTypeName; } else { m_returnValue = correctedReturnValue; break; } } else break; } } }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name, m_fgs.FloatNames[0] }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_fgs.ReturnTypeName = IntegerType.INTEGER; m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); m_smv = tmpFAI[0].Type as G25.SMV; }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // dual(gmv) = gmv else { m_smv = tmpFAI[0].Type as G25.SMV; // get symbolic result m_reverseValue = RefGA.Multivector.Reverse(tmpFAI[0].MultivectorValue[0]); m_n2Value = RefGA.Multivector.gp(m_reverseValue, tmpFAI[0].MultivectorValue[0], m_M); if (m_G25M.m_round) m_n2Value = m_n2Value.Round(1e-14); if (m_n2Value.HasSymbolicScalars() || (!m_n2Value.IsScalar()) || m_n2Value.IsZero()) { m_inverseValue = RefGA.Multivector.gp(m_reverseValue, RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(new RefGA.BasisBlade(0, 1.0, m_normSquaredName)))); } else { m_inverseValue = RefGA.Multivector.gp(m_reverseValue, new RefGA.Multivector(1.0 / m_n2Value.RealScalarPart())); m_n2Value = null; } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_inverseValue).GetName(); } m_returnType = m_specification.GetType(m_fgs.m_returnTypeName); }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// /// As the return type is required, many functions will also compute the return value and other info /// needed for generating the code inside this function. These intermediate values are then /// stored in class variables so they can be reused in WriteFunction() /// </summary> public override void CompleteFGS() { NB_ARGS = m_fgs.NbArguments; // all arguments must be explicitly listed // in C language, all arguments are pointers if (m_fgs.ArgumentPtr.Length == 0) { bool ptr = m_specification.OutputC(); m_fgs.m_argumentPtr = new bool[] { ptr, ptr }; m_fgs.m_argumentArr = new bool[] { false, false }; } // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_smv1 = tmpFAI[0].Type as G25.SMV; m_smv2 = tmpFAI[1].Type as G25.SMV; { // compute return value // compute symbolic distance squared value m_returnValue = RefGA.Multivector.gp( RefGA.Multivector.ScalarProduct(tmpFAI[0].MultivectorValue[0], tmpFAI[1].MultivectorValue[0], m_M), -2.0); // apply sqrt(fabs()) if distance should not be squared: if (IsDistance(m_fgs)) m_returnValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(RefGA.Symbolic.UnaryScalarOp.Abs(m_returnValue)); // round value if required by metric if (m_G25M.m_round) m_returnValue = m_returnValue.Round(1e-14); } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); }
/// <summary> /// If this FunctionGenerator can implement 'F', then this function should complete the (possible) /// blanks in 'F'. This means: /// - Fill in F.m_returnTypeName if it is empty /// - Fill in F.m_argumentTypeNames (and m_argumentVariableNames) if it is empty. /// </summary> public override void CompleteFGS() { // fill in ArgumentTypeNames if (m_fgs.ArgumentTypeNames.Length == 0) m_fgs.m_argumentTypeNames = new String[] { m_gmv.Name }; // init argument pointers from the completed typenames (language sensitive); m_fgs.InitArgumentPtrFromTypeNames(m_specification); // get all function info FloatType FT = m_specification.GetFloatType(m_fgs.FloatNames[0]); bool computeMultivectorValue = true; G25.CG.Shared.FuncArgInfo[] tmpFAI = G25.CG.Shared.FuncArgInfo.GetAllFuncArgInfo(m_specification, m_fgs, NB_ARGS, FT, m_specification.m_GMV.Name, computeMultivectorValue); m_gmvFunc = !tmpFAI[0].IsScalarOrSMV(); // compute intermediate results, set return type if (m_gmvFunc) m_fgs.m_returnTypeName = m_gmv.Name; // unit(gmv) = gmv else { m_smv = tmpFAI[0].Type as G25.SMV; // get symbolic result RefGA.Multivector value = tmpFAI[0].MultivectorValue[0]; RefGA.Multivector reverseValue = RefGA.Multivector.Reverse(value); RefGA.Multivector n2Value = RefGA.Multivector.gp(reverseValue, value, m_M); m_nValue = n2Value; if (!m_M.IsPositiveDefinite()) m_nValue = RefGA.Symbolic.UnaryScalarOp.Abs(m_nValue); m_nValue = RefGA.Symbolic.UnaryScalarOp.Sqrt(m_nValue); // round value if required by metric if (m_G25M.m_round) m_nValue = m_nValue.Round(1e-14); try // try to m_nValue = evaluate(m_nValue) { m_nValue = m_nValue.SymbolicEval(new RefGA.Symbolic.HashtableSymbolicEvaluator()); } catch (ArgumentException) { } if (m_nValue.HasSymbolicScalars() || (!m_nValue.IsScalar()) || m_nValue.IsZero()) { RefGA.Multivector inverseNValue = RefGA.Symbolic.UnaryScalarOp.Inverse(new RefGA.Multivector(normName)); m_returnValue = RefGA.Multivector.gp(value, inverseNValue); } else { // no extra step required m_returnValue = RefGA.Multivector.gp(value, new RefGA.Multivector(1.0 / m_nValue.RealScalarPart())); m_nValue = null; } // get name of return type if (m_fgs.m_returnTypeName.Length == 0) m_fgs.m_returnTypeName = G25.CG.Shared.SpecializedReturnType.GetReturnType(m_specification, m_cgd, m_fgs, FT, m_returnValue).GetName(); } m_returnType = m_specification.GetType(m_fgs.m_returnTypeName); }