// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2014 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_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<typename XprType, typename EvaluatorKind>
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<typename XprType>
class InnerIterator
{
protected:
  typedef internal::inner_iterator_selector<XprType, typename internal::evaluator_traits<XprType>::Kind> IteratorType;
  typedef internal::evaluator<XprType> EvaluatorType;
  typedef typename internal::traits<XprType>::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; }
  /// \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<double,RowMajor> A;
  //   SparseMatrix<double>::InnerIterator it(A,0);
  template<typename T> InnerIterator(const EigenBase<T>&,Index outer);
};

namespace internal {

// Generic inner iterator implementation for dense objects
template<typename XprType>
class inner_iterator_selector<XprType, IndexBased>
{
protected:
  typedef evaluator<XprType> EvaluatorType;
  typedef typename traits<XprType>::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<typename XprType>
class inner_iterator_selector<XprType, IteratorBased>
 : public evaluator<XprType>::InnerIterator
{
protected:
  typedef typename evaluator<XprType>::InnerIterator Base;
  typedef evaluator<XprType> 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
