As of now the match() method modifies the list of matched subexpressions (its second argument) even if the expression in question does not match the pattern. Thus, this simple program #include <iostream> #include <ginac/ginac.h> using namespace GiNaC; int main(int argc, char** argv) { symbol x; ex e = pow(x, 5); ex pattern = pow(wild(), -1); lst repl; bool test = e.match(pattern, repl); std::cout << "repl = " << repl << std::endl; } prints repl = {x} Such behaviour is a bit unexpected. Sometimes it confuses even GiNaC developers, see e.g. http://www.ginac.de/pipermail/ginac-devel/2006-April/000942.html Hence this patch. Now the above program prints repl = {} as expected. --- doc/tutorial/ginac.texi | 5 +---- ginac/basic.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 555b2d6..05fdca4 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -4420,10 +4420,7 @@ This function returns @code{true} when the expression matches the pattern and @code{false} if it doesn't. If used in the second form, the actual subexpressions matched by the wildcards get returned in the @code{repls} object as a list of relations of the form @samp{wildcard == expression}. -If @code{match()} returns false, the state of @code{repls} is undefined. -For reproducible results, the list should be empty when passed to -@code{match()}, but it is also possible to find similarities in multiple -expressions by passing in the result of a previous match. +If @code{match()} returns false, @code{repls} remains unmodified. The matching algorithm works as follows: diff --git a/ginac/basic.cpp b/ginac/basic.cpp index a3de04a..7a0633d 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -585,12 +585,18 @@ bool basic::match(const ex & pattern, lst & repl_lst) const if (!match_same_type(ex_to<basic>(pattern))) return false; + // 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. + lst tmp_repl = repl_lst; // Otherwise the subexpressions must match one-to-one for (size_t i=0; i<nops(); i++) - if (!op(i).match(pattern.op(i), repl_lst)) + if (!op(i).match(pattern.op(i), tmp_repl)) return false; // Looks similar enough, match found + repl_lst = tmp_repl; return true; } } -- 1.5.6 -- All science is either physics or stamp collecting.