/// <summary> /// Generates code for returning a scalar value. The input is a scalar-valued multivector. /// </summary> /// <param name="S">Specification (used for output language).</param> /// <param name="FT">Floating point type which must be returned.</param> /// <param name="mustCast">Set to true if the returned value must be cast to <c>FT</c>, that is /// if you are not sure that the multivector has the same float type as the return type <c>FT</c>.</param> /// <param name="value">The symbolic multivector value to be returned.</param> /// <returns>Code for returning a scalar value.</returns> public static string GenerateScalarReturnCode(Specification S, FloatType FT, bool mustCast, RefGA.Multivector value) { if (value.IsZero()) { return "return " + FT.DoubleToString(S, 0.0) + ";"; } else { return "return " + ((mustCast) ? (FT.castStr + "(") : "") + CodeUtil.ScalarToLangString(S, FT, value.BasisBlades[0]) + ((mustCast) ? ")" : "") + ";"; } }
/// <summary> /// Converts scalar part of 'value' to ouput language dependent string. /// </summary> private static string ScalarOpValueToLangString(G25.Specification S, G25.FloatType FT, RefGA.Multivector value) { if (!value.IsScalar()) throw new Exception("G25.CG.Shared.BasisBlade.ScalarOpValueToLangString(): value should be scalar, found: " + value.ToString(S.m_basisVectorNames)); if (value.IsZero()) return ScalarToLangString(S, FT, RefGA.BasisBlade.ZERO); else return ScalarToLangString(S, FT, value.BasisBlades[0]); }
/// <summary> /// This function contains a function to find a tightly matching specialized multivector. /// Given a Multivector 'M', it find the best match which can contain it. /// /// The function tries each SMV in the specification. It rates them as follows: /// -missing variable basis blade: disqualified /// -constant coordinate mismatch: disqualified /// -constant coordinate match: +1 /// -excess variable coordinate : -1 /// /// If the symbolic multivector 'M' has a scalar return type, the function will insist on returning /// a scalar type! It will not (for example) return a rotor. /// </summary> /// <param name="S">Specification of algebra, used for the m_SMV</param> /// <param name="M">The multivector for which a matching SMV is sought.</param> /// <param name="FT">The preferred floating point type (only used when scalar is returned).</param> /// <returns>null when no match found; the selected G25.SMV or G25.FloatType otherwise.</returns> public static G25.VariableType FindTightestMatch(G25.Specification S, RefGA.Multivector M, FloatType FT) { G25.SMV bestSMV = null; const int LOWEST_RATING = -10000000; // rating of good-enough blades _can_ be negative, if they have excess variable coordinates int bestRating = LOWEST_RATING; const double EPSILON = 1e-6; // make this user controllable?? foreach (G25.SMV smv in S.m_SMV) { int rating = 0; int nbConstMatched = 0; // number of elements from M.BasisBlades matched with const coordinates for (int i = 0; i < M.BasisBlades.Length; i++) { // get blade, see if it is constant RefGA.BasisBlade B = M.BasisBlades[i]; bool constant = (B.symScale == null); // if constant, then try constant blades first bool found = false; // set to true when matching basis blade is found if (constant) { // loop over all constant basis blades for (int j = 0; j < smv.NbConstBasisBlade; j++) { // get basis blade, compare bitmaps RefGA.BasisBlade C = smv.ConstBasisBlade(j); if (C.bitmap == B.bitmap) { if (Math.Abs(C.scale - B.scale) / Math.Abs(C.scale) > EPSILON) { rating = LOWEST_RATING; break; // this break the outer loop (over 'i') too } else { rating++; nbConstMatched++; found = true; break; } } } } if (rating == LOWEST_RATING) break; // if no constant basis blade was found, loop over all variable basis blades if (!found) { for (int j = 0; j < smv.NbNonConstBasisBlade; j++) { // get basis blade, compare bitmaps RefGA.BasisBlade C = smv.NonConstBasisBlade(j); if (C.bitmap == B.bitmap) { found = true; break; } } } if (!found) {// if neither constant nor variable basis blade found: no match rating = LOWEST_RATING; break; } } // disqualify 'smv' when it has const coords not present in 'M' if (nbConstMatched < smv.NbConstBasisBlade) rating = LOWEST_RATING; if (rating != LOWEST_RATING) { // adjust rating for excess variable coordinates: int nbNonConstCoords = M.BasisBlades.Length - nbConstMatched; int nbExcess = smv.NbNonConstBasisBlade - nbNonConstCoords; if (nbExcess > 0) rating -= nbExcess; // subtract 1 for each non-const coordinate that is in 'smv' without actually being useful } // keep best SMV so far if (rating > bestRating) { bestRating = rating; bestSMV = smv; } } if ((M.IsZero() || M.IsScalar()) && (bestRating < 0)) return FT; // insist on retuning a scalar type else return bestSMV; }