2017-01-06 00:01:44 +01:00
|
|
|
// 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 {
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
// Pseudo keywords: all, last, end
|
|
|
|
|
//--------------------------------------------------------------------------------
|
2017-01-06 00:01:44 +01:00
|
|
|
|
|
|
|
|
struct all_t { all_t() {} };
|
|
|
|
|
static const all_t all;
|
|
|
|
|
|
|
|
|
|
struct shifted_last {
|
|
|
|
|
explicit shifted_last(int o) : offset(o) {}
|
|
|
|
|
int offset;
|
|
|
|
|
shifted_last operator+ (int x) const { return shifted_last(offset+x); }
|
|
|
|
|
shifted_last operator- (int x) const { return shifted_last(offset-x); }
|
|
|
|
|
int operator- (shifted_last x) const { return offset-x.offset; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct last_t {
|
|
|
|
|
last_t() {}
|
|
|
|
|
shifted_last operator- (int offset) const { return shifted_last(-offset); }
|
|
|
|
|
shifted_last operator+ (int offset) const { return shifted_last(+offset); }
|
|
|
|
|
int operator- (last_t) const { return 0; }
|
|
|
|
|
int operator- (shifted_last x) const { return -x.offset; }
|
|
|
|
|
};
|
|
|
|
|
static const last_t last;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct shifted_end {
|
|
|
|
|
explicit shifted_end(int o) : offset(o) {}
|
|
|
|
|
int offset;
|
|
|
|
|
shifted_end operator+ (int x) const { return shifted_end(offset+x); }
|
|
|
|
|
shifted_end operator- (int x) const { return shifted_end(offset-x); }
|
|
|
|
|
int operator- (shifted_end x) const { return offset-x.offset; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct end_t {
|
|
|
|
|
end_t() {}
|
|
|
|
|
shifted_end operator- (int offset) const { return shifted_end (-offset); }
|
|
|
|
|
shifted_end operator+ (int offset) const { return shifted_end ( offset); }
|
|
|
|
|
int operator- (end_t) const { return 0; }
|
|
|
|
|
int operator- (shifted_end x) const { return -x.offset; }
|
|
|
|
|
};
|
|
|
|
|
static const end_t end;
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
// integral constant
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
template<int N> struct fix_t {
|
2017-01-06 00:01:44 +01:00
|
|
|
static const int value = N;
|
|
|
|
|
operator int() const { return value; }
|
2017-01-06 13:10:10 +01:00
|
|
|
fix_t (fix_t<N> (*)() ) {}
|
|
|
|
|
fix_t() {}
|
|
|
|
|
// Needed in C++14 to allow fix<N>():
|
|
|
|
|
fix_t operator() () const { return *this; }
|
2017-01-06 00:01:44 +01:00
|
|
|
};
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename T, int Default=Dynamic> struct get_compile_time {
|
|
|
|
|
enum { value = Default };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<int N,int Default> struct get_compile_time<fix_t<N>,Default> {
|
|
|
|
|
enum { value = N };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename T> struct is_compile_time { enum { value = false }; };
|
|
|
|
|
template<int N> struct is_compile_time<fix_t<N> > { enum { value = true }; };
|
|
|
|
|
|
|
|
|
|
#if __cplusplus > 201103L
|
|
|
|
|
template<int N>
|
|
|
|
|
static const fix_t<N> fix{};
|
|
|
|
|
#else
|
|
|
|
|
template<int N>
|
|
|
|
|
inline fix_t<N> fix() { return fix_t<N>(); }
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-01-06 00:01:44 +01:00
|
|
|
//--------------------------------------------------------------------------------
|
2017-01-09 17:35:21 +01:00
|
|
|
// seq(first,last,incr) and seqN(first,size,incr)
|
2017-01-06 00:01:44 +01:00
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType=Index,typename LastType=Index,typename IncrType=fix_t<1> >
|
2017-01-09 17:35:21 +01:00
|
|
|
class ArithemeticSequenceProxyWithBounds
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
ArithemeticSequenceProxyWithBounds(FirstType f, LastType l) : m_first(f), m_last(l) {}
|
|
|
|
|
ArithemeticSequenceProxyWithBounds(FirstType f, LastType l, IncrType s) : m_first(f), m_last(l), m_incr(s) {}
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
SizeAtCompileTime = -1,
|
|
|
|
|
IncrAtCompileTime = get_compile_time<IncrType,DynamicIndex>::value
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Index size() const { return (m_last-m_first+m_incr)/m_incr; }
|
|
|
|
|
Index operator[](Index i) const { return m_first + i * m_incr; }
|
|
|
|
|
|
|
|
|
|
const FirstType& firstObject() const { return m_first; }
|
|
|
|
|
const LastType& lastObject() const { return m_last; }
|
|
|
|
|
const IncrType& incrObject() const { return m_incr; }
|
2017-01-06 00:01:44 +01:00
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
protected:
|
2017-01-06 00:01:44 +01:00
|
|
|
FirstType m_first;
|
|
|
|
|
LastType m_last;
|
2017-01-06 13:10:10 +01:00
|
|
|
IncrType m_incr;
|
2017-01-06 00:01:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename T> struct cleanup_slice_type { typedef Index type; };
|
|
|
|
|
template<> struct cleanup_slice_type<last_t> { typedef last_t type; };
|
|
|
|
|
template<> struct cleanup_slice_type<shifted_last> { typedef shifted_last type; };
|
|
|
|
|
template<> struct cleanup_slice_type<end_t> { typedef end_t type; };
|
|
|
|
|
template<> struct cleanup_slice_type<shifted_end> { typedef shifted_end type; };
|
2017-01-06 13:10:10 +01:00
|
|
|
template<int N> struct cleanup_slice_type<fix_t<N> > { typedef fix_t<N> type; };
|
|
|
|
|
template<int N> struct cleanup_slice_type<fix_t<N> (*)() > { typedef fix_t<N> type; };
|
2017-01-06 00:01:44 +01:00
|
|
|
|
|
|
|
|
template<typename FirstType,typename LastType>
|
2017-01-09 17:35:21 +01:00
|
|
|
ArithemeticSequenceProxyWithBounds<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<LastType>::type >
|
|
|
|
|
seq(FirstType f, LastType l) {
|
|
|
|
|
return ArithemeticSequenceProxyWithBounds<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<LastType>::type>(f,l);
|
2017-01-06 00:01:44 +01:00
|
|
|
}
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType,typename LastType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
ArithemeticSequenceProxyWithBounds<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<LastType>::type,typename cleanup_slice_type<IncrType>::type >
|
|
|
|
|
seq(FirstType f, LastType l, IncrType s) {
|
|
|
|
|
return ArithemeticSequenceProxyWithBounds<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<LastType>::type,typename cleanup_slice_type<IncrType>::type>(f,l,typename cleanup_slice_type<IncrType>::type(s));
|
2017-01-06 00:01:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
template<typename FirstType=Index,typename SizeType=Index,typename IncrType=fix_t<1> >
|
|
|
|
|
class ArithemeticSequenceProxyWithSize
|
|
|
|
|
{
|
2017-01-06 00:01:44 +01:00
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
public:
|
|
|
|
|
ArithemeticSequenceProxyWithSize(FirstType first, SizeType size) : m_first(first), m_size(size) {}
|
|
|
|
|
ArithemeticSequenceProxyWithSize(FirstType first, SizeType size, IncrType incr) : m_first(first), m_size(size), m_incr(incr) {}
|
2017-01-06 00:01:44 +01:00
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
enum {
|
|
|
|
|
SizeAtCompileTime = get_compile_time<SizeType>::value,
|
|
|
|
|
IncrAtCompileTime = get_compile_time<IncrType,DynamicIndex>::value
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Index size() const { return m_size; }
|
|
|
|
|
Index operator[](Index i) const { return m_first + i * m_incr; }
|
2017-01-06 00:01:44 +01:00
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
const FirstType& firstObject() const { return m_first; }
|
|
|
|
|
const SizeType& sizeObject() const { return m_size; }
|
|
|
|
|
const IncrType& incrObject() const { return m_incr; }
|
|
|
|
|
|
|
|
|
|
protected:
|
2017-01-06 00:01:44 +01:00
|
|
|
FirstType m_first;
|
|
|
|
|
SizeType m_size;
|
2017-01-06 13:10:10 +01:00
|
|
|
IncrType m_incr;
|
2017-01-06 00:01:44 +01:00
|
|
|
};
|
|
|
|
|
|
2017-01-09 17:35:21 +01:00
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType,typename SizeType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
ArithemeticSequenceProxyWithSize<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<SizeType>::type,typename cleanup_slice_type<IncrType>::type >
|
|
|
|
|
seqN(FirstType first, SizeType size, IncrType incr) {
|
|
|
|
|
return ArithemeticSequenceProxyWithSize<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<SizeType>::type,typename cleanup_slice_type<IncrType>::type>(first,size,incr);
|
2017-01-06 00:01:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename FirstType,typename SizeType>
|
2017-01-09 17:35:21 +01:00
|
|
|
ArithemeticSequenceProxyWithSize<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<SizeType>::type >
|
|
|
|
|
seqN(FirstType first, SizeType size) {
|
|
|
|
|
return ArithemeticSequenceProxyWithSize<typename cleanup_slice_type<FirstType>::type,typename cleanup_slice_type<SizeType>::type>(first,size);
|
2017-01-06 00:01:44 +01:00
|
|
|
}
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
|
2017-01-06 00:01:44 +01:00
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
|
|
2017-01-06 21:53:32 +01:00
|
|
|
template<typename T>
|
|
|
|
|
Index size(const T& x) { return x.size(); }
|
|
|
|
|
|
|
|
|
|
template<typename T,std::size_t N>
|
|
|
|
|
Index size(const T (&x) [N]) { return N; }
|
|
|
|
|
|
2017-01-06 13:29:33 +01:00
|
|
|
template<typename T, int XprSize, typename EnableIf = void> struct get_compile_time_size {
|
2017-01-06 15:54:55 +01:00
|
|
|
enum { value = Dynamic };
|
2017-01-06 13:10:10 +01:00
|
|
|
};
|
|
|
|
|
|
2017-01-06 13:29:33 +01:00
|
|
|
template<typename T, int XprSize> struct get_compile_time_size<T,XprSize,typename internal::enable_if<((T::SizeAtCompileTime&0)==0)>::type> {
|
2017-01-06 13:10:10 +01:00
|
|
|
enum { value = T::SizeAtCompileTime };
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-06 22:01:23 +01:00
|
|
|
template<typename T, int XprSize, int N> struct get_compile_time_size<const T (&)[N],XprSize> {
|
|
|
|
|
enum { value = N };
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
#ifdef EIGEN_HAS_CXX11
|
2017-01-06 22:04:49 +01:00
|
|
|
template<typename T, int XprSize, std::size_t N> struct get_compile_time_size<std::array<T,N>,XprSize> {
|
2017-01-06 13:10:10 +01:00
|
|
|
enum { value = N };
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-01-06 15:54:55 +01:00
|
|
|
template<typename T, typename EnableIf = void> struct get_compile_time_incr {
|
|
|
|
|
enum { value = UndefinedIncr };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename FirstType,typename LastType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
struct get_compile_time_incr<ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType> > {
|
2017-01-06 15:54:55 +01:00
|
|
|
enum { value = get_compile_time<IncrType,DynamicIndex>::value };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename FirstType,typename SizeType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
struct get_compile_time_incr<ArithemeticSequenceProxyWithSize<FirstType,SizeType,IncrType> > {
|
2017-01-06 15:54:55 +01:00
|
|
|
enum { value = get_compile_time<IncrType,DynamicIndex>::value };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-01-06 00:01:44 +01:00
|
|
|
// 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>
|
2017-01-06 15:54:55 +01:00
|
|
|
const T& make_indexing(const T& x, Index /*size*/) { return x; }
|
2017-01-06 00:01:44 +01:00
|
|
|
|
|
|
|
|
struct IntAsArray {
|
2017-01-06 13:10:10 +01:00
|
|
|
enum {
|
|
|
|
|
SizeAtCompileTime = 1
|
|
|
|
|
};
|
2017-01-06 00:01:44 +01:00
|
|
|
IntAsArray(Index val) : m_value(val) {}
|
|
|
|
|
Index operator[](Index) const { return m_value; }
|
|
|
|
|
Index size() const { return 1; }
|
|
|
|
|
Index m_value;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-06 15:54:55 +01:00
|
|
|
template<> struct get_compile_time_incr<IntAsArray> {
|
|
|
|
|
enum { value = 1 }; // 1 or 0 ??
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-06 00:01:44 +01:00
|
|
|
// 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
|
|
|
|
|
Index symbolic2value(Index x, Index /* size */) { return x; }
|
|
|
|
|
Index symbolic2value(last_t, Index size) { return size-1; }
|
|
|
|
|
Index symbolic2value(shifted_last x, Index size) { return size+x.offset-1; }
|
|
|
|
|
Index symbolic2value(end_t, Index size) { return size; }
|
|
|
|
|
Index symbolic2value(shifted_end x, Index size) { return size+x.offset; }
|
|
|
|
|
|
|
|
|
|
// Convert a symbolic range into a usable one (i.e., remove last/end "keywords")
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType,typename LastType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
struct MakeIndexing<ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType> > {
|
|
|
|
|
typedef ArithemeticSequenceProxyWithBounds<Index,Index,IncrType> type;
|
2017-01-06 00:01:44 +01:00
|
|
|
};
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType,typename LastType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
ArithemeticSequenceProxyWithBounds<Index,Index,IncrType> make_indexing(const ArithemeticSequenceProxyWithBounds<FirstType,LastType,IncrType>& ids, Index size) {
|
|
|
|
|
return ArithemeticSequenceProxyWithBounds<Index,Index,IncrType>(symbolic2value(ids.firstObject(),size),symbolic2value(ids.lastObject(),size),ids.incrObject());
|
2017-01-06 00:01:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert a symbolic span into a usable one (i.e., remove last/end "keywords")
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType,typename SizeType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
struct MakeIndexing<ArithemeticSequenceProxyWithSize<FirstType,SizeType,IncrType> > {
|
|
|
|
|
typedef ArithemeticSequenceProxyWithSize<Index,SizeType,IncrType> type;
|
2017-01-06 00:01:44 +01:00
|
|
|
};
|
|
|
|
|
|
2017-01-06 13:10:10 +01:00
|
|
|
template<typename FirstType,typename SizeType,typename IncrType>
|
2017-01-09 17:35:21 +01:00
|
|
|
ArithemeticSequenceProxyWithSize<Index,SizeType,IncrType> make_indexing(const ArithemeticSequenceProxyWithSize<FirstType,SizeType,IncrType>& ids, Index size) {
|
|
|
|
|
return ArithemeticSequenceProxyWithSize<Index,SizeType,IncrType>(symbolic2value(ids.firstObject(),size),ids.sizeObject(),ids.incrObject());
|
2017-01-06 00:01:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 m_size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct MakeIndexing<all_t> {
|
|
|
|
|
typedef AllRange type;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
AllRange make_indexing(all_t , Index size) {
|
|
|
|
|
return AllRange(size);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-06 13:29:33 +01:00
|
|
|
template<int XprSize> struct get_compile_time_size<AllRange,XprSize> {
|
|
|
|
|
enum { value = XprSize };
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-06 15:54:55 +01:00
|
|
|
template<> struct get_compile_time_incr<AllRange> {
|
|
|
|
|
enum { value = 1 };
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-06 00:01:44 +01:00
|
|
|
} // end namespace internal
|
|
|
|
|
|
|
|
|
|
} // end namespace Eigen
|
|
|
|
|
|
|
|
|
|
#endif // EIGEN_ARITHMETIC_SEQUENCE_H
|