Home | History | Annotate | Download | only in Core
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      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 */
     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.
     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   /// \returns the column or row index of the current coefficient.
     52   EIGEN_STRONG_INLINE Index index() const           { return m_iter.index(); }
     53   /// \returns the row index of the current coefficient.
     54   EIGEN_STRONG_INLINE Index row() const             { return m_iter.row(); }
     55   /// \returns the column index of the current coefficient.
     56   EIGEN_STRONG_INLINE Index col() const             { return m_iter.col(); }
     57   /// \returns \c true if the iterator \c *this still references a valid coefficient.
     58   EIGEN_STRONG_INLINE operator bool() const         { return m_iter; }
     59 
     60 protected:
     61   EvaluatorType m_eval;
     62   IteratorType m_iter;
     63 private:
     64   // If you get here, then you're not using the right InnerIterator type, e.g.:
     65   //   SparseMatrix<double,RowMajor> A;
     66   //   SparseMatrix<double>::InnerIterator it(A,0);
     67   template<typename T> InnerIterator(const EigenBase<T>&,Index outer);
     68 };
     69 
     70 namespace internal {
     71 
     72 // Generic inner iterator implementation for dense objects
     73 template<typename XprType>
     74 class inner_iterator_selector<XprType, IndexBased>
     75 {
     76 protected:
     77   typedef evaluator<XprType> EvaluatorType;
     78   typedef typename traits<XprType>::Scalar Scalar;
     79   enum { IsRowMajor = (XprType::Flags&RowMajorBit)==RowMajorBit };
     80 
     81 public:
     82   EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &innerSize)
     83     : m_eval(eval), m_inner(0), m_outer(outerId), m_end(innerSize)
     84   {}
     85 
     86   EIGEN_STRONG_INLINE Scalar value() const
     87   {
     88     return (IsRowMajor) ? m_eval.coeff(m_outer, m_inner)
     89                         : m_eval.coeff(m_inner, m_outer);
     90   }
     91 
     92   EIGEN_STRONG_INLINE inner_iterator_selector& operator++() { m_inner++; return *this; }
     93 
     94   EIGEN_STRONG_INLINE Index index() const { return m_inner; }
     95   inline Index row() const { return IsRowMajor ? m_outer : index(); }
     96   inline Index col() const { return IsRowMajor ? index() : m_outer; }
     97 
     98   EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; }
     99 
    100 protected:
    101   const EvaluatorType& m_eval;
    102   Index m_inner;
    103   const Index m_outer;
    104   const Index m_end;
    105 };
    106 
    107 // For iterator-based evaluator, inner-iterator is already implemented as
    108 // evaluator<>::InnerIterator
    109 template<typename XprType>
    110 class inner_iterator_selector<XprType, IteratorBased>
    111  : public evaluator<XprType>::InnerIterator
    112 {
    113 protected:
    114   typedef typename evaluator<XprType>::InnerIterator Base;
    115   typedef evaluator<XprType> EvaluatorType;
    116 
    117 public:
    118   EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &/*innerSize*/)
    119     : Base(eval, outerId)
    120   {}
    121 };
    122 
    123 } // end namespace internal
    124 
    125 } // end namespace Eigen
    126 
    127 #endif // EIGEN_COREITERATORS_H
    128