| // 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 | |
| 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"; | |
| * | |
| * // In c++98/11, only one symbol per expression is supported for now: | |
| * auto expr98 = (3-x)/2; | |
| * std::cout << expr98.eval(x=6) << "\n"; | |
| * \endcode | |
| * | |
| * It is currently only used internally to define and manipulate the Eigen::last and Eigen::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> | |
| 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); } | |
| #if EIGEN_HAS_CXX14 | |
| template<typename... Types> | |
| Index eval(Types&&... values) const { return derived().eval_impl(std::make_tuple(values...)); } | |
| #endif | |
| 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()); } | |
| #if (!EIGEN_HAS_CXX14) | |
| 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()); } | |
| #endif | |
| 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(); } | |
| #if EIGEN_HAS_CXX14 | |
| // 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(); } | |
| #endif | |
| }; | |
| 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 |