1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008-2014 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_COREITERATORS_H 11 #define EIGEN_COREITERATORS_H 12 13 namespace Eigen { 14 15 /* This file contains the respective InnerIterator definition of the expressions defined in Eigen/Core 16 */ 17 18 namespace internal { 19 20 template<typename XprType, typename EvaluatorKind> 21 class inner_iterator_selector; 22 23 } 24 25 /** \class InnerIterator 26 * \brief An InnerIterator allows to loop over the element of any matrix expression. 27 * 28 * \warning To be used with care because an evaluator is constructed every time an InnerIterator iterator is constructed. 29 * 30 * TODO: add a usage example 31 */ 32 template<typename XprType> 33 class InnerIterator 34 { 35 protected: 36 typedef internal::inner_iterator_selector<XprType, typename internal::evaluator_traits<XprType>::Kind> IteratorType; 37 typedef internal::evaluator<XprType> EvaluatorType; 38 typedef typename internal::traits<XprType>::Scalar Scalar; 39 public: 40 /** Construct an iterator over the \a outerId -th row or column of \a xpr */ InnerIterator(const XprType & xpr,const Index & outerId)41 InnerIterator(const XprType &xpr, const Index &outerId) 42 : m_eval(xpr), m_iter(m_eval, outerId, xpr.innerSize()) 43 {} 44 45 /// \returns the value of the current coefficient. value()46 EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); } 47 /** Increment the iterator \c *this to the next non-zero coefficient. 48 * Explicit zeros are not skipped over. To skip explicit zeros, see class SparseView 49 */ 50 EIGEN_STRONG_INLINE InnerIterator& operator++() { m_iter.operator++(); return *this; } 51 EIGEN_STRONG_INLINE InnerIterator& operator+=(Index i) { m_iter.operator+=(i); return *this; } 52 EIGEN_STRONG_INLINE InnerIterator operator+(Index i) 53 { InnerIterator result(*this); result+=i; return result; } 54 55 56 /// \returns the column or row index of the current coefficient. index()57 EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); } 58 /// \returns the row index of the current coefficient. row()59 EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); } 60 /// \returns the column index of the current coefficient. col()61 EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); } 62 /// \returns \c true if the iterator \c *this still references a valid coefficient. 63 EIGEN_STRONG_INLINE operator bool() const { return m_iter; } 64 65 protected: 66 EvaluatorType m_eval; 67 IteratorType m_iter; 68 private: 69 // If you get here, then you're not using the right InnerIterator type, e.g.: 70 // SparseMatrix<double,RowMajor> A; 71 // SparseMatrix<double>::InnerIterator it(A,0); 72 template<typename T> InnerIterator(const EigenBase<T>&,Index outer); 73 }; 74 75 namespace internal { 76 77 // Generic inner iterator implementation for dense objects 78 template<typename XprType> 79 class inner_iterator_selector<XprType, IndexBased> 80 { 81 protected: 82 typedef evaluator<XprType> EvaluatorType; 83 typedef typename traits<XprType>::Scalar Scalar; 84 enum { IsRowMajor = (XprType::Flags&RowMajorBit)==RowMajorBit }; 85 86 public: inner_iterator_selector(const EvaluatorType & eval,const Index & outerId,const Index & innerSize)87 EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &innerSize) 88 : m_eval(eval), m_inner(0), m_outer(outerId), m_end(innerSize) 89 {} 90 value()91 EIGEN_STRONG_INLINE Scalar value() const 92 { 93 return (IsRowMajor) ? m_eval.coeff(m_outer, m_inner) 94 : m_eval.coeff(m_inner, m_outer); 95 } 96 97 EIGEN_STRONG_INLINE inner_iterator_selector& operator++() { m_inner++; return *this; } 98 index()99 EIGEN_STRONG_INLINE Index index() const { return m_inner; } row()100 inline Index row() const { return IsRowMajor ? m_outer : index(); } col()101 inline Index col() const { return IsRowMajor ? index() : m_outer; } 102 103 EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; } 104 105 protected: 106 const EvaluatorType& m_eval; 107 Index m_inner; 108 const Index m_outer; 109 const Index m_end; 110 }; 111 112 // For iterator-based evaluator, inner-iterator is already implemented as 113 // evaluator<>::InnerIterator 114 template<typename XprType> 115 class inner_iterator_selector<XprType, IteratorBased> 116 : public evaluator<XprType>::InnerIterator 117 { 118 protected: 119 typedef typename evaluator<XprType>::InnerIterator Base; 120 typedef evaluator<XprType> EvaluatorType; 121 122 public: inner_iterator_selector(const EvaluatorType & eval,const Index & outerId,const Index &)123 EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &/*innerSize*/) 124 : Base(eval, outerId) 125 {} 126 }; 127 128 } // end namespace internal 129 130 } // end namespace Eigen 131 132 #endif // EIGEN_COREITERATORS_H 133