// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2017 Gael Guennebaud // // 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; * struct y_tag {}; static const Symbolic::SymbolExpr y; * struct z_tag {}; static const Symbolic::SymbolExpr 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 minipulate the placeholders::last and placeholders::end symbols in Eigen::seq and Eigen::seqN. * */ namespace Symbolic { template class Symbol; template class NegateExpr; template class AddExpr; template class ProductExpr; template class QuotientExpr; // A simple wrapper around an integral value to provide the eval method. // We could also use a free-function symbolic_eval... template class ValueExpr { public: ValueExpr(IndexType val) : m_value(val) {} template 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 class ValueExpr > { public: ValueExpr() {} template Index eval_impl(const T&) const { return N; } }; /** \class BaseExpr * \ingroup Core_Module * Common base class of any symbolic expressions */ template class BaseExpr { public: const Derived& derived() const { return *static_cast(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 Index eval(const T& values) const { return derived().eval_impl(values); } #if EIGEN_HAS_CXX14 template Index eval(Types&&... values) const { return derived().eval_impl(std::make_tuple(values...)); } #endif NegateExpr operator-() const { return NegateExpr(derived()); } AddExpr > operator+(Index b) const { return AddExpr >(derived(), b); } AddExpr > operator-(Index a) const { return AddExpr >(derived(), -a); } ProductExpr > operator*(Index a) const { return ProductExpr >(derived(),a); } QuotientExpr > operator/(Index a) const { return QuotientExpr >(derived(),a); } friend AddExpr > operator+(Index a, const BaseExpr& b) { return AddExpr >(b.derived(), a); } friend AddExpr,ValueExpr<> > operator-(Index a, const BaseExpr& b) { return AddExpr,ValueExpr<> >(-b.derived(), a); } friend ProductExpr,Derived> operator*(Index a, const BaseExpr& b) { return ProductExpr,Derived>(a,b.derived()); } friend QuotientExpr,Derived> operator/(Index a, const BaseExpr& b) { return QuotientExpr,Derived>(a,b.derived()); } template AddExpr > > operator+(internal::FixedInt) const { return AddExpr > >(derived(), ValueExpr >()); } template AddExpr > > operator-(internal::FixedInt) const { return AddExpr > >(derived(), ValueExpr >()); } template ProductExpr > > operator*(internal::FixedInt) const { return ProductExpr > >(derived(),ValueExpr >()); } template QuotientExpr > > operator/(internal::FixedInt) const { return QuotientExpr > >(derived(),ValueExpr >()); } template friend AddExpr > > operator+(internal::FixedInt, const BaseExpr& b) { return AddExpr > >(b.derived(), ValueExpr >()); } template friend AddExpr,ValueExpr > > operator-(internal::FixedInt, const BaseExpr& b) { return AddExpr,ValueExpr > >(-b.derived(), ValueExpr >()); } template friend ProductExpr >,Derived> operator*(internal::FixedInt, const BaseExpr& b) { return ProductExpr >,Derived>(ValueExpr >(),b.derived()); } template friend QuotientExpr >,Derived> operator/(internal::FixedInt, const BaseExpr& b) { return QuotientExpr > ,Derived>(ValueExpr >(),b.derived()); } #if (!EIGEN_HAS_CXX14) template AddExpr > > operator+(internal::FixedInt (*)()) const { return AddExpr > >(derived(), ValueExpr >()); } template AddExpr > > operator-(internal::FixedInt (*)()) const { return AddExpr > >(derived(), ValueExpr >()); } template ProductExpr > > operator*(internal::FixedInt (*)()) const { return ProductExpr > >(derived(),ValueExpr >()); } template QuotientExpr > > operator/(internal::FixedInt (*)()) const { return QuotientExpr > >(derived(),ValueExpr >()); } template friend AddExpr > > operator+(internal::FixedInt (*)(), const BaseExpr& b) { return AddExpr > >(b.derived(), ValueExpr >()); } template friend AddExpr,ValueExpr > > operator-(internal::FixedInt (*)(), const BaseExpr& b) { return AddExpr,ValueExpr > >(-b.derived(), ValueExpr >()); } template friend ProductExpr >,Derived> operator*(internal::FixedInt (*)(), const BaseExpr& b) { return ProductExpr >,Derived>(ValueExpr >(),b.derived()); } template friend QuotientExpr >,Derived> operator/(internal::FixedInt (*)(), const BaseExpr& b) { return QuotientExpr > ,Derived>(ValueExpr >(),b.derived()); } #endif template AddExpr operator+(const BaseExpr &b) const { return AddExpr(derived(), b.derived()); } template AddExpr > operator-(const BaseExpr &b) const { return AddExpr >(derived(), -b.derived()); } template ProductExpr operator*(const BaseExpr &b) const { return ProductExpr(derived(), b.derived()); } template QuotientExpr operator/(const BaseExpr &b) const { return QuotientExpr(derived(), b.derived()); } }; template struct is_symbolic { // BaseExpr has no conversion ctor, so we only have to check whether T can be staticaly cast to its base class BaseExpr. enum { value = internal::is_convertible >::value }; }; // Specialization for functions, because is_convertible fails in this case. // Useful in c++98/11 mode when testing is_symbolic)> template struct is_symbolic { enum { value = false }; }; /** 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 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 class SymbolExpr : public BaseExpr > { 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 operator=(Index val) const { return SymbolValue(val); } Index eval_impl(const SymbolValue &values) const { return values.value(); } #if EIGEN_HAS_CXX14 // C++14 versions suitable for multiple symbols template Index eval_impl(const std::tuple& values) const { return std::get >(values).value(); } #endif }; template class NegateExpr : public BaseExpr > { public: NegateExpr(const Arg0& arg0) : m_arg0(arg0) {} template Index eval_impl(const T& values) const { return -m_arg0.eval_impl(values); } protected: Arg0 m_arg0; }; template class AddExpr : public BaseExpr > { public: AddExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} template 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 class ProductExpr : public BaseExpr > { public: ProductExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} template 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 class QuotientExpr : public BaseExpr > { public: QuotientExpr(const Arg0& arg0, const Arg1& arg1) : m_arg0(arg0), m_arg1(arg1) {} template 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