+/** Function object to be applied by basic::evalm(). */
+struct evalm_map_function : public map_function {
+ ex operator()(const ex & e) { return evalm(e); }
+} map_evalm;
+
+/** Evaluate sums, products and integer powers of matrices. */
+ex basic::evalm() const
+{
+ if (nops() == 0)
+ return *this;
+ else
+ return map(map_evalm);
+}
+
+/** Function object to be applied by basic::eval_integ(). */
+struct eval_integ_map_function : public map_function {
+ ex operator()(const ex & e) { return eval_integ(e); }
+} map_eval_integ;
+
+/** Evaluate integrals, if result is known. */
+ex basic::eval_integ() const
+{
+ if (nops() == 0)
+ return *this;
+ else
+ return map(map_eval_integ);
+}
+
+/** Perform automatic symbolic evaluations on indexed expression that
+ * contains this object as the base expression. */
+ex basic::eval_indexed(const basic & i) const
+ // this function can't take a "const ex & i" because that would result
+ // in an infinite eval() loop
+{
+ // There is nothing to do for basic objects
+ return i.hold();
+}
+
+/** Add two indexed expressions. They are guaranteed to be of class indexed
+ * (or a subclass) and their indices are compatible. This function is used
+ * internally by simplify_indexed().
+ *
+ * @param self First indexed expression; its base object is *this
+ * @param other Second indexed expression
+ * @return sum of self and other
+ * @see ex::simplify_indexed() */
+ex basic::add_indexed(const ex & self, const ex & other) const
+{
+ return self + other;
+}
+
+/** Multiply an indexed expression with a scalar. This function is used
+ * internally by simplify_indexed().
+ *
+ * @param self Indexed expression; its base object is *this
+ * @param other Numeric value
+ * @return product of self and other
+ * @see ex::simplify_indexed() */
+ex basic::scalar_mul_indexed(const ex & self, const numeric & other) const
+{
+ return self * other;
+}
+
+/** Try to contract two indexed expressions that appear in the same product.
+ * If a contraction exists, the function overwrites one or both of the
+ * expressions and returns true. Otherwise it returns false. It is
+ * guaranteed that both expressions are of class indexed (or a subclass)
+ * and that at least one dummy index has been found. This functions is
+ * used internally by simplify_indexed().
+ *
+ * @param self Pointer to first indexed expression; its base object is *this
+ * @param other Pointer to second indexed expression
+ * @param v The complete vector of factors
+ * @return true if the contraction was successful, false otherwise
+ * @see ex::simplify_indexed() */
+bool basic::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
+{
+ // Do nothing
+ return false;
+}
+
+/** 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;
+ }
+}
+
+/** 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;
+}
+
+/** Substitute a set of objects by arbitrary expressions. The ex returned
+ * will already be evaluated. */
+ex basic::subs(const exmap & m, unsigned options) const
+{
+ size_t num = nops();
+ if (num) {
+
+ // Substitute in subexpressions
+ for (size_t i=0; i<num; i++) {
+ const ex & orig_op = op(i);
+ const ex & subsed_op = orig_op.subs(m, options);
+ if (!are_ex_trivially_equal(orig_op, subsed_op)) {
+
+ // Something changed, clone the object
+ basic *copy = duplicate();
+ copy->setflag(status_flags::dynallocated);
+ copy->clearflag(status_flags::hash_calculated | status_flags::expanded);
+
+ // Substitute the changed operand
+ copy->let_op(i++) = subsed_op;
+
+ // Substitute the other operands
+ for (; i<num; i++)
+ copy->let_op(i) = op(i).subs(m, options);
+
+ // Perform substitutions on the new object as a whole
+ return copy->subs_one_level(m, options);
+ }
+ }
+ }
+
+ // Nothing changed or no subexpressions
+ return subs_one_level(m, options);
+}
+
+/** 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() const
+{
+ return exvector(); // return an empty exvector
+}
+
+ex basic::conjugate() const
+{
+ return *this;
+}
+
+ex basic::real_part() const