X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fexpairseq.cpp;h=b29f3802c13f2be0f0a55977d6b129c00dd2cdad;hp=7c6e5223653889730407aa0fd5a246417cc06f6d;hb=c323cd8d5b0386ffb3d23456d97dfdafec6bbc2c;hpb=bb0f99d6298fccb8cf1421fa0c7463c647f543a7 diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 7c6e5223..b29f3802 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -3,7 +3,7 @@ * Implementation of sequences of expression pairs. */ /* - * GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ #include "utils.h" #include "hash_seed.h" #include "indexed.h" +#include "compiler.h" #include #if EXPAIRSEQ_USE_HASHTAB @@ -394,6 +395,12 @@ bool expairseq::match(const ex & pattern, exmap & repl_lst) const } } + // Even if the expression does not match the pattern, some of + // its subexpressions could match it. For example, x^5*y^(-1) + // does not match the pattern $0^5, but its subexpression x^5 + // does. So, save repl_lst in order to not add bogus entries. + exmap tmp_repl = repl_lst; + // Unfortunately, this is an O(N^2) operation because we can't // sort the pattern in a useful way... @@ -411,7 +418,7 @@ bool expairseq::match(const ex & pattern, exmap & repl_lst) const continue; exvector::iterator it = ops.begin(), itend = ops.end(); while (it != itend) { - if (it->match(p, repl_lst)) { + if (it->match(p, tmp_repl)) { ops.erase(it); goto found; } @@ -432,10 +439,16 @@ found: ; for (size_t i=0; ipush_back(split_ex_to_pair(ops[i])); ex rest = thisexpairseq(vp, default_overall_coeff()); - for (exmap::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) { - if (it->first.is_equal(global_wildcard)) - return rest.is_equal(it->second); + for (exmap::const_iterator it = tmp_repl.begin(); it != tmp_repl.end(); ++it) { + if (it->first.is_equal(global_wildcard)) { + if (rest.is_equal(it->second)) { + repl_lst = tmp_repl; + return true; + } + return false; + } } + repl_lst = tmp_repl; repl_lst[global_wildcard] = rest; return true; @@ -443,7 +456,11 @@ found: ; // No global wildcard, then the match fails if there are any // unmatched terms left - return ops.empty(); + if (ops.empty()) { + repl_lst = tmp_repl; + return true; + } + return false; } } return inherited::match(pattern, repl_lst); @@ -645,7 +662,7 @@ ex expairseq::expand(unsigned options) const * has (at least) two possible different semantics but we want to inherit * methods thus avoiding code duplication. Sometimes a method in expairseq * has to create a new one of the same semantics, which cannot be done by a - * ctor because the name (add, mul,...) is unknown on the expaiseq level. In + * ctor because the name (add, mul,...) is unknown on the expairseq level. In * order for this trick to work a derived class must of course override this * definition. */ ex expairseq::thisexpairseq(const epvector &v, const ex &oc, bool do_index_renaming) const @@ -1508,7 +1525,7 @@ bool expairseq::is_canonical() const return 1; #if EXPAIRSEQ_USE_HASHTAB - if (hashtabsize > 0) return 1; // not canoncalized + if (hashtabsize > 0) return 1; // not canonicalized #endif // EXPAIRSEQ_USE_HASHTAB epvector::const_iterator it = seq.begin(), itend = seq.end(); @@ -1594,7 +1611,7 @@ std::auto_ptr expairseq::evalchildren(int level) const // returns a pointer to a newly created epvector otherwise // (which has to be deleted somewhere else) - if (level==1) + if (likely(level==1)) return std::auto_ptr(0); if (level == -max_recursion_level)