1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2017 Gael Guennebaud <[email protected]> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_ARITHMETIC_SEQUENCE_H 11 #define EIGEN_ARITHMETIC_SEQUENCE_H 12 13 namespace Eigen { 14 15 namespace internal { 16 17 #if (!EIGEN_HAS_CXX11) || !((!EIGEN_COMP_GNUC) || EIGEN_COMP_GNUC>=48) 18 template<typename T> struct aseq_negate {}; 19 20 template<> struct aseq_negate<Index> { 21 typedef Index type; 22 }; 23 24 template<int N> struct aseq_negate<FixedInt<N> > { 25 typedef FixedInt<-N> type; 26 }; 27 28 // Compilation error in the following case: 29 template<> struct aseq_negate<FixedInt<DynamicIndex> > {}; 30 31 template<typename FirstType,typename SizeType,typename IncrType, 32 bool FirstIsSymbolic=symbolic::is_symbolic<FirstType>::value, 33 bool SizeIsSymbolic =symbolic::is_symbolic<SizeType>::value> 34 struct aseq_reverse_first_type { 35 typedef Index type; 36 }; 37 38 template<typename FirstType,typename SizeType,typename IncrType> 39 struct aseq_reverse_first_type<FirstType,SizeType,IncrType,true,true> { 40 typedef symbolic::AddExpr<FirstType, 41 symbolic::ProductExpr<symbolic::AddExpr<SizeType,symbolic::ValueExpr<FixedInt<-1> > >, 42 symbolic::ValueExpr<IncrType> > 43 > type; 44 }; 45 46 template<typename SizeType,typename IncrType,typename EnableIf = void> 47 struct aseq_reverse_first_type_aux { 48 typedef Index type; 49 }; 50 51 template<typename SizeType,typename IncrType> 52 struct aseq_reverse_first_type_aux<SizeType,IncrType,typename internal::enable_if<bool((SizeType::value+IncrType::value)|0x1)>::type> { 53 typedef FixedInt<(SizeType::value-1)*IncrType::value> type; 54 }; 55 56 template<typename FirstType,typename SizeType,typename IncrType> 57 struct aseq_reverse_first_type<FirstType,SizeType,IncrType,true,false> { 58 typedef typename aseq_reverse_first_type_aux<SizeType,IncrType>::type Aux; 59 typedef symbolic::AddExpr<FirstType,symbolic::ValueExpr<Aux> > type; 60 }; 61 62 template<typename FirstType,typename SizeType,typename IncrType> 63 struct aseq_reverse_first_type<FirstType,SizeType,IncrType,false,true> { 64 typedef symbolic::AddExpr<symbolic::ProductExpr<symbolic::AddExpr<SizeType,symbolic::ValueExpr<FixedInt<-1> > >, 65 symbolic::ValueExpr<IncrType> >, 66 symbolic::ValueExpr<> > type; 67 }; 68 #endif 69 70 // Helper to cleanup the type of the increment: 71 template<typename T> struct cleanup_seq_incr { 72 typedef typename cleanup_index_type<T,DynamicIndex>::type type; 73 }; 74 75 } 76 77 //-------------------------------------------------------------------------------- 78 // seq(first,last,incr) and seqN(first,size,incr) 79 //-------------------------------------------------------------------------------- 80 81 template<typename FirstType=Index,typename SizeType=Index,typename IncrType=internal::FixedInt<1> > 82 class ArithmeticSequence; 83 84 template<typename FirstType,typename SizeType,typename IncrType> 85 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type, 86 typename internal::cleanup_index_type<SizeType>::type, 87 typename internal::cleanup_seq_incr<IncrType>::type > 88 seqN(FirstType first, SizeType size, IncrType incr); 89 90 /** \class ArithmeticSequence 91 * \ingroup Core_Module 92 * 93 * This class represents an arithmetic progression \f$ a_0, a_1, a_2, ..., a_{n-1}\f$ defined by 94 * its \em first value \f$ a_0 \f$, its \em size (aka length) \em n, and the \em increment (aka stride) 95 * that is equal to \f$ a_{i+1}-a_{i}\f$ for any \em i. 96 * 97 * It is internally used as the return type of the Eigen::seq and Eigen::seqN functions, and as the input arguments 98 * of DenseBase::operator()(const RowIndices&, const ColIndices&), and most of the time this is the 99 * only way it is used. 100 * 101 * \tparam FirstType type of the first element, usually an Index, 102 * but internally it can be a symbolic expression 103 * \tparam SizeType type representing the size of the sequence, usually an Index 104 * or a compile time integral constant. Internally, it can also be a symbolic expression 105 * \tparam IncrType type of the increment, can be a runtime Index, or a compile time integral constant (default is compile-time 1) 106 * 107 * \sa Eigen::seq, Eigen::seqN, DenseBase::operator()(const RowIndices&, const ColIndices&), class IndexedView 108 */ 109 template<typename FirstType,typename SizeType,typename IncrType> 110 class ArithmeticSequence 111 { 112 public: 113 ArithmeticSequence(FirstType first, SizeType size) : m_first(first), m_size(size) {} 114 ArithmeticSequence(FirstType first, SizeType size, IncrType incr) : m_first(first), m_size(size), m_incr(incr) {} 115 116 enum { 117 SizeAtCompileTime = internal::get_fixed_value<SizeType>::value, 118 IncrAtCompileTime = internal::get_fixed_value<IncrType,DynamicIndex>::value 119 }; 120 121 /** \returns the size, i.e., number of elements, of the sequence */ 122 Index size() const { return m_size; } 123 124 /** \returns the first element \f$ a_0 \f$ in the sequence */ 125 Index first() const { return m_first; } 126 127 /** \returns the value \f$ a_i \f$ at index \a i in the sequence. */ 128 Index operator[](Index i) const { return m_first + i * m_incr; } 129 130 const FirstType& firstObject() const { return m_first; } 131 const SizeType& sizeObject() const { return m_size; } 132 const IncrType& incrObject() const { return m_incr; } 133 134 protected: 135 FirstType m_first; 136 SizeType m_size; 137 IncrType m_incr; 138 139 public: 140 141 #if EIGEN_HAS_CXX11 && ((!EIGEN_COMP_GNUC) || EIGEN_COMP_GNUC>=48) 142 auto reverse() const -> decltype(Eigen::seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr)) { 143 return seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr); 144 } 145 #else 146 protected: 147 typedef typename internal::aseq_negate<IncrType>::type ReverseIncrType; 148 typedef typename internal::aseq_reverse_first_type<FirstType,SizeType,IncrType>::type ReverseFirstType; 149 public: 150 ArithmeticSequence<ReverseFirstType,SizeType,ReverseIncrType> 151 reverse() const { 152 return seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr); 153 } 154 #endif 155 }; 156 157 /** \returns an ArithmeticSequence starting at \a first, of length \a size, and increment \a incr 158 * 159 * \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */ 160 template<typename FirstType,typename SizeType,typename IncrType> 161 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type,typename internal::cleanup_seq_incr<IncrType>::type > 162 seqN(FirstType first, SizeType size, IncrType incr) { 163 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); 164 } 165 166 /** \returns an ArithmeticSequence starting at \a first, of length \a size, and unit increment 167 * 168 * \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType) */ 169 template<typename FirstType,typename SizeType> 170 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type > 171 seqN(FirstType first, SizeType size) { 172 return ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type>(first,size); 173 } 174 175 #ifdef EIGEN_PARSED_BY_DOXYGEN 176 177 /** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and with positive (or negative) increment \a incr 178 * 179 * It is essentially an alias to: 180 * \code 181 * seqN(f, (l-f+incr)/incr, incr); 182 * \endcode 183 * 184 * \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType) 185 */ 186 template<typename FirstType,typename LastType, typename IncrType> 187 auto seq(FirstType f, LastType l, IncrType incr); 188 189 /** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and unit increment 190 * 191 * It is essentially an alias to: 192 * \code 193 * seqN(f,l-f+1); 194 * \endcode 195 * 196 * \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) 197 */ 198 template<typename FirstType,typename LastType> 199 auto seq(FirstType f, LastType l); 200 201 #else // EIGEN_PARSED_BY_DOXYGEN 202 203 #if EIGEN_HAS_CXX11 204 template<typename FirstType,typename LastType> 205 auto seq(FirstType f, LastType l) -> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f), 206 ( typename internal::cleanup_index_type<LastType>::type(l) 207 - typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()))) 208 { 209 return seqN(typename internal::cleanup_index_type<FirstType>::type(f), 210 (typename internal::cleanup_index_type<LastType>::type(l) 211 -typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>())); 212 } 213 214 template<typename FirstType,typename LastType, typename IncrType> 215 auto seq(FirstType f, LastType l, IncrType incr) 216 -> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f), 217 ( typename internal::cleanup_index_type<LastType>::type(l) 218 - typename internal::cleanup_index_type<FirstType>::type(f)+typename internal::cleanup_seq_incr<IncrType>::type(incr) 219 ) / typename internal::cleanup_seq_incr<IncrType>::type(incr), 220 typename internal::cleanup_seq_incr<IncrType>::type(incr))) 221 { 222 typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType; 223 return seqN(typename internal::cleanup_index_type<FirstType>::type(f), 224 ( typename internal::cleanup_index_type<LastType>::type(l) 225 -typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr)) / CleanedIncrType(incr), 226 CleanedIncrType(incr)); 227 } 228 229 #else // EIGEN_HAS_CXX11 230 231 template<typename FirstType,typename LastType> 232 typename internal::enable_if<!(symbolic::is_symbolic<FirstType>::value || symbolic::is_symbolic<LastType>::value), 233 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,Index> >::type 234 seq(FirstType f, LastType l) 235 { 236 return seqN(typename internal::cleanup_index_type<FirstType>::type(f), 237 Index((typename internal::cleanup_index_type<LastType>::type(l)-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()))); 238 } 239 240 template<typename FirstTypeDerived,typename LastType> 241 typename internal::enable_if<!symbolic::is_symbolic<LastType>::value, 242 ArithmeticSequence<FirstTypeDerived, symbolic::AddExpr<symbolic::AddExpr<symbolic::NegateExpr<FirstTypeDerived>,symbolic::ValueExpr<> >, 243 symbolic::ValueExpr<internal::FixedInt<1> > > > >::type 244 seq(const symbolic::BaseExpr<FirstTypeDerived> &f, LastType l) 245 { 246 return seqN(f.derived(),(typename internal::cleanup_index_type<LastType>::type(l)-f.derived()+fix<1>())); 247 } 248 249 template<typename FirstType,typename LastTypeDerived> 250 typename internal::enable_if<!symbolic::is_symbolic<FirstType>::value, 251 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type, 252 symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,symbolic::ValueExpr<> >, 253 symbolic::ValueExpr<internal::FixedInt<1> > > > >::type 254 seq(FirstType f, const symbolic::BaseExpr<LastTypeDerived> &l) 255 { 256 return seqN(typename internal::cleanup_index_type<FirstType>::type(f),(l.derived()-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>())); 257 } 258 259 template<typename FirstTypeDerived,typename LastTypeDerived> 260 ArithmeticSequence<FirstTypeDerived, 261 symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,symbolic::NegateExpr<FirstTypeDerived> >,symbolic::ValueExpr<internal::FixedInt<1> > > > 262 seq(const symbolic::BaseExpr<FirstTypeDerived> &f, const symbolic::BaseExpr<LastTypeDerived> &l) 263 { 264 return seqN(f.derived(),(l.derived()-f.derived()+fix<1>())); 265 } 266 267 268 template<typename FirstType,typename LastType, typename IncrType> 269 typename internal::enable_if<!(symbolic::is_symbolic<FirstType>::value || symbolic::is_symbolic<LastType>::value), 270 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,Index,typename internal::cleanup_seq_incr<IncrType>::type> >::type 271 seq(FirstType f, LastType l, IncrType incr) 272 { 273 typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType; 274 return seqN(typename internal::cleanup_index_type<FirstType>::type(f), 275 Index((typename internal::cleanup_index_type<LastType>::type(l)-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr)), incr); 276 } 277 278 template<typename FirstTypeDerived,typename LastType, typename IncrType> 279 typename internal::enable_if<!symbolic::is_symbolic<LastType>::value, 280 ArithmeticSequence<FirstTypeDerived, 281 symbolic::QuotientExpr<symbolic::AddExpr<symbolic::AddExpr<symbolic::NegateExpr<FirstTypeDerived>, 282 symbolic::ValueExpr<> >, 283 symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >, 284 symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >, 285 typename internal::cleanup_seq_incr<IncrType>::type> >::type 286 seq(const symbolic::BaseExpr<FirstTypeDerived> &f, LastType l, IncrType incr) 287 { 288 typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType; 289 return seqN(f.derived(),(typename internal::cleanup_index_type<LastType>::type(l)-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr); 290 } 291 292 template<typename FirstType,typename LastTypeDerived, typename IncrType> 293 typename internal::enable_if<!symbolic::is_symbolic<FirstType>::value, 294 ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type, 295 symbolic::QuotientExpr<symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,symbolic::ValueExpr<> >, 296 symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >, 297 symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >, 298 typename internal::cleanup_seq_incr<IncrType>::type> >::type 299 seq(FirstType f, const symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr) 300 { 301 typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType; 302 return seqN(typename internal::cleanup_index_type<FirstType>::type(f), 303 (l.derived()-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr), incr); 304 } 305 306 template<typename FirstTypeDerived,typename LastTypeDerived, typename IncrType> 307 ArithmeticSequence<FirstTypeDerived, 308 symbolic::QuotientExpr<symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived, 309 symbolic::NegateExpr<FirstTypeDerived> >, 310 symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >, 311 symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >, 312 typename internal::cleanup_seq_incr<IncrType>::type> 313 seq(const symbolic::BaseExpr<FirstTypeDerived> &f, const symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr) 314 { 315 typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType; 316 return seqN(f.derived(),(l.derived()-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr); 317 } 318 #endif // EIGEN_HAS_CXX11 319 320 #endif // EIGEN_PARSED_BY_DOXYGEN 321 322 323 #if EIGEN_HAS_CXX11 || defined(EIGEN_PARSED_BY_DOXYGEN) 324 /** \cpp11 325 * \returns a symbolic ArithmeticSequence representing the last \a size elements with increment \a incr. 326 * 327 * It is a shortcut for: \code seqN(last-(size-fix<1>)*incr, size, incr) \endcode 328 * 329 * \sa lastN(SizeType), seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */ 330 template<typename SizeType,typename IncrType> 331 auto lastN(SizeType size, IncrType incr) 332 -> decltype(seqN(Eigen::last-(size-fix<1>())*incr, size, incr)) 333 { 334 return seqN(Eigen::last-(size-fix<1>())*incr, size, incr); 335 } 336 337 /** \cpp11 338 * \returns a symbolic ArithmeticSequence representing the last \a size elements with a unit increment. 339 * 340 * It is a shortcut for: \code seq(last+fix<1>-size, last) \endcode 341 * 342 * \sa lastN(SizeType,IncrType, seqN(FirstType,SizeType), seq(FirstType,LastType) */ 343 template<typename SizeType> 344 auto lastN(SizeType size) 345 -> decltype(seqN(Eigen::last+fix<1>()-size, size)) 346 { 347 return seqN(Eigen::last+fix<1>()-size, size); 348 } 349 #endif 350 351 namespace internal { 352 353 // Convert a symbolic span into a usable one (i.e., remove last/end "keywords") 354 template<typename T> 355 struct make_size_type { 356 typedef typename internal::conditional<symbolic::is_symbolic<T>::value, Index, T>::type type; 357 }; 358 359 template<typename FirstType,typename SizeType,typename IncrType,int XprSize> 360 struct IndexedViewCompatibleType<ArithmeticSequence<FirstType,SizeType,IncrType>, XprSize> { 361 typedef ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType> type; 362 }; 363 364 template<typename FirstType,typename SizeType,typename IncrType> 365 ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType> 366 makeIndexedViewCompatible(const ArithmeticSequence<FirstType,SizeType,IncrType>& ids, Index size,SpecializedType) { 367 return ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>( 368 eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.sizeObject(),size),ids.incrObject()); 369 } 370 371 template<typename FirstType,typename SizeType,typename IncrType> 372 struct get_compile_time_incr<ArithmeticSequence<FirstType,SizeType,IncrType> > { 373 enum { value = get_fixed_value<IncrType,DynamicIndex>::value }; 374 }; 375 376 } // end namespace internal 377 378 /** \namespace Eigen::indexing 379 * \ingroup Core_Module 380 * 381 * The sole purpose of this namespace is to be able to import all functions 382 * and symbols that are expected to be used within operator() for indexing 383 * and slicing. If you already imported the whole Eigen namespace: 384 * \code using namespace Eigen; \endcode 385 * then you are already all set. Otherwise, if you don't want/cannot import 386 * the whole Eigen namespace, the following line: 387 * \code using namespace Eigen::indexing; \endcode 388 * is equivalent to: 389 * \code 390 using Eigen::all; 391 using Eigen::seq; 392 using Eigen::seqN; 393 using Eigen::lastN; // c++11 only 394 using Eigen::last; 395 using Eigen::lastp1; 396 using Eigen::fix; 397 \endcode 398 */ 399 namespace indexing { 400 using Eigen::all; 401 using Eigen::seq; 402 using Eigen::seqN; 403 #if EIGEN_HAS_CXX11 404 using Eigen::lastN; 405 #endif 406 using Eigen::last; 407 using Eigen::lastp1; 408 using Eigen::fix; 409 } 410 411 } // end namespace Eigen 412 413 #endif // EIGEN_ARITHMETIC_SEQUENCE_H 414