# HG changeset patch # Parent 743776e6544255dcde77e8c461ce98df6b922d0f diff --git a/Eigen/src/Core/CoreIterators.h b/Eigen/src/Core/CoreIterators.h --- a/Eigen/src/Core/CoreIterators.h +++ b/Eigen/src/Core/CoreIterators.h @@ -26,36 +26,39 @@ namespace Eigen { template class DenseBase::InnerIterator { protected: typedef typename Derived::Scalar Scalar; typedef typename Derived::Index Index; enum { IsRowMajor = (Derived::Flags&RowMajorBit)==RowMajorBit }; public: + InnerIterator() + : m_expression(0),m_inner(0),m_outer(0),m_end(0) + {} EIGEN_STRONG_INLINE InnerIterator(const Derived& expr, Index outer) - : m_expression(expr), m_inner(0), m_outer(outer), m_end(expr.innerSize()) + : m_expression(&expr), m_inner(0), m_outer(outer), m_end(expr.innerSize()) {} EIGEN_STRONG_INLINE Scalar value() const { - return (IsRowMajor) ? m_expression.coeff(m_outer, m_inner) - : m_expression.coeff(m_inner, m_outer); + return (IsRowMajor) ? m_expression->coeff(m_outer, m_inner) + : m_expression->coeff(m_inner, m_outer); } EIGEN_STRONG_INLINE InnerIterator& 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 Derived& m_expression; + const Derived* m_expression; Index m_inner; - const Index m_outer; - const Index m_end; + Index m_outer; + Index m_end; }; } // end namespace Eigen #endif // EIGEN_COREITERATORS_H diff --git a/Eigen/src/SparseCore/MappedSparseMatrix.h b/Eigen/src/SparseCore/MappedSparseMatrix.h --- a/Eigen/src/SparseCore/MappedSparseMatrix.h +++ b/Eigen/src/SparseCore/MappedSparseMatrix.h @@ -111,69 +111,93 @@ class MappedSparseMatrix /** Empty destructor */ inline ~MappedSparseMatrix() {} }; template class MappedSparseMatrix::InnerIterator { public: + InnerIterator() + : m_matrix(0), + m_outer(-1), + m_id(0), + m_start(0), + m_end(0) + { } + InnerIterator(const MappedSparseMatrix& mat, Index outer) - : m_matrix(mat), + : m_matrix(&mat), m_outer(outer), m_id(mat.outerIndexPtr()[outer]), m_start(m_id), m_end(mat.outerIndexPtr()[outer+1]) {} inline InnerIterator& operator++() { m_id++; return *this; } - inline Scalar value() const { return m_matrix.valuePtr()[m_id]; } - inline Scalar& valueRef() { return const_cast(m_matrix.valuePtr()[m_id]); } + inline Scalar value() const { return m_matrix->valuePtr()[m_id]; } + inline Scalar& valueRef() { return const_cast(m_matrix->valuePtr()[m_id]); } + + // Unlike the pos() function in SparseMatrix::InnerIterator, + // this is rather an offset than a position + inline Index pos() const {return (m_id - m_start); } + inline InnerIterator& operator+=(Index offset) {m_id += offset; return *this; } - inline Index index() const { return m_matrix.innerIndexPtr()[m_id]; } + inline Index index() const { return m_matrix->innerIndexPtr()[m_id]; } inline Index row() const { return IsRowMajor ? m_outer : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer; } inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); } protected: - const MappedSparseMatrix& m_matrix; - const Index m_outer; + const MappedSparseMatrix *m_matrix; + Index m_outer; Index m_id; - const Index m_start; - const Index m_end; + Index m_start; + Index m_end; }; template class MappedSparseMatrix::ReverseInnerIterator { public: + ReverseInnerIterator() + : m_matrix(0), + m_outer(-1), + m_id(0), + m_start(0), + m_end(0) + { } + ReverseInnerIterator(const MappedSparseMatrix& mat, Index outer) - : m_matrix(mat), + : m_matrix(&mat), m_outer(outer), m_id(mat.outerIndexPtr()[outer+1]), m_start(mat.outerIndexPtr()[outer]), m_end(m_id) {} inline ReverseInnerIterator& operator--() { m_id--; return *this; } - inline Scalar value() const { return m_matrix.valuePtr()[m_id-1]; } - inline Scalar& valueRef() { return const_cast(m_matrix.valuePtr()[m_id-1]); } + inline Scalar value() const { return m_matrix->valuePtr()[m_id-1]; } + inline Scalar& valueRef() { return const_cast(m_matrix->valuePtr()[m_id-1]); } - inline Index index() const { return m_matrix.innerIndexPtr()[m_id-1]; } + inline Index pos() const {return (m_end - m_id); } + inline ReverseInnerIterator& operator-=(Index offset) {m_id -= offset; return *this; } + + inline Index index() const { return m_matrix->innerIndexPtr()[m_id-1]; } inline Index row() const { return IsRowMajor ? m_outer : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer; } inline operator bool() const { return (m_id <= m_end) && (m_id>m_start); } protected: - const MappedSparseMatrix& m_matrix; - const Index m_outer; + const MappedSparseMatrix* m_matrix; + Index m_outer; Index m_id; - const Index m_start; - const Index m_end; + Index m_start; + Index m_end; }; } // end namespace Eigen #endif // EIGEN_MAPPED_SPARSEMATRIX_H diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h --- a/Eigen/src/SparseCore/SparseBlock.h +++ b/Eigen/src/SparseCore/SparseBlock.h @@ -23,27 +23,33 @@ public: protected: enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; public: EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) class InnerIterator: public XprType::InnerIterator { public: + inline InnerIterator() + : XprType::InnerIterator(), m_outer(-1) + {} inline InnerIterator(const BlockType& xpr, Index outer) : XprType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : this->index(); } inline Index col() const { return IsRowMajor ? this->index() : m_outer; } protected: Index m_outer; }; class ReverseInnerIterator: public XprType::ReverseInnerIterator { public: + inline ReverseInnerIterator() + : XprType::ReverseInnerIterator(), m_outer(-1) + {} inline ReverseInnerIterator(const BlockType& xpr, Index outer) : XprType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : this->index(); } inline Index col() const { return IsRowMajor ? this->index() : m_outer; } protected: Index m_outer; }; @@ -83,27 +89,33 @@ public: EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) protected: enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; public: class InnerIterator: public SparseMatrixType::InnerIterator { public: + inline InnerIterator() + : SparseMatrixType::InnerIterator(),m_outer(-1) + {} inline InnerIterator(const BlockType& xpr, Index outer) : SparseMatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : this->index(); } inline Index col() const { return IsRowMajor ? this->index() : m_outer; } protected: Index m_outer; }; class ReverseInnerIterator: public SparseMatrixType::ReverseInnerIterator { public: + inline ReverseInnerIterator() + : SparseMatrixType::ReverseInnerIterator(),m_outer(-1) + {} inline ReverseInnerIterator(const BlockType& xpr, Index outer) : SparseMatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : this->index(); } inline Index col() const { return IsRowMajor ? this->index() : m_outer; } protected: Index m_outer; }; @@ -338,56 +350,61 @@ public: m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); } inline const _MatrixTypeNested& nestedExpression() const { return m_matrix; } class InnerIterator : public _MatrixTypeNested::InnerIterator { typedef typename _MatrixTypeNested::InnerIterator Base; - const BlockType& m_block; + const BlockType *m_block; Index m_end; public: + InnerIterator() + : Base(), m_block(0),m_end(0) + {} EIGEN_STRONG_INLINE InnerIterator(const BlockType& block, Index outer) : Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())), - m_block(block), + m_block(&block), m_end(IsRowMajor ? block.m_startCol.value()+block.m_blockCols.value() : block.m_startRow.value()+block.m_blockRows.value()) { - while( (Base::operator bool()) && (Base::index() < (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value())) ) + while( (Base::operator bool()) && (Base::index() < (IsRowMajor ? m_block->m_startCol.value() : m_block->m_startRow.value())) ) Base::operator++(); } - inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); } - inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); } - inline Index row() const { return Base::row() - m_block.m_startRow.value(); } - inline Index col() const { return Base::col() - m_block.m_startCol.value(); } + inline Index index() const { return Base::index() - (IsRowMajor ? m_block->m_startCol.value() : m_block->m_startRow.value()); } + inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block->m_startRow.value() : m_block->m_startCol.value()); } + inline Index row() const { return Base::row() - m_block->m_startRow.value(); } + inline Index col() const { return Base::col() - m_block->m_startCol.value(); } inline operator bool() const { return Base::operator bool() && Base::index() < m_end; } }; class ReverseInnerIterator : public _MatrixTypeNested::ReverseInnerIterator { typedef typename _MatrixTypeNested::ReverseInnerIterator Base; - const BlockType& m_block; + const BlockType* m_block; Index m_begin; public: - + ReverseInnerIterator() + : m_block(0),m_begin(0) + {} EIGEN_STRONG_INLINE ReverseInnerIterator(const BlockType& block, Index outer) : Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())), - m_block(block), + m_block(*block), m_begin(IsRowMajor ? block.m_startCol.value() : block.m_startRow.value()) { - while( (Base::operator bool()) && (Base::index() >= (IsRowMajor ? m_block.m_startCol.value()+block.m_blockCols.value() : m_block.m_startRow.value()+block.m_blockRows.value())) ) + while( (Base::operator bool()) && (Base::index() >= (IsRowMajor ? m_block->m_startCol.value()+block.m_blockCols.value() : m_block->m_startRow.value()+block.m_blockRows.value())) ) Base::operator--(); } - inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); } - inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); } - inline Index row() const { return Base::row() - m_block.m_startRow.value(); } - inline Index col() const { return Base::col() - m_block.m_startCol.value(); } + inline Index index() const { return Base::index() - (IsRowMajor ? m_block->m_startCol.value() : m_block->m_startRow.value()); } + inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block->m_startRow.value() : m_block->m_startCol.value()); } + inline Index row() const { return Base::row() - m_block->m_startRow.value(); } + inline Index col() const { return Base::col() - m_block->m_startCol.value(); } inline operator bool() const { return Base::operator bool() && Base::index() >= m_begin; } }; protected: friend class InnerIterator; friend class ReverseInnerIterator; typename XprType::Nested m_matrix; diff --git a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h --- a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -67,17 +67,18 @@ class CwiseBinaryOpImpl class CwiseBinaryOpImpl::InnerIterator : public internal::sparse_cwise_binary_op_inner_iterator_selector::InnerIterator> { public: typedef typename Lhs::Index Index; typedef internal::sparse_cwise_binary_op_inner_iterator_selector< BinaryOp,Lhs,Rhs, InnerIterator> Base; - + + InnerIterator() : Base() {} EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, typename CwiseBinaryOpImpl::Index outer) : Base(binOp.derived(),outer) {} }; /*************************************************************************** * Implementation of inner-iterators ***************************************************************************/ diff --git a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h --- a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -32,40 +32,40 @@ class CwiseUnaryOpImpl class CwiseUnaryOpImpl::InnerIterator : public CwiseUnaryOpImpl::MatrixTypeIterator { typedef typename CwiseUnaryOpImpl::Scalar Scalar; typedef typename CwiseUnaryOpImpl::MatrixTypeIterator Base; public: - + InnerIterator() : Base() { } EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOpImpl& unaryOp, typename CwiseUnaryOpImpl::Index outer) : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) {} EIGEN_STRONG_INLINE InnerIterator& operator++() { Base::operator++(); return *this; } EIGEN_STRONG_INLINE typename CwiseUnaryOpImpl::Scalar value() const { return m_functor(Base::value()); } protected: - const UnaryOp m_functor; + UnaryOp m_functor; private: typename CwiseUnaryOpImpl::Scalar& valueRef(); }; template class CwiseUnaryOpImpl::ReverseInnerIterator : public CwiseUnaryOpImpl::MatrixTypeReverseIterator { typedef typename CwiseUnaryOpImpl::Scalar Scalar; typedef typename CwiseUnaryOpImpl::MatrixTypeReverseIterator Base; public: - + ReverseInnerIterator() : Base() { } EIGEN_STRONG_INLINE ReverseInnerIterator(const CwiseUnaryOpImpl& unaryOp, typename CwiseUnaryOpImpl::Index outer) : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) {} EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() { Base::operator--(); return *this; } EIGEN_STRONG_INLINE typename CwiseUnaryOpImpl::Scalar value() const { return m_functor(Base::value()); } @@ -96,51 +96,51 @@ class CwiseUnaryViewImpl class CwiseUnaryViewImpl::InnerIterator : public CwiseUnaryViewImpl::MatrixTypeIterator { typedef typename CwiseUnaryViewImpl::Scalar Scalar; typedef typename CwiseUnaryViewImpl::MatrixTypeIterator Base; public: - + InnerIterator() : Base() { } EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryViewImpl& unaryOp, typename CwiseUnaryViewImpl::Index outer) : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) {} EIGEN_STRONG_INLINE InnerIterator& operator++() { Base::operator++(); return *this; } EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar value() const { return m_functor(Base::value()); } EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar& valueRef() { return m_functor(Base::valueRef()); } protected: - const ViewOp m_functor; + ViewOp m_functor; }; template class CwiseUnaryViewImpl::ReverseInnerIterator : public CwiseUnaryViewImpl::MatrixTypeReverseIterator { typedef typename CwiseUnaryViewImpl::Scalar Scalar; typedef typename CwiseUnaryViewImpl::MatrixTypeReverseIterator Base; public: - + ReverseInnerIterator() : Base() { } EIGEN_STRONG_INLINE ReverseInnerIterator(const CwiseUnaryViewImpl& unaryOp, typename CwiseUnaryViewImpl::Index outer) : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) {} EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() { Base::operator--(); return *this; } EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar value() const { return m_functor(Base::value()); } EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar& valueRef() { return m_functor(Base::valueRef()); } protected: - const ViewOp m_functor; + ViewOp m_functor; }; template EIGEN_STRONG_INLINE Derived& SparseMatrixBase::operator*=(const Scalar& other) { for (Index j=0; j class SparseDenseOuterProduct::InnerIterator : public _LhsNested::InnerIterator { typedef typename _LhsNested::InnerIterator Base; public: + InnerIterator() + : Base(),m_outer(-1),m_factor(0) + {} EIGEN_STRONG_INLINE InnerIterator(const SparseDenseOuterProduct& prod, Index outer) : Base(prod.lhs(), 0), m_outer(outer), m_factor(prod.rhs().coeff(outer)) { } inline Index outer() const { return m_outer; } inline Index row() const { return Transpose ? Base::row() : m_outer; } inline Index col() const { return Transpose ? m_outer : Base::row(); } diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -860,78 +860,92 @@ private: RealScalar epsilon; }; }; template class SparseMatrix::InnerIterator { public: + InnerIterator() + : m_values(0),m_indices(0),m_outer(-1),m_id(0),m_end(0) + { } + InnerIterator(const SparseMatrix& mat, Index outer) - : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_id(mat.m_outerIndex[outer]) + : m_values(mat.valuePtr()+mat.m_outerIndex[outer]), m_indices(mat.innerIndexPtr()+mat.m_outerIndex[outer]), m_outer(outer), m_id(0) { if(mat.isCompressed()) - m_end = mat.m_outerIndex[outer+1]; + m_end = mat.m_outerIndex[outer+1]-mat.m_outerIndex[outer]; else - m_end = m_id + mat.m_innerNonZeros[outer]; + m_end = mat.m_innerNonZeros[outer]; } inline InnerIterator& operator++() { m_id++; return *this; } + + inline InnerIterator& operator+=(Index offset) { m_id+=offset; return *this; } + inline Index pos() const { return m_id; } inline const Scalar& value() const { return m_values[m_id]; } inline Scalar& valueRef() { return const_cast(m_values[m_id]); } inline Index index() const { return m_indices[m_id]; } inline Index outer() const { return m_outer; } inline Index row() const { return IsRowMajor ? m_outer : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer; } inline operator bool() const { return (m_id < m_end); } protected: const Scalar* m_values; const Index* m_indices; - const Index m_outer; + Index m_outer; Index m_id; Index m_end; }; + template class SparseMatrix::ReverseInnerIterator { public: + ReverseInnerIterator() + : m_values(0),m_indices(0),m_outer(-1),m_id(0) + { } ReverseInnerIterator(const SparseMatrix& mat, Index outer) - : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_start(mat.m_outerIndex[outer]) + : m_values(mat.valuePtr()+mat.m_outerIndex[outer]), m_indices(mat.innerIndexPtr()+mat.m_outerIndex[outer]), m_outer(outer) { if(mat.isCompressed()) - m_id = mat.m_outerIndex[outer+1]; + m_id = mat.m_outerIndex[outer+1] - mat.m_outerIndex[outer]; else - m_id = m_start + mat.m_innerNonZeros[outer]; + m_id = mat.m_innerNonZeros[outer]; + m_end = m_id; } inline ReverseInnerIterator& operator--() { --m_id; return *this; } - + + inline Index pos() const {return m_end - m_id; } + inline ReverseInnerIterator& operator-=(Index offset) { m_id -= offset; return *this; } + inline const Scalar& value() const { return m_values[m_id-1]; } inline Scalar& valueRef() { return const_cast(m_values[m_id-1]); } inline Index index() const { return m_indices[m_id-1]; } inline Index outer() const { return m_outer; } inline Index row() const { return IsRowMajor ? m_outer : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer; } - inline operator bool() const { return (m_id > m_start); } + inline operator bool() const { return (m_id > 0); } protected: const Scalar* m_values; const Index* m_indices; const Index m_outer; Index m_id; - const Index m_start; + Index m_end; }; - namespace internal { template void set_from_triplets(const InputIterator& begin, const InputIterator& end, SparseMatrixType& mat, int Options = 0) { EIGEN_UNUSED_VARIABLE(Options); enum { IsRowMajor = SparseMatrixType::IsRowMajor }; typedef typename SparseMatrixType::Scalar Scalar; diff --git a/Eigen/src/SparseCore/SparseTranspose.h b/Eigen/src/SparseCore/SparseTranspose.h --- a/Eigen/src/SparseCore/SparseTranspose.h +++ b/Eigen/src/SparseCore/SparseTranspose.h @@ -30,30 +30,31 @@ template class Tran // a typedef typename TransposeImpl::Index Index; // does not fix the issue. // An alternative is to define the nested class in the parent class itself. template class TransposeImpl::InnerIterator : public _MatrixTypeNested::InnerIterator { typedef typename _MatrixTypeNested::InnerIterator Base; public: - + InnerIterator() : Base() { } + EIGEN_STRONG_INLINE InnerIterator(const TransposeImpl& trans, typename TransposeImpl::Index outer) : Base(trans.derived().nestedExpression(), outer) {} inline typename TransposeImpl::Index row() const { return Base::col(); } inline typename TransposeImpl::Index col() const { return Base::row(); } }; template class TransposeImpl::ReverseInnerIterator : public _MatrixTypeNested::ReverseInnerIterator { typedef typename _MatrixTypeNested::ReverseInnerIterator Base; public: - + ReverseInnerIterator() : Base() { } EIGEN_STRONG_INLINE ReverseInnerIterator(const TransposeImpl& xpr, typename TransposeImpl::Index outer) : Base(xpr.derived().nestedExpression(), outer) {} inline typename TransposeImpl::Index row() const { return Base::col(); } inline typename TransposeImpl::Index col() const { return Base::row(); } }; } // end namespace Eigen diff --git a/Eigen/src/SparseCore/SparseVector.h b/Eigen/src/SparseCore/SparseVector.h --- a/Eigen/src/SparseCore/SparseVector.h +++ b/Eigen/src/SparseCore/SparseVector.h @@ -333,74 +333,80 @@ protected: Storage m_data; Index m_size; }; template class SparseVector::InnerIterator { public: + InnerIterator() + : m_data(0),m_id(0),m_end(0) + {} InnerIterator(const SparseVector& vec, Index outer=0) - : m_data(vec.m_data), m_id(0), m_end(static_cast(m_data.size())) + : m_data(*vec.m_data), m_id(0), m_end(static_cast(m_data.size())) { EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); } InnerIterator(const internal::CompressedStorage& data) - : m_data(data), m_id(0), m_end(static_cast(m_data.size())) + : m_data(*data), m_id(0), m_end(static_cast(m_data.size())) {} inline InnerIterator& operator++() { m_id++; return *this; } - inline Scalar value() const { return m_data.value(m_id); } - inline Scalar& valueRef() { return const_cast(m_data.value(m_id)); } + inline Scalar value() const { return m_data->value(m_id); } + inline Scalar& valueRef() { return const_cast(m_data->value(m_id)); } - inline Index index() const { return m_data.index(m_id); } + inline Index index() const { return m_data->index(m_id); } inline Index row() const { return IsColVector ? index() : 0; } inline Index col() const { return IsColVector ? 0 : index(); } inline operator bool() const { return (m_id < m_end); } protected: - const internal::CompressedStorage& m_data; + const internal::CompressedStorage* m_data; Index m_id; - const Index m_end; + Index m_end; }; template class SparseVector::ReverseInnerIterator { public: + ReverseInnerIterator() + : m_data(0),m_id(0),m_start(0) + {} ReverseInnerIterator(const SparseVector& vec, Index outer=0) - : m_data(vec.m_data), m_id(static_cast(m_data.size())), m_start(0) + : m_data(*vec.m_data), m_id(static_cast(m_data.size())), m_start(0) { EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); } ReverseInnerIterator(const internal::CompressedStorage& data) - : m_data(data), m_id(static_cast(m_data.size())), m_start(0) + : m_data(*data), m_id(static_cast(m_data.size())), m_start(0) {} inline ReverseInnerIterator& operator--() { m_id--; return *this; } - inline Scalar value() const { return m_data.value(m_id-1); } - inline Scalar& valueRef() { return const_cast(m_data.value(m_id-1)); } + inline Scalar value() const { return m_data->value(m_id-1); } + inline Scalar& valueRef() { return const_cast(m_data->value(m_id-1)); } - inline Index index() const { return m_data.index(m_id-1); } + inline Index index() const { return m_data->index(m_id-1); } inline Index row() const { return IsColVector ? index() : 0; } inline Index col() const { return IsColVector ? 0 : index(); } inline operator bool() const { return (m_id > m_start); } protected: - const internal::CompressedStorage& m_data; + const internal::CompressedStorage* m_data; Index m_id; - const Index m_start; + Index m_start; }; template template EIGEN_DONT_INLINE SparseVector& SparseVector::assign(const SparseMatrixBase& _other) { const OtherDerived& other(_other.derived()); const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); diff --git a/Eigen/src/SparseCore/SparseView.h b/Eigen/src/SparseCore/SparseView.h --- a/Eigen/src/SparseCore/SparseView.h +++ b/Eigen/src/SparseCore/SparseView.h @@ -53,38 +53,40 @@ protected: typename NumTraits::Real m_epsilon; }; template class SparseView::InnerIterator : public _MatrixTypeNested::InnerIterator { public: typedef typename _MatrixTypeNested::InnerIterator IterBase; + InnerIterator() : IterBase(),m_view(0) + {} InnerIterator(const SparseView& view, Index outer) : - IterBase(view.m_matrix, outer), m_view(view) + IterBase(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; + const SparseView* m_view; private: void incrementToNonZero() { - while((bool(*this)) && internal::isMuchSmallerThan(value(), m_view.m_reference, m_view.m_epsilon)) + while((bool(*this)) && internal::isMuchSmallerThan(value(), m_view->m_reference, m_view->m_epsilon)) { IterBase::operator++(); } } }; template const SparseView MatrixBase::sparseView(const Scalar& m_reference, diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -224,16 +224,17 @@ ei_add_test(prec_inverse_4x4) ei_add_test(vectorwiseop) ei_add_test(special_numbers) ei_add_test(simplicial_cholesky) ei_add_test(conjugate_gradient) ei_add_test(bicgstab) ei_add_test(sparselu) ei_add_test(sparseqr) +ei_add_test(sparse_iterators) # ei_add_test(denseLM) if(QT4_FOUND) ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}") endif(QT4_FOUND) ei_add_test(eigen2support) diff --git a/test/sparse_iterators.cpp b/test/sparse_iterators.cpp new file mode 100644 --- /dev/null +++ b/test/sparse_iterators.cpp @@ -0,0 +1,150 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2013 Désiré Nuentsa +// +// 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/. + +#include "sparse.h" +template +void kernel_sparse_iterator(const SparseMatrixType& mS, const DenseMatrix& refS) +{ + typedef typename SparseMatrixType::Scalar Scalar; + typedef typename SparseMatrixType::Index Index; + typedef Matrix DenseVector; + Index size = mS.cols(); + + // Test the function pos() of SparseMatrixType::InnerIterator and ReverseInnerTerator + { + VectorXi forward_pos(size); // for the internal positions of iterator + VectorXi reverse_pos(size); // internal positions of reverse iterator + VectorXi forward_idx(size); // Row Index in each column where to stop iterating + VectorXi reverse_idx(size); // Row Index in each column where to stop reverse iterating + for (Index j = 0; j < size; j++) + { + forward_idx(j) = internal::random(0, j); + reverse_idx(j) = internal::random(j, size - 1); + } + + /* Browse the matrix mS until the selected row indexes or the diagonal element + * and save the positions of the iterators for each column + */ + forward_pos.setZero(); reverse_pos.setZero(); + for (Index j = 0; j < size; j++) + { + for (typename SparseMatrixType::InnerIterator it(mS,j); it; ++it) + { + if ( (it.index() == forward_idx(j)) || (it.index() == j)) + { + forward_pos(j) = it.pos(); + forward_idx(j) = it.index(); + break; + } + } + for (typename SparseMatrixType::ReverseInnerIterator r_it(mS, j); r_it; --r_it) + { + if ( (r_it.index() == reverse_idx(j)) || (r_it.index() == j)) + { + reverse_pos(j) = r_it.pos(); + reverse_idx(j) = r_it.index(); + break; + } + } + } + // Get the values of refS and mS in the saved positions + DenseVector refdS(size), refsS(size); + for(Index j = 0; j < size; ++j) refdS(j) = refS.coeffByOuterInner(j,forward_idx(j)); + //refS.coeffByOuterInner(j,forward_idx(j)) + for (Index j = 0; j < size; ++j) + { + typename SparseMatrixType::InnerIterator it(mS, j); + it += forward_pos(j); + refsS(j) = it.value(); + } + + VERIFY_IS_APPROX(refdS, refsS); + + for(Index j = 0; j < size; ++j) refdS(j) = refS.coeffByOuterInner(j,reverse_idx(j)); + for (Index j = 0; j < size; ++j) + { + typename SparseMatrixType::ReverseInnerIterator it(mS, j); + it -= reverse_pos(j); + refsS(j) = it.value(); + } + VERIFY_IS_APPROX(refdS, refsS); + } + + /* Test copy constructors + * for SparseMatrix::InnerIterator + * and SparseMatrix::ReverseInnerIterator + */ + { + Index c = internal::random(0, size - 1); + Index r1 = internal::random(0, c); + typename SparseMatrixType::InnerIterator it(mS, c); + //Iterate until mS(r,c) if it exists otherwise mS(c, c) + for (; it; ++it) + { + if ( (it.index() == r1) || (it.index() == c)) + { + r1 = it.index(); // Save the row index effectively found + break; + } + } + //Copy the constructor + typename SparseMatrixType::InnerIterator itc(it); + VERIFY_IS_EQUAL(itc.value(), refS.coeffByOuterInner(c, r1)); + //Same stuffs with ReverseInnerTerator + Index r2 = internal::random(c, size - 1); + typename SparseMatrixType::ReverseInnerIterator r_it(mS, c); + for (; r_it; --r_it) + { + if ( (r_it.index() == r2) || (r_it.index() == c)) + { + r2 = r_it.index(); + break; + } + } + typename SparseMatrixType::ReverseInnerIterator r_itc(r_it); + VERIFY_IS_EQUAL(r_itc.value(), refS.coeffByOuterInner(c, r2)); + } +} + + +template +void sparse_iterator() +{ + typedef typename SparseMatrixType::Index Index; + typedef typename SparseMatrixType::Scalar Scalar; + typedef Matrix DenseMatrix; + + // Generate the matrices + Index n = 100; + const Index size = internal::random(1,n); + DenseMatrix refS(size,size); + SparseMatrixType mS(size, size); + double density = (std::max)(8./(size*size), 0.1); + initSparse(density, refS, mS, ForceNonZeroDiag); + + // Test with the full matrix + kernel_sparse_iterator(mS, refS); + const Index r = internal::random(0, n/2); + + // Test with the block matrices + // kernel_sparse_iterator(mS.topLeftCorner(r, r), refS.topLeftCorner(r,r)); + // kernel_sparse_iterator(mS.bottomRightCorner(r, r), refS.bottomRightCorner(r,r)); + // Test with the mapped sparse matrix ... applicable ?? +} + +void test_sparse_iterators() +{ + for (int i = 0; i < g_repeat; i++) + { + CALL_SUBTEST_1( (sparse_iterator >()) ); + CALL_SUBTEST_1( (sparse_iterator >()) ); + CALL_SUBTEST_2( (sparse_iterator, ColMajor> >()) ); + CALL_SUBTEST_2( (sparse_iterator, RowMajor> >()) ); + } +} diff --git a/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h b/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h --- a/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h +++ b/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h @@ -320,38 +320,44 @@ template class DynamicSparseMatrix::InnerIterator : public SparseVector::InnerIterator { typedef typename SparseVector::InnerIterator Base; public: + InnerIterator() + : Base(),m_outer(-1) + {} InnerIterator(const DynamicSparseMatrix& mat, Index outer) : Base(mat.m_data[outer]), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : Base::index(); } inline Index col() const { return IsRowMajor ? Base::index() : m_outer; } protected: - const Index m_outer; + Index m_outer; }; template class DynamicSparseMatrix::ReverseInnerIterator : public SparseVector::ReverseInnerIterator { typedef typename SparseVector::ReverseInnerIterator Base; public: + ReverseInnerIterator() + : Base(),m_outer(-1) + {} ReverseInnerIterator(const DynamicSparseMatrix& mat, Index outer) : Base(mat.m_data[outer]), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : Base::index(); } inline Index col() const { return IsRowMajor ? Base::index() : m_outer; } protected: - const Index m_outer; + Index m_outer; }; } // end namespace Eigen #endif // EIGEN_DYNAMIC_SPARSEMATRIX_H