Merged in ggael/eigen-flexidexing (pull request PR-294)

generalized operator() for indexed access and slicing
This commit is contained in:
Gael Guennebaud
2017-01-26 08:04:23 +00:00
21 changed files with 2589 additions and 154 deletions

View File

@@ -0,0 +1,350 @@
// 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_ARITHMETIC_SEQUENCE_H
#define EIGEN_ARITHMETIC_SEQUENCE_H
namespace Eigen {
namespace internal {
#if !EIGEN_HAS_CXX11
template<typename T> struct aseq_negate {};
template<> struct aseq_negate<Index> {
typedef Index type;
};
template<int N> struct aseq_negate<FixedInt<N> > {
typedef FixedInt<-N> type;
};
// Compilation error in the following case:
template<> struct aseq_negate<FixedInt<DynamicIndex> > {};
template<typename FirstType,typename SizeType,typename IncrType,
bool FirstIsSymbolic=Symbolic::is_symbolic<FirstType>::value,
bool SizeIsSymbolic =Symbolic::is_symbolic<SizeType>::value>
struct aseq_reverse_first_type {
typedef Index type;
};
template<typename FirstType,typename SizeType,typename IncrType>
struct aseq_reverse_first_type<FirstType,SizeType,IncrType,true,true> {
typedef Symbolic::AddExpr<FirstType,
Symbolic::ProductExpr<Symbolic::AddExpr<SizeType,Symbolic::ValueExpr<FixedInt<-1> > >,
Symbolic::ValueExpr<IncrType> >
> type;
};
template<typename SizeType,typename IncrType,typename EnableIf = void>
struct aseq_reverse_first_type_aux {
typedef Index type;
};
template<typename SizeType,typename IncrType>
struct aseq_reverse_first_type_aux<SizeType,IncrType,typename internal::enable_if<bool((SizeType::value+IncrType::value)|0x1)>::type> {
typedef FixedInt<(SizeType::value-1)*IncrType::value> type;
};
template<typename FirstType,typename SizeType,typename IncrType>
struct aseq_reverse_first_type<FirstType,SizeType,IncrType,true,false> {
typedef typename aseq_reverse_first_type_aux<SizeType,IncrType>::type Aux;
typedef Symbolic::AddExpr<FirstType,Symbolic::ValueExpr<Aux> > type;
};
template<typename FirstType,typename SizeType,typename IncrType>
struct aseq_reverse_first_type<FirstType,SizeType,IncrType,false,true> {
typedef Symbolic::AddExpr<Symbolic::ProductExpr<Symbolic::AddExpr<SizeType,Symbolic::ValueExpr<FixedInt<-1> > >,
Symbolic::ValueExpr<IncrType> >,
Symbolic::ValueExpr<> > type;
};
#endif
// Helper to cleanup the type of the increment:
template<typename T> struct cleanup_seq_incr {
typedef typename cleanup_index_type<T,DynamicIndex>::type type;
};
}
//--------------------------------------------------------------------------------
// seq(first,last,incr) and seqN(first,size,incr)
//--------------------------------------------------------------------------------
template<typename FirstType=Index,typename SizeType=Index,typename IncrType=internal::FixedInt<1> >
class ArithmeticSequence;
template<typename FirstType,typename SizeType,typename IncrType>
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,
typename internal::cleanup_index_type<SizeType>::type,
typename internal::cleanup_seq_incr<IncrType>::type >
seqN(FirstType first, SizeType size, IncrType incr);
/** \class ArithmeticSequence
* \ingroup Core_Module
*
* This class represents an arithmetic progression \f$ a_0, a_1, a_2, ..., a_{n-1}\f$ defined by
* its \em first value \f$ a_0 \f$, its \em size (aka length) \em n, and the \em increment (aka stride)
* that is equal to \f$ a_{i+1}-a_{i}\f$ for any \em i.
*
* It is internally used as the return type of the Eigen::seq and Eigen::seqN functions, and as the input arguments
* of DenseBase::operator()(const RowIndices&, const ColIndices&), and most of the time this is the
* only way it is used.
*
* \tparam FirstType type of the first element, usually an Index,
* but internally it can be a symbolic expression
* \tparam SizeType type representing the size of the sequence, usually an Index
* or a compile time integral constant. Internally, it can also be a symbolic expression
* \tparam IncrType type of the increment, can be a runtime Index, or a compile time integral constant (default is compile-time 1)
*
* \sa Eigen::seq, Eigen::seqN, DenseBase::operator()(const RowIndices&, const ColIndices&), class IndexedView
*/
template<typename FirstType,typename SizeType,typename IncrType>
class ArithmeticSequence
{
public:
ArithmeticSequence(FirstType first, SizeType size) : m_first(first), m_size(size) {}
ArithmeticSequence(FirstType first, SizeType size, IncrType incr) : m_first(first), m_size(size), m_incr(incr) {}
enum {
SizeAtCompileTime = internal::get_fixed_value<SizeType>::value,
IncrAtCompileTime = internal::get_fixed_value<IncrType,DynamicIndex>::value
};
/** \returns the size, i.e., number of elements, of the sequence */
Index size() const { return m_size; }
/** \returns the first element \f$ a_0 \f$ in the sequence */
Index first() const { return m_first; }
/** \returns the value \f$ a_i \f$ at index \a i in the sequence. */
Index operator[](Index i) const { return m_first + i * m_incr; }
const FirstType& firstObject() const { return m_first; }
const SizeType& sizeObject() const { return m_size; }
const IncrType& incrObject() const { return m_incr; }
protected:
FirstType m_first;
SizeType m_size;
IncrType m_incr;
public:
#if EIGEN_HAS_CXX11
auto reverse() const -> decltype(Eigen::seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr)) {
return seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr);
}
#else
protected:
typedef typename internal::aseq_negate<IncrType>::type ReverseIncrType;
typedef typename internal::aseq_reverse_first_type<FirstType,SizeType,IncrType>::type ReverseFirstType;
public:
ArithmeticSequence<ReverseFirstType,SizeType,ReverseIncrType>
reverse() const {
return seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr);
}
#endif
};
/** \returns an ArithmeticSequence starting at \a first, of length \a size, and increment \a incr
*
* \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */
template<typename FirstType,typename SizeType,typename IncrType>
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type,typename internal::cleanup_seq_incr<IncrType>::type >
seqN(FirstType first, SizeType size, IncrType incr) {
return ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type,typename internal::cleanup_seq_incr<IncrType>::type>(first,size,incr);
}
/** \returns an ArithmeticSequence starting at \a first, of length \a size, and unit increment
*
* \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType) */
template<typename FirstType,typename SizeType>
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type >
seqN(FirstType first, SizeType size) {
return ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type>(first,size);
}
#ifdef EIGEN_PARSED_BY_DOXYGEN
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and with positive (or negative) increment \a incr
*
* It is essentially an alias to:
* \code
* seqN(f, (l-f+incr)/incr, incr);
* \endcode
*
* \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType)
*/
template<typename FirstType,typename LastType, typename IncrType>
auto seq(FirstType f, LastType l, IncrType incr);
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and unit increment
*
* It is essentially an alias to:
* \code
* seqN(f,l-f+1);
* \endcode
*
* \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType)
*/
template<typename FirstType,typename LastType>
auto seq(FirstType f, LastType l);
#else // EIGEN_PARSED_BY_DOXYGEN
#if EIGEN_HAS_CXX11
template<typename FirstType,typename LastType>
auto seq(FirstType f, LastType l) -> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f),
( typename internal::cleanup_index_type<LastType>::type(l)
- typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>())))
{
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
(typename internal::cleanup_index_type<LastType>::type(l)
-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()));
}
template<typename FirstType,typename LastType, typename IncrType>
auto seq(FirstType f, LastType l, IncrType incr)
-> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f),
( typename internal::cleanup_index_type<LastType>::type(l)
- typename internal::cleanup_index_type<FirstType>::type(f)+typename internal::cleanup_seq_incr<IncrType>::type(incr)
) / typename internal::cleanup_seq_incr<IncrType>::type(incr),
typename internal::cleanup_seq_incr<IncrType>::type(incr)))
{
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
( typename internal::cleanup_index_type<LastType>::type(l)
-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr)) / CleanedIncrType(incr),
CleanedIncrType(incr));
}
#else
template<typename FirstType,typename LastType>
typename internal::enable_if<!(Symbolic::is_symbolic<FirstType>::value || Symbolic::is_symbolic<LastType>::value),
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,Index> >::type
seq(FirstType f, LastType l)
{
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
Index((typename internal::cleanup_index_type<LastType>::type(l)-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>())));
}
template<typename FirstTypeDerived,typename LastType>
typename internal::enable_if<!Symbolic::is_symbolic<LastType>::value,
ArithmeticSequence<FirstTypeDerived, Symbolic::AddExpr<Symbolic::AddExpr<Symbolic::NegateExpr<FirstTypeDerived>,Symbolic::ValueExpr<> >,
Symbolic::ValueExpr<internal::FixedInt<1> > > > >::type
seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, LastType l)
{
return seqN(f.derived(),(typename internal::cleanup_index_type<LastType>::type(l)-f.derived()+fix<1>()));
}
template<typename FirstType,typename LastTypeDerived>
typename internal::enable_if<!Symbolic::is_symbolic<FirstType>::value,
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,
Symbolic::AddExpr<Symbolic::AddExpr<LastTypeDerived,Symbolic::ValueExpr<> >,
Symbolic::ValueExpr<internal::FixedInt<1> > > > >::type
seq(FirstType f, const Symbolic::BaseExpr<LastTypeDerived> &l)
{
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),(l.derived()-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()));
}
template<typename FirstTypeDerived,typename LastTypeDerived>
ArithmeticSequence<FirstTypeDerived,
Symbolic::AddExpr<Symbolic::AddExpr<LastTypeDerived,Symbolic::NegateExpr<FirstTypeDerived> >,Symbolic::ValueExpr<internal::FixedInt<1> > > >
seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, const Symbolic::BaseExpr<LastTypeDerived> &l)
{
return seqN(f.derived(),(l.derived()-f.derived()+fix<1>()));
}
template<typename FirstType,typename LastType, typename IncrType>
typename internal::enable_if<!(Symbolic::is_symbolic<FirstType>::value || Symbolic::is_symbolic<LastType>::value),
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,Index,typename internal::cleanup_seq_incr<IncrType>::type> >::type
seq(FirstType f, LastType l, IncrType incr)
{
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
Index((typename internal::cleanup_index_type<LastType>::type(l)-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr)), incr);
}
template<typename FirstTypeDerived,typename LastType, typename IncrType>
typename internal::enable_if<!Symbolic::is_symbolic<LastType>::value,
ArithmeticSequence<FirstTypeDerived,
Symbolic::QuotientExpr<Symbolic::AddExpr<Symbolic::AddExpr<Symbolic::NegateExpr<FirstTypeDerived>,
Symbolic::ValueExpr<> >,
Symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
Symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
typename internal::cleanup_seq_incr<IncrType>::type> >::type
seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, LastType l, IncrType incr)
{
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
return seqN(f.derived(),(typename internal::cleanup_index_type<LastType>::type(l)-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr);
}
template<typename FirstType,typename LastTypeDerived, typename IncrType>
typename internal::enable_if<!Symbolic::is_symbolic<FirstType>::value,
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,
Symbolic::QuotientExpr<Symbolic::AddExpr<Symbolic::AddExpr<LastTypeDerived,Symbolic::ValueExpr<> >,
Symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
Symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
typename internal::cleanup_seq_incr<IncrType>::type> >::type
seq(FirstType f, const Symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr)
{
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
(l.derived()-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr), incr);
}
template<typename FirstTypeDerived,typename LastTypeDerived, typename IncrType>
ArithmeticSequence<FirstTypeDerived,
Symbolic::QuotientExpr<Symbolic::AddExpr<Symbolic::AddExpr<LastTypeDerived,
Symbolic::NegateExpr<FirstTypeDerived> >,
Symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
Symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
typename internal::cleanup_seq_incr<IncrType>::type>
seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, const Symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr)
{
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
return seqN(f.derived(),(l.derived()-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr);
}
#endif
#endif // EIGEN_PARSED_BY_DOXYGEN
namespace internal {
// Convert a symbolic span into a usable one (i.e., remove last/end "keywords")
template<typename T>
struct make_size_type {
typedef typename internal::conditional<Symbolic::is_symbolic<T>::value, Index, T>::type type;
};
template<typename FirstType,typename SizeType,typename IncrType,int XprSize>
struct IndexedViewCompatibleType<ArithmeticSequence<FirstType,SizeType,IncrType>, XprSize> {
typedef ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType> type;
};
template<typename FirstType,typename SizeType,typename IncrType>
ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>
makeIndexedViewCompatible(const ArithmeticSequence<FirstType,SizeType,IncrType>& ids, Index size,SpecializedType) {
return ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>(
eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.sizeObject(),size),ids.incrObject());
}
template<typename FirstType,typename SizeType,typename IncrType>
struct get_compile_time_incr<ArithmeticSequence<FirstType,SizeType,IncrType> > {
enum { value = get_fixed_value<IncrType,DynamicIndex>::value };
};
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_ARITHMETIC_SEQUENCE_H

View File

@@ -563,6 +563,7 @@ template<typename Derived> class DenseBase
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
# include "../plugins/CommonCwiseUnaryOps.h"
# include "../plugins/BlockMethods.h"
# include "../plugins/IndexedViewMethods.h"
# ifdef EIGEN_DENSEBASE_PLUGIN
# include EIGEN_DENSEBASE_PLUGIN
# endif

View File

@@ -0,0 +1,207 @@
// 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_INDEXED_VIEW_H
#define EIGEN_INDEXED_VIEW_H
namespace Eigen {
namespace internal {
template<typename XprType, typename RowIndices, typename ColIndices>
struct traits<IndexedView<XprType, RowIndices, ColIndices> >
: traits<XprType>
{
enum {
RowsAtCompileTime = array_size<RowIndices>::value,
ColsAtCompileTime = array_size<ColIndices>::value,
MaxRowsAtCompileTime = RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) : int(traits<XprType>::MaxRowsAtCompileTime),
MaxColsAtCompileTime = ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) : int(traits<XprType>::MaxColsAtCompileTime),
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
: XprTypeIsRowMajor,
RowIncr = get_compile_time_incr<RowIndices>::value,
ColIncr = get_compile_time_incr<ColIndices>::value,
InnerIncr = IsRowMajor ? ColIncr : RowIncr,
OuterIncr = IsRowMajor ? RowIncr : ColIncr,
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
XprInnerStride = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType>::ret) : int(outer_stride_at_compile_time<XprType>::ret),
XprOuterstride = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time<XprType>::ret) : int(inner_stride_at_compile_time<XprType>::ret),
InnerSize = XprTypeIsRowMajor ? ColsAtCompileTime : RowsAtCompileTime,
IsBlockAlike = InnerIncr==1 && OuterIncr==1,
IsInnerPannel = HasSameStorageOrderAsXprType && is_same<AllRange<InnerSize>,typename conditional<XprTypeIsRowMajor,ColIndices,RowIndices>::type>::value,
InnerStrideAtCompileTime = InnerIncr<0 || InnerIncr==DynamicIndex || XprInnerStride==Dynamic ? Dynamic : XprInnerStride * InnerIncr,
OuterStrideAtCompileTime = OuterIncr<0 || OuterIncr==DynamicIndex || XprOuterstride==Dynamic ? Dynamic : XprOuterstride * OuterIncr,
ReturnAsScalar = is_same<RowIndices,SingleRange>::value && is_same<ColIndices,SingleRange>::value,
ReturnAsBlock = (!ReturnAsScalar) && IsBlockAlike,
ReturnAsIndexedView = (!ReturnAsScalar) && (!ReturnAsBlock),
// FIXME we deal with compile-time strides if and only if we have DirectAccessBit flag,
// but this is too strict regarding negative strides...
DirectAccessMask = (InnerIncr!=UndefinedIncr && OuterIncr!=UndefinedIncr && InnerIncr>=0 && OuterIncr>=0) ? DirectAccessBit : 0,
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
Flags = (traits<XprType>::Flags & (HereditaryBits | DirectAccessMask)) | FlagsLvalueBit | FlagsRowMajorBit
};
typedef Block<XprType,RowsAtCompileTime,ColsAtCompileTime,IsInnerPannel> BlockType;
};
}
template<typename XprType, typename RowIndices, typename ColIndices, typename StorageKind>
class IndexedViewImpl;
/** \class IndexedView
* \ingroup Core_Module
*
* \brief Expression of a non-sequential sub-matrix defined by arbitrary sequences of row and column indices
*
* \tparam XprType the type of the expression in which we are taking the intersections of sub-rows and sub-columns
* \tparam RowIndices the type of the object defining the sequence of row indices
* \tparam ColIndices the type of the object defining the sequence of column indices
*
* This class represents an expression of a sub-matrix (or sub-vector) defined as the intersection
* of sub-sets of rows and columns, that are themself defined by generic sequences of row indices \f$ \{r_0,r_1,..r_{m-1}\} \f$
* and column indices \f$ \{c_0,c_1,..c_{n-1} \}\f$. Let \f$ A \f$ be the nested matrix, then the resulting matrix \f$ B \f$ has \c m
* rows and \c n columns, and its entries are given by: \f$ B(i,j) = A(r_i,c_j) \f$.
*
* The \c RowIndices and \c ColIndices types must be compatible with the following API:
* \code
* <integral type> operator[](Index) const;
* Index size() const;
* \endcode
*
* Typical supported types thus include:
* - std::vector<int>
* - std::valarray<int>
* - std::array<int>
* - Plain C arrays: int[N]
* - Eigen::ArrayXi
* - decltype(ArrayXi::LinSpaced(...))
* - Any view/expressions of the previous types
* - Eigen::ArithmeticSequence
* - Eigen::internal::AllRange (helper for Eigen::all)
* - Eigen::internal::SingleRange (helper for single index)
* - etc.
*
* In typical usages of %Eigen, this class should never be used directly. It is the return type of
* DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* \sa class Block
*/
template<typename XprType, typename RowIndices, typename ColIndices>
class IndexedView : public IndexedViewImpl<XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind>
{
public:
typedef typename IndexedViewImpl<XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(IndexedView)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedView)
typedef typename internal::ref_selector<XprType>::non_const_type MatrixTypeNested;
typedef typename internal::remove_all<XprType>::type NestedExpression;
template<typename T0, typename T1>
IndexedView(XprType& xpr, const T0& rowIndices, const T1& colIndices)
: m_xpr(xpr), m_rowIndices(rowIndices), m_colIndices(colIndices)
{}
/** \returns number of rows */
Index rows() const { return internal::size(m_rowIndices); }
/** \returns number of columns */
Index cols() const { return internal::size(m_colIndices); }
/** \returns the nested expression */
const typename internal::remove_all<XprType>::type&
nestedExpression() const { return m_xpr; }
/** \returns the nested expression */
typename internal::remove_reference<XprType>::type&
nestedExpression() { return m_xpr.const_cast_derived(); }
/** \returns a const reference to the object storing/generating the row indices */
const RowIndices& rowIndices() const { return m_rowIndices; }
/** \returns a const reference to the object storing/generating the column indices */
const ColIndices& colIndices() const { return m_colIndices; }
protected:
MatrixTypeNested m_xpr;
RowIndices m_rowIndices;
ColIndices m_colIndices;
};
// Generic API dispatcher
template<typename XprType, typename RowIndices, typename ColIndices, typename StorageKind>
class IndexedViewImpl
: public internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices> >::type
{
public:
typedef typename internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices> >::type Base;
};
namespace internal {
template<typename ArgType, typename RowIndices, typename ColIndices>
struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
: evaluator_base<IndexedView<ArgType, RowIndices, ColIndices> >
{
typedef IndexedView<ArgType, RowIndices, ColIndices> XprType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost /* TODO + cost of row/col index */,
Flags = (evaluator<ArgType>::Flags & (HereditaryBits /*| LinearAccessBit | DirectAccessBit*/)),
Alignment = 0
};
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_xpr(xpr)
{
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
}
typedef typename XprType::Scalar Scalar;
typedef typename XprType::CoeffReturnType CoeffReturnType;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
CoeffReturnType coeff(Index row, Index col) const
{
return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Scalar& coeffRef(Index row, Index col)
{
return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
}
protected:
evaluator<ArgType> m_argImpl;
const XprType& m_xpr;
};
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_INDEXED_VIEW_H

View File

@@ -25,6 +25,10 @@ const int Dynamic = -1;
*/
const int DynamicIndex = 0xffffff;
/** This value means that the increment to go from one value to another in a sequence is not constant for each step.
*/
const int UndefinedIncr = 0xfffffe;
/** This value means +Infinity; it is currently used only as the p parameter to MatrixBase::lpNorm<int>().
* The value Infinity there means the L-infinity norm.
*/

View File

@@ -83,6 +83,7 @@ template<typename ExpressionType> class ForceAlignedAccess;
template<typename ExpressionType> class SwapWrapper;
template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false> class Block;
template<typename XprType, typename RowIndices, typename ColIndices> class IndexedView;
template<typename MatrixType, int Size=Dynamic> class VectorBlock;
template<typename MatrixType> class Transpose;

View File

@@ -0,0 +1,187 @@
// 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_INDEXED_VIEW_HELPER_H
#define EIGEN_INDEXED_VIEW_HELPER_H
namespace Eigen {
/** \namespace Eigen::placeholders
* \ingroup Core_Module
*
* Namespace containing symbolic placeholder and identifiers
*/
namespace placeholders {
namespace internal {
struct symbolic_last_tag {};
}
/** \var last
* \ingroup Core_Module
*
* Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last element/row/columns
* of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* This symbolic placeholder support standard arithmetic operation.
*
* A typical usage example would be:
* \code
* using namespace Eigen;
* using Eigen::placeholders::last;
* VectorXd v(n);
* v(seq(2,last-2)).setOnes();
* \endcode
*
* \sa end
*/
static const Symbolic::SymbolExpr<internal::symbolic_last_tag> last;
/** \var end
* \ingroup Core_Module
*
* Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last+1 element/row/columns
* of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* This symbolic placeholder support standard arithmetic operation.
* It is essentially an alias to last+1
*
* \sa last
*/
#ifdef EIGEN_PARSED_BY_DOXYGEN
static const auto end = last+1;
#else
// Using a FixedExpr<1> expression is important here to make sure the compiler
// can fully optimize the computation starting indices with zero overhead.
static const Symbolic::AddExpr<Symbolic::SymbolExpr<internal::symbolic_last_tag>,Symbolic::ValueExpr<Eigen::internal::FixedInt<1> > > end(last+fix<1>());
#endif
} // end namespace placeholders
namespace internal {
// Replace symbolic last/end "keywords" by their true runtime value
inline Index eval_expr_given_size(Index x, Index /* size */) { return x; }
template<int N>
FixedInt<N> eval_expr_given_size(FixedInt<N> x, Index /*size*/) { return x; }
template<typename Derived>
Index eval_expr_given_size(const Symbolic::BaseExpr<Derived> &x, Index size)
{
return x.derived().eval(placeholders::last=size-1);
}
// Extract increment/step at compile time
template<typename T, typename EnableIf = void> struct get_compile_time_incr {
enum { value = UndefinedIncr };
};
// Analogue of std::get<0>(x), but tailored for our needs.
template<typename T>
Index first(const T& x) { return x.first(); }
// IndexedViewCompatibleType/makeIndexedViewCompatible turn an arbitrary object of type T into something usable by MatrixSlice
// The generic implementation is a no-op
template<typename T,int XprSize,typename EnableIf=void>
struct IndexedViewCompatibleType {
typedef T type;
};
template<typename T,typename Q>
const T& makeIndexedViewCompatible(const T& x, Index /*size*/, Q) { return x; }
//--------------------------------------------------------------------------------
// Handling of a single Index
//--------------------------------------------------------------------------------
struct SingleRange {
enum {
SizeAtCompileTime = 1
};
SingleRange(Index val) : m_value(val) {}
Index operator[](Index) const { return m_value; }
Index size() const { return 1; }
Index first() const { return m_value; }
Index m_value;
};
template<> struct get_compile_time_incr<SingleRange> {
enum { value = 1 }; // 1 or 0 ??
};
// Turn a single index into something that looks like an array (i.e., that exposes a .size(), and operatro[](int) methods)
template<typename T, int XprSize>
struct IndexedViewCompatibleType<T,XprSize,typename internal::enable_if<internal::is_integral<T>::value>::type> {
// Here we could simply use Array, but maybe it's less work for the compiler to use
// a simpler wrapper as SingleRange
//typedef Eigen::Array<Index,1,1> type;
typedef SingleRange type;
};
template<typename T, int XprSize>
struct IndexedViewCompatibleType<T, XprSize, typename enable_if<Symbolic::is_symbolic<T>::value>::type> {
typedef SingleRange type;
};
template<typename T>
typename enable_if<Symbolic::is_symbolic<T>::value,SingleRange>::type
makeIndexedViewCompatible(const T& id, Index size, SpecializedType) {
return eval_expr_given_size(id,size);
}
//--------------------------------------------------------------------------------
// Handling of all
//--------------------------------------------------------------------------------
struct all_t { all_t() {} };
// Convert a symbolic 'all' into a usable range type
template<int XprSize>
struct AllRange {
enum { SizeAtCompileTime = XprSize };
AllRange(Index size = XprSize) : m_size(size) {}
Index operator[](Index i) const { return i; }
Index size() const { return m_size.value(); }
Index first() const { return 0; }
variable_if_dynamic<Index,XprSize> m_size;
};
template<int XprSize>
struct IndexedViewCompatibleType<all_t,XprSize> {
typedef AllRange<XprSize> type;
};
template<typename XprSizeType>
inline AllRange<get_fixed_value<XprSizeType>::value> makeIndexedViewCompatible(all_t , XprSizeType size, SpecializedType) {
return AllRange<get_fixed_value<XprSizeType>::value>(size);
}
template<int Size> struct get_compile_time_incr<AllRange<Size> > {
enum { value = 1 };
};
} // end namespace internal
namespace placeholders {
/** \var all
* \ingroup Core_Module
* Can be used as a parameter to DenseBase::operator()(const RowIndices&, const ColIndices&) to index all rows or columns
*/
static const Eigen::internal::all_t all;
}
} // end namespace Eigen
#endif // EIGEN_INDEXED_VIEW_HELPER_H

View File

@@ -0,0 +1,270 @@
// 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> class FixedInt;
template<int N> class VariableAndFixedInt;
/** \internal
* \class FixedInt
*
* This class embeds a compile-time integer \c N.
*
* It is similar to c++11 std::integral_constant<int,N> but with some additional features
* such as:
* - implicit conversion to int
* - arithmetic and some bitwise operators: -, +, *, /, %, &, |
* - c++98/14 compatibility with fix<N> and fix<N>() syntax to define integral constants.
*
* It is strongly discouraged to directly deal with this class FixedInt. Instances are expcected to
* be created by the user using Eigen::fix<N> or Eigen::fix<N>(). In C++98-11, the former syntax does
* not create a FixedInt<N> instance but rather a point to function that needs to be \em cleaned-up
* using the generic helper:
* \code
* internal::cleanup_index_type<T>::type
* internal::cleanup_index_type<T,DynamicKey>::type
* \endcode
* where T can a FixedInt<N>, a pointer to function FixedInt<N> (*)(), or numerous other integer-like representations.
* \c DynamicKey is either Dynamic (default) or DynamicIndex and used to identify true compile-time values.
*
* For convenience, you can extract the compile-time value \c N in a generic way using the following helper:
* \code
* internal::get_fixed_value<T,DefaultVal>::value
* \endcode
* that will give you \c N if T equals FixedInt<N> or FixedInt<N> (*)(), and \c DefaultVal if T does not embed any compile-time value (e.g., T==int).
*
* \sa fix<N>, class VariableAndFixedInt
*/
template<int N> class FixedInt
{
public:
static const int value = N;
operator int() const { return value; }
FixedInt() {}
FixedInt( VariableAndFixedInt<N> other) {
EIGEN_ONLY_USED_FOR_DEBUG(other);
eigen_internal_assert(int(other)==N);
}
FixedInt<-N> operator-() const { return FixedInt<-N>(); }
template<int M>
FixedInt<N+M> operator+( FixedInt<M>) const { return FixedInt<N+M>(); }
template<int M>
FixedInt<N-M> operator-( FixedInt<M>) const { return FixedInt<N-M>(); }
template<int M>
FixedInt<N*M> operator*( FixedInt<M>) const { return FixedInt<N*M>(); }
template<int M>
FixedInt<N/M> operator/( FixedInt<M>) const { return FixedInt<N/M>(); }
template<int M>
FixedInt<N%M> operator%( FixedInt<M>) const { return FixedInt<N%M>(); }
template<int M>
FixedInt<N|M> operator|( FixedInt<M>) const { return FixedInt<N|M>(); }
template<int M>
FixedInt<N&M> operator&( FixedInt<M>) const { return FixedInt<N&M>(); }
#if EIGEN_HAS_CXX14
// Needed in C++14 to allow fix<N>():
FixedInt operator() () const { return *this; }
VariableAndFixedInt<N> operator() (int val) const { return VariableAndFixedInt<N>(val); }
#else
FixedInt ( FixedInt<N> (*)() ) {}
#endif
#if EIGEN_HAS_CXX11
FixedInt(std::integral_constant<int,N>) {}
#endif
};
/** \internal
* \class VariableAndFixedInt
*
* This class embeds both a compile-time integer \c N and a runtime integer.
* Both values are supposed to be equal unless the compile-time value \c N has a special
* value meaning that the runtime-value should be used. Depending on the context, this special
* value can be either Eigen::Dynamic (for positive quantities) or Eigen::DynamicIndex (for
* quantities that can be negative).
*
* It is the return-type of the function Eigen::fix<N>(int), and most of the time this is the only
* way it is used. It is strongly discouraged to directly deal with instances of VariableAndFixedInt.
* Indeed, in order to write generic code, it is the responsibility of the callee to properly convert
* it to either a true compile-time quantity (i.e. a FixedInt<N>), or to a runtime quantity (e.g., an Index)
* using the following generic helper:
* \code
* internal::cleanup_index_type<T>::type
* internal::cleanup_index_type<T,DynamicKey>::type
* \endcode
* where T can be a template instantiation of VariableAndFixedInt or numerous other integer-like representations.
* \c DynamicKey is either Dynamic (default) or DynamicIndex and used to identify true compile-time values.
*
* For convenience, you can also extract the compile-time value \c N using the following helper:
* \code
* internal::get_fixed_value<T,DefaultVal>::value
* \endcode
* that will give you \c N if T equals VariableAndFixedInt<N>, and \c DefaultVal if T does not embed any compile-time value (e.g., T==int).
*
* \sa fix<N>(int), class FixedInt
*/
template<int N> class VariableAndFixedInt
{
public:
static const int value = N;
operator int() const { return m_value; }
VariableAndFixedInt(int val) { m_value = val; }
protected:
int m_value;
};
template<typename T, int Default=Dynamic> struct get_fixed_value {
static const int value = Default;
};
template<int N,int Default> struct get_fixed_value<FixedInt<N>,Default> {
static const int value = N;
};
#if !EIGEN_HAS_CXX14
template<int N,int Default> struct get_fixed_value<FixedInt<N> (*)(),Default> {
static const int value = N;
};
#endif
template<int N,int Default> struct get_fixed_value<VariableAndFixedInt<N>,Default> {
static const int value = N ;
};
template<typename T, int N, int Default>
struct get_fixed_value<variable_if_dynamic<T,N>,Default> {
static const int value = N;
};
template<typename T> Index get_runtime_value(const T &x) { return x; }
#if !EIGEN_HAS_CXX14
template<int N> Index get_runtime_value(FixedInt<N> (*)()) { return N; }
#endif
// Cleanup integer/FixedInt/VariableAndFixedInt/etc types:
// By default, no cleanup:
template<typename T, int DynamicKey=Dynamic, typename EnableIf=void> struct cleanup_index_type { typedef T type; };
// Convert any integral type (e.g., short, int, unsigned int, etc.) to Eigen::Index
template<typename T, int DynamicKey> struct cleanup_index_type<T,DynamicKey,typename internal::enable_if<internal::is_integral<T>::value>::type> { typedef Index type; };
#if !EIGEN_HAS_CXX14
// In c++98/c++11, fix<N> is a pointer to function that we better cleanup to a true FixedInt<N>:
template<int N, int DynamicKey> struct cleanup_index_type<FixedInt<N> (*)(), DynamicKey> { typedef FixedInt<N> type; };
#endif
// If VariableAndFixedInt does not match DynamicKey, then we turn it to a pure compile-time value:
template<int N, int DynamicKey> struct cleanup_index_type<VariableAndFixedInt<N>, DynamicKey> { typedef FixedInt<N> type; };
// If VariableAndFixedInt matches DynamicKey, then we turn it to a pure runtime-value (aka Index):
template<int DynamicKey> struct cleanup_index_type<VariableAndFixedInt<DynamicKey>, DynamicKey> { typedef Index type; };
#if EIGEN_HAS_CXX11
template<int N, int DynamicKey> struct cleanup_index_type<std::integral_constant<int,N>, DynamicKey> { typedef FixedInt<N> type; };
#endif
} // end namespace internal
#ifndef EIGEN_PARSED_BY_DOXYGEN
#if EIGEN_HAS_CXX14
template<int N>
static const internal::FixedInt<N> fix{};
#else
template<int N>
inline internal::FixedInt<N> fix() { return internal::FixedInt<N>(); }
// The generic typename T is mandatory. Otherwise, a code like fix<N> could refer to either the function above or this next overload.
// This way a code like fix<N> can only refer to the previous function.
template<int N,typename T>
inline internal::VariableAndFixedInt<N> fix(T val) { return internal::VariableAndFixedInt<N>(val); }
#endif
#else // EIGEN_PARSED_BY_DOXYGEN
/** \var fix<N>()
* \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
*
* See also the function fix(int) to pass both a compile-time and runtime value.
*
* In c++14, it is implemented as:
* \code
* template<int N> static const internal::FixedInt<N> fix{};
* \endcode
* where internal::FixedInt<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::FixedInt<N>.
*
* In c++98/11, it is implemented as a function:
* \code
* template<int N> inline internal::FixedInt<N> fix();
* \endcode
* Here internal::FixedInt<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.
*
* \sa fix<N>(int), seq, seqN
*/
template<int N>
static const auto fix();
/** \fn fix<N>(int)
* \ingroup Core_Module
*
* This function returns an object embedding both a compile-time integer \c N, and a fallback runtime value \a val.
*
* \tparam N the compile-time integer value
* \param val the fallback runtime integer value
*
* This function is a more general version of the \ref fix identifier/function that can be used in template code
* where the compile-time value could turn out to actually mean "undefined at compile-time". For positive integers
* such as a size or a dimension, this case is identified by Eigen::Dynamic, whereas runtime signed integers
* (e.g., an increment/stride) are identified as Eigen::DynamicIndex. In such a case, the runtime value \a val
* will be used as a fallback.
*
* A typical use case would be:
* \code
* template<typename Derived> void foo(const MatrixBase<Derived> &mat) {
* const int N = Derived::RowsAtCompileTime==Dynamic ? Dynamic : Derived::RowsAtCompileTime/2;
* const int n = mat.rows()/2;
* ... mat( seqN(0,fix<N>(n) ) ...;
* }
* \endcode
* In this example, the function Eigen::seqN knows that the second argument is expected to be a size.
* If the passed compile-time value N equals Eigen::Dynamic, then the proxy object returned by fix will be dissmissed, and converted to an Eigen::Index of value \c n.
* Otherwise, the runtime-value \c n will be dissmissed, and the returned ArithmeticSequence will be of the exact same type as <tt> seqN(0,fix<N>) </tt>.
*
* \sa fix, seqN, class ArithmeticSequence
*/
template<int N>
static const auto fix(int val);
#endif // EIGEN_PARSED_BY_DOXYGEN
} // end namespace Eigen
#endif // EIGEN_INTEGRAL_CONSTANT_H

View File

@@ -362,6 +362,11 @@
#define EIGEN_HAS_CXX11 0
#endif
#if EIGEN_MAX_CPP_VER>=14 && (defined(__cplusplus) && (__cplusplus > 201103L) || EIGEN_COMP_MSVC >= 1900)
#define EIGEN_HAS_CXX14 1
#else
#define EIGEN_HAS_CXX14 0
#endif
// Do we support r-value references?
#ifndef EIGEN_HAS_RVALUE_REFERENCES
@@ -865,7 +870,8 @@ namespace Eigen {
typedef typename Eigen::internal::ref_selector<Derived>::type Nested; \
typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \
typedef typename Eigen::internal::traits<Derived>::StorageIndex StorageIndex; \
enum { RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
enum CompileTimeTraits \
{ RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
ColsAtCompileTime = Eigen::internal::traits<Derived>::ColsAtCompileTime, \
Flags = Eigen::internal::traits<Derived>::Flags, \
SizeAtCompileTime = Base::SizeAtCompileTime, \

View File

@@ -278,6 +278,59 @@ protected:
EIGEN_DEVICE_FUNC ~noncopyable() {}
};
/** \internal
* Provides access to the number of elements in the object of as a compile-time constant expression.
* It "returns" Eigen::Dynamic if the size cannot be resolved at compile-time (default).
*
* Similar to std::tuple_size, but more general.
*
* It currently supports:
* - any types T defining T::SizeAtCompileTime
* - plain C arrays as T[N]
* - std::array (c++11)
* - some internal types such as SingleRange and AllRange
*
* The second template parameter eases SFINAE-based specializations.
*/
template<typename T, typename EnableIf = void> struct array_size {
enum { value = Dynamic };
};
template<typename T> struct array_size<T,typename internal::enable_if<((T::SizeAtCompileTime&0)==0)>::type> {
enum { value = T::SizeAtCompileTime };
};
template<typename T, int N> struct array_size<const T (&)[N]> {
enum { value = N };
};
template<typename T, int N> struct array_size<T (&)[N]> {
enum { value = N };
};
#if EIGEN_HAS_CXX11
template<typename T, std::size_t N> struct array_size<const std::array<T,N> > {
enum { value = N };
};
template<typename T, std::size_t N> struct array_size<std::array<T,N> > {
enum { value = N };
};
#endif
/** \internal
* Analogue of the std::size free function.
* It returns the size of the container or view \a x of type \c T
*
* It currently supports:
* - any types T defining a member T::size() const
* - plain C arrays as T[N]
*
*/
template<typename T>
Index size(const T& x) { return x.size(); }
template<typename T,std::size_t N>
Index size(const T (&) [N]) { return N; }
/** \internal
* Convenient struct to get the result type of a unary or binary functor.
*

View File

@@ -0,0 +1,300 @@
// 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 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 staticaly cast to its base class BaseExpr<T>.
enum { value = internal::is_convertible<T,BaseExpr<T> >::value };
};
// Specialization for functions, because is_convertible fails in this case.
// Useful in c++98/11 mode when testing is_symbolic<decltype(fix<N>)>
template<typename T>
struct is_symbolic<T (*)()> {
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<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

View File

@@ -109,6 +109,7 @@ template<typename T, int Value> class variable_if_dynamic
EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T value() { return T(Value); }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator T() const { return T(Value); }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T) {}
};
@@ -119,6 +120,7 @@ template<typename T> class variable_if_dynamic<T, Dynamic>
public:
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit variable_if_dynamic(T value) : m_value(value) {}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T value() const { return m_value; }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator T() const { return m_value; }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void setValue(T value) { m_value = value; }
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,260 @@
// 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_PARSED_BY_DOXYGEN
// This file is automatically included twice to generate const and non-const versions
#ifndef EIGEN_INDEXED_VIEW_METHOD_2ND_PASS
#define EIGEN_INDEXED_VIEW_METHOD_CONST const
#define EIGEN_INDEXED_VIEW_METHOD_TYPE ConstIndexedViewType
#else
#define EIGEN_INDEXED_VIEW_METHOD_CONST
#define EIGEN_INDEXED_VIEW_METHOD_TYPE IndexedViewType
#endif
#ifndef EIGEN_INDEXED_VIEW_METHOD_2ND_PASS
protected:
// define some aliases to ease readability
template<typename Indices>
struct IvcRowType : public internal::IndexedViewCompatibleType<Indices,RowsAtCompileTime> {};
template<typename Indices>
struct IvcColType : public internal::IndexedViewCompatibleType<Indices,ColsAtCompileTime> {};
template<typename Indices>
struct IvcType : public internal::IndexedViewCompatibleType<Indices,SizeAtCompileTime> {};
typedef typename internal::IndexedViewCompatibleType<Index,1>::type IvcIndex;
template<typename Indices>
typename IvcRowType<Indices>::type
ivcRow(const Indices& indices) const {
return internal::makeIndexedViewCompatible(indices, internal::variable_if_dynamic<Index,RowsAtCompileTime>(derived().rows()),Specialized);
}
template<typename Indices>
typename IvcColType<Indices>::type
ivcCol(const Indices& indices) const {
return internal::makeIndexedViewCompatible(indices, internal::variable_if_dynamic<Index,ColsAtCompileTime>(derived().cols()),Specialized);
}
template<typename Indices>
typename IvcColType<Indices>::type
ivcSize(const Indices& indices) const {
return internal::makeIndexedViewCompatible(indices, internal::variable_if_dynamic<Index,SizeAtCompileTime>(derived().size()),Specialized);
}
template<typename RowIndices, typename ColIndices>
struct valid_indexed_view_overload {
// Here we use is_convertible to Index instead of is_integral in order to treat enums as Index.
// In c++11 we could use is_integral<T> && is_enum<T> if is_convertible appears to be too permissive.
enum { value = !(internal::is_convertible<RowIndices,Index>::value && internal::is_convertible<ColIndices,Index>::value) };
};
public:
#endif
template<typename RowIndices, typename ColIndices>
struct EIGEN_INDEXED_VIEW_METHOD_TYPE {
typedef IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,
typename IvcRowType<RowIndices>::type,
typename IvcColType<ColIndices>::type> type;
};
// This is the generic version
template<typename RowIndices, typename ColIndices>
typename internal::enable_if<valid_indexed_view_overload<RowIndices,ColIndices>::value
&& internal::traits<typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type>::ReturnAsIndexedView,
typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type >::type
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
return typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type
(derived(), ivcRow(rowIndices), ivcCol(colIndices));
}
// The following overload returns a Block<> object
template<typename RowIndices, typename ColIndices>
typename internal::enable_if<valid_indexed_view_overload<RowIndices,ColIndices>::value
&& internal::traits<typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type>::ReturnAsBlock,
typename internal::traits<typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type>::BlockType>::type
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
typedef typename internal::traits<typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type>::BlockType BlockType;
typename IvcRowType<RowIndices>::type actualRowIndices = ivcRow(rowIndices);
typename IvcColType<ColIndices>::type actualColIndices = ivcCol(colIndices);
return BlockType(derived(),
internal::first(actualRowIndices),
internal::first(actualColIndices),
internal::size(actualRowIndices),
internal::size(actualColIndices));
}
// The following overload returns a Scalar
template<typename RowIndices, typename ColIndices>
typename internal::enable_if<valid_indexed_view_overload<RowIndices,ColIndices>::value
&& internal::traits<typename EIGEN_INDEXED_VIEW_METHOD_TYPE<RowIndices,ColIndices>::type>::ReturnAsScalar,
CoeffReturnType >::type
operator()(const RowIndices& rowIndices, const ColIndices& colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
return Base::operator()(internal::eval_expr_given_size(rowIndices,rows()),internal::eval_expr_given_size(colIndices,cols()));
}
// The folowing three overloads are needed to handle raw Index[N] arrays.
template<typename RowIndicesT, std::size_t RowIndicesN, typename ColIndices>
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,const RowIndicesT (&)[RowIndicesN],typename IvcColType<ColIndices>::type>
operator()(const RowIndicesT (&rowIndices)[RowIndicesN], const ColIndices& colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,const RowIndicesT (&)[RowIndicesN],typename IvcColType<ColIndices>::type>
(derived(), rowIndices, ivcCol(colIndices));
}
template<typename RowIndices, typename ColIndicesT, std::size_t ColIndicesN>
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,typename IvcRowType<RowIndices>::type, const ColIndicesT (&)[ColIndicesN]>
operator()(const RowIndices& rowIndices, const ColIndicesT (&colIndices)[ColIndicesN]) EIGEN_INDEXED_VIEW_METHOD_CONST
{
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,typename IvcRowType<RowIndices>::type,const ColIndicesT (&)[ColIndicesN]>
(derived(), ivcRow(rowIndices), colIndices);
}
template<typename RowIndicesT, std::size_t RowIndicesN, typename ColIndicesT, std::size_t ColIndicesN>
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,const RowIndicesT (&)[RowIndicesN], const ColIndicesT (&)[ColIndicesN]>
operator()(const RowIndicesT (&rowIndices)[RowIndicesN], const ColIndicesT (&colIndices)[ColIndicesN]) EIGEN_INDEXED_VIEW_METHOD_CONST
{
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,const RowIndicesT (&)[RowIndicesN],const ColIndicesT (&)[ColIndicesN]>
(derived(), rowIndices, colIndices);
}
// Overloads for 1D vectors/arrays
template<typename Indices>
typename internal::enable_if<
IsRowMajor && (!(internal::get_compile_time_incr<typename IvcType<Indices>::type>::value==1 || internal::is_integral<Indices>::value)),
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,IvcIndex,typename IvcType<Indices>::type> >::type
operator()(const Indices& indices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,IvcIndex,typename IvcType<Indices>::type>
(derived(), IvcIndex(0), ivcCol(indices));
}
template<typename Indices>
typename internal::enable_if<
(!IsRowMajor) && (!(internal::get_compile_time_incr<typename IvcType<Indices>::type>::value==1 || internal::is_integral<Indices>::value)),
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,typename IvcType<Indices>::type,IvcIndex> >::type
operator()(const Indices& indices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,typename IvcType<Indices>::type,IvcIndex>
(derived(), ivcRow(indices), IvcIndex(0));
}
template<typename Indices>
typename internal::enable_if<
(internal::get_compile_time_incr<typename IvcType<Indices>::type>::value==1) && (!internal::is_integral<Indices>::value) && (!Symbolic::is_symbolic<Indices>::value),
VectorBlock<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,internal::array_size<Indices>::value> >::type
operator()(const Indices& indices) EIGEN_INDEXED_VIEW_METHOD_CONST
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
typename IvcType<Indices>::type actualIndices = ivcSize(indices);
return VectorBlock<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,internal::array_size<Indices>::value>
(derived(), internal::first(actualIndices), internal::size(actualIndices));
}
template<typename IndexType>
typename internal::enable_if<Symbolic::is_symbolic<IndexType>::value, CoeffReturnType >::type
operator()(const IndexType& id) EIGEN_INDEXED_VIEW_METHOD_CONST
{
return Base::operator()(internal::eval_expr_given_size(id,size()));
}
template<typename IndicesT, std::size_t IndicesN>
typename internal::enable_if<IsRowMajor,
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,IvcIndex,const IndicesT (&)[IndicesN]> >::type
operator()(const IndicesT (&indices)[IndicesN]) EIGEN_INDEXED_VIEW_METHOD_CONST
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,IvcIndex,const IndicesT (&)[IndicesN]>
(derived(), IvcIndex(0), indices);
}
template<typename IndicesT, std::size_t IndicesN>
typename internal::enable_if<!IsRowMajor,
IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,const IndicesT (&)[IndicesN],IvcIndex> >::type
operator()(const IndicesT (&indices)[IndicesN]) EIGEN_INDEXED_VIEW_METHOD_CONST
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return IndexedView<EIGEN_INDEXED_VIEW_METHOD_CONST Derived,const IndicesT (&)[IndicesN],IvcIndex>
(derived(), indices, IvcIndex(0));
}
#undef EIGEN_INDEXED_VIEW_METHOD_CONST
#undef EIGEN_INDEXED_VIEW_METHOD_TYPE
#ifndef EIGEN_INDEXED_VIEW_METHOD_2ND_PASS
#define EIGEN_INDEXED_VIEW_METHOD_2ND_PASS
#include "IndexedViewMethods.h"
#undef EIGEN_INDEXED_VIEW_METHOD_2ND_PASS
#endif
#else // EIGEN_PARSED_BY_DOXYGEN
/**
* \returns a generic submatrix view defined by the rows and columns indexed \a rowIndices and \a colIndices respectively.
*
* Each parameter must either be:
* - An integer indexing a single row or column
* - Eigen::all indexing the full set of respective rows or columns in increasing order
* - An ArithmeticSequence as returned by the Eigen::seq and Eigen::seqN functions
* - Any %Eigen's vector/array of integers or expressions
* - Plain C arrays: \c int[N]
* - And more generally any type exposing the following two member functions:
* \code
* <integral type> operator[](<integral type>) const;
* <integral type> size() const;
* \endcode
* where \c <integral \c type> stands for any integer type compatible with Eigen::Index (i.e. \c std::ptrdiff_t).
*
* The last statement implies compatibility with \c std::vector, \c std::valarray, \c std::array, many of the Range-v3's ranges, etc.
*
* If the submatrix can be represented using a starting position \c (i,j) and positive sizes \c (rows,columns), then this
* method will returns a Block object after extraction of the relevant information from the passed arguments. This is the case
* when all arguments are either:
* - An integer
* - Eigen::all
* - An ArithmeticSequence with compile-time increment strictly equal to 1, as returned by Eigen::seq(a,b), and Eigen::seqN(a,N).
*
* Otherwise a more general IndexedView<Derived,RowIndices',ColIndices'> object will be returned, after conversion of the inputs
* to more suitable types \c RowIndices' and \c ColIndices'.
*
* For 1D vectors and arrays, you better use the operator()(const Indices&) overload, which behave the same way but taking a single parameter.
*
* \sa operator()(const Indices&), class Block, class IndexedView, DenseBase::block(Index,Index,Index,Index)
*/
template<typename RowIndices, typename ColIndices>
IndexedView_or_Block
operator()(const RowIndices& rowIndices, const ColIndices& colIndices);
/** This is an overload of operator()(const RowIndices&, const ColIndices&) for 1D vectors or arrays
*
* \only_for_vectors
*/
template<typename Indices>
IndexedView_or_VectorBlock
operator()(const Indices& indices);
#endif // EIGEN_PARSED_BY_DOXYGEN