expr symbol_::subs(const exmap &m) const { exmap::const_iterator it = m.find( this ), en = m.end(); if( it != en ) return it->second; return this; }
expr basic::subs_once(const exmap &map) const { auto end = map.cend(); auto it = map.find( this ); if( it != end ) return it->second.subs( map ); match_state s; for( it = map.begin(); it != end; ++it ) if( match( it->first, s ) ) { exmap m; s.as_exmap( m ); return it->second.subs( m ); } return this->eval(2); }
/** Helper function for subs(). Does not recurse into subexpressions. */ ex basic::subs_one_level(const exmap & m, unsigned options) const { exmap::const_iterator it; if (options & subs_options::no_pattern) { ex thisex = *this; it = m.find(thisex); if (it != m.end()) return it->second; return thisex; } else { for (it = m.begin(); it != m.end(); ++it) { exmap repl_lst; if (match(ex_to<basic>(it->first), repl_lst)) return it->second.subs(repl_lst, options | subs_options::no_pattern); // avoid infinite recursion when re-substituting the wildcards } } return *this; }
/** Check whether the expression matches a given pattern. For every wildcard * object in the pattern, a pair with the wildcard as a key and matching * expression as a value is added to repl_lst. */ bool basic::match(const ex & pattern, exmap& repl_lst) const { /* Sweet sweet shapes, sweet sweet shapes, That's the key thing, right right. Feed feed face, feed feed shapes, But who is the king tonight? Who is the king tonight? Pattern is the thing, the key thing-a-ling, But who is the king of Pattern? But who is the king, the king thing-a-ling, Who is the king of Pattern? Bog is the king, the king thing-a-ling, Bog is the king of Pattern. Ba bu-bu-bu-bu bu-bu-bu-bu-bu-bu bu-bu Bog is the king of Pattern. */ if (is_exactly_a<wildcard>(pattern)) { // Wildcard matches anything, but check whether we already have found // a match for that wildcard first (if so, the earlier match must be // the same expression) for (exmap::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) { if (it->first.is_equal(pattern)) return is_equal(ex_to<basic>(it->second)); } repl_lst[pattern] = *this; return true; } else { // Expression must be of the same type as the pattern if (typeid(*this) != typeid(ex_to<basic>(pattern))) return false; // Number of subexpressions must match if (nops() != pattern.nops()) return false; // No subexpressions? Then just compare the objects (there can't be // wildcards in the pattern) if (nops() == 0) return is_equal_same_type(ex_to<basic>(pattern)); // Check whether attributes that are not subexpressions match 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. exmap 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), tmp_repl)) return false; // Looks similar enough, match found repl_lst = tmp_repl; return true; } }