// 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_SPARSE_BLOCK_H
#define EIGEN_SPARSE_BLOCK_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

// Subset of columns or rows
template <typename XprType, int BlockRows, int BlockCols>
class BlockImpl<XprType, BlockRows, BlockCols, true, Sparse>
    : public SparseMatrixBase<Block<XprType, BlockRows, BlockCols, true> > {
  typedef internal::remove_all_t<typename XprType::Nested> MatrixTypeNested_;
  typedef Block<XprType, BlockRows, BlockCols, true> BlockType;

 public:
  enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };

 protected:
  enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
  typedef SparseMatrixBase<BlockType> Base;
  using Base::convert_index;

 public:
  EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)

  inline BlockImpl(XprType& xpr, Index i) : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) {}

  inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
      : m_matrix(xpr),
        m_outerStart(convert_index(IsRowMajor ? startRow : startCol)),
        m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) {}

  EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
  EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }

  Index nonZeros() const {
    typedef internal::evaluator<XprType> EvaluatorType;
    EvaluatorType matEval(m_matrix);
    Index nnz = 0;
    Index end = m_outerStart + m_outerSize.value();
    for (Index j = m_outerStart; j < end; ++j)
      for (typename EvaluatorType::InnerIterator it(matEval, j); it; ++it) ++nnz;
    return nnz;
  }

  inline const Scalar coeff(Index row, Index col) const {
    return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
  }

  inline const Scalar coeff(Index index) const {
    return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
  }

  inline const XprType& nestedExpression() const { return m_matrix; }
  inline XprType& nestedExpression() { return m_matrix; }
  Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
  Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
  Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
  Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }

 protected:
  typename internal::ref_selector<XprType>::non_const_type m_matrix;
  Index m_outerStart;
  const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;

 protected:
  // Disable assignment with clear error message.
  // Note that simply removing operator= yields compilation errors with ICC+MSVC
  template <typename T>
  BlockImpl& operator=(const T&) {
    EIGEN_STATIC_ASSERT(sizeof(T) == 0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
    return *this;
  }
};

/***************************************************************************
 * specialization for SparseMatrix
 ***************************************************************************/

namespace internal {

template <typename SparseMatrixType, int BlockRows, int BlockCols>
class sparse_matrix_block_impl : public SparseCompressedBase<Block<SparseMatrixType, BlockRows, BlockCols, true> > {
  typedef internal::remove_all_t<typename SparseMatrixType::Nested> MatrixTypeNested_;
  typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType;
  typedef SparseCompressedBase<Block<SparseMatrixType, BlockRows, BlockCols, true> > Base;
  using Base::convert_index;

 public:
  enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
  EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
 protected:
  typedef typename Base::IndexVector IndexVector;
  enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };

 public:
  inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index i)
      : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) {}

  inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows,
                                  Index blockCols)
      : m_matrix(xpr),
        m_outerStart(convert_index(IsRowMajor ? startRow : startCol)),
        m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) {}

  template <typename OtherDerived>
  inline BlockType& operator=(const SparseMatrixBase<OtherDerived>& other) {
    typedef internal::remove_all_t<typename SparseMatrixType::Nested> NestedMatrixType_;
    NestedMatrixType_& matrix = m_matrix;
    // This assignment is slow if this vector set is not empty
    // and/or it is not at the end of the nonzeros of the underlying matrix.

    // 1 - eval to a temporary to avoid transposition and/or aliasing issues
    Ref<const SparseMatrix<Scalar, IsRowMajor ? RowMajor : ColMajor, StorageIndex> > tmp(other.derived());
    eigen_internal_assert(tmp.outerSize() == m_outerSize.value());

    // 2 - let's check whether there is enough allocated memory
    Index nnz = tmp.nonZeros();
    Index start =
        m_outerStart == 0 ? 0 : m_matrix.outerIndexPtr()[m_outerStart];        // starting position of the current block
    Index end = m_matrix.outerIndexPtr()[m_outerStart + m_outerSize.value()];  // ending position of the current block
    Index block_size = end - start;                                            // available room in the current block
    Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end;

    Index free_size = m_matrix.isCompressed() ? Index(matrix.data().allocatedSize()) + block_size : block_size;

    Index tmp_start = tmp.outerIndexPtr()[0];

    bool update_trailing_pointers = false;
    if (nnz > free_size) {
      // realloc manually to reduce copies
      typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz);

      internal::smart_copy(m_matrix.valuePtr(), m_matrix.valuePtr() + start, newdata.valuePtr());
      internal::smart_copy(m_matrix.innerIndexPtr(), m_matrix.innerIndexPtr() + start, newdata.indexPtr());

      internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, newdata.valuePtr() + start);
      internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz,
                           newdata.indexPtr() + start);

      internal::smart_copy(matrix.valuePtr() + end, matrix.valuePtr() + end + tail_size,
                           newdata.valuePtr() + start + nnz);
      internal::smart_copy(matrix.innerIndexPtr() + end, matrix.innerIndexPtr() + end + tail_size,
                           newdata.indexPtr() + start + nnz);

      newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz);

      matrix.data().swap(newdata);

      update_trailing_pointers = true;
    } else {
      if (m_matrix.isCompressed() && nnz != block_size) {
        // no need to realloc, simply copy the tail at its respective position and insert tmp
        matrix.data().resize(start + nnz + tail_size);

        internal::smart_memmove(matrix.valuePtr() + end, matrix.valuePtr() + end + tail_size,
                                matrix.valuePtr() + start + nnz);
        internal::smart_memmove(matrix.innerIndexPtr() + end, matrix.innerIndexPtr() + end + tail_size,
                                matrix.innerIndexPtr() + start + nnz);

        update_trailing_pointers = true;
      }

      internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, matrix.valuePtr() + start);
      internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz,
                           matrix.innerIndexPtr() + start);
    }

    // update outer index pointers and innerNonZeros
    if (IsVectorAtCompileTime) {
      if (!m_matrix.isCompressed()) matrix.innerNonZeroPtr()[m_outerStart] = StorageIndex(nnz);
      matrix.outerIndexPtr()[m_outerStart] = StorageIndex(start);
    } else {
      StorageIndex p = StorageIndex(start);
      for (Index k = 0; k < m_outerSize.value(); ++k) {
        StorageIndex nnz_k = internal::convert_index<StorageIndex>(tmp.innerVector(k).nonZeros());
        if (!m_matrix.isCompressed()) matrix.innerNonZeroPtr()[m_outerStart + k] = nnz_k;
        matrix.outerIndexPtr()[m_outerStart + k] = p;
        p += nnz_k;
      }
    }

    if (update_trailing_pointers) {
      StorageIndex offset = internal::convert_index<StorageIndex>(nnz - block_size);
      for (Index k = m_outerStart + m_outerSize.value(); k <= matrix.outerSize(); ++k) {
        matrix.outerIndexPtr()[k] += offset;
      }
    }

    return derived();
  }

  inline BlockType& operator=(const BlockType& other) { return operator= <BlockType>(other); }

  inline const Scalar* valuePtr() const { return m_matrix.valuePtr(); }
  inline Scalar* valuePtr() { return m_matrix.valuePtr(); }

  inline const StorageIndex* innerIndexPtr() const { return m_matrix.innerIndexPtr(); }
  inline StorageIndex* innerIndexPtr() { return m_matrix.innerIndexPtr(); }

  inline const StorageIndex* outerIndexPtr() const { return m_matrix.outerIndexPtr() + m_outerStart; }
  inline StorageIndex* outerIndexPtr() { return m_matrix.outerIndexPtr() + m_outerStart; }

  inline const StorageIndex* innerNonZeroPtr() const {
    return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr() + m_outerStart);
  }
  inline StorageIndex* innerNonZeroPtr() { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr() + m_outerStart); }

  bool isCompressed() const { return m_matrix.innerNonZeroPtr() == 0; }

  inline Scalar& coeffRef(Index row, Index col) {
    return m_matrix.coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
  }

  inline const Scalar coeff(Index row, Index col) const {
    return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
  }

  inline const Scalar coeff(Index index) const {
    return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
  }

  const Scalar& lastCoeff() const {
    EIGEN_STATIC_ASSERT_VECTOR_ONLY(sparse_matrix_block_impl);
    eigen_assert(Base::nonZeros() > 0);
    if (m_matrix.isCompressed())
      return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart + 1] - 1];
    else
      return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart] + m_matrix.innerNonZeroPtr()[m_outerStart] - 1];
  }

  EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
  EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }

  inline const SparseMatrixType& nestedExpression() const { return m_matrix; }
  inline SparseMatrixType& nestedExpression() { return m_matrix; }
  Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
  Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
  Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
  Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }

 protected:
  typename internal::ref_selector<SparseMatrixType>::non_const_type m_matrix;
  Index m_outerStart;
  const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
};

}  // namespace internal

template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
class BlockImpl<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true, Sparse>
    : public internal::sparse_matrix_block_impl<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols> {
 public:
  typedef StorageIndex_ StorageIndex;
  typedef SparseMatrix<Scalar_, Options_, StorageIndex_> SparseMatrixType;
  typedef internal::sparse_matrix_block_impl<SparseMatrixType, BlockRows, BlockCols> Base;
  inline BlockImpl(SparseMatrixType& xpr, Index i) : Base(xpr, i) {}

  inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
      : Base(xpr, startRow, startCol, blockRows, blockCols) {}

  using Base::operator=;
};

template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
class BlockImpl<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true, Sparse>
    : public internal::sparse_matrix_block_impl<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows,
                                                BlockCols> {
 public:
  typedef StorageIndex_ StorageIndex;
  typedef const SparseMatrix<Scalar_, Options_, StorageIndex_> SparseMatrixType;
  typedef internal::sparse_matrix_block_impl<SparseMatrixType, BlockRows, BlockCols> Base;
  inline BlockImpl(SparseMatrixType& xpr, Index i) : Base(xpr, i) {}

  inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
      : Base(xpr, startRow, startCol, blockRows, blockCols) {}

  using Base::operator=;

 private:
  template <typename Derived>
  BlockImpl(const SparseMatrixBase<Derived>& xpr, Index i);
  template <typename Derived>
  BlockImpl(const SparseMatrixBase<Derived>& xpr);
};

//----------

/** Generic implementation of sparse Block expression.
 * Real-only.
 */
template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Sparse>
    : public SparseMatrixBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >, internal::no_assignment_operator {
  typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
  typedef SparseMatrixBase<BlockType> Base;
  using Base::convert_index;

 public:
  enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
  EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)

  typedef internal::remove_all_t<typename XprType::Nested> MatrixTypeNested_;

  /** Column or Row constructor
   */
  inline BlockImpl(XprType& xpr, Index i)
      : m_matrix(xpr),
        m_startRow((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) ? convert_index(i) : 0),
        m_startCol((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) ? convert_index(i) : 0),
        m_blockRows(BlockRows == 1 ? 1 : xpr.rows()),
        m_blockCols(BlockCols == 1 ? 1 : xpr.cols()) {}

  /** Dynamic-size constructor
   */
  inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
      : m_matrix(xpr),
        m_startRow(convert_index(startRow)),
        m_startCol(convert_index(startCol)),
        m_blockRows(convert_index(blockRows)),
        m_blockCols(convert_index(blockCols)) {}

  inline Index rows() const { return m_blockRows.value(); }
  inline Index cols() const { return m_blockCols.value(); }

  inline Scalar& coeffRef(Index row, Index col) {
    return m_matrix.coeffRef(row + m_startRow.value(), col + m_startCol.value());
  }

  inline const Scalar coeff(Index row, Index col) const {
    return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
  }

  inline Scalar& coeffRef(Index index) {
    return m_matrix.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
                             m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
  }

  inline const Scalar coeff(Index index) const {
    return m_matrix.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
                          m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
  }

  inline const XprType& nestedExpression() const { return m_matrix; }
  inline XprType& nestedExpression() { return m_matrix; }
  Index startRow() const { return m_startRow.value(); }
  Index startCol() const { return m_startCol.value(); }
  Index blockRows() const { return m_blockRows.value(); }
  Index blockCols() const { return m_blockCols.value(); }

 protected:
  //     friend class internal::GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel>;
  friend struct internal::unary_evaluator<Block<XprType, BlockRows, BlockCols, InnerPanel>, internal::IteratorBased,
                                          Scalar>;

  Index nonZeros() const { return Dynamic; }

  typename internal::ref_selector<XprType>::non_const_type m_matrix;
  const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
  const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
  const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
  const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;

 protected:
  // Disable assignment with clear error message.
  // Note that simply removing operator= yields compilation errors with ICC+MSVC
  template <typename T>
  BlockImpl& operator=(const T&) {
    EIGEN_STATIC_ASSERT(sizeof(T) == 0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
    return *this;
  }
};

namespace internal {

template <typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
struct unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IteratorBased>
    : public evaluator_base<Block<ArgType, BlockRows, BlockCols, InnerPanel> > {
  class InnerVectorInnerIterator;
  class OuterVectorInnerIterator;

 public:
  typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename XprType::Scalar Scalar;

  enum {
    IsRowMajor = XprType::IsRowMajor,
    OuterVector = (BlockCols == 1 && ArgType::IsRowMajor) || (BlockRows == 1 && !ArgType::IsRowMajor),
    CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
    Flags = XprType::Flags
  };

  typedef std::conditional_t<OuterVector, OuterVectorInnerIterator, InnerVectorInnerIterator> InnerIterator;

  explicit unary_evaluator(const XprType& op) : m_argImpl(op.nestedExpression()), m_block(op) {}

  inline Index nonZerosEstimate() const {
    const Index nnz = m_block.nonZeros();
    if (nnz < 0) {
      // Scale the non-zero estimate for the underlying expression linearly with block size.
      // Return zero if the underlying block is empty.
      const Index nested_sz = m_block.nestedExpression().size();
      return nested_sz == 0 ? 0 : m_argImpl.nonZerosEstimate() * m_block.size() / nested_sz;
    }
    return nnz;
  }

 protected:
  typedef typename evaluator<ArgType>::InnerIterator EvalIterator;

  evaluator<ArgType> m_argImpl;
  const XprType& m_block;
};

template <typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
class unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IteratorBased>::InnerVectorInnerIterator
    : public EvalIterator {
  // NOTE MSVC fails to compile if we don't explicitly "import" IsRowMajor from unary_evaluator
  //      because the base class EvalIterator has a private IsRowMajor enum too. (bug #1786)
  // NOTE We cannot call it IsRowMajor because it would shadow unary_evaluator::IsRowMajor
  enum { XprIsRowMajor = unary_evaluator::IsRowMajor };
  const XprType& m_block;
  Index m_end;

 public:
  EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer)
      : EvalIterator(aEval.m_argImpl, outer + (XprIsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())),
        m_block(aEval.m_block),
        m_end(XprIsRowMajor ? aEval.m_block.startCol() + aEval.m_block.blockCols()
                            : aEval.m_block.startRow() + aEval.m_block.blockRows()) {
    while ((EvalIterator::operator bool()) &&
           (EvalIterator::index() < (XprIsRowMajor ? m_block.startCol() : m_block.startRow())))
      EvalIterator::operator++();
  }

  inline StorageIndex index() const {
    return EvalIterator::index() - convert_index<StorageIndex>(XprIsRowMajor ? m_block.startCol() : m_block.startRow());
  }
  inline Index outer() const {
    return EvalIterator::outer() - (XprIsRowMajor ? m_block.startRow() : m_block.startCol());
  }
  inline Index row() const { return EvalIterator::row() - m_block.startRow(); }
  inline Index col() const { return EvalIterator::col() - m_block.startCol(); }

  inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; }
};

template <typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
class unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IteratorBased>::OuterVectorInnerIterator {
  // NOTE see above
  enum { XprIsRowMajor = unary_evaluator::IsRowMajor };
  const unary_evaluator& m_eval;
  Index m_outerPos;
  const Index m_innerIndex;
  Index m_end;
  EvalIterator m_it;

 public:
  EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer)
      : m_eval(aEval),
        m_outerPos((XprIsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow())),
        m_innerIndex(XprIsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()),
        m_end(XprIsRowMajor ? aEval.m_block.startCol() + aEval.m_block.blockCols()
                            : aEval.m_block.startRow() + aEval.m_block.blockRows()),
        m_it(m_eval.m_argImpl, m_outerPos) {
    EIGEN_UNUSED_VARIABLE(outer);
    eigen_assert(outer == 0);

    while (m_it && m_it.index() < m_innerIndex) ++m_it;
    if ((!m_it) || (m_it.index() != m_innerIndex)) ++(*this);
  }

  inline StorageIndex index() const {
    return convert_index<StorageIndex>(m_outerPos -
                                       (XprIsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow()));
  }
  inline Index outer() const { return 0; }
  inline Index row() const { return XprIsRowMajor ? 0 : index(); }
  inline Index col() const { return XprIsRowMajor ? index() : 0; }

  inline Scalar value() const { return m_it.value(); }
  inline Scalar& valueRef() { return m_it.valueRef(); }

  inline OuterVectorInnerIterator& operator++() {
    // search next non-zero entry
    while (++m_outerPos < m_end) {
      // Restart iterator at the next inner-vector:
      internal::destroy_at(&m_it);
      internal::construct_at(&m_it, m_eval.m_argImpl, m_outerPos);
      // search for the key m_innerIndex in the current outer-vector
      while (m_it && m_it.index() < m_innerIndex) ++m_it;
      if (m_it && m_it.index() == m_innerIndex) break;
    }
    return *this;
  }

  inline operator bool() const { return m_outerPos < m_end; }
};

template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
struct unary_evaluator<Block<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true>, IteratorBased>
    : evaluator<
          SparseCompressedBase<Block<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true> > > {
  typedef Block<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true> XprType;
  typedef evaluator<SparseCompressedBase<XprType> > Base;
  explicit unary_evaluator(const XprType& xpr) : Base(xpr) {}
};

template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
struct unary_evaluator<Block<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true>,
                       IteratorBased>
    : evaluator<SparseCompressedBase<
          Block<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true> > > {
  typedef Block<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true> XprType;
  typedef evaluator<SparseCompressedBase<XprType> > Base;
  explicit unary_evaluator(const XprType& xpr) : Base(xpr) {}
};

}  // end namespace internal

}  // end namespace Eigen

#endif  // EIGEN_SPARSE_BLOCK_H
