bool match(const ex & pattern, lst & repl_lst) const { return bp->match(pattern, repl_lst); }
// substitutions
- ex subs(const lst & ls, const lst & lr, unsigned options = 0) const { return bp->subs(ls, lr, options); }
- ex subs(const ex & e, unsigned options = 0) const { return bp->subs(e, options); }
+ ex subs(const exmap & m, unsigned options = 0) const;
+ ex subs(const lst & ls, const lst & lr, unsigned options = 0) const;
+ ex subs(const ex & e, unsigned options = 0) const;
// function mapping
ex map(map_function & f) const { return bp->map(f); }
inline bool match(const ex & thisex, const ex & pattern, lst & repl_lst)
{ return thisex.match(pattern, repl_lst); }
-inline ex subs(const ex & thisex, const ex & e, unsigned options = 0)
-{ return thisex.subs(e, options); }
-
-inline ex subs(const ex & thisex, const lst & ls, const lst & lr, unsigned options = 0)
-{ return thisex.subs(ls, lr, options); }
-
inline ex simplify_indexed(const ex & thisex)
{ return thisex.simplify_indexed(); }
void operator() (ex &lh, ex &rh) const { lh.swap(rh); }
};
+inline ex ex::subs(const exmap & m, unsigned options) const
+{
+ return bp->subs(m, options);
+}
+
+inline ex subs(const ex & thisex, const exmap & m, unsigned options = 0)
+{ return thisex.subs(m, options); }
+
+inline ex subs(const ex & thisex, const lst & ls, const lst & lr, unsigned options = 0)
+{ return thisex.subs(ls, lr, options); }
+
+inline ex subs(const ex & thisex, const ex & e, unsigned options = 0)
+{ return thisex.subs(e, options); }
+
/* Convert function pointer to function object suitable for map(). */
class pointer_to_map_function : public map_function {
protected:
ex (*ptr)(const ex &);
public:
- explicit pointer_to_map_function(ex (*x)(const ex &)) : ptr(x) {}
+ explicit pointer_to_map_function(ex x(const ex &)) : ptr(x) {}
ex operator()(const ex & e) { return ptr(e); }
};
ex (*ptr)(const ex &, T1);
T1 arg1;
public:
- explicit pointer_to_map_function_1arg(ex (*x)(const ex &, T1), T1 a1) : ptr(x), arg1(a1) {}
+ explicit pointer_to_map_function_1arg(ex x(const ex &, T1), T1 a1) : ptr(x), arg1(a1) {}
ex operator()(const ex & e) { return ptr(e, arg1); }
};
T1 arg1;
T2 arg2;
public:
- explicit pointer_to_map_function_2args(ex (*x)(const ex &, T1, T2), T1 a1, T2 a2) : ptr(x), arg1(a1), arg2(a2) {}
+ explicit pointer_to_map_function_2args(ex x(const ex &, T1, T2), T1 a1, T2 a2) : ptr(x), arg1(a1), arg2(a2) {}
ex operator()(const ex & e) { return ptr(e, arg1, arg2); }
};
T2 arg2;
T3 arg3;
public:
- explicit pointer_to_map_function_3args(ex (*x)(const ex &, T1, T2, T3), T1 a1, T2 a2, T3 a3) : ptr(x), arg1(a1), arg2(a2), arg3(a3) {}
+ explicit pointer_to_map_function_3args(ex x(const ex &, T1, T2, T3), T1 a1, T2 a2, T3 a3) : ptr(x), arg1(a1), arg2(a2), arg3(a3) {}
ex operator()(const ex & e) { return ptr(e, arg1, arg2, arg3); }
};
-inline ex ex::map(ex (*f)(const ex & e)) const
+inline ex ex::map(ex f(const ex &)) const
{
pointer_to_map_function fcn(f);
return bp->map(fcn);
}
+// convenience type checker template functions
+
+/** Check if ex is a handle to a T, including base classes. */
+template <class T>
+inline bool is_a(const ex &obj)
+{
+ return is_a<T>(*obj.bp);
+}
+
+/** Check if ex is a handle to a T, not including base classes. */
+template <class T>
+inline bool is_exactly_a(const ex &obj)
+{
+ return is_exactly_a<T>(*obj.bp);
+}
+
+/** Return a reference to the basic-derived class T object embedded in an
+ * expression. This is fast but unsafe: the result is undefined if the
+ * expression does not contain a T object at its top level. Hence, you
+ * should generally check the type of e first.
+ *
+ * @param e expression
+ * @return reference to object of class T
+ * @see is_exactly_a<class T>() */
+template <class T>
+inline const T &ex_to(const ex &e)
+{
+ GINAC_ASSERT(is_a<T>(e));
+ return static_cast<const T &>(*e.bp);
+}
} // namespace GiNaC