// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2014 Gael Guennebaud // // 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_COREITERATORS_H #define EIGEN_COREITERATORS_H namespace Eigen { /* This file contains the respective InnerIterator definition of the expressions defined in Eigen/Core */ namespace internal { template class inner_iterator_selector; } /** \class InnerIterator * \brief An InnerIterator allows to loop over the element of any matrix expression. * * \warning To be used with care because an evaluator is constructed every time an InnerIterator iterator is constructed. * * TODO: add a usage example */ template class InnerIterator { protected: typedef internal::inner_iterator_selector::Kind> IteratorType; typedef internal::evaluator EvaluatorType; typedef typename internal::traits::Scalar Scalar; public: /** Construct an iterator over the \a outerId -th row or column of \a xpr */ InnerIterator(const XprType &xpr, const Index &outerId) : m_eval(xpr), m_iter(m_eval, outerId, xpr.innerSize()) {} /// \returns the value of the current coefficient. EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); } /** Increment the iterator \c *this to the next non-zero coefficient. * Explicit zeros are not skipped over. To skip explicit zeros, see class SparseView */ EIGEN_STRONG_INLINE InnerIterator& operator++() { m_iter.operator++(); return *this; } EIGEN_STRONG_INLINE InnerIterator& operator+=(Index i) { m_iter.operator+=(i); return *this; } EIGEN_STRONG_INLINE InnerIterator operator+(Index i) { InnerIterator result(*this); result+=i; return result; } /// \returns the column or row index of the current coefficient. EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); } /// \returns the row index of the current coefficient. EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); } /// \returns the column index of the current coefficient. EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); } /// \returns \c true if the iterator \c *this still references a valid coefficient. EIGEN_STRONG_INLINE operator bool() const { return m_iter; } protected: EvaluatorType m_eval; IteratorType m_iter; private: // If you get here, then you're not using the right InnerIterator type, e.g.: // SparseMatrix A; // SparseMatrix::InnerIterator it(A,0); template InnerIterator(const EigenBase&,Index outer); }; namespace internal { // Generic inner iterator implementation for dense objects template class inner_iterator_selector { protected: typedef evaluator EvaluatorType; typedef typename traits::Scalar Scalar; enum { IsRowMajor = (XprType::Flags&RowMajorBit)==RowMajorBit }; public: EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &innerSize) : m_eval(eval), m_inner(0), m_outer(outerId), m_end(innerSize) {} EIGEN_STRONG_INLINE Scalar value() const { return (IsRowMajor) ? m_eval.coeff(m_outer, m_inner) : m_eval.coeff(m_inner, m_outer); } EIGEN_STRONG_INLINE inner_iterator_selector& operator++() { m_inner++; return *this; } EIGEN_STRONG_INLINE Index index() const { return m_inner; } inline Index row() const { return IsRowMajor ? m_outer : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer; } EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; } protected: const EvaluatorType& m_eval; Index m_inner; const Index m_outer; const Index m_end; }; // For iterator-based evaluator, inner-iterator is already implemented as // evaluator<>::InnerIterator template class inner_iterator_selector : public evaluator::InnerIterator { protected: typedef typename evaluator::InnerIterator Base; typedef evaluator EvaluatorType; public: EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &/*innerSize*/) : Base(eval, outerId) {} }; } // end namespace internal } // end namespace Eigen #endif // EIGEN_COREITERATORS_H