// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Daniel Lowengrub <lowdanie@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#ifndef EIGEN_SPARSEVIEW_H
#define EIGEN_SPARSEVIEW_H

template<typename MatrixType>
struct ei_traits<SparseView<MatrixType> > : ei_traits<MatrixType> {};

template<typename MatrixType>
class SparseView : public SparseMatrixBase<SparseView<MatrixType> >
{
public:
  EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView)

  SparseView(const MatrixType& mat, const Scalar& m_reference = Scalar(0),
             typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) : 
    m_matrix(mat), m_reference(m_reference), m_epsilon(m_epsilon) {}
  class InnerIterator;

  inline Index rows() const { return m_matrix.rows(); }
  inline Index cols() const { return m_matrix.cols(); }

  inline Index innerSize() const { return m_matrix.innerSize(); }
  inline Index outerSize() const { return m_matrix.outerSize(); }

protected:
  const typename MatrixType::Nested m_matrix;
  Scalar m_reference;
  typename NumTraits<Scalar>::Real m_epsilon;
};

template<typename MatrixType>
class SparseView<MatrixType>::InnerIterator : public MatrixType::InnerIterator
{
public:
  typedef typename MatrixType::InnerIterator IterBase;
  InnerIterator(const SparseView& view, Index outer) :
  DenseBase<MatrixType>::InnerIterator(view.m_matrix, outer), m_view(view)
  {
    incrementToNonZero();
  }

  EIGEN_STRONG_INLINE InnerIterator& operator++()
  {
    IterBase::operator++();
    incrementToNonZero();
    return *this;
  }

  using IterBase::value;

protected:
  const SparseView& m_view;

private:
  void incrementToNonZero()
  {
    while(ei_isMuchSmallerThan(value(), m_view.m_reference, m_view.m_epsilon) && (bool(*this)))
      {
        IterBase::operator++();
      }
  }
};

template<typename Derived>
const SparseView<Derived> MatrixBase<Derived>::sparseView(const Scalar& m_reference,
                                                          typename NumTraits<Scalar>::Real m_epsilon) const
{
  return SparseView<Derived>(derived(), m_reference, m_epsilon);
}

#endif
