mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-01-30 17:40:05 +08:00
Merged in ggael/eigen-flexidexing (pull request PR-294)
generalized operator() for indexed access and slicing
This commit is contained in:
commit
25a1703579
@ -363,6 +363,9 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/util/StaticAssert.h"
|
||||
#include "src/Core/util/XprHelper.h"
|
||||
#include "src/Core/util/Memory.h"
|
||||
#include "src/Core/util/IntegralConstant.h"
|
||||
#include "src/Core/util/SymbolicIndex.h"
|
||||
|
||||
|
||||
#include "src/Core/NumTraits.h"
|
||||
#include "src/Core/MathFunctions.h"
|
||||
@ -427,6 +430,8 @@ using std::ptrdiff_t;
|
||||
// on CUDA devices
|
||||
#include "src/Core/arch/CUDA/Complex.h"
|
||||
|
||||
#include "src/Core/util/IndexedViewHelper.h"
|
||||
#include "src/Core/ArithmeticSequence.h"
|
||||
#include "src/Core/DenseCoeffsBase.h"
|
||||
#include "src/Core/DenseBase.h"
|
||||
#include "src/Core/MatrixBase.h"
|
||||
@ -467,6 +472,7 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/Ref.h"
|
||||
#include "src/Core/Block.h"
|
||||
#include "src/Core/VectorBlock.h"
|
||||
#include "src/Core/IndexedView.h"
|
||||
#include "src/Core/Transpose.h"
|
||||
#include "src/Core/DiagonalMatrix.h"
|
||||
#include "src/Core/Diagonal.h"
|
||||
|
350
Eigen/src/Core/ArithmeticSequence.h
Normal file
350
Eigen/src/Core/ArithmeticSequence.h
Normal 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
|
@ -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
|
||||
|
207
Eigen/src/Core/IndexedView.h
Normal file
207
Eigen/src/Core/IndexedView.h
Normal 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
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
187
Eigen/src/Core/util/IndexedViewHelper.h
Normal file
187
Eigen/src/Core/util/IndexedViewHelper.h
Normal 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
|
270
Eigen/src/Core/util/IntegralConstant.h
Normal file
270
Eigen/src/Core/util/IntegralConstant.h
Normal 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
|
@ -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, \
|
||||
|
@ -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.
|
||||
*
|
||||
|
300
Eigen/src/Core/util/SymbolicIndex.h
Normal file
300
Eigen/src/Core/util/SymbolicIndex.h
Normal 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
|
@ -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
260
Eigen/src/plugins/IndexedViewMethods.h
Normal file
260
Eigen/src/plugins/IndexedViewMethods.h
Normal 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
|
||||
|
@ -229,7 +229,8 @@ ALIASES = "only_for_vectors=This is only for vectors (either row-
|
||||
"blank= " \
|
||||
"cpp11=<span class='cpp11'>[c++11]</span>" \
|
||||
"cpp14=<span class='cpp14'>[c++14]</span>" \
|
||||
"cpp17=<span class='cpp17'>[c++17]</span>"
|
||||
"cpp17=<span class='cpp17'>[c++17]</span>" \
|
||||
"newin{1}=<span class='newin3x'>New in %Eigen \1.</span>"
|
||||
|
||||
|
||||
ALIASES += "eigenAutoToc= "
|
||||
@ -409,7 +410,7 @@ EXTRACT_PACKAGE = NO
|
||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_STATIC = YES
|
||||
|
||||
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
|
||||
# defined locally in source files will be included in the documentation.
|
||||
|
@ -181,6 +181,11 @@ span.cpp11,span.cpp14,span.cpp17 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.newin3x {
|
||||
color: #a37c1a;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**** old Eigen's styles ****/
|
||||
|
||||
|
||||
|
@ -161,6 +161,8 @@ ei_add_test(redux)
|
||||
ei_add_test(visitor)
|
||||
ei_add_test(block)
|
||||
ei_add_test(corners)
|
||||
ei_add_test(symbolic_index)
|
||||
ei_add_test(indexed_view)
|
||||
ei_add_test(swap)
|
||||
ei_add_test(resize)
|
||||
ei_add_test(conservative_resize)
|
||||
|
@ -29,6 +29,13 @@ block_real_only(const MatrixType &, Index, Index, Index, Index, const Scalar&) {
|
||||
return Scalar(0);
|
||||
}
|
||||
|
||||
// Check at compile-time that T1==T2, and at runtime-time that a==b
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_block(const T1& a, const T2& b)
|
||||
{
|
||||
return a.isApprox(b);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void block(const MatrixType& m)
|
||||
{
|
||||
@ -106,6 +113,11 @@ template<typename MatrixType> void block(const MatrixType& m)
|
||||
m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols)(0,3) = m1.template block<2,5>(1,1)(1,2);
|
||||
Matrix<Scalar,Dynamic,Dynamic> b2 = m1.template block<Dynamic,BlockCols>(3,3,2,5);
|
||||
VERIFY_IS_EQUAL(b2, m1.block(3,3,BlockRows,BlockCols));
|
||||
|
||||
VERIFY(is_same_block(m1.block(3,3,BlockRows,BlockCols), m1.block(3,3,fix<Dynamic>(BlockRows),fix<Dynamic>(BlockCols))));
|
||||
VERIFY(is_same_block(m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols), m1.block(1,1,fix<BlockRows>,BlockCols)));
|
||||
VERIFY(is_same_block(m1.template block<BlockRows,BlockCols>(1,1,BlockRows,BlockCols), m1.block(1,1,fix<BlockRows>(),fix<BlockCols>)));
|
||||
VERIFY(is_same_block(m1.template block<BlockRows,BlockCols>(1,1,BlockRows,BlockCols), m1.block(1,1,fix<BlockRows>,fix<BlockCols>(BlockCols))));
|
||||
}
|
||||
|
||||
if (rows>2)
|
||||
|
378
test/indexed_view.cpp
Normal file
378
test/indexed_view.cpp
Normal file
@ -0,0 +1,378 @@
|
||||
// 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/.
|
||||
|
||||
#ifdef EIGEN_TEST_PART_2
|
||||
// Make sure we also check c++11 max implementation
|
||||
#define EIGEN_MAX_CPP_VER 11
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_TEST_PART_3
|
||||
// Make sure we also check c++98 max implementation
|
||||
#define EIGEN_MAX_CPP_VER 03
|
||||
#endif
|
||||
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
#include "main.h"
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
typedef std::pair<Index,Index> IndexPair;
|
||||
|
||||
int encode(Index i, Index j) {
|
||||
return int(i*100 + j);
|
||||
}
|
||||
|
||||
IndexPair decode(Index ij) {
|
||||
return IndexPair(ij / 100, ij % 100);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool match(const T& xpr, std::string ref, std::string str_xpr = "") {
|
||||
EIGEN_UNUSED_VARIABLE(str_xpr);
|
||||
std::stringstream str;
|
||||
str << xpr;
|
||||
if(!(str.str() == ref))
|
||||
std::cout << str_xpr << "\n" << xpr << "\n\n";
|
||||
return str.str() == ref;
|
||||
}
|
||||
|
||||
#define MATCH(X,R) match(X, R, #X)
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_eq(const T1& a, const T2& b)
|
||||
{
|
||||
return (a == b).all();
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
bool is_same_seq(const T1& a, const T2& b)
|
||||
{
|
||||
bool ok = a.first()==b.first() && a.size() == b.size() && Index(a.incrObject())==Index(b.incrObject());;
|
||||
if(!ok)
|
||||
{
|
||||
std::cerr << "seqN(" << a.first() << ", " << a.size() << ", " << Index(a.incrObject()) << ") != ";
|
||||
std::cerr << "seqN(" << b.first() << ", " << b.size() << ", " << Index(b.incrObject()) << ")\n";
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_seq_type(const T1& a, const T2& b)
|
||||
{
|
||||
return is_same_seq(a,b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define VERIFY_EQ_INT(A,B) VERIFY_IS_APPROX(int(A),int(B))
|
||||
|
||||
void check_indexed_view()
|
||||
{
|
||||
using Eigen::placeholders::all;
|
||||
using Eigen::placeholders::last;
|
||||
using Eigen::placeholders::end;
|
||||
|
||||
Index n = 10;
|
||||
|
||||
ArrayXd a = ArrayXd::LinSpaced(n,0,n-1);
|
||||
Array<double,1,Dynamic> b = a.transpose();
|
||||
|
||||
ArrayXXi A = ArrayXXi::NullaryExpr(n,n, std::ptr_fun(encode));
|
||||
|
||||
for(Index i=0; i<n; ++i)
|
||||
for(Index j=0; j<n; ++j)
|
||||
VERIFY( decode(A(i,j)) == IndexPair(i,j) );
|
||||
|
||||
Array4i eii(4); eii << 3, 1, 6, 5;
|
||||
std::valarray<int> vali(4); Map<ArrayXi>(&vali[0],4) = eii;
|
||||
std::vector<int> veci(4); Map<ArrayXi>(veci.data(),4) = eii;
|
||||
|
||||
VERIFY( MATCH( A(3, seq(9,3,-1)),
|
||||
"309 308 307 306 305 304 303")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(seqN(2,5), seq(9,3,-1)),
|
||||
"209 208 207 206 205 204 203\n"
|
||||
"309 308 307 306 305 304 303\n"
|
||||
"409 408 407 406 405 404 403\n"
|
||||
"509 508 507 506 505 504 503\n"
|
||||
"609 608 607 606 605 604 603")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(seqN(2,5), 5),
|
||||
"205\n"
|
||||
"305\n"
|
||||
"405\n"
|
||||
"505\n"
|
||||
"605")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(seqN(last,5,-1), seq(2,last)),
|
||||
"902 903 904 905 906 907 908 909\n"
|
||||
"802 803 804 805 806 807 808 809\n"
|
||||
"702 703 704 705 706 707 708 709\n"
|
||||
"602 603 604 605 606 607 608 609\n"
|
||||
"502 503 504 505 506 507 508 509")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(eii, veci),
|
||||
"303 301 306 305\n"
|
||||
"103 101 106 105\n"
|
||||
"603 601 606 605\n"
|
||||
"503 501 506 505")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(eii, all),
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"100 101 102 103 104 105 106 107 108 109\n"
|
||||
"600 601 602 603 604 605 606 607 608 609\n"
|
||||
"500 501 502 503 504 505 506 507 508 509")
|
||||
);
|
||||
|
||||
// takes the row numer 3, and repeat it 5 times
|
||||
VERIFY( MATCH( A(seqN(3,5,0), all),
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( a(seqN(3,3),0), "3\n4\n5" ) );
|
||||
VERIFY( MATCH( a(seq(3,5)), "3\n4\n5" ) );
|
||||
VERIFY( MATCH( a(seqN(3,3,1)), "3\n4\n5" ) );
|
||||
VERIFY( MATCH( a(seqN(5,3,-1)), "5\n4\n3" ) );
|
||||
|
||||
VERIFY( MATCH( b(0,seqN(3,3)), "3 4 5" ) );
|
||||
VERIFY( MATCH( b(seq(3,5)), "3 4 5" ) );
|
||||
VERIFY( MATCH( b(seqN(3,3,1)), "3 4 5" ) );
|
||||
VERIFY( MATCH( b(seqN(5,3,-1)), "5 4 3" ) );
|
||||
|
||||
VERIFY( MATCH( b(all), "0 1 2 3 4 5 6 7 8 9" ) );
|
||||
VERIFY( MATCH( b(eii), "3 1 6 5" ) );
|
||||
|
||||
Array44i B;
|
||||
B.setRandom();
|
||||
VERIFY( (A(seqN(2,5), 5)).ColsAtCompileTime == 1);
|
||||
VERIFY( (A(seqN(2,5), 5)).RowsAtCompileTime == Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), 5)).InnerStrideAtCompileTime , A.InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), 5)).OuterStrideAtCompileTime , A.col(5).OuterStrideAtCompileTime);
|
||||
|
||||
VERIFY_EQ_INT( (A(5,seqN(2,5))).InnerStrideAtCompileTime , A.row(5).InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(5,seqN(2,5))).OuterStrideAtCompileTime , A.row(5).OuterStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(1,seqN(1,2))).InnerStrideAtCompileTime , B.row(1).InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(1,seqN(1,2))).OuterStrideAtCompileTime , B.row(1).OuterStrideAtCompileTime);
|
||||
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), seq(1,3))).InnerStrideAtCompileTime , A.InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), seq(1,3))).OuterStrideAtCompileTime , A.OuterStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2), seq(1,3))).InnerStrideAtCompileTime , B.InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2), seq(1,3))).OuterStrideAtCompileTime , B.OuterStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,2), seq(1,3,2))).InnerStrideAtCompileTime , Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,2), seq(1,3,2))).OuterStrideAtCompileTime , Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,fix<2>), seq(1,3,fix<3>))).InnerStrideAtCompileTime , 2);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,fix<2>), seq(1,3,fix<3>))).OuterStrideAtCompileTime , Dynamic);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2,fix<2>), seq(1,3,fix<3>))).InnerStrideAtCompileTime , 2);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2,fix<2>), seq(1,3,fix<3>))).OuterStrideAtCompileTime , 3*4);
|
||||
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>), seqN(1,fix<3>))).RowsAtCompileTime, 5);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>), seqN(1,fix<3>))).ColsAtCompileTime, 3);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>(5)), seqN(1,fix<3>(3)))).RowsAtCompileTime, 5);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>(5)), seqN(1,fix<3>(3)))).ColsAtCompileTime, 3);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).RowsAtCompileTime, Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).ColsAtCompileTime, Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).rows(), 5);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).cols(), 3);
|
||||
|
||||
VERIFY( is_same_seq_type( seqN(2,5,fix<-1>), seqN(2,5,fix<-1>(-1)) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,5), seqN(2,5,fix<1>(1)) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,5,3), seqN(2,5,fix<DynamicIndex>(3)) ) );
|
||||
VERIFY( is_same_seq_type( seq(2,7,fix<3>), seqN(2,2,fix<3>) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,fix<Dynamic>(5),3), seqN(2,5,fix<DynamicIndex>(3)) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,fix<5>(5),fix<-2>), seqN(2,fix<5>,fix<-2>()) ) );
|
||||
|
||||
VERIFY( is_same_seq_type( seq(2,fix<5>), seqN(2,4) ) );
|
||||
#if EIGEN_HAS_CXX11
|
||||
VERIFY( is_same_seq_type( seq(fix<2>,fix<5>), seqN(fix<2>,fix<4>) ) );
|
||||
VERIFY( is_same_seq( seqN(2,std::integral_constant<int,5>(),std::integral_constant<int,-2>()), seqN(2,fix<5>,fix<-2>()) ) );
|
||||
VERIFY( is_same_seq( seq(std::integral_constant<int,1>(),std::integral_constant<int,5>(),std::integral_constant<int,2>()),
|
||||
seq(fix<1>,fix<5>,fix<2>()) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,std::integral_constant<int,5>(),std::integral_constant<int,-2>()), seqN(2,fix<5>,fix<-2>()) ) );
|
||||
VERIFY( is_same_seq_type( seq(std::integral_constant<int,1>(),std::integral_constant<int,5>(),std::integral_constant<int,2>()),
|
||||
seq(fix<1>,fix<5>,fix<2>()) ) );
|
||||
|
||||
VERIFY( is_same_seq_type( seqN(2,std::integral_constant<int,5>()), seqN(2,fix<5>) ) );
|
||||
VERIFY( is_same_seq_type( seq(std::integral_constant<int,1>(),std::integral_constant<int,5>()), seq(fix<1>,fix<5>) ) );
|
||||
#else
|
||||
// sorry, no compile-time size recovery in c++98/03
|
||||
VERIFY( is_same_seq( seq(fix<2>,fix<5>), seqN(fix<2>,fix<4>) ) );
|
||||
#endif
|
||||
|
||||
VERIFY( (A(seqN(2,fix<5>), 5)).RowsAtCompileTime == 5);
|
||||
VERIFY( (A(4, all)).ColsAtCompileTime == Dynamic);
|
||||
VERIFY( (A(4, all)).RowsAtCompileTime == 1);
|
||||
VERIFY( (B(1, all)).ColsAtCompileTime == 4);
|
||||
VERIFY( (B(1, all)).RowsAtCompileTime == 1);
|
||||
VERIFY( (B(all,1)).ColsAtCompileTime == 1);
|
||||
VERIFY( (B(all,1)).RowsAtCompileTime == 4);
|
||||
|
||||
VERIFY(int( (A(all, eii)).ColsAtCompileTime) == int(eii.SizeAtCompileTime));
|
||||
VERIFY_EQ_INT( (A(eii, eii)).Flags&DirectAccessBit, (unsigned int)(0));
|
||||
VERIFY_EQ_INT( (A(eii, eii)).InnerStrideAtCompileTime, 0);
|
||||
VERIFY_EQ_INT( (A(eii, eii)).OuterStrideAtCompileTime, 0);
|
||||
|
||||
VERIFY_IS_APPROX( A(seq(n-1,2,-2), seqN(n-1-6,3,-1)), A(seq(last,2,fix<-2>), seqN(last-6,3,fix<-1>)) );
|
||||
|
||||
VERIFY_IS_APPROX( A(seq(n-1,2,-2), seqN(n-1-6,4)), A(seq(last,2,-2), seqN(last-6,4)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-6,n-1-2), seqN(n-1-6,4)), A(seq(last-6,last-2), seqN(6+last-6-6,4)) );
|
||||
VERIFY_IS_APPROX( A(seq((n-1)/2,(n)/2+3), seqN(2,4)), A(seq(last/2,(last+1)/2+3), seqN(last+2-last,4)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-2,2,-2), seqN(n-8,4)), A(seq(end-2,2,-2), seqN(end-8,4)) );
|
||||
|
||||
// Check all combinations of seq:
|
||||
VERIFY_IS_APPROX( A(seq(1,n-1-2,2), seq(1,n-1-2,2)), A(seq(1,last-2,2), seq(1,last-2,fix<2>)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-5,n-1-2,2), seq(n-1-5,n-1-2,2)), A(seq(last-5,last-2,2), seq(last-5,last-2,fix<2>)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-5,7,2), seq(n-1-5,7,2)), A(seq(last-5,7,2), seq(last-5,7,fix<2>)) );
|
||||
VERIFY_IS_APPROX( A(seq(1,n-1-2), seq(n-1-5,7)), A(seq(1,last-2), seq(last-5,7)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-5,n-1-2), seq(n-1-5,n-1-2)), A(seq(last-5,last-2), seq(last-5,last-2)) );
|
||||
|
||||
VERIFY_IS_APPROX( A.col(A.cols()-1), A(all,last) );
|
||||
VERIFY_IS_APPROX( A(A.rows()-2, A.cols()/2), A(last-1, end/2) );
|
||||
VERIFY_IS_APPROX( a(a.size()-2), a(last-1) );
|
||||
VERIFY_IS_APPROX( a(a.size()/2), a((last+1)/2) );
|
||||
|
||||
// Check fall-back to Block
|
||||
{
|
||||
VERIFY( is_same_eq(A.col(0), A(all,0)) );
|
||||
VERIFY( is_same_eq(A.row(0), A(0,all)) );
|
||||
VERIFY( is_same_eq(A.block(0,0,2,2), A(seqN(0,2),seq(0,1))) );
|
||||
VERIFY( is_same_eq(A.middleRows(2,4), A(seqN(2,4),all)) );
|
||||
VERIFY( is_same_eq(A.middleCols(2,4), A(all,seqN(2,4))) );
|
||||
|
||||
VERIFY( is_same_eq(A.col(A.cols()-1), A(all,last)) );
|
||||
|
||||
const ArrayXXi& cA(A);
|
||||
VERIFY( is_same_eq(cA.col(0), cA(all,0)) );
|
||||
VERIFY( is_same_eq(cA.row(0), cA(0,all)) );
|
||||
VERIFY( is_same_eq(cA.block(0,0,2,2), cA(seqN(0,2),seq(0,1))) );
|
||||
VERIFY( is_same_eq(cA.middleRows(2,4), cA(seqN(2,4),all)) );
|
||||
VERIFY( is_same_eq(cA.middleCols(2,4), cA(all,seqN(2,4))) );
|
||||
|
||||
VERIFY( is_same_eq(a.head(4), a(seq(0,3))) );
|
||||
VERIFY( is_same_eq(a.tail(4), a(seqN(last-3,4))) );
|
||||
VERIFY( is_same_eq(a.tail(4), a(seq(end-4,last))) );
|
||||
VERIFY( is_same_eq(a.segment<4>(3), a(seqN(3,fix<4>))) );
|
||||
}
|
||||
|
||||
ArrayXXi A1=A, A2 = ArrayXXi::Random(4,4);
|
||||
ArrayXi range25(4); range25 << 3,2,4,5;
|
||||
A1(seqN(3,4),seq(2,5)) = A2;
|
||||
VERIFY_IS_APPROX( A1.block(3,2,4,4), A2 );
|
||||
A1 = A;
|
||||
A2.setOnes();
|
||||
A1(seq(6,3,-1),range25) = A2;
|
||||
VERIFY_IS_APPROX( A1.block(3,2,4,4), A2 );
|
||||
|
||||
// check reverse
|
||||
{
|
||||
VERIFY( is_same_seq_type( seq(3,7).reverse(), seqN(7,5,fix<-1>) ) );
|
||||
VERIFY( is_same_seq_type( seq(7,3,fix<-2>).reverse(), seqN(3,3,fix<2>) ) );
|
||||
VERIFY_IS_APPROX( a(seqN(2,last/2).reverse()), a(seqN(2+(last/2-1)*1,last/2,fix<-1>)) );
|
||||
VERIFY_IS_APPROX( a(seqN(last/2,fix<4>).reverse()),a(seqN(last/2,fix<4>)).reverse() );
|
||||
VERIFY_IS_APPROX( A(seq(last-5,last-1,2).reverse(), seqN(last-3,3,fix<-2>).reverse()),
|
||||
A(seq(last-5,last-1,2), seqN(last-3,3,fix<-2>)).reverse() );
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
VERIFY( (A(all, std::array<int,4>{{1,3,2,4}})).ColsAtCompileTime == 4);
|
||||
|
||||
VERIFY_IS_APPROX( (A(std::array<int,3>{{1,3,5}}, std::array<int,4>{{9,6,3,0}})), A(seqN(1,3,2), seqN(9,4,-3)) );
|
||||
|
||||
#if (!EIGEN_COMP_CLANG) || (EIGEN_COMP_CLANG>=308 && !defined(__apple_build_version__))
|
||||
VERIFY_IS_APPROX( A({3, 1, 6, 5}, all), A(std::array<int,4>{{3, 1, 6, 5}}, all) );
|
||||
VERIFY_IS_APPROX( A(all,{3, 1, 6, 5}), A(all,std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
VERIFY_IS_APPROX( A({1,3,5},{3, 1, 6, 5}), A(std::array<int,3>{{1,3,5}},std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
|
||||
VERIFY_IS_EQUAL( A({1,3,5},{3, 1, 6, 5}).RowsAtCompileTime, 3 );
|
||||
VERIFY_IS_EQUAL( A({1,3,5},{3, 1, 6, 5}).ColsAtCompileTime, 4 );
|
||||
|
||||
VERIFY_IS_APPROX( a({3, 1, 6, 5}), a(std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
VERIFY_IS_EQUAL( a({1,3,5}).SizeAtCompileTime, 3 );
|
||||
|
||||
VERIFY_IS_APPROX( b({3, 1, 6, 5}), b(std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
VERIFY_IS_EQUAL( b({1,3,5}).SizeAtCompileTime, 3 );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// check mat(i,j) with weird types for i and j
|
||||
{
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime-1, 1), A(3,1) );
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime, 1), A(4,1) );
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime-1, B.ColsAtCompileTime-1), A(3,3) );
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime, B.ColsAtCompileTime), A(4,4) );
|
||||
const Index I = 3, J = 4;
|
||||
VERIFY_IS_APPROX( A(I,J), A(3,4) );
|
||||
}
|
||||
|
||||
// check extended block API
|
||||
{
|
||||
VERIFY( is_same_eq( A.block<3,4>(1,1), A.block(1,1,fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.block<3,4>(1,1,3,4), A.block(1,1,fix<3>(),fix<4>(4))) );
|
||||
VERIFY( is_same_eq( A.block<3,Dynamic>(1,1,3,4), A.block(1,1,fix<3>,4)) );
|
||||
VERIFY( is_same_eq( A.block<Dynamic,4>(1,1,3,4), A.block(1,1,fix<Dynamic>(3),fix<4>)) );
|
||||
VERIFY( is_same_eq( A.block(1,1,3,4), A.block(1,1,fix<Dynamic>(3),fix<Dynamic>(4))) );
|
||||
|
||||
VERIFY( is_same_eq( A.topLeftCorner<3,4>(), A.topLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.bottomLeftCorner<3,4>(), A.bottomLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.bottomRightCorner<3,4>(), A.bottomRightCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.topRightCorner<3,4>(), A.topRightCorner(fix<3>,fix<4>)) );
|
||||
|
||||
VERIFY( is_same_eq( A.leftCols<3>(), A.leftCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.rightCols<3>(), A.rightCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.middleCols<3>(1), A.middleCols(1,fix<3>)) );
|
||||
|
||||
VERIFY( is_same_eq( A.topRows<3>(), A.topRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.bottomRows<3>(), A.bottomRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.middleRows<3>(1), A.middleRows(1,fix<3>)) );
|
||||
|
||||
VERIFY( is_same_eq( a.segment<3>(1), a.segment(1,fix<3>)) );
|
||||
VERIFY( is_same_eq( a.head<3>(), a.head(fix<3>)) );
|
||||
VERIFY( is_same_eq( a.tail<3>(), a.tail(fix<3>)) );
|
||||
|
||||
const ArrayXXi& cA(A);
|
||||
VERIFY( is_same_eq( cA.block<Dynamic,4>(1,1,3,4), cA.block(1,1,fix<Dynamic>(3),fix<4>)) );
|
||||
|
||||
VERIFY( is_same_eq( cA.topLeftCorner<3,4>(), cA.topLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( cA.bottomLeftCorner<3,4>(), cA.bottomLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( cA.bottomRightCorner<3,4>(), cA.bottomRightCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( cA.topRightCorner<3,4>(), cA.topRightCorner(fix<3>,fix<4>)) );
|
||||
|
||||
VERIFY( is_same_eq( cA.leftCols<3>(), cA.leftCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.rightCols<3>(), cA.rightCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.middleCols<3>(1), cA.middleCols(1,fix<3>)) );
|
||||
|
||||
VERIFY( is_same_eq( cA.topRows<3>(), cA.topRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.bottomRows<3>(), cA.bottomRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.middleRows<3>(1), cA.middleRows(1,fix<3>)) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_indexed_view()
|
||||
{
|
||||
// for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( check_indexed_view() );
|
||||
CALL_SUBTEST_2( check_indexed_view() );
|
||||
CALL_SUBTEST_3( check_indexed_view() );
|
||||
// }
|
||||
}
|
104
test/symbolic_index.cpp
Normal file
104
test/symbolic_index.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
// 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/.
|
||||
|
||||
#ifdef EIGEN_TEST_PART_2
|
||||
#define EIGEN_MAX_CPP_VER 03
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename T>
|
||||
bool match(const T& xpr, std::string ref, std::string str_xpr = "") {
|
||||
EIGEN_UNUSED_VARIABLE(str_xpr);
|
||||
std::stringstream str;
|
||||
str << xpr;
|
||||
if(!(str.str() == ref))
|
||||
std::cout << str_xpr << "\n" << xpr << "\n\n";
|
||||
return str.str() == ref;
|
||||
}
|
||||
|
||||
#define MATCH(X,R) match(X, R, #X)
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_fixed(const T1& a, const T2& b)
|
||||
{
|
||||
return (Index(a) == Index(b));
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
bool is_same_seq(const T1& a, const T2& b)
|
||||
{
|
||||
bool ok = a.first()==b.first() && a.size() == b.size() && Index(a.incrObject())==Index(b.incrObject());;
|
||||
if(!ok)
|
||||
{
|
||||
std::cerr << "seqN(" << a.first() << ", " << a.size() << ", " << Index(a.incrObject()) << ") != ";
|
||||
std::cerr << "seqN(" << b.first() << ", " << b.size() << ", " << Index(b.incrObject()) << ")\n";
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_type(const T1&, const T2&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
bool is_same_symb(const T1& a, const T2& b, Index size)
|
||||
{
|
||||
using Eigen::placeholders::last;
|
||||
return a.eval(last=size-1) == b.eval(last=size-1);
|
||||
}
|
||||
|
||||
|
||||
#define VERIFY_EQ_INT(A,B) VERIFY_IS_APPROX(int(A),int(B))
|
||||
|
||||
void check_symbolic_index()
|
||||
{
|
||||
using Eigen::placeholders::last;
|
||||
using Eigen::placeholders::end;
|
||||
|
||||
Index size=100;
|
||||
|
||||
// First, let's check FixedInt arithmetic:
|
||||
VERIFY( is_same_type( (fix<5>()-fix<3>())*fix<9>()/(-fix<3>()), fix<-(5-3)*9/3>() ) );
|
||||
VERIFY( is_same_type( (fix<5>()-fix<3>())*fix<9>()/fix<2>(), fix<(5-3)*9/2>() ) );
|
||||
VERIFY( is_same_type( fix<9>()/fix<2>(), fix<9/2>() ) );
|
||||
VERIFY( is_same_type( fix<9>()%fix<2>(), fix<9%2>() ) );
|
||||
VERIFY( is_same_type( fix<9>()&fix<2>(), fix<9&2>() ) );
|
||||
VERIFY( is_same_type( fix<9>()|fix<2>(), fix<9|2>() ) );
|
||||
VERIFY( is_same_type( fix<9>()/2, int(9/2) ) );
|
||||
|
||||
VERIFY( is_same_symb( end-1, last, size) );
|
||||
VERIFY( is_same_symb( end-fix<1>, last, size) );
|
||||
|
||||
VERIFY_IS_EQUAL( ( (last*5-2)/3 ).eval(last=size-1), ((size-1)*5-2)/3 );
|
||||
VERIFY_IS_EQUAL( ( (last*fix<5>-fix<2>)/fix<3> ).eval(last=size-1), ((size-1)*5-2)/3 );
|
||||
VERIFY_IS_EQUAL( ( -last*end ).eval(last=size-1), -(size-1)*size );
|
||||
VERIFY_IS_EQUAL( ( end-3*last ).eval(last=size-1), size- 3*(size-1) );
|
||||
VERIFY_IS_EQUAL( ( (end-3*last)/end ).eval(last=size-1), (size- 3*(size-1))/size );
|
||||
|
||||
#if EIGEN_HAS_CXX14
|
||||
{
|
||||
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;
|
||||
|
||||
VERIFY_IS_APPROX( int(((x+3)/y+z).eval(x=6,y=3,z=-13)), (6+3)/3+(-13) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_symbolic_index()
|
||||
{
|
||||
CALL_SUBTEST_1( check_symbolic_index() );
|
||||
CALL_SUBTEST_2( check_symbolic_index() );
|
||||
}
|
@ -200,19 +200,15 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array<T,N>& a) {
|
||||
return a[I];
|
||||
}
|
||||
|
||||
template <typename T> struct array_size;
|
||||
template<class T, std::size_t N> struct array_size<array<T,N> > {
|
||||
static const size_t value = N;
|
||||
};
|
||||
template <typename T> struct array_size;
|
||||
template<class T, std::size_t N> struct array_size<array<T,N>& > {
|
||||
static const size_t value = N;
|
||||
};
|
||||
template <typename T> struct array_size;
|
||||
template<class T, std::size_t N> struct array_size<const array<T,N> > {
|
||||
static const size_t value = N;
|
||||
};
|
||||
template <typename T> struct array_size;
|
||||
template<class T, std::size_t N> struct array_size<const array<T,N>& > {
|
||||
static const size_t value = N;
|
||||
};
|
||||
@ -251,14 +247,6 @@ template<std::size_t I, class T, std::size_t N> constexpr inline T const& array_
|
||||
|
||||
#undef STD_GET_ARR_HACK
|
||||
|
||||
template <typename T> struct array_size;
|
||||
template<class T, std::size_t N> struct array_size<const std::array<T,N> > {
|
||||
static const size_t value = N;
|
||||
};
|
||||
template <typename T> struct array_size;
|
||||
template<class T, std::size_t N> struct array_size<std::array<T,N> > {
|
||||
static const size_t value = N;
|
||||
};
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user