private static void ParseOperatorAttributes(Specification S, string elementName, XmlAttributeCollection A) { int nbArgs = (elementName == XML_UNARY_OPERATOR) ? 1 : 2; String symbol = ""; String function = ""; bool prefix = true; bool prefixAttributeSpecified = false; for (int i = 0; i < A.Count; i++) { switch (A[i].Name) { case XML_PREFIX: prefix = (A[i].Value.ToLower() == XML_TRUE); prefixAttributeSpecified = true; break; case XML_FUNCTION: function = A[i].Value; break; case XML_SYMBOL: symbol = A[i].Value; break; default: throw new G25.UserException("XML parsing error: Unknown attribute '" + A[i].Name + "' in specification."); } } if ((nbArgs != 1) && prefixAttributeSpecified) throw new G25.UserException("Prefix specified for operator '" + symbol + "' bound to '" + function + "' (todo: improve this error message)."); S.AddOperator(new Operator(nbArgs, prefix, symbol, function)); }
/// <summary> /// Throws an exception when the same basis blade is listed twice, or /// when a basis blade is not contained in the algebra space. /// </summary> /// <param name="S">Specification of the algebra.</param> /// <param name="bvNames">Names of all basis vectors (used for converting basis blades to strings when throwing the exception).</param> public virtual void SanityCheck(Specification S, String[] bvNames) { int spaceDim = S.m_dimension; bool[] present = new bool[1 << spaceDim]; for (int i = 0; i < m_basisBlades.Length; i++) { for (int j = 0; j < m_basisBlades[i].Length; j++) { if (m_basisBlades[i][j].bitmap > (1 << spaceDim)) throw new Exception("MV.SanityCheck: basis blade is not contained within the space of the algebra"); if (present[m_basisBlades[i][j].bitmap]) throw new G25.UserException("Basis blade '" + m_basisBlades[i][j].ToString(bvNames) + "' is listed more than once in multivector type " + Name + "."); present[m_basisBlades[i][j].bitmap] = true; } } }
/// <summary> /// Returns the language identifier of non-constant coordinate 'nonConstCoordIdx'. Depending /// on 'CS', the may be a string like "c[1]" or a string like "e1_e2"; /// </summary> /// <param name="nonConstCoordIdx">index of the coordinate (counting only variable coordinates)</param> /// <param name="S">The specification (only S.m_coordStorage and S.m_basisVectorNames are used).</param> /// <param name="CS">The way coordinates are stored (VARIABLES or ARRAY).</param> /// <returns>the language identifier of non-constant coordinate 'nonConstCoordIdx'.</returns> public virtual String GetCoordLangID(int nonConstCoordIdx, Specification S, COORD_STORAGE CS) { // todo: make adjustment for SMVOM here (or make this function virtual) if (CS == COORD_STORAGE.ARRAY) { string coordArrayName = "c"; return coordArrayName + "[" + nonConstCoordIdx + "]"; } else return NonConstBasisBlade(nonConstCoordIdx).ToLangString(S.m_basisVectorNames); }
/// <summary> /// Returns the language identifier of non-constant coordinate 'nonConstCoordIdx'. /// This is approximately "m" + m_gradeOM + "[" + (m_columnOM + nonConstCoordIdx * domainSize + "]"; /// </summary> /// <param name="nonConstCoordIdx">index of the coordinate (counting only variable coordinates)</param> /// <param name="S">The specification (only S.m_coordStorage and S.m_basisVectorNames are used).</param> /// <param name="CS">The way coordinates are stored (VARIABLES or ARRAY).</param> /// <returns>the language identifier of non-constant coordinate 'nonConstCoordIdx'.</returns> public override String GetCoordLangID(int nonConstCoordIdx, Specification S, COORD_STORAGE CS) { return "m" + m_gradeOM + "[" + m_parentOM.getCoordinateIndex(m_gradeOM, m_columnOM, nonConstCoordIdx) + // (m_columnOM + m_parentOM.DomainForGrade(m_gradeOM).Length * nonConstCoordIdx) + "]"; }
public static bool CanConvertSumToGmv(Specification S, SMV smv1, SMV smv2) { if (S.m_GMV.MemoryAllocationMethod == GMV.MEM_ALLOC_METHOD.PARITY_PURE) return (smv1.IsEven() && smv2.IsEven()) || (smv1.IsOdd() && smv2.IsOdd()); else return true; }
/// <summary> /// Determines whether this fgs is a converter. To be a converted, the name /// of the function should start with and underscore (<c>_</c>) and the remaining /// part of the name should be a specialized multivector typename. /// </summary> /// <returns>true if this fgs is a converter (underscore constructor).</returns> public bool IsConverter(Specification S) { if (ArgumentTypeNames.Length != 1) return false; else if ((Name.Length > 0) && (Name[0] == '_')) return (S.IsSpecializedMultivectorName(Name.Substring(1))); else return false; }
/// <summary> /// Determines whether this fgs is a converter with source 'type'/'FT'. /// </summary> public bool IsConverterSource(Specification S, G25.SMV smv, FloatType FT) { if (!IsConverter(S)) return false; if (!ArgumentTypeNames[0].Equals(smv.GetName())) return false; foreach (string floatName in FloatNames) { if (floatName.Equals(FT.type)) return true; } return false; }
/// <summary> /// Initializes an empty Specification from an XML document /// </summary> public static void InitFromXmlDocument(Specification S, XmlDocument doc) { XmlElement rootElement = doc.DocumentElement; //System.Console.WriteLine(rootElement.Name); if (rootElement.Name != XML_G25_SPEC) throw new G25.UserException("Missing root element " + XML_G25_SPEC + " in XML file."); ParseRootElement(S, rootElement); // initializes the RefGA.Metric variables of the m_metrics S.FinishMetric(); // check if specification is sane S.CheckSpecificationSanity(); }
public static void ParseFunction(Specification S, XmlElement E) { // storage for all info: String functionName = null; String outputFunctionName = null; const int MAX_NB_ARGS = 100; String returnTypeName = ""; String[] argumentTypeNames = new String[MAX_NB_ARGS]; String[] argumentVariableName = new String[MAX_NB_ARGS]; List<String> floatNames = new List<string>(); String metricName = "default"; String comment = ""; int nbArgs = 0; Dictionary<String, String> options = new Dictionary<string, string>(); { // handle attributes XmlAttributeCollection A = E.Attributes; // handle all attributes for (int i = 0; i < A.Count; i++) { // functionName if (A[i].Name == XML_NAME) functionName = A[i].Value; // functionName else if (A[i].Name == XML_OUTPUT_NAME) outputFunctionName = A[i].Value; // metricName else if (A[i].Name == XML_METRIC) metricName = A[i].Value.ToLower(); // comment else if (A[i].Name == XML_COMMENT) comment = A[i].Value; // floatType else if (A[i].Name == XML_FLOAT_TYPE) floatNames.Add(A[i].Value); // return type else if (A[i].Name == XML_RETURN_TYPE) { returnTypeName = A[i].Value; if (!S.IsTypeName(returnTypeName)) { if (returnTypeName.ToLower() == XML_SCALAR) // "scalar" is also allowed as returntype { returnTypeName = XML_SCALAR; } else throw new G25.UserException("Error parsing function '" + functionName + "': '" + returnTypeName + "' is not a type (inside element '" + XML_FUNCTION + "')."); } } // argNameX else if (A[i].Name.StartsWith(XML_ARGNAME)) { int argNameIdx = 0; try { argNameIdx = System.Int32.Parse(A[i].Name.Substring(XML_ARGNAME.Length)) - 1; } catch (System.Exception) { throw new G25.UserException("Error parsing function '" + functionName + "': invalid attribute '" + A[i].Name + "' in element '" + XML_FUNCTION + "'."); } if ((argNameIdx >= argumentVariableName.Length) || (argNameIdx < 0)) throw new G25.UserException("Error parsing function '" + functionName + "': invalid attribute index '" + A[i].Name + "' in element '" + XML_FUNCTION + "'."); argumentVariableName[argNameIdx] = A[i].Value; } // argX else if (A[i].Name.StartsWith(XML_ARG)) { int argIdx = 0; try { argIdx = System.Int32.Parse(A[i].Name.Substring(XML_ARG.Length)) - 1; } catch (System.Exception) { throw new G25.UserException("Error parsing function '" + functionName + "': invalid attribute '" + A[i].Name + "' in element '" + XML_FUNCTION + "'."); } if ((argIdx >= argumentTypeNames.Length) || (argIdx < 0)) throw new G25.UserException("Error parsing function '" + functionName + "': invalid attribute index '" + A[i].Name + "' in element '" + XML_FUNCTION + "'."); string typeName = A[i].Value; if (!S.IsTypeName(typeName)) { // it may be a constant, like 'e1', try adding a "_t" if (S.IsTypeName(typeName + Specification.CONSTANT_TYPE_SUFFIX)) { typeName = typeName + Specification.CONSTANT_TYPE_SUFFIX; } else throw new G25.UserException("Error parsing function '" + functionName + "': '" + typeName + "' is not a type (inside element '" + XML_FUNCTION + "')"); } argumentTypeNames[argIdx] = typeName; if (argIdx >= nbArgs) nbArgs = argIdx + 1; } else if (A[i].Name.StartsWith(XML_OPTION)) { String optionName = A[i].Name.Substring(XML_OPTION.Length).ToLower(); if (optionName.Length > 0) { String optionValue = A[i].Value; options[optionName] = optionValue; } } } // check if function name was specified: if (functionName == null) throw new G25.UserException("Missing attribute '" + XML_NAME + "' in element '" + XML_FUNCTION + "'"); // if output function name is missing, just use the regular function name if (outputFunctionName == null) outputFunctionName = functionName; // if no float type are specified, copy all from specification if (floatNames.Count == 0) { foreach (FloatType FT in S.m_floatTypes) floatNames.Add(FT.type); } // resize arguments arrays: Array.Resize(ref argumentTypeNames, nbArgs); Array.Resize(ref argumentVariableName, nbArgs); // check for nulls in argument arrays for (int i = 0; i < argumentTypeNames.Length; i++) { if (argumentTypeNames[i] == null) throw new G25.UserException("XML parsing error in function '" + functionName + "': Missing attribute '" + XML_ARG + (1 + i).ToString() + "' in element '" + XML_FUNCTION + "'"); if (argumentVariableName[i] == null) argumentVariableName[i] = fgs.DefaultArgumentName(i); } } fgs F = new fgs(functionName, outputFunctionName, returnTypeName, argumentTypeNames, argumentVariableName, floatNames.ToArray(), metricName, comment, options); S.m_functions.Add(F); }
private static void ParseSOMelementAndAttributes(Specification S, XmlElement E) { bool specialized = true; SOM som = ParseOMelementAndAttributes(S, E, specialized) as SOM; if (S.IsTypeName(som.Name)) throw new G25.UserException("In specialized outermorphism definition: a type '" + som.Name + "' already exists."); S.AddSpecializedOM(som); }
/// <summary> /// Converts a G25.fgs to an XML string representation. /// </summary> /// <param name="S"></param> /// <param name="F"></param> /// <returns>XML string representation of 'F'.</returns> public static string FunctionToXmlString(Specification S, G25.fgs F) { StringBuilder SB = new StringBuilder(); SB.Append("<" + XML_FUNCTION); // name SB.Append(" " + XML_NAME + "=\"" + F.Name + "\""); // output name, if different if (F.Name != F.OutputName) SB.Append(" " + XML_OUTPUT_NAME + "=\"" + F.OutputName + "\""); // return type, if set if (F.ReturnTypeName.Length > 0) SB.Append(" " + XML_RETURN_TYPE + "=\"" + F.ReturnTypeName + "\""); // argument types, names for (int a = 0; a < F.NbArguments; a++) { string argTypeName = F.ArgumentTypeNames[a]; if (argTypeName.EndsWith(Specification.CONSTANT_TYPE_SUFFIX)) // check if it is a constant { G25.SMV smv = S.GetType(argTypeName) as G25.SMV; if ((smv != null) && smv.IsConstant()) { // if constant, remove the "_t" from the typename argTypeName = argTypeName.Substring(0, argTypeName.Length - Specification.CONSTANT_TYPE_SUFFIX.Length); } } SB.Append(" " + XML_ARG + (a + 1).ToString() + "=\"" + F.ArgumentTypeNames[a] + "\""); if (F.ArgumentVariableNames[a] != fgs.DefaultArgumentName(a)) SB.Append(" " + XML_ARGNAME + (a + 1).ToString() + "=\"" + F.ArgumentVariableNames[a] + "\""); } // options { foreach (KeyValuePair<String, String> KVP in F.Options) { SB.Append(" " + XML_OPTION + KVP.Key + "=\"" + KVP.Value + "\""); } } // float names, if not all float names of algebra are used: if (!F.UsesAllFloatTypes(S.m_floatTypes)) { for (int f = 0; f < F.NbFloatNames; f++) { SB.Append(" " + XML_FLOAT_TYPE + "=\"" + F.FloatNames[f] + "\""); } } // metric name, if not default if (F.MetricName != "default") SB.Append(" " + XML_METRIC + "=\"" + F.MetricName + "\""); // metric name, if not default if (F.Comment.Length > 0) SB.Append(" " + XML_COMMENT + "=\"" + F.Comment + "\""); SB.Append("/>"); return SB.ToString(); }
/// <summary> /// Parses an XML_SMV element and stores the result. /// /// The XML_SMV element should contain the name, and optionally the type, const property and constant name. /// /// If the const property is true and no name is specified, the regular name is used as the name /// of the singleton constant and the name of the type is renamed to name_t. /// /// </summary> /// <param name="E">XML_SMV element</param> private static void ParseSMVelementAndAttributes(Specification S, XmlElement E) { string typeName = null; bool isConstant = false; string constantName = null; SMV.MULTIVECTOR_TYPE mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR; { // handle attributes XmlAttributeCollection A = E.Attributes; // handle all attributes for (int i = 0; i < A.Count; i++) { // name if (A[i].Name == XML_NAME) typeName = A[i].Value; // const else if (A[i].Name == XML_CONST) isConstant = (A[i].Value.ToLower() == XML_TRUE); // type else if (A[i].Name == XML_TYPE) { if (A[i].Value == XML_MULTIVECTOR) mvType = SMV.MULTIVECTOR_TYPE.MULTIVECTOR; else if (A[i].Value == XML_BLADE) mvType = SMV.MULTIVECTOR_TYPE.BLADE; else if (A[i].Value == XML_ROTOR) mvType = SMV.MULTIVECTOR_TYPE.ROTOR; else if (A[i].Value == XML_VERSOR) mvType = SMV.MULTIVECTOR_TYPE.VERSOR; else throw new G25.UserException("XML parsing error: Invalid value for attribute'" + XML_TYPE + "':'" + A[i].Value + "' in element '" + XML_SMV + "'."); } } // sanity check on name if (typeName == null) throw new G25.UserException("XML parsing error: Missing '" + XML_NAME + "' attribute in element '" + XML_SMV + "'."); // if constant and no constantName provided, use the typeName as the constantName, and set typeName to typeName + "_t" if (isConstant && (constantName == null)) { // if a constant should be generated and no constant name is specified constantName = typeName; typeName = constantName + Specification.CONSTANT_TYPE_SUFFIX; } // check if name is already present if (S.IsTypeName(typeName)) throw new G25.UserException("In specialized multivector definition: type '" + typeName + "' already exists."); } // end of 'handle attributes' // parse list of basis blades and optional comment List<G25.rsbbp.BasisBlade> L = ParseBasisBladeList(S, E.FirstChild, typeName); string comment = ParseComment(S, E.FirstChild); if (L == null) throw new G25.UserException("XML parsing error in element '" + XML_SMV + "': Missing basis blade list for specialized multivector '" + typeName + "'"); SMV smv = new SMV(typeName, L.ToArray(), mvType, comment); // add new type to list of specialized multivectors S.AddSpecializedMV(smv); // if constant name is specified, the user wants a constant: if (constantName != null) S.AddConstant(new ConstantSMV(constantName, smv, null, comment)); }
/// <summary> /// Parses the attributes of the XML_G25_SPEC root element /// </summary> private static void ParseRootElementAttributes(Specification S, XmlAttributeCollection A) { // parse all attributes of the root element for (int i = 0; i < A.Count; i++) { switch (A[i].Name) { case XML_LICENSE: S.SetLicense(A[i].Value); break; case XML_COPYRIGHT: S.m_copyright = A[i].Value; break; case XML_LANGUAGE: S.SetLanguage(A[i].Value); break; case XML_NAMESPACE: S.m_namespace = A[i].Value; break; case XML_COORD_STORAGE: if (A[i].Value == XML_ARRAY) S.m_coordStorage = COORD_STORAGE.ARRAY; else if (A[i].Value == XML_VARIABLES) S.m_coordStorage = COORD_STORAGE.VARIABLES; else throw new G25.UserException("XML parsing error: Unknown attribute value '" + A[i].Value + "' for attribute '" + XML_COORD_STORAGE + "'."); break; case XML_DEFAULT_OPERATOR_BINDINGS: if (A[i].Value.ToLower() == XML_TRUE) S.SetDefaultOperatorBindings(); break; case XML_DIMENSION: int dim; try { dim = System.Int32.Parse(A[i].Value); } catch (System.Exception) { throw new G25.UserException("Invalid dimension for space of algebra: '" + A[i].Value + "'."); } S.SetDimension(dim); break; case XML_REPORT_USAGE: S.m_reportUsage = (A[i].Value.ToLower() == XML_TRUE); break; case XML_GMV_CODE: if (A[i].Value.ToLower() == XML_RUNTIME) S.m_gmvCodeGeneration = GMV_CODE.RUNTIME; else if (A[i].Value.ToLower() == XML_EXPAND) S.m_gmvCodeGeneration = GMV_CODE.EXPAND; else throw new G25.UserException("Invalid value '" + A[i].Value + "' for attribute '" + XML_GMV_CODE + "'."); break; case XML_PARSER: if (A[i].Value.ToLower() == XML_NONE) S.m_parserType = PARSER.NONE; else if (A[i].Value.ToLower() == XML_ANTLR) S.m_parserType = PARSER.ANTLR; else if (A[i].Value.ToLower() == XML_BUILTIN) S.m_parserType = PARSER.BUILTIN; else throw new G25.UserException("Invalid value '" + A[i].Value + "' for attribute '" + XML_PARSER + "'."); break; case XML_TEST_SUITE: S.m_generateTestSuite = (A[i].Value.ToLower() == XML_TRUE); break; default: throw new G25.UserException("XML parsing error: Unknown XML attribute '" + A[i].Name + "' in root element '" + XML_G25_SPEC + "'."); } } }
private static void ParseRootElement(Specification S, XmlElement rootElement) { ParseRootElementAttributes(S, rootElement.Attributes); XmlNode _E = rootElement.FirstChild; while (_E != null) { XmlElement E = _E as XmlElement; if (E != null) { switch (E.Name) { case XML_CUSTOM_LICENSE: { if (S.m_license != XML_CUSTOM) throw new G25.UserException("License was not set to '" + XML_CUSTOM + "' but there still is a '" + XML_CUSTOM_LICENSE + "' in the specification"); XmlText T = E.FirstChild as XmlText; if (T != null) S.m_license = T.Value; } break; case XML_OUTPUT_DIRECTORY: S.SetOutputDir(E.GetAttribute(XML_PATH)); break; case XML_OUTPUT_FILENAME: S.SetOutputFilename(E.GetAttribute(XML_DEFAULT_NAME), E.GetAttribute(XML_CUSTOM_NAME)); break; case XML_INLINE: ParseInlineAttributes(S, E.Attributes); break; case XML_FLOAT_TYPE: ParseFloatTypeAttributes(S, E.Attributes); break; case XML_UNARY_OPERATOR: case XML_BINARY_OPERATOR: ParseOperatorAttributes(S, E.Name, E.Attributes); break; case XML_BASIS_VECTOR_NAMES: ParseBasisVectorNamesAttributes(S, E.Attributes); break; case XML_METRIC: { // name string name = E.GetAttribute(XML_NAME); if (name == null) name = "default"; // parse actual metric: XmlText T = E.FirstChild as XmlText; if (T == null) throw new G25.UserException("Invalid '" + XML_METRIC + "' element in specification."); ParseMetric(S, name, T.Value); // round? if (E.GetAttribute(XML_ROUND) != null) { S.GetMetric(name).m_round = !(E.GetAttribute(XML_ROUND).ToLower() == XML_FALSE); } } break; case XML_MV: ParseMVelementAndAttributes(S, E); break; case XML_SMV: ParseSMVelementAndAttributes(S, E); break; case XML_OM: ParseGOMelementAndAttributes(S, E); break; case XML_SOM: ParseSOMelementAndAttributes(S, E); break; case XML_CONSTANT: ParseConstantElementAndAttributes(S, E); break; case XML_FUNCTION: ParseFunction(S, E); break; case XML_VERBATIM: ParseVerbatim(S, E); break; default: System.Console.WriteLine("Specification.ParseRootElement(): warning: unknown element '" + E.Name + "' in specification"); break; } } _E = _E.NextSibling; } }
/// <summary> /// Returns the whether argument 'argIdx' is a pointer. /// If not filled in, 'false' is returned. /// </summary> /// <param name="S">Specification.</param> /// <param name="argIdx">Index of argument.</param> /// <returns>name of argument 'argIdx'.</returns> public bool GetArgumentPtr(Specification S, int argIdx) { if (argIdx < 0) return (S.OutputC()) ? true : false; else if (NbArguments == 0) return false; else return ArgumentPtr[argIdx]; }
public static void ParseVerbatim(Specification S, XmlElement E) { List<string> filenames = new List<string>(); VerbatimCode.POSITION where = VerbatimCode.POSITION.INVALID; string customMarker = null; string verbatimCode = null; string verbatimCodeFile = null; { // handle attributes XmlAttributeCollection A = E.Attributes; // handle all attributes for (int i = 0; i < A.Count; i++) { // filename if (A[i].Name.StartsWith(XML.XML_FILENAME)) { filenames.Add(A[i].Value); } // position else if (A[i].Name == XML.XML_POSITION) { if (A[i].Value == XML.XML_TOP) where = VerbatimCode.POSITION.TOP; else if (A[i].Value == XML.XML_BOTTOM) where = VerbatimCode.POSITION.BOTTOM; else if (A[i].Value == XML.XML_BEFORE_MARKER) where = VerbatimCode.POSITION.BEFORE_MARKER; else if (A[i].Value == XML.XML_AFTER_MARKER) where = VerbatimCode.POSITION.AFTER_MARKER; else throw new G25.UserException("Invalid " + XML.XML_POSITION + " '" + A[i].Value + "' in element '" + XML.XML_VERBATIM + "'."); } // marker else if (A[i].Name == XML.XML_MARKER) { customMarker = A[i].Value; } // codeFilename else if (A[i].Name == XML.XML_CODE_FILENAME) { if (A[i].Value.Length > 0) verbatimCodeFile = A[i].Value; } else throw new G25.UserException("Invalid attribute '" + A[i].Name + "' in element '" + XML.XML_VERBATIM + "'."); } { // get verbatim code from _inside_ the element: XmlText T = E.FirstChild as XmlText; if ((T != null) && (T.Length > 0)) verbatimCode = T.Value; } // check if function name was specified: if (filenames.Count == 0) throw new G25.UserException("Missing attribute '" + XML.XML_FILENAME + "' in element '" + XML.XML_VERBATIM + "'"); if (where == VerbatimCode.POSITION.INVALID) throw new G25.UserException("Missing attribute '" + XML.XML_POSITION + "' in element '" + XML.XML_VERBATIM + "'"); if (((where == VerbatimCode.POSITION.BEFORE_MARKER) || (where == VerbatimCode.POSITION.AFTER_MARKER)) && (customMarker == null)) { throw new G25.UserException("Missing attribute '" + XML.XML_MARKER + "' in element '" + XML.XML_VERBATIM + "'"); } if ((verbatimCode == null) && (verbatimCodeFile == null)) throw new G25.UserException("Missing/empty verbatim code or verbatim code filename in element '" + XML.XML_VERBATIM + "'"); } // end of 'handle attributes' S.m_verbatimCode.Add(new VerbatimCode(filenames, where, customMarker, verbatimCode, verbatimCodeFile)); }
/// <summary> /// Initializes <c>m_argumentPtr</c> automatically from the <c>m_argumentTypeNames</c>. /// The length of the <c>m_argumentPtr</c> array is adjusted to match <c>m_argumentTypeNames</c>. /// Existing values are not changed. The other values are set in a language-dependent way. /// (currently only for 'C' language). /// /// Does nothing when <c>m_argumentTypeNames</c> is null. /// </summary> /// <param name="S">Used for <c>m_outputLanguage</c> and the types.</param> public void InitArgumentPtrFromTypeNames(Specification S) { if (m_argumentTypeNames == null) return; int i = (m_argumentPtr == null) ? 0 : m_argumentPtr.Length; if (i != m_argumentTypeNames.Length) {// resize the array System.Array.Resize<bool>(ref m_argumentPtr, m_argumentTypeNames.Length); System.Array.Resize<bool>(ref m_argumentArr, m_argumentTypeNames.Length); } if (S.OutputC()) { // if it is not a float or a double, then it is a pointer for (; i < m_argumentTypeNames.Length; i++) { //m_argumentPtr[i] = !(S.IsFloatType(m_argumentTypeNames[i]); m_argumentPtr[i] = S.IsGaTypeName(m_argumentTypeNames[i]); } } }
/// <summary> /// Converts a G25.SMV to an XML string representation. /// </summary> /// <param name="S"></param> /// <param name="smv"></param> /// <returns>XML string representation of 'smv'.</returns> public static string SMVtoXmlString(Specification S, G25.SMV smv) { StringBuilder SB = new StringBuilder(); bool constant = smv.IsConstant() && (S.GetMatchingConstant(smv) != null); string name = smv.Name; // remove the extra constant suffix? if (constant && name.EndsWith(Specification.CONSTANT_TYPE_SUFFIX)) name = name.Substring(0, name.Length - Specification.CONSTANT_TYPE_SUFFIX.Length); SB.Append("<" + XML_SMV); // name SB.Append(" " + XML_NAME + "=\"" + name + "\""); // constant? if (constant) SB.Append(" " + XML_CONST + "=\"" + XML_TRUE + "\""); // type SB.Append(" " + XML_TYPE + "=\"" + smv.MvTypeString + "\""); // end of XML_SMV tag SB.Append(">"); { // emit coordinate order: string[] bvNames = (string[])S.m_basisVectorNames.ToArray(); // loop over all basis blades for (int b = 0; b < smv.Group(0).Length; b++) { if (b > 0) SB.Append(" "); string bbStr = BasisBladeToString(smv.BasisBlade(0, b), bvNames); SB.Append(bbStr); // if constant, add '=....' if (smv.IsCoordinateConstant(b)) SB.Append("=" + smv.ConstBasisBladeValue(smv.BladeIdxToConstBladeIdx(b)).ToString()); } if (smv.Comment.Length > 0) SB.Append(" <" + XML_COMMENT + ">" + smv.Comment + "</" + XML_COMMENT + ">"); } SB.Append("</" + XML_SMV + ">\n"); return SB.ToString(); }
/// <summary> /// Determines whether this fgs is a converter for destination 'type'/'FT'. /// </summary> public bool IsConverterDestination(Specification S, G25.SMV smv, FloatType FT) { if (!IsConverter(S)) return false; if (!Name.Equals("_" + smv.GetName())) return false; foreach (string floatName in FloatNames) { if (floatName.Equals(FT.type)) return true; } return false; }
/// <summary> /// Converts this specification to XML (that can be parsed by the constructor) /// </summary> /// <returns>An XML string that can be parsed by the constructor</returns> public static string ToXmlString(Specification S) { StringBuilder SB = new StringBuilder(); SB.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"); SB.AppendLine(""); // empty line SB.Append("<" + XML_G25_SPEC + "\n"); bool customLicense = false; // used later on to know whether to emit full license text { // output attributes of g25spec element { // license string licString = S.m_license; if (licString == Licenses.GPL_LICENSE) licString = XML_GPL; else if (licString == Licenses.BSD_LICENSE) licString = XML_BSD; else { licString = XML_CUSTOM; customLicense = true; } SB.Append("\t" + XML_LICENSE + "=\"" + licString + "\"\n"); } { // copyright if ((S.m_copyright != null) && (S.m_copyright.Length > 0)) SB.Append("\t" + XML_COPYRIGHT + "=\"" + S.m_copyright + "\"\n"); } { // language SB.Append("\t" + XML_LANGUAGE + "=\"" + S.GetOutputLanguageString() + "\"\n"); } // namespace if ((S.m_namespace != null) && (S.m_namespace.Length > 0)) SB.Append("\t" + XML_NAMESPACE + "=\"" + S.m_namespace + "\"\n"); // coordinate storage SB.Append("\t" + XML_COORD_STORAGE + "=\"" + ((S.m_coordStorage == COORD_STORAGE.ARRAY) ? XML_ARRAY : XML_VARIABLES) + "\"\n"); // operator bindings SB.Append("\t" + XML_DEFAULT_OPERATOR_BINDINGS + "=\"" + (S.DefaultOperatorBindings() ? XML_TRUE : XML_FALSE) + "\"\n"); // dimension SB.Append("\t" + XML_DIMENSION + "=\"" + S.m_dimension.ToString() + "\"\n"); // report usage of non-optimized functions SB.Append("\t" + XML_REPORT_USAGE + "=\"" + (S.m_reportUsage ? XML_TRUE : XML_FALSE) + "\"\n"); { // what type of GMV code to generate: SB.Append("\t" + XML_GMV_CODE + "=\""); switch (S.m_gmvCodeGeneration) { case GMV_CODE.EXPAND: SB.Append(XML_EXPAND); break; case GMV_CODE.RUNTIME: SB.Append(XML_RUNTIME); break; default: SB.Append("BAD GMV CODE OPTION"); break; } SB.Append("\"\n"); } { // what type of parser to generate: SB.Append("\t" + XML_PARSER + "=\""); switch (S.m_parserType) { case PARSER.NONE: SB.Append(XML_NONE); break; case PARSER.ANTLR: SB.Append(XML_ANTLR); break; case PARSER.BUILTIN: SB.Append(XML_BUILTIN); break; default: SB.Append("BAD PARSER OPTION"); break; } SB.Append("\"\n"); } // generate test suite SB.Append("\t" + XML_TEST_SUITE + "=\"" + (S.m_generateTestSuite ? XML_TRUE : XML_FALSE) + "\"\n"); } SB.Append("\t>\n"); // end of <g25spec> entry SB.AppendLine(""); // empty line if (customLicense) // output custom license SB.Append("<" + XML_CUSTOM_LICENSE + ">" + S.m_license + "</" + XML_CUSTOM_LICENSE + ">\n"); if (S.m_verbatimCode.Count > 0) // output verbatim code { foreach (VerbatimCode VC in S.m_verbatimCode) { // determine if code is in XML or in file: bool hasCode = ((VC.m_verbatimCode != null) && (VC.m_verbatimCode.Length > 0)); // open XML tag SB.Append("<" + XML_VERBATIM); // output all filenames to which verbatim code should be applied for (int f = 0; f < VC.m_filenames.Count; f++) { SB.Append(" " + XML_FILENAME); if (f > 0) SB.Append((f + 1).ToString()); SB.Append("=\"" + VC.m_filenames[f] + "\""); } // output the filename where verbatim code comes from if ((VC.m_verbatimCodeFile != null) && (VC.m_verbatimCodeFile.Length > 0)) SB.Append(" " + XML_CODE_FILENAME + "=\"" + VC.m_verbatimCodeFile + "\""); // output position SB.Append(" " + XML_POSITION + "="); switch (VC.m_where) { case VerbatimCode.POSITION.TOP: SB.Append("\"" + XML_TOP + "\""); break; case VerbatimCode.POSITION.BOTTOM: SB.Append("\"" + XML_BOTTOM + "\""); break; case VerbatimCode.POSITION.BEFORE_MARKER: SB.Append("\"" + XML_BEFORE_MARKER + "\""); break; case VerbatimCode.POSITION.AFTER_MARKER: SB.Append("\"" + XML_AFTER_MARKER + "\""); break; } if ((VC.m_where == VerbatimCode.POSITION.BEFORE_MARKER) || (VC.m_where == VerbatimCode.POSITION.AFTER_MARKER)) { SB.Append(" " + XML_MARKER + "=\"" + VC.m_customMarker + "\""); } // output verbatim code that goes into XML, if present if (hasCode) { SB.Append(">" + VC.m_verbatimCode + "</" + XML_VERBATIM + ">\n"); } else SB.Append("/>\n"); } } if (S.m_outputDirectoryExplicitlySet) // output dir SB.Append("<" + XML_OUTPUT_DIRECTORY + " " + XML_PATH + "=\"" + S.m_outputDirectory + "\"/>\n"); { // overrides foreach (KeyValuePair<string, string> kvp in S.m_outputFilenameOverrides) { SB.Append("<" + XML_OUTPUT_FILENAME + " " + XML_DEFAULT_NAME + "=\"" + kvp.Key + "\" " + XML_CUSTOM_NAME + "=\"" + kvp.Value + "\"/>\n"); } } SB.AppendLine(""); // empty line { // inline SB.Append("<" + XML_INLINE + "\n"); SB.Append("\t" + XML_CONSTRUCTORS + "=\"" + ((S.m_inlineConstructors) ? XML_TRUE : XML_FALSE) + "\"\n"); SB.Append("\t" + XML_SET + "=\"" + ((S.m_inlineSet) ? XML_TRUE : XML_FALSE) + "\"\n"); SB.Append("\t" + XML_ASSIGN + "=\"" + ((S.m_inlineAssign) ? XML_TRUE : XML_FALSE) + "\"\n"); SB.Append("\t" + XML_OPERATORS + "=\"" + ((S.m_inlineOperators) ? XML_TRUE : XML_FALSE) + "\"\n"); SB.Append("\t" + XML_FUNCTIONS + "=\"" + ((S.m_inlineFunctions) ? XML_TRUE : XML_FALSE) + "\"\n"); SB.Append("\t/>\n"); // end of <inline> entry } SB.AppendLine(""); // empty line { // float types foreach (FloatType FT in S.m_floatTypes) { SB.Append("<" + XML_FLOAT_TYPE + " " + XML_TYPE + "=\"" + FT.type + "\""); if (FT.prefix.Length > 0) SB.Append(" " + XML_PREFIX + "=\"" + FT.prefix + "\""); if (FT.suffix.Length > 0) SB.Append(" " + XML_SUFFIX + "=\"" + FT.suffix + "\""); SB.Append("/>\n"); // end of <floatType> entry } } SB.AppendLine(""); // empty line { // basis vector names SB.Append("<" + XML_BASIS_VECTOR_NAMES); for (int i = 0; i < S.m_basisVectorNames.Count; i++) SB.Append("\n\t" + XML_NAME + (i + 1).ToString() + "=\"" + S.m_basisVectorNames[i] + "\""); SB.Append("\n\t/>\n"); // end of <basisVectorNames> entry } SB.AppendLine(""); // empty line { // metric // printed out in order of basisvectors foreach (Metric M in S.m_metric) { if (M.m_name == Specification.INTERNAL_EUCLIDEAN_METRIC) continue; // do not emit auto-generated metric to XML for (int v1 = 0; v1 < S.m_dimension; v1++) for (int v2 = 0; v2 < S.m_dimension; v2++) for (int i = 0; i < M.m_metricBasisVectorIdx1.Count; i++) if ((v1 == M.m_metricBasisVectorIdx1[i]) && (v2 == M.m_metricBasisVectorIdx2[i])) { SB.Append("<" + XML_METRIC + " " + XML_NAME + "=\"" + M.m_name + "\""); if (!M.m_round) // default = true, so only print when false SB.Append(" " + XML_ROUND + "=\"" + XML_FALSE + "\""); SB.Append(">"); SB.Append(S.m_basisVectorNames[v1] + "." + S.m_basisVectorNames[v2] + "=" + M.m_metricValue[i]); SB.Append("</" + XML_METRIC + ">\n"); } } } SB.AppendLine(""); // empty line // operators foreach (Operator op in S.m_operators) { // first check if this isn't a 'default operator' if (S.m_defaultOperators.Contains(op)) continue; bool unary = (op.NbArguments == 1); string opStr = (unary) ? XML_UNARY_OPERATOR : XML_BINARY_OPERATOR; SB.Append("<" + opStr + " " + XML_SYMBOL + "=\"" + op.Symbol + "\" " + XML_FUNCTION + "=\"" + op.FunctionName + "\""); if (unary && (!op.IsPrefix)) { SB.Append(" " + XML_PREFIX + "=\"" + XML_FALSE + "\""); } SB.Append("/>\n"); } SB.AppendLine(""); // empty line if (S.m_GMV != null) // general multivector: { SB.Append("<" + XML_MV); // name SB.Append(" " + XML_NAME + "=\"" + S.m_GMV.Name + "\""); // compression (by grade, group) bool compressedByGrade = S.m_GMV.IsGroupedByGrade(S.m_dimension); SB.Append(" " + XML_COMPRESS + "=\""); if (compressedByGrade) SB.Append(XML_BY_GRADE + "\""); else SB.Append(XML_BY_GROUP + "\""); // coordinate order bool defaultCoordinateOrder = (compressedByGrade && S.m_GMV.CompareBasisBladeOrder(rsbbp.ListToDoubleArray(S.m_basisBladeParser.GetDefaultBasisBlades()))); SB.Append(" " + XML_COORDINATE_ORDER + "=\""); if (defaultCoordinateOrder) SB.Append(XML_DEFAULT + "\""); else SB.Append(XML_CUSTOM + "\""); // memory allocation method SB.Append(" " + XML_MEM_ALLOC + "=\""); if (S.m_GMV.MemoryAllocationMethod == GMV.MEM_ALLOC_METHOD.PARITY_PURE) SB.Append(XML_PARITY_PURE + "\""); else if (S.m_GMV.MemoryAllocationMethod == GMV.MEM_ALLOC_METHOD.FULL) SB.Append(XML_FULL + "\""); else SB.Append(XML_DYNAMIC + "\""); SB.Append(">\n"); if (!defaultCoordinateOrder) { // emit coordinate order: string[] bvNames = (string[])S.m_basisVectorNames.ToArray(); // loop over all groups: for (int g = 0; g < S.m_GMV.NbGroups; g++) { SB.Append("<" + XML_GROUP + ">"); // loop over all basis blades of group for (int i = 0; i < S.m_GMV.Group(g).Length; i++) { if (i > 0) SB.Append(" "); string bbStr = BasisBladeToString(S.m_GMV.BasisBlade(g, i), bvNames); SB.Append(bbStr); } SB.Append("</" + XML_GROUP + ">\n"); } } SB.Append("</" + XML_MV + ">\n"); } SB.AppendLine(""); // empty line // specialized multivectors for (int i = 0; i < S.m_SMV.Count; i++) { SB.Append(SMVtoXmlString(S, S.m_SMV[i])); } SB.AppendLine(""); // empty line // constants for (int i = 0; i < S.m_constant.Count; i++) { // assume only SMV constants for now ConstantSMV C = S.m_constant[i] as ConstantSMV; if (C == null) continue; // check if type has name X+CONSTANT_TYPE_SUFFIX and is constant if ((C.Type.GetName().Equals(C.Name + Specification.CONSTANT_TYPE_SUFFIX)) && (C.Type as SMV).IsConstant()) continue; SB.Append(ConstantToXmlString(S, C)); } SB.AppendLine(""); // empty line // outermorphisms { // i = -1 = m_GOM, the rest is m_SOM for (int i = -1; i < S.m_SOM.Count; i++) { if (i == 0) SB.AppendLine(""); // empty line OM om = (i == -1) ? S.m_GOM as OM : S.m_SOM[i] as OM; if (om == null) continue; string XMLtag = ((om is GOM) ? XML_OM : XML_SOM); SB.Append("<" + XMLtag); // name SB.Append(" " + XML_NAME + "=\"" + om.Name + "\""); // coordinate order: bool rangeEqualsDomain = om.DomainAndRangeAreEqual(); bool defaultCoordOrder = rangeEqualsDomain && om.CompareDomainOrder(rsbbp.ListToDoubleArray(S.m_basisBladeParser.GetDefaultBasisBlades())); SB.Append(" " + XML_COORDINATE_ORDER + "=\"" + ((defaultCoordOrder) ? XML_DEFAULT : XML_CUSTOM) + "\""); // end of XMLtag SB.Append(">\n"); if (!defaultCoordOrder) { string[] bvNames = (string[])S.m_basisVectorNames.ToArray(); for (int dr = 0; dr < 2; dr++) { string XML_DOMAIN_OR_RANGE = (dr == 0) ? XML_DOMAIN : XML_RANGE; RefGA.BasisBlade[][] B = (dr == 0) ? om.Domain : om.Range; if ((dr == 1) && rangeEqualsDomain) continue; SB.Append("<" + XML_DOMAIN_OR_RANGE + ">"); bool first = true; for (int g = 0; g < B.Length; g++) { for (int b = 0; b < B[g].Length; b++) { if (!first) SB.Append(" "); String bbStr = BasisBladeToString(B[g][b], bvNames); SB.Append(bbStr); first = false; } } SB.Append("</" + XML_DOMAIN_OR_RANGE + ">\n"); } // output domain info if (!rangeEqualsDomain) { // output range info } } SB.Append("</" + XMLtag + ">\n"); } } SB.AppendLine(""); // empty line // function generation specifications for (int i = 0; i < S.m_functions.Count; i++) SB.AppendLine(FunctionToXmlString(S, S.m_functions[i])); SB.AppendLine(""); // empty line SB.Append("</" + XML_G25_SPEC + ">\n"); return SB.ToString(); }
public rsbbp(Specification S) { m_spec = S; InitBasisBladeParser(); }
/// <summary> /// Parses basis blade list of SMVs and constants. /// </summary> /// <returns>List of basis blades, or null if 'F' does not contain such a list.</returns> private static List<G25.rsbbp.BasisBlade> ParseBasisBladeList(Specification S, XmlNode _F, string parentName) { while (_F != null) { XmlText FT = _F as XmlText; // is it text? if (FT != null) { try { return S.m_basisBladeParser.ParseBasisBlades(FT); } catch (Exception Ex) { throw new G25.UserException("While parsing basis blades of '" + parentName + "':\n" + Ex.Message); } } _F = _F.NextSibling; } return null; }
/// <summary> /// Throws an exception when MV.SanityCheck(int spaceDim, String[] bvNames) throws an exception, or when not all basis blades are listed, /// or when blades of different grades are in the same group. /// </summary> /// <param name="S">Specification of the algebra.</param> /// <param name="bvNames">Names of all basis vectors (used for converting basis blades to strings when throwing the exception).</param> public override void SanityCheck(Specification S, String[] bvNames) { base.SanityCheck(S, bvNames); int spaceDim = S.m_dimension; bool[] present = new bool[1 << spaceDim]; for (int i = 0; i < m_basisBlades.Length; i++) { int grade = -1; for (int j = 0; j < m_basisBlades[i].Length; j++) { if (j == 0) grade = m_basisBlades[i][j].Grade(); else if (m_basisBlades[i][j].Grade() != grade) throw new G25.UserException("In the general multivector type " + Name + ":\n"+ "Group " + (i+1) + " contains blades of different grades."); present[m_basisBlades[i][j].bitmap] = true; } } if ((S.OutputC()) && (MemoryAllocationMethod == MEM_ALLOC_METHOD.DYNAMIC)) throw new G25.UserException("Dynamic memory allocation of general multivector type " + Name + " is not supported for the 'C' language."); for (int i = 0; i < (1 << spaceDim); i++) if (!present[i]) throw new G25.UserException("In the general multivector type " + Name + ":\n"+ "Missing basis blade '" + (new RefGA.BasisBlade((uint)i)).ToString(bvNames) + "'."); }
/// <summary> /// Sets all basis vector names to "", then handle XML attributes (nameX = "..") and then checks if all names have been set. /// </summary> private static void ParseBasisVectorNamesAttributes(Specification S, XmlAttributeCollection A) { // reset all names to "" for (int i = 0; i < S.m_basisVectorNames.Count; i++) S.m_basisVectorNames[i] = ""; // handle all attributes for (int i = 0; i < A.Count; i++) { if (!A[i].Name.StartsWith(XML_NAME)) throw new G25.UserException("XML parsing error: Invalid attribute '" + A[i].Name + "' in element '" + XML_BASIS_VECTOR_NAMES + "'."); int idx; try { idx = System.Int32.Parse(A[i].Name.Substring(XML_NAME.Length)) - 1; } catch (System.Exception) { throw new G25.UserException("XML parsing error: Invalid attribute '" + A[i].Name + "' in element '" + XML_BASIS_VECTOR_NAMES + "'."); } S.SetBasisVectorName(idx, A[i].Value); } // check if all have been set S.CheckBasisVectorNames(); }
/// <returns>true when this type can be converted to a general multivector /// This depends on whether this type is parity pure, and parity pure memory allocation is being used for GMV.</returns> public bool CanConvertToGmv(Specification S) { if (S.m_GMV.MemoryAllocationMethod == GMV.MEM_ALLOC_METHOD.PARITY_PURE) return IsParityPure(); else return true; }
/// <summary> /// Parses a comment for SMVs and constants. /// </summary> /// <returns>Comment string, or null if 'F' does not contain a comment.</returns> private static string ParseComment(Specification S, XmlNode _F) { while (_F != null) { // or comment? XmlElement FE = _F as XmlElement; if ((FE != null) && (FE.Name == XML_COMMENT)) { XmlText CT = FE.FirstChild as XmlText; return CT.Value; } _F = _F.NextSibling; } return null; }
/// <summary> /// Returns the language identifier of non-constant coordinate 'nonConstCoordIdx'. Depending /// on the specification, the may be a string like "c[1]" or a string like "e1_e2"; /// </summary> /// <param name="nonConstCoordIdx">index of the coordinate (counting only variable coordinates)</param> /// <param name="S">The specification (only S.m_coordStorage and S.m_basisVectorNames are used).</param> /// <returns>the language identifier of non-constant coordinate 'nonConstCoordIdx'.</returns> public string GetCoordLangID(int nonConstCoordIdx, Specification S) { return GetCoordLangID(nonConstCoordIdx, S, S.m_coordStorage); }
/// <summary> /// Returns the whether argument 'argIdx' is an array. /// If not filled in, 'false' is returned. /// </summary> /// <param name="S">Specification.</param> /// <param name="argIdx">Index of argument.</param> /// <returns>name of argument 'argIdx'.</returns> public bool GetArgumentArr(Specification S, int argIdx) { if (argIdx < 0) return false; else if (NbArguments == 0) return false; else return ArgumentArr[argIdx]; }
/// <summary> /// Throws an exception when MV.SanityCheck(int spaceDim, String[] bvNames) throws an exception. /// </summary> /// <param name="S">Specification of the algebra.</param> /// <param name="bvNames">Names of all basis vectors (used for converting basis blades to strings when throwing the exception).</param> public override void SanityCheck(Specification S, String[] bvNames) { base.SanityCheck(S, bvNames); // complain when a converter to GMV cannot be written if (!CanConvertToGmv(S)) { System.Console.WriteLine("Warning: the type"); System.Console.WriteLine(ToString()); System.Console.WriteLine("is not parity pure. The general multivector uses parity pure memory allocation, so " + Name + " type cannot be converted to a general multivector."); System.Console.WriteLine(""); } }
/// <summary> /// Converts a G25.Constant to an XML string representation. /// </summary> /// <param name="C"></param> /// <param name="S"></param> /// <returns>XML string representation of 'smv'.</returns> public static string ConstantToXmlString(Specification S, G25.Constant C) { StringBuilder SB = new StringBuilder(); SB.Append("<" + XML_CONSTANT); // name SB.Append(" " + XML_NAME + "=\"" + C.Name + "\""); // type SB.Append(" " + XML_TYPE + "=\"" + C.Type.GetName() + "\""); // end of XML_CONSTANT tag SB.Append(">"); { // emit value (assuming only SMV constants, for now) SMV smv = C.Type as SMV; ConstantSMV Csmv = C as ConstantSMV; string[] bvNames = (string[])S.m_basisVectorNames.ToArray(); for (int b = 0; b < smv.NbNonConstBasisBlade; b++) { RefGA.BasisBlade B = smv.NonConstBasisBlade(b); String basisBladeString = BasisBladeToString(B, bvNames); if (b > 0) SB.Append(" "); SB.Append(basisBladeString); SB.Append("=" + Csmv.Value[b]); } if (C.Comment.Length > 0) SB.Append(" <" + XML_COMMENT + ">" + C.Comment + "</" + XML_COMMENT + ">"); } SB.Append("</" + XML_CONSTANT + ">\n"); return SB.ToString(); }