Fix power::subs() in some special cases.
authorRichard Kreckel <kreckel@ginac.de>
Wed, 23 Mar 2022 20:21:48 +0000 (21:21 +0100)
committerRichard Kreckel <kreckel@ginac.de>
Wed, 23 Mar 2022 20:29:18 +0000 (21:29 +0100)
In some cases, after subs'ing in basis and exponent, an extra
substitution was performed. This could lead to messed-up final results
because, e.g. substituting x==1/x in 1/x evaluated to x, but then
another substitution x==1/x was performed.

Reported by Feng Feng <f.feng@outlook.com>.

check/exam_misc.cpp
ginac/power.cpp

index 3595c9a2e817d9f5aba0b24006b4432a4298ac64..31dc1bad1c6551dec79e32c570d4283b76d1406c 100644 (file)
@@ -192,6 +192,24 @@ static unsigned exam_subs()
                ++result;
        }
 
+       // This used to fail in GiNaC 1.8.2 with subs_options::no_pattern
+       e1 = 1/x;
+       e2 = e1.subs(x == 1/x);
+       if (!e2.is_equal(x)) {
+               clog << "(1/x).subs(x==1/x) erroneously returned " << e2 << " instead of x" << endl;
+               ++result;
+       }
+       e2 = e1.subs(x == 1/x, subs_options::no_pattern);
+       if (!e2.is_equal(x)) {
+               clog << "(1/x).subs(x==1/x, subs_options::no_pattern) erroneously returned " << e2 << " instead of x" << endl;
+               ++result;
+       }
+       e2 = e1.subs(x == 1/x, subs_options::algebraic);
+       if (!e2.is_equal(x)) {
+               clog << "(1/x).subs(x==1/x, subs_options::algebraic) erroneously returned " << e2 << " instead of x" << endl;
+               ++result;
+       }
+
        return result;
 }
 
index 97095b2a2dec1ee0f8d7a4429e6eac734356f724..9019b376d1b52ecfaa791aadc255558a29192005 100644 (file)
@@ -619,7 +619,7 @@ ex power::subs(const exmap & m, unsigned options) const
 
        if (!are_ex_trivially_equal(basis, subsed_basis)
         || !are_ex_trivially_equal(exponent, subsed_exponent)) 
-               return power(subsed_basis, subsed_exponent).subs_one_level(m, options);
+               return dynallocate<power>(subsed_basis, subsed_exponent);
 
        if (!(options & subs_options::algebraic))
                return subs_one_level(m, options);