blob: 136942c357aa1e4c014dea26e49f4a02a189fcc8 [file] [log] [blame]
// 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