From 192ed7390b7b2b705ad100e3db0a92eedd2b20ad Mon Sep 17 00:00:00 2001 From: Alexei Sheplyakov Date: Tue, 15 Jul 2008 21:08:22 +0400 Subject: [PATCH] match: don't modify subexpression list if expression doesn't match the pattern. 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 #include 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 eed9fef3..11c67f91 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 a3de04aa..7a0633de 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(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