virtual ex & let_op(int i);
virtual ex operator[](const ex & index) const;
virtual ex operator[](int i) const;
+ virtual ex expand(unsigned options = 0) const;
virtual bool has(const ex & other) const;
virtual ex map(map_function & f) const;
virtual int degree(const ex & s) const;
virtual ex smod(const numeric &xi) const;
virtual numeric max_coefficient(void) const;
virtual exvector get_free_indices(void) const;
- virtual ex simplify_ncmul(const exvector & v) const;
virtual ex eval_indexed(const basic & i) const;
virtual ex add_indexed(const ex & self, const ex & other) const;
virtual ex scalar_mul_indexed(const ex & self, const numeric & other) const;
virtual bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
-protected: // non-const functions should be called from class ex only
+ virtual unsigned return_type(void) const;
+ virtual unsigned return_type_tinfo(void) const;
+protected: // functions that should be called from class ex only
virtual ex derivative(const symbol & s) const;
virtual int compare_same_type(const basic & other) const;
virtual bool is_equal_same_type(const basic & other) const;
- virtual unsigned return_type(void) const;
- virtual unsigned return_type_tinfo(void) const;
virtual unsigned calchash(void) const;
- virtual ex expand(unsigned options = 0) const;
+ virtual ex simplify_ncmul(const exvector & v) const;
// non-virtual functions in this class
public:
/** Check if obj is a T, including base classes. */
template <class T>
inline bool is_a(const basic & obj)
-{ return dynamic_cast<const T *>(&obj)!=0; }
+{
+ return dynamic_cast<const T *>(&obj)!=0;
+}
/** Check if obj is a T, not including base classes. This one is just an
* inefficient default. It should in all time-critical cases be overridden
* by template specializations that don't create a temporary. */
template <class T>
inline bool is_exactly_a(const class basic & obj)
-{ const T foo; return foo.tinfo()==obj.tinfo(); }
+{
+ const T foo; return foo.tinfo()==obj.tinfo();
+}
/** 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); }
+{
+ 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 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.
+ *
+ * @param e expression
+ * @return reference to pseries object
+ * @see is_exactly_a<class T>() */
+template <class T>
+inline const T &ex_to(const ex &e)
+{
+ return static_cast<const T &>(*e.bp);
+}
} // namespace GiNaC