+/*
+ 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_ex_exactly_of_type(pattern, wildcard)) {
+
+ // Wildcard matches anything, but check whether we already have found
+ // a match for that wildcard first (if so, it the earlier match must
+ // be the same expression)
+ for (unsigned i=0; i<repl_lst.nops(); i++) {
+ if (repl_lst.op(i).op(0).is_equal(pattern))
+ return is_equal(*repl_lst.op(i).op(1).bp);
+ }
+ repl_lst.append(pattern == *this);
+ return true;
+
+ } else {
+
+ // Expression must be of the same type as the pattern
+ if (tinfo() != pattern.bp->tinfo())
+ 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(*pattern.bp);
+
+ // Check whether attributes that are not subexpressions match
+ if (!match_same_type(*pattern.bp))
+ return false;
+
+ // Otherwise the subexpressions must match one-to-one
+ for (unsigned i=0; i<nops(); i++)
+ if (!op(i).match(pattern.op(i), repl_lst))
+ return false;
+
+ // Looks similar enough, match found
+ return true;
+ }
+}
+
+/** Substitute a set of objects by arbitrary expressions. The ex returned
+ * will already be evaluated. */
+ex basic::subs(const lst & ls, const lst & lr, bool no_pattern) const
+{
+ GINAC_ASSERT(ls.nops() == lr.nops());
+
+ if (no_pattern) {
+ for (unsigned i=0; i<ls.nops(); i++) {
+ if (is_equal(*ls.op(i).bp))
+ return lr.op(i);
+ }
+ } else {
+ for (unsigned i=0; i<ls.nops(); i++) {
+ lst repl_lst;
+ if (match(*ls.op(i).bp, repl_lst))
+ return lr.op(i).bp->subs(repl_lst, true); // avoid infinite recursion when re-substituting the wildcards
+ }
+ }
+
+ return *this;
+}
+
+/** Default interface of nth derivative ex::diff(s, n). It should be called
+ * instead of ::derivative(s) for first derivatives and for nth derivatives it
+ * just recurses down.
+ *
+ * @param s symbol to differentiate in
+ * @param nth order of differentiation
+ * @see ex::diff */
+ex basic::diff(const symbol & s, unsigned nth) const
+{
+ // trivial: zeroth derivative
+ if (nth==0)
+ return ex(*this);
+
+ // evaluate unevaluated *this before differentiating
+ if (!(flags & status_flags::evaluated))
+ return ex(*this).diff(s, nth);
+
+ ex ndiff = this->derivative(s);
+ while (!ndiff.is_zero() && // stop differentiating zeros
+ nth>1) {
+ ndiff = ndiff.diff(s);
+ --nth;
+ }
+ return ndiff;
+}
+
+/** Return a vector containing the free indices of an expression. */
+exvector basic::get_free_indices(void) const
+{
+ return exvector(); // return an empty exvector