Large code refactoring:

- generalize some utilities and move them to Meta (size(), array_size())
 - move handling of all and single indices to IndexedViewHelper.h
 - several cleanup changes
This commit is contained in:
Gael Guennebaud
2017-01-11 17:24:02 +01:00
parent f93d1c58e0
commit 752bd92ba5
7 changed files with 244 additions and 154 deletions

View File

@@ -12,26 +12,10 @@
namespace Eigen {
//--------------------------------------------------------------------------------
// Pseudo keywords: all, last, end
//--------------------------------------------------------------------------------
namespace internal {
struct all_t { all_t() {} };
}
/** \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 internal::all_t all;
/** \namespace Eigen::placeholders
* \ingroup Core_Module
*
* Namespace containing symbolic placeholders
* Namespace containing symbolic placeholder and identifiers
*/
namespace placeholders {
@@ -268,7 +252,7 @@ typename internal::enable_if<!Symbolic::is_symbolic<FirstType>::value,
Symbolic::QuotientExpr<Symbolic::AddExpr<Symbolic::AddExpr<LastTypeDerived,Symbolic::ValueExpr>,
Symbolic::ValueExpr>,
Symbolic::ValueExpr>,
typename internal::cleanup_seq_type<IncrType>::type> >::type
typename internal::cleanup_seq_type<IncrType>::type> >::type
seq(FirstType f, const Symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr)
{
typedef typename internal::cleanup_seq_type<IncrType>::type CleanedIncrType;
@@ -281,7 +265,7 @@ ArithemeticSequence<FirstTypeDerived,
Symbolic::NegateExpr<FirstTypeDerived> >,
Symbolic::ValueExpr>,
Symbolic::ValueExpr>,
typename internal::cleanup_seq_type<IncrType>::type>
typename internal::cleanup_seq_type<IncrType>::type>
seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, const Symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr)
{
typedef typename internal::cleanup_seq_type<IncrType>::type CleanedIncrType;
@@ -293,76 +277,6 @@ seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, const Symbolic::BaseExpr<Last
namespace internal {
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; }
template<typename T>
Index first(const T& x) { return x.first(); }
template<typename T, int XprSize, typename EnableIf = void> struct get_compile_time_size {
enum { value = Dynamic };
};
template<typename T, int XprSize> struct get_compile_time_size<T,XprSize,typename internal::enable_if<((T::SizeAtCompileTime&0)==0)>::type> {
enum { value = T::SizeAtCompileTime };
};
template<typename T, int XprSize, int N> struct get_compile_time_size<const T (&)[N],XprSize> {
enum { value = N };
};
#ifdef EIGEN_HAS_CXX11
template<typename T, int XprSize, std::size_t N> struct get_compile_time_size<std::array<T,N>,XprSize> {
enum { value = N };
};
#endif
template<typename T, typename EnableIf = void> struct get_compile_time_incr {
enum { value = UndefinedIncr };
};
template<typename FirstType,typename SizeType,typename IncrType>
struct get_compile_time_incr<ArithemeticSequence<FirstType,SizeType,IncrType> > {
enum { value = get_compile_time<IncrType,DynamicIndex>::value };
};
// MakeIndexing/make_indexing turn an arbitrary object of type T into something usable by MatrixSlice
template<typename T,typename EnableIf=void>
struct MakeIndexing {
typedef T type;
};
template<typename T>
const T& make_indexing(const T& x, Index /*size*/) { return x; }
struct IntAsArray {
enum {
SizeAtCompileTime = 1
};
IntAsArray(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<IntAsArray> {
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>
struct MakeIndexing<T,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 IntAsArray
//typedef Eigen::Array<Index,1,1> type;
typedef IntAsArray type;
};
// Replace symbolic last/end "keywords" by their true runtime value
inline Index eval_expr_given_size(Index x, Index /* size */) { return x; }
@@ -381,45 +295,21 @@ struct make_size_type {
typedef typename internal::conditional<Symbolic::is_symbolic<T>::value, Index, T>::type type;
};
template<typename FirstType,typename SizeType,typename IncrType>
struct MakeIndexing<ArithemeticSequence<FirstType,SizeType,IncrType> > {
template<typename FirstType,typename SizeType,typename IncrType,int XprSize>
struct IndexedViewCompatibleType<ArithemeticSequence<FirstType,SizeType,IncrType>, XprSize> {
typedef ArithemeticSequence<Index,typename make_size_type<SizeType>::type,IncrType> type;
};
template<typename FirstType,typename SizeType,typename IncrType>
ArithemeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>
make_indexing(const ArithemeticSequence<FirstType,SizeType,IncrType>& ids, Index size) {
makeIndexedViewCompatible(const ArithemeticSequence<FirstType,SizeType,IncrType>& ids, Index size) {
return ArithemeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>(
eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.sizeObject(),size),ids.incrObject());
}
// Convert a symbolic 'all' into a usable range
// Implementation-wise, it would be more efficient to not having to store m_size since
// this information is already in the nested expression. To this end, we would need a
// get_size(indices, underlying_size); function returning indices.size() by default.
struct AllRange {
AllRange(Index size) : m_size(size) {}
Index operator[](Index i) const { return i; }
Index size() const { return m_size; }
Index first() const { return 0; }
Index m_size;
};
template<>
struct MakeIndexing<all_t> {
typedef AllRange type;
};
inline AllRange make_indexing(all_t , Index size) {
return AllRange(size);
}
template<int XprSize> struct get_compile_time_size<AllRange,XprSize> {
enum { value = XprSize };
};
template<> struct get_compile_time_incr<AllRange> {
enum { value = 1 };
template<typename FirstType,typename SizeType,typename IncrType>
struct get_compile_time_incr<ArithemeticSequence<FirstType,SizeType,IncrType> > {
enum { value = get_compile_time<IncrType,DynamicIndex>::value };
};
} // end namespace internal
@@ -428,6 +318,7 @@ template<> struct get_compile_time_incr<AllRange> {
namespace legacy {
// Here are some initial code that I keep here for now to compare the quality of the code generated by the compilers
// This part will be removed once we have checked everything is right.
struct shifted_last {
explicit shifted_last(int o) : offset(o) {}
@@ -522,14 +413,14 @@ struct get_compile_time_incr<legacy::ArithemeticSequenceProxyWithBounds<FirstTyp
};
// Convert a symbolic range into a usable one (i.e., remove last/end "keywords")
template<typename FirstType,typename LastType,typename IncrType>
struct MakeIndexing<legacy::ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType> > {
template<typename FirstType,typename LastType,typename IncrType,int XprSize>
struct IndexedViewCompatibleType<legacy::ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType>,XprSize> {
typedef legacy::ArithemeticSequenceProxyWithBounds<Index,Index,IncrType> type;
};
template<typename FirstType,typename LastType,typename IncrType>
legacy::ArithemeticSequenceProxyWithBounds<Index,Index,IncrType>
make_indexing(const legacy::ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType>& ids, Index size) {
makeIndexedViewCompatible(const legacy::ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType>& ids, Index size) {
return legacy::ArithemeticSequenceProxyWithBounds<Index,Index,IncrType>(
eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.lastObject(),size),ids.incrObject());
}

View File

@@ -19,8 +19,8 @@ struct traits<IndexedView<XprType, RowIndices, ColIndices> >
: traits<XprType>
{
enum {
RowsAtCompileTime = get_compile_time_size<RowIndices,traits<XprType>::RowsAtCompileTime>::value,
ColsAtCompileTime = get_compile_time_size<ColIndices,traits<XprType>::ColsAtCompileTime>::value,
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),
@@ -38,8 +38,9 @@ struct traits<IndexedView<XprType, RowIndices, ColIndices> >
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,typename conditional<XprTypeIsRowMajor,ColIndices,RowIndices>::type>::value,
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,

View File

@@ -0,0 +1,111 @@
// 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 internal {
// 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>
const T& makeIndexedViewCompatible(const T& x, Index /*size*/) { 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;
};
//--------------------------------------------------------------------------------
// 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_compile_time<XprSizeType>::value> makeIndexedViewCompatible(all_t , XprSizeType size) {
return AllRange<get_compile_time<XprSizeType>::value>(size);
}
template<int Size> struct get_compile_time_incr<AllRange<Size> > {
enum { value = 1 };
};
} // end namespace internal
namespace placeholders {
/** \var all
* \ingroup Core_Module
* Can be used as a parameter to DenseBase::operator()(const RowIndices&, const ColIndices&) to index all rows or columns
*/
static const Eigen::internal::all_t all;
}
} // end namespace Eigen
#endif // EIGEN_INDEXED_VIEW_HELPER_H

View File

@@ -278,6 +278,53 @@ 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 ease 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 };
};
#ifdef EIGEN_HAS_CXX11
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.
*