X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=blobdiff_plain;ds=sidebyside;f=ginac%2Fbasic.cpp;h=fa6e1d9679be426b90bd75acfee56c8babb4835b;hb=b573b0146341709649f373e0fc5c0d440877ebaf;hp=a3de04aab9cd306eda820e8d7b50dadc492f3164;hpb=67467d256b44f5e08498ca81c946d9ffaa25d1e2;p=ginac.git diff --git a/ginac/basic.cpp b/ginac/basic.cpp index a3de04aa..fa6e1d96 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -22,9 +22,7 @@ #include #include -#ifdef DO_GINAC_ASSERT -# include -#endif +#include #include "basic.h" #include "ex.h" @@ -65,7 +63,7 @@ basic::basic(const basic & other) : tinfo_key(other.tinfo_key), flags(other.flag const basic & basic::operator=(const basic & other) { unsigned fl = other.flags & ~status_flags::dynallocated; - if (tinfo_key != other.tinfo_key) { + if (typeid(*this) != typeid(other)) { // The other object is of a derived class, so clear the flags as they // might no longer apply (especially hash_calculated). Oh, and don't // copy the tinfo_key: it is already set correctly for this object. @@ -290,7 +288,7 @@ ex & basic::operator[](size_t i) * but e.has(x+y) is false. */ bool basic::has(const ex & pattern, unsigned options) const { - lst repl_lst; + exmap repl_lst; if (match(pattern, repl_lst)) return true; for (size_t i=0; iop(0).is_equal(pattern)) - return is_equal(ex_to(it->op(1))); + for (exmap::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) { + if (it->first.is_equal(pattern)) + return is_equal(ex_to(it->second)); } - repl_lst.append(pattern == *this); + repl_lst[pattern] = *this; return true; } else { // Expression must be of the same type as the pattern - if (tinfo() != ex_to(pattern).tinfo()) + if (typeid(*this) != typeid(ex_to(pattern))) return false; // Number of subexpressions must match @@ -585,12 +583,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. + exmap tmp_repl = repl_lst; // Otherwise the subexpressions must match one-to-one for (size_t i=0; i(it->first), repl_lst)) - return it->second.subs(repl_lst, options | subs_options::no_pattern); // avoid infinite recursion when re-substituting the wildcards + return it->second.subs(repl_lst, options | subs_options::no_pattern); + // avoid infinite recursion when re-substituting the wildcards } } @@ -782,7 +787,8 @@ tinfo_t basic::return_type_tinfo() const * would all end up with the same hashvalue. */ unsigned basic::calchash() const { - unsigned v = golden_ratio_hash((p_int)tinfo()); + const void* this_tinfo = (const void*)typeid(*this).name(); + unsigned v = golden_ratio_hash((p_int)this_tinfo); for (size_t i=0; iop(i).gethash(); @@ -839,10 +845,9 @@ int basic::compare(const basic & other) const compare_statistics.compare_same_hashvalue++; #endif - const tinfo_t typeid_this = tinfo(); - const tinfo_t typeid_other = other.tinfo(); - if (typeid_this==typeid_other) { - GINAC_ASSERT(typeid(*this)==typeid(other)); + const std::type_info& typeid_this = typeid(*this); + const std::type_info& typeid_other = typeid(other); + if (typeid_this == typeid_other) { // int cmpval = compare_same_type(other); // if (cmpval!=0) { // std::cout << "hash collision, same type: " @@ -864,7 +869,7 @@ int basic::compare(const basic & other) const // std::cout << " and "; // other.print(print_tree(std::cout)); // std::cout << std::endl; - return (typeid_thistinfo()!=other.tinfo()) + if (typeid(*this) != typeid(other)) return false; - GINAC_ASSERT(typeid(*this)==typeid(other)); - #ifdef GINAC_COMPARE_STATISTICS compare_statistics.is_equal_same_type++; #endif