From: Christian Bauer Date: Fri, 25 May 2001 20:51:35 +0000 (+0000) Subject: - removed debugging code in match() X-Git-Tag: release_0-9-0~37 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=commitdiff_plain;h=df5f8db62815995d87ebd4f97a5dbc0d1a327b94;p=ginac.git - removed debugging code in match() - added ex::match(const ex & pattern) which doesn't take a list as second argument - expairseq::subs() substitutes in recombined pairs when the pattern is a product or a power; this is necessary for things like subs(2*x^2,x^2==3) because the first expression is mul(,2) and only substituting in the "rest" part of the expair is not enough --- diff --git a/ginac/basic.cpp b/ginac/basic.cpp index c899d19f..90b9c145 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -213,10 +213,10 @@ ex basic::operator[](int i) const return op(i); } -/** Search ocurrences. An object 'has' an expression if it is the expression +/** Search ocurrences. An object 'has' an expression if it is the expression * itself or one of the children 'has' it. As a consequence (according to * the definition of children) given e=x+y+z, e.has(x) is true but e.has(x+y) - * is false. */ + * is false. The expression can also contain wildcards. */ bool basic::has(const ex & other) const { GINAC_ASSERT(other.bp!=0); @@ -405,7 +405,22 @@ bool basic::contract_with(exvector::iterator self, exvector::iterator other, exv * is added to repl_lst. */ bool basic::match(const ex & pattern, lst & repl_lst) const { -//clog << "match " << *this << " with " << pattern << ", repl_lst = " << repl_lst << endl; +/* + Sweet sweet shapes, sweet sweet shapes, + Thats the key thing, right right. + Feed feed face, feed feed shapes, + But who is the king tonight? + Who is the king tonight? + Pattern is the thing, the key thing-a-ling, + But who is the king of pattern? + But who is the king, the king thing-a-ling, + Who is the king of Pattern? + Bog is the king, the king thing-a-ling, + Bog is the king of Pattern. + Ba bu-bu-bu-bu bu-bu-bu-bu-bu-bu bu-bu + Bog is the king of Pattern. +*/ + if (is_ex_exactly_of_type(pattern, wildcard)) { // Wildcard matches anything, but check whether we already have found @@ -458,7 +473,7 @@ ex basic::subs(const lst & ls, const lst & lr, bool no_pattern) const for (unsigned i=0; isubs(repl_lst, true); // avoid recursion when re-substituting the wildcards + return lr.op(i).bp->subs(repl_lst, true); // avoid infinite recursion when re-substituting the wildcards } } diff --git a/ginac/ex.cpp b/ginac/ex.cpp index 02d20e88..e8ce2da1 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -31,6 +31,7 @@ #include "power.h" #include "relational.h" #include "indexed.h" +#include "lst.h" #include "input_lexer.h" #include "debugmsg.h" #include "utils.h" @@ -136,6 +137,13 @@ ex ex::diff(const symbol & s, unsigned nth) const return bp->diff(s, nth); } +/** Check whether expression matches a specified pattern. */ +bool ex::match(const ex & pattern) const +{ + lst repl_lst; + return bp->match(pattern, repl_lst); +} + /** Simplify/canonicalize expression containing indexed objects. This * performs contraction of dummy indices where possible and checks whether * the free indices in sums are consistent. diff --git a/ginac/ex.h b/ginac/ex.h index 1449b635..34ce8b8c 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -105,6 +105,7 @@ public: ex evalf(int level = 0) const { return bp->evalf(level); } ex diff(const symbol & s, unsigned nth = 1) const; ex series(const ex & r, int order, unsigned options = 0) const; + bool match(const ex & pattern) const; bool match(const ex & pattern, lst & repl_lst) const { return bp->match(pattern, repl_lst); } ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const { return bp->subs(ls, lr, no_pattern); } ex subs(const ex & e, bool no_pattern = false) const { return bp->subs(e, no_pattern); } diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 2d9a8f6b..9421570a 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -324,7 +324,6 @@ ex expairseq::normal(lst &sym_lst, lst &repl_lst, int level) const bool expairseq::match(const ex & pattern, lst & repl_lst) const { -//clog << "match " << *this << " with " << pattern << ", repl_lst = " << repl_lst << endl; // This differs from basic::match() because we want "a+b+c+d" to // match "d+*+b" with "*" being "a+c", and we want to honor commutativity @@ -1659,47 +1658,89 @@ epvector expairseq::diffchildren(const symbol &y) const /** Member-wise substitute in this sequence. * * @see expairseq::subs() - * @return pointer to epvector containing pairs after application of subs or zero - * pointer, if no members were changed. */ + * @return pointer to epvector containing pairs after application of subs, + * or NULL pointer if no members were changed. */ epvector * expairseq::subschildren(const lst &ls, const lst &lr, bool no_pattern) const { - // returns a NULL pointer if nothing had to be substituted - // returns a pointer to a newly created epvector otherwise - // (which has to be deleted somewhere else) GINAC_ASSERT(ls.nops()==lr.nops()); - - epvector::const_iterator last = seq.end(); - epvector::const_iterator cit = seq.begin(); - while (cit!=last) { - const ex &subsed_ex=(*cit).rest.subs(ls,lr,no_pattern); - if (!are_ex_trivially_equal((*cit).rest,subsed_ex)) { + + // The substitution is "complex" when any of the objects to be substituted + // is a product or power. In this case we have to recombine the pairs + // because the numeric coefficients may be part of the search pattern. + bool complex_subs = false; + for (unsigned i=0; ireserve(seq.size()); + + // Copy parts of seq which are known not to have changed + s->insert(s->begin(), seq.begin(), cit); + + // Copy first changed element + s->push_back(split_ex_to_pair(subsed_ex)); + ++cit; + + // Copy rest + while (cit != last) { + s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit).subs(ls, lr, no_pattern))); + ++cit; + } + return s; + } + + ++cit; + } + + } else { + + // Substitute only in the "rest" part of the pairs + epvector::const_iterator cit = seq.begin(), last = seq.end(); + while (cit != last) { + + const ex &subsed_ex = cit->rest.subs(ls, lr, no_pattern); + if (!are_ex_trivially_equal(cit->rest, subsed_ex)) { - // something changed, copy seq, subs and return it - epvector *s = new epvector; - s->reserve(seq.size()); + // Something changed, copy seq, subs and return it + epvector *s = new epvector; + s->reserve(seq.size()); + + // Copy parts of seq which are known not to have changed + s->insert(s->begin(), seq.begin(), cit); - // copy parts of seq which are known not to have changed - epvector::const_iterator cit2 = seq.begin(); - while (cit2!=cit) { - s->push_back(*cit2); - ++cit2; - } - // copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, - (*cit2).coeff)); - ++cit2; - // copy rest - while (cit2!=last) { - s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.subs(ls,lr,no_pattern), - (*cit2).coeff)); - ++cit2; + // Copy first changed element + s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, cit->coeff)); + ++cit; + + // Copy rest + while (cit != last) { + s->push_back(combine_ex_with_coeff_to_pair(cit->rest.subs(ls, lr, no_pattern), + cit->coeff)); + ++cit; + } + return s; } - return s; + + ++cit; } - ++cit; } - return 0; // signalling nothing has changed + // Nothing has changed + return NULL; } ////////// diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 117a02b2..7088c5bd 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -305,17 +305,45 @@ int spinidx::compare_same_type(const basic & other) const GINAC_ASSERT(is_of_type(other, spinidx)); const spinidx &o = static_cast(other); + // Check dottedness first so dummy indices will end up next to each other + if (dotted != o.dotted) + return dotted ? -1 : 1; + int cmpval = inherited::compare_same_type(other); if (cmpval) return cmpval; - // Check variance and dottedness last so dummy indices will end up next to each other + return 0; +} + +bool idx::match(const ex & pattern, lst & repl_lst) const +{ + if (!is_ex_of_type(pattern, idx)) + return false; + const idx &o = ex_to_idx(pattern); + if (!dim.is_equal(o.dim)) + return false; + return value.match(o.value, repl_lst); +} + +bool varidx::match(const ex & pattern, lst & repl_lst) const +{ + if (!is_ex_of_type(pattern, varidx)) + return false; + const varidx &o = ex_to_varidx(pattern); if (covariant != o.covariant) - return covariant ? -1 : 1; - if (dotted != o.dotted) - return dotted ? -1 : 1; + return false; + return inherited::match(pattern, repl_lst); +} - return 0; +bool spinidx::match(const ex & pattern, lst & repl_lst) const +{ + if (!is_ex_of_type(pattern, spinidx)) + return false; + const spinidx &o = ex_to_spinidx(pattern); + if (dotted != o.dotted) + return false; + return inherited::match(pattern, repl_lst); } ex idx::subs(const lst & ls, const lst & lr, bool no_pattern) const diff --git a/ginac/idx.h b/ginac/idx.h index 02caba5a..8f952b84 100644 --- a/ginac/idx.h +++ b/ginac/idx.h @@ -51,7 +51,7 @@ public: bool info(unsigned inf) const; unsigned nops() const; ex & let_op(int i); -protected: + bool match(const ex & pattern, lst & repl_lst) const; ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const; // new virtual functions in this class @@ -105,6 +105,7 @@ public: // functions overriding virtual functions from bases classes public: void print(const print_context & c, unsigned level = 0) const; + bool match(const ex & pattern, lst & repl_lst) const; bool is_dummy_pair_same_type(const basic & other) const; // non-virtual functions in this class @@ -147,6 +148,7 @@ public: // functions overriding virtual functions from bases classes public: void print(const print_context & c, unsigned level = 0) const; + bool match(const ex & pattern, lst & repl_lst) const; bool is_dummy_pair_same_type(const basic & other) const; // non-virtual functions in this class