| // This file is part of Eigen, a lightweight C++ template library |
| // for linear algebra. |
| // |
| // Copyright (C) 2017 Gael Guennebaud <gael.guennebaud@inria.fr> |
| // |
| // This Source Code Form is subject to the terms of the Mozilla |
| // Public License v. 2.0. If a copy of the MPL was not distributed |
| // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| #ifndef EIGEN_SYMBOLIC_INDEX_H |
| #define EIGEN_SYMBOLIC_INDEX_H |
| |
| // IWYU pragma: private |
| #include "../InternalHeaderCheck.h" |
| |
| namespace Eigen { |
| |
| /** \namespace Eigen::symbolic |
| * \ingroup Core_Module |
| * |
| * This namespace defines a set of classes and functions to build and evaluate symbolic expressions of scalar type Index. |
| * Here is a simple example: |
| * |
| * \code |
| * // First step, defines symbols: |
| * struct x_tag {}; static const symbolic::SymbolExpr<x_tag> x; |
| * struct y_tag {}; static const symbolic::SymbolExpr<y_tag> y; |
| * struct z_tag {}; static const symbolic::SymbolExpr<z_tag> z; |
| * |
| * // Defines an expression: |
| * auto expr = (x+3)/y+z; |
| * |
| * // And evaluate it: (c++14) |
| * std::cout << expr.eval(x=6,y=3,z=-13) << "\n"; |
| * |
| * \endcode |
| * |
| * It is currently only used internally to define and manipulate the |
| * Eigen::placeholders::last and Eigen::placeholders::lastp1 symbols in |
| * Eigen::seq and Eigen::seqN. |
| * |
| */ |
| namespace symbolic { |
| |
| template<typename Tag> class Symbol; |
| template<typename Arg0> class NegateExpr; |
| template<typename Arg1,typename Arg2> class AddExpr; |
| template<typename Arg1,typename Arg2> class ProductExpr; |
| template<typename Arg1,typename Arg2> class QuotientExpr; |
| |
| // A simple wrapper around an integral value to provide the eval method. |
| // We could also use a free-function symbolic_eval... |
| template<typename IndexType=Index> |
| class ValueExpr { |
| public: |
| ValueExpr(IndexType val) : m_value(val) {} |
| template<typename T> |
| IndexType eval_impl(const T&) const { return m_value; } |
| protected: |
| IndexType m_value; |
| }; |
| |
| // Specialization for compile-time value, |
| // It is similar to ValueExpr(N) but this version helps the compiler to generate better code. |
| template<int N> |
| class ValueExpr<internal::FixedInt<N> > { |
| public: |
| ValueExpr() {} |
| template<typename T> |
| EIGEN_CONSTEXPR Index eval_impl(const T&) const { return N; } |
| }; |
| |
| |
| /** \class BaseExpr |
| * \ingroup Core_Module |
| * Common base class of any symbolic expressions |
| */ |
| template<typename Derived> |
| class BaseExpr |
| { |
| public: |
| const Derived& derived() const { return *static_cast<const Derived*>(this); } |
| |
| /** Evaluate the expression given the \a values of the symbols. |
| * |
| * \param values defines the values of the symbols, it can either be a SymbolValue or a std::tuple of SymbolValue |
| * as constructed by SymbolExpr::operator= operator. |
| * |
| */ |
| template<typename T> |
| Index eval(const T& values) const { return derived().eval_impl(values); } |
| |
| template<typename... Types> |
| Index eval(Types&&... values) const { return derived().eval_impl(std::make_tuple(values...)); } |
| |
| NegateExpr<Derived> operator-() const { return NegateExpr<Derived>(derived()); } |
| |
| AddExpr<Derived,ValueExpr<> > operator+(Index b) const |
| { return AddExpr<Derived,ValueExpr<> >(derived(), b); } |
| AddExpr<Derived,ValueExpr<> > operator-(Index a) const |
| { return AddExpr<Derived,ValueExpr<> >(derived(), -a); } |
| ProductExpr<Derived,ValueExpr<> > operator*(Index a) const |
| { return ProductExpr<Derived,ValueExpr<> >(derived(),a); } |
| QuotientExpr<Derived,ValueExpr<> > operator/(Index a) const |
| { return QuotientExpr<Derived,ValueExpr<> >(derived(),a); } |
| |
| friend AddExpr<Derived,ValueExpr<> > operator+(Index a, const BaseExpr& b) |
| { return AddExpr<Derived,ValueExpr<> >(b.derived(), a); } |
| friend AddExpr<NegateExpr<Derived>,ValueExpr<> > operator-(Index a, const BaseExpr& b) |
| { return AddExpr<NegateExpr<Derived>,ValueExpr<> >(-b.derived(), a); } |
| friend ProductExpr<ValueExpr<>,Derived> operator*(Index a, const BaseExpr& b) |
| { return ProductExpr<ValueExpr<>,Derived>(a,b.derived()); } |
| friend QuotientExpr<ValueExpr<>,Derived> operator/(Index a, const BaseExpr& b) |
| { return QuotientExpr<ValueExpr<>,Derived>(a,b.derived()); } |
| |
| template<int N> |
| AddExpr<Derived,ValueExpr<internal::FixedInt<N> > > operator+(internal::FixedInt<N>) const |
| { return AddExpr<Derived,ValueExpr<internal::FixedInt<N> > >(derived(), ValueExpr<internal::FixedInt<N> >()); } |
| template<int N> |
| AddExpr<Derived,ValueExpr<internal::FixedInt<-N> > > operator-(internal::FixedInt<N>) const |
| { return AddExpr<Derived,ValueExpr<internal::FixedInt<-N> > >(derived(), ValueExpr<internal::FixedInt<-N> >()); } |
| template<int N> |
| ProductExpr<Derived,ValueExpr<internal::FixedInt<N> > > operator*(internal::FixedInt<N>) const |
| { return ProductExpr<Derived,ValueExpr<internal::FixedInt<N> > >(derived(),ValueExpr<internal::FixedInt<N> >()); } |
| template<int N> |
| QuotientExpr<Derived,ValueExpr<internal::FixedInt<N> > > operator/(internal::FixedInt<N>) const |
| { return QuotientExpr<Derived,ValueExpr<internal::FixedInt<N> > >(derived(),ValueExpr<internal::FixedInt<N> >()); } |
| |
| template<int N> |
| friend AddExpr<Derived,ValueExpr<internal::FixedInt<N> > > operator+(internal::FixedInt<N>, const BaseExpr& b) |
| { return AddExpr<Derived,ValueExpr<internal::FixedInt<N> > >(b.derived(), ValueExpr<internal::FixedInt<N> >()); } |
| template<int N> |
| friend AddExpr<NegateExpr<Derived>,ValueExpr<internal::FixedInt<N> > > operator-(internal::FixedInt<N>, const BaseExpr& b) |
| { return AddExpr<NegateExpr<Derived>,ValueExpr<internal::FixedInt<N> > >(-b.derived(), ValueExpr<internal::FixedInt<N> >()); } |
| template<int N> |
| friend ProductExpr<ValueExpr<internal::FixedInt<N> >,Derived> operator*(internal::FixedInt<N>, const BaseExpr& b) |
| { return ProductExpr<ValueExpr<internal::FixedInt<N> >,Derived>(ValueExpr<internal::FixedInt<N> >(),b.derived()); } |
| template<int N> |
| friend QuotientExpr<ValueExpr<internal::FixedInt<N> >,Derived> operator/(internal::FixedInt<N>, const BaseExpr& b) |
| { return QuotientExpr<ValueExpr<internal::FixedInt<N> > ,Derived>(ValueExpr<internal::FixedInt<N> >(),b.derived()); } |
| |
| |
| template<typename OtherDerived> |
| AddExpr<Derived,OtherDerived> operator+(const BaseExpr<OtherDerived> &b) const |
| { return AddExpr<Derived,OtherDerived>(derived(), b.derived()); } |
| |
| template<typename OtherDerived> |
| AddExpr<Derived,NegateExpr<OtherDerived> > operator-(const BaseExpr<OtherDerived> &b) const |
| { return AddExpr<Derived,NegateExpr<OtherDerived> >(derived(), -b.derived()); } |
| |
| template<typename OtherDerived> |
| ProductExpr<Derived,OtherDerived> operator*(const BaseExpr<OtherDerived> &b) const |
| { return ProductExpr<Derived,OtherDerived>(derived(), b.derived()); } |
| |
| template<typename OtherDerived> |
| QuotientExpr<Derived,OtherDerived> operator/(const BaseExpr<OtherDerived> &b) const |
| { return QuotientExpr<Derived,OtherDerived>(derived(), b.derived()); } |
| }; |
| |
| template<typename T> |
| struct is_symbolic { |
| // BaseExpr has no conversion ctor, so we only have to check whether T can be statically cast to its base class BaseExpr<T>. |
| enum { value = internal::is_convertible<T,BaseExpr<T> >::value }; |
| }; |
| |
| /** Represents the actual value of a symbol identified by its tag |
| * |
| * It is the return type of SymbolValue::operator=, and most of the time this is only way it is used. |
| */ |
| template<typename Tag> |
| class SymbolValue |
| { |
| public: |
| /** Default constructor from the value \a val */ |
| SymbolValue(Index val) : m_value(val) {} |
| |
| /** \returns the stored value of the symbol */ |
| Index value() const { return m_value; } |
| protected: |
| Index m_value; |
| }; |
| |
| /** Expression of a symbol uniquely identified by the template parameter type \c tag */ |
| template<typename tag> |
| class SymbolExpr : public BaseExpr<SymbolExpr<tag> > |
| { |
| public: |
| /** Alias to the template parameter \c tag */ |
| typedef tag Tag; |
| |
| SymbolExpr() {} |
| |
| /** Associate the value \a val to the given symbol \c *this, uniquely identified by its \c Tag. |
| * |
| * The returned object should be passed to ExprBase::eval() to evaluate a given expression with this specified runtime-time value. |
| */ |
| SymbolValue<Tag> operator=(Index val) const { |
| return SymbolValue<Tag>(val); |
| } |
| |
| Index eval_impl(const SymbolValue<Tag> &values) const { return values.value(); } |
| |
| // C++14 versions suitable for multiple symbols |
| template<typename... Types> |
| Index eval_impl(const std::tuple<Types...>& values) const { return std::get<SymbolValue<Tag> >(values).value(); } |
| }; |
| |
| template<typename Arg0> |
| class NegateExpr : public BaseExpr<NegateExpr<Arg0> > |
| { |
| public: |
| NegateExpr(const Arg0& arg0) : m_arg0(arg0) {} |
| |
| template<typename T> |
| Index eval_impl(const T& values) const { return -m_arg0.eval_impl(values); } |
| protected: |
| Arg0 m_arg0; |
| }; |
| |
| template<typename Arg0, typename Arg1> |
| class AddExpr : public BaseExpr<AddExpr<Arg0,Arg1> > |
| { |
| public: |
| AddExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} |
| |
| template<typename T> |
| Index eval_impl(const T& values) const { return m_arg0.eval_impl(values) + m_arg1.eval_impl(values); } |
| protected: |
| Arg0 m_arg0; |
| Arg1 m_arg1; |
| }; |
| |
| template<typename Arg0, typename Arg1> |
| class ProductExpr : public BaseExpr<ProductExpr<Arg0,Arg1> > |
| { |
| public: |
| ProductExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} |
| |
| template<typename T> |
| Index eval_impl(const T& values) const { return m_arg0.eval_impl(values) * m_arg1.eval_impl(values); } |
| protected: |
| Arg0 m_arg0; |
| Arg1 m_arg1; |
| }; |
| |
| template<typename Arg0, typename Arg1> |
| class QuotientExpr : public BaseExpr<QuotientExpr<Arg0,Arg1> > |
| { |
| public: |
| QuotientExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} |
| |
| template<typename T> |
| Index eval_impl(const T& values) const { return m_arg0.eval_impl(values) / m_arg1.eval_impl(values); } |
| protected: |
| Arg0 m_arg0; |
| Arg1 m_arg1; |
| }; |
| |
| } // end namespace symbolic |
| |
| } // end namespace Eigen |
| |
| #endif // EIGEN_SYMBOLIC_INDEX_H |