From 1b43860bc164056834c106378d35c9e62a228010 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 6 Oct 2015 11:41:03 +0200 Subject: Make SparseVector derive from SparseCompressedBase, thus improving compatibility between sparse vectors and matrices --- Eigen/src/SparseCore/SparseCompressedBase.h | 71 ++++++++++++++++------- Eigen/src/SparseCore/SparseVector.h | 88 ++++------------------------- 2 files changed, 63 insertions(+), 96 deletions(-) (limited to 'Eigen/src') diff --git a/Eigen/src/SparseCore/SparseCompressedBase.h b/Eigen/src/SparseCore/SparseCompressedBase.h index 0dbb94faf..ad3085a55 100644 --- a/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/Eigen/src/SparseCore/SparseCompressedBase.h @@ -45,13 +45,14 @@ class SparseCompressedBase /** \returns the number of non zero coefficients */ inline Index nonZeros() const { - if(isCompressed()) + if(Derived::IsVectorAtCompileTime && outerIndexPtr()==0) + return derived().nonZeros(); + else if(isCompressed()) return outerIndexPtr()[derived().outerSize()]-outerIndexPtr()[0]; else if(derived().outerSize()==0) return 0; else return innerNonZeros().sum(); - } /** \returns a const pointer to the array of values. @@ -74,10 +75,12 @@ class SparseCompressedBase /** \returns a const pointer to the array of the starting positions of the inner vectors. * This function is aimed at interoperability with other libraries. + * \warning it returns the null pointer 0 for SparseVector * \sa valuePtr(), innerIndexPtr() */ inline const StorageIndex* outerIndexPtr() const { return derived().outerIndexPtr(); } /** \returns a non-const pointer to the array of the starting positions of the inner vectors. * This function is aimed at interoperability with other libraries. + * \warning it returns the null pointer 0 for SparseVector * \sa valuePtr(), innerIndexPtr() */ inline StorageIndex* outerIndexPtr() { return derived().outerIndexPtr(); } @@ -100,12 +103,27 @@ class SparseCompressedBase::InnerIterator { public: InnerIterator(const SparseCompressedBase& mat, Index outer) - : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_id(mat.outerIndexPtr()[outer]) + : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer) { - if(mat.isCompressed()) - m_end = mat.outerIndexPtr()[outer+1]; + if(Derived::IsVectorAtCompileTime && mat.outerIndexPtr()==0) + { + m_id = 0; + m_end = mat.nonZeros(); + } else - m_end = m_id + mat.innerNonZeroPtr()[outer]; + { + m_id = mat.outerIndexPtr()[outer]; + if(mat.isCompressed()) + m_end = mat.outerIndexPtr()[outer+1]; + else + m_end = m_id + mat.innerNonZeroPtr()[outer]; + } + } + + InnerIterator(const SparseCompressedBase& mat) + : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(0), m_id(0), m_end(mat.nonZeros()) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); } inline InnerIterator& operator++() { m_id++; return *this; } @@ -114,16 +132,16 @@ class SparseCompressedBase::InnerIterator inline Scalar& valueRef() { return const_cast(m_values[m_id]); } inline StorageIndex 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 Index outer() const { return m_outer.value(); } + inline Index row() const { return IsRowMajor ? m_outer.value() : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer.value(); } inline operator bool() const { return (m_id < m_end); } protected: const Scalar* m_values; const StorageIndex* m_indices; - const Index m_outer; + const internal::variable_if_dynamic m_outer; Index m_id; Index m_end; private: @@ -138,32 +156,45 @@ class SparseCompressedBase::ReverseInnerIterator { public: ReverseInnerIterator(const SparseCompressedBase& mat, Index outer) - : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_start(mat.outerIndexPtr()[outer]) + : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer) { - if(mat.isCompressed()) - m_id = mat.outerIndexPtr()[outer+1]; + if(Derived::IsVectorAtCompileTime && mat.outerIndexPtr()==0) + { + m_start = 0; + m_id = mat.nonZeros(); + } else - m_id = m_start + mat.innerNonZeroPtr()[outer]; + { + m_start.value() = mat.outerIndexPtr()[outer]; + if(mat.isCompressed()) + m_id = mat.outerIndexPtr()[outer+1]; + else + m_id = m_start.value() + mat.innerNonZeroPtr()[outer]; + } } + ReverseInnerIterator(const SparseCompressedBase& mat) + : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(0), m_start(0), m_id(mat.nonZeros()) + {} + inline ReverseInnerIterator& operator--() { --m_id; 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 StorageIndex 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 Index outer() const { return m_outer.value(); } + inline Index row() const { return IsRowMajor ? m_outer.value() : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer.value(); } - inline operator bool() const { return (m_id > m_start); } + inline operator bool() const { return (m_id > m_start.value()); } protected: const Scalar* m_values; const StorageIndex* m_indices; - const Index m_outer; + const internal::variable_if_dynamic m_outer; Index m_id; - const Index m_start; + const internal::variable_if_dynamic m_start; }; namespace internal { diff --git a/Eigen/src/SparseCore/SparseVector.h b/Eigen/src/SparseCore/SparseVector.h index ccf9364f2..38b5a53df 100644 --- a/Eigen/src/SparseCore/SparseVector.h +++ b/Eigen/src/SparseCore/SparseVector.h @@ -40,7 +40,7 @@ struct traits > ColsAtCompileTime = IsColVector ? 1 : Dynamic, MaxRowsAtCompileTime = RowsAtCompileTime, MaxColsAtCompileTime = ColsAtCompileTime, - Flags = _Options | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit), + Flags = _Options | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit) | CompressedAccessBit, CoeffReadCost = NumTraits::ReadCost, SupportedAccessPatterns = InnerRandomAccessPattern }; @@ -63,12 +63,12 @@ struct sparse_vector_assign_selector; template class SparseVector - : public SparseMatrixBase > + : public SparseCompressedBase > { - typedef SparseMatrixBase SparseBase; + typedef SparseCompressedBase Base; public: - EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector) + _EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector) EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=) EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=) @@ -89,6 +89,11 @@ class SparseVector EIGEN_STRONG_INLINE const StorageIndex* innerIndexPtr() const { return &m_data.index(0); } EIGEN_STRONG_INLINE StorageIndex* innerIndexPtr() { return &m_data.index(0); } + + inline const StorageIndex* outerIndexPtr() const { return 0; } + inline StorageIndex* outerIndexPtr() { return 0; } + inline const StorageIndex* innerNonZeroPtr() const { return 0; } + inline StorageIndex* innerNonZeroPtr() { return 0; } /** \internal */ inline Storage& data() { return m_data; } @@ -126,8 +131,8 @@ class SparseVector public: - class InnerIterator; - class ReverseInnerIterator; + typedef typename Base::InnerIterator InnerIterator; + typedef typename Base::ReverseInnerIterator ReverseInnerIterator; inline void setZero() { m_data.clear(); } @@ -235,7 +240,7 @@ class SparseVector } inline SparseVector(const SparseVector& other) - : SparseBase(other), m_size(0) + : Base(other), m_size(0) { check_template_parameters(); *this = other.derived(); @@ -357,75 +362,6 @@ protected: Index m_size; }; -template -class SparseVector::InnerIterator -{ - public: - explicit InnerIterator(const SparseVector& vec, Index outer=0) - : m_data(vec.m_data), m_id(0), m_end(m_data.size()) - { - EIGEN_UNUSED_VARIABLE(outer); - eigen_assert(outer==0); - } - - explicit InnerIterator(const internal::CompressedStorage& data) - : m_data(data), m_id(0), m_end(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 StorageIndex 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; - Index m_id; - const Index m_end; - 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 SparseMatrixBase&,Index outer=0); -}; - -template -class SparseVector::ReverseInnerIterator -{ - public: - explicit ReverseInnerIterator(const SparseVector& vec, Index outer=0) - : m_data(vec.m_data), m_id(m_data.size()), m_start(0) - { - EIGEN_UNUSED_VARIABLE(outer); - eigen_assert(outer==0); - } - - explicit ReverseInnerIterator(const internal::CompressedStorage& data) - : m_data(data), m_id(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 StorageIndex 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; - Index m_id; - const Index m_start; -}; - namespace internal { template -- cgit v1.2.3