Move fix and symbolic to their own file, and improve doxygen compatibility

This commit is contained in:
Gael Guennebaud
2017-01-11 14:28:28 +01:00
parent 04397f17e2
commit b1dc0fa813
6 changed files with 356 additions and 260 deletions

View File

@@ -0,0 +1,87 @@
// 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_INTEGRAL_CONSTANT_H
#define EIGEN_INTEGRAL_CONSTANT_H
namespace Eigen {
namespace internal {
template<int N> struct fix_t {
static const int value = N;
operator int() const { return value; }
fix_t (fix_t<N> (*)() ) {}
fix_t() {}
// Needed in C++14 to allow fix<N>():
fix_t operator() () const { return *this; }
};
template<typename T, int Default=Dynamic> struct get_compile_time {
enum { value = Default };
};
template<int N,int Default> struct get_compile_time<fix_t<N>,Default> {
enum { value = N };
};
template<typename T> struct is_compile_time { enum { value = false }; };
template<int N> struct is_compile_time<fix_t<N> > { enum { value = true }; };
} // end namespace internal
#ifndef EIGEN_PARSED_BY_DOXYGEN
#if __cplusplus > 201103L
template<int N>
static const internal::fix_t<N> fix{};
#else
template<int N>
inline internal::fix_t<N> fix() { return internal::fix_t<N>(); }
#endif
#else // EIGEN_PARSED_BY_DOXYGEN
/** \var fix
* \ingroup Core_Module
*
* This \em identifier permits to construct an object embedding a compile-time integer \c N.
*
* \tparam N the compile-time integer value
*
* It is typically used in conjunction with the Eigen::seq and Eigen::seqN functions to pass compile-time values to them:
* \code
* seqN(10,fix<4>,fix<-3>) // <=> [10 7 4 1]
* \endcode
*
* In c++14, it is implemented as:
* \code
* template<int N> static const internal::fix_t<N> fix{};
* \endcode
* where internal::fix_t<N> is an internal template class similar to
* <a href="http://en.cppreference.com/w/cpp/types/integral_constant">\c std::integral_constant </a><tt> <int,N> </tt>
* Here, \c fix<N> is thus an object of type \c internal::fix_t<N>.
*
* In c++98/11, it is implemented as a function:
* \code
* template<int N> inline internal::fix_t<N> fix();
* \endcode
* Here internal::fix_t<N> is thus a pointer to function.
*
* If for some reason you want a true object in c++98 then you can write: \code fix<N>() \endcode which is also valid in c++14.
*/
template<int N>
static const auto fix;
#endif // EIGEN_PARSED_BY_DOXYGEN
} // end namespace Eigen
#endif // EIGEN_INTEGRAL_CONSTANT_H

View File

@@ -0,0 +1,218 @@
// 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 minipulate the placeholders::last and placeholders::end 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 Index to provide the eval method.
// We could also use a free-function symbolic_eval...
class ValueExpr {
public:
ValueExpr(Index val) : m_value(val) {}
template<typename T>
Index eval_impl(const T&) const { return m_value; }
protected:
Index m_value;
};
/** \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 __cplusplus > 201103L
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); }
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 AddExpr<ValueExpr,Derived> operator/(Index a, const BaseExpr& b)
{ return AddExpr<ValueExpr,Derived>(a,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>
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 staticaly 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 __cplusplus > 201103L
// 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