diff options
-rw-r--r-- | Eigen/src/Core/util/StaticAssert.h | 3 | ||||
-rw-r--r-- | Eigen/src/Sparse/DynamicSparseMatrix.h | 3 | ||||
-rw-r--r-- | Eigen/src/Sparse/SparseBlock.h | 215 | ||||
-rw-r--r-- | Eigen/src/Sparse/SparseCwiseBinaryOp.h | 2 | ||||
-rw-r--r-- | Eigen/src/Sparse/SparseMatrixBase.h | 27 | ||||
-rw-r--r-- | Eigen/src/Sparse/SparseUtil.h | 2 | ||||
-rw-r--r-- | Eigen/src/Sparse/SparseVector.h | 20 | ||||
-rw-r--r-- | test/sparse_basic.cpp | 18 |
8 files changed, 237 insertions, 53 deletions
diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index 60055683e..7ceeabb5f 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -73,7 +73,8 @@ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES, THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES, - INVALID_MATRIX_TEMPLATE_PARAMETERS + INVALID_MATRIX_TEMPLATE_PARAMETERS, + BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER }; }; diff --git a/Eigen/src/Sparse/DynamicSparseMatrix.h b/Eigen/src/Sparse/DynamicSparseMatrix.h index d59b81458..74916e0ab 100644 --- a/Eigen/src/Sparse/DynamicSparseMatrix.h +++ b/Eigen/src/Sparse/DynamicSparseMatrix.h @@ -83,6 +83,9 @@ class DynamicSparseMatrix inline int innerSize() const { return m_innerSize; } inline int outerSize() const { return m_data.size(); } inline int innerNonZeros(int j) const { return m_data[j].size(); } + + std::vector<CompressedStorage<Scalar> >& _data() { return m_data; } + const std::vector<CompressedStorage<Scalar> >& _data() const { return m_data; } /** \returns the coefficient value at given position \a row, \a col * This operation involes a log(rho*outer_size) binary search. diff --git a/Eigen/src/Sparse/SparseBlock.h b/Eigen/src/Sparse/SparseBlock.h index cbec36e61..a90ccd812 100644 --- a/Eigen/src/Sparse/SparseBlock.h +++ b/Eigen/src/Sparse/SparseBlock.h @@ -26,61 +26,154 @@ #ifndef EIGEN_SPARSE_BLOCK_H #define EIGEN_SPARSE_BLOCK_H -template<typename MatrixType> -struct ei_traits<SparseInnerVector<MatrixType> > +template<typename MatrixType, int Size> +struct ei_traits<SparseInnerVectorSet<MatrixType, Size> > { typedef typename ei_traits<MatrixType>::Scalar Scalar; enum { IsRowMajor = (int(MatrixType::Flags)&RowMajorBit)==RowMajorBit, Flags = MatrixType::Flags, - RowsAtCompileTime = IsRowMajor ? 1 : MatrixType::RowsAtCompileTime, - ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : 1, + RowsAtCompileTime = IsRowMajor ? Size : MatrixType::RowsAtCompileTime, + ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : Size, CoeffReadCost = MatrixType::CoeffReadCost }; }; -template<typename MatrixType> -class SparseInnerVector : ei_no_assignment_operator, - public SparseMatrixBase<SparseInnerVector<MatrixType> > +template<typename MatrixType, int Size> +class SparseInnerVectorSet : ei_no_assignment_operator, + public SparseMatrixBase<SparseInnerVectorSet<MatrixType, Size> > { - enum { - IsRowMajor = ei_traits<SparseInnerVector>::IsRowMajor - }; -public: + enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor }; + public: - EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVector) - class InnerIterator; + EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet) + class InnerIterator: public MatrixType::InnerIterator + { + public: + inline InnerIterator(const SparseInnerVectorSet& xpr, int outer) + : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer) + {} + }; - inline SparseInnerVector(const MatrixType& matrix, int outer) - : m_matrix(matrix), m_outer(outer) + inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize) + : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize) { + ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) ); + } + + inline SparseInnerVectorSet(const MatrixType& matrix, int outer) + : m_matrix(matrix), m_outerStart(outer) + { + ei_assert(Size==1); ei_assert( (outer>=0) && (outer<matrix.outerSize()) ); } + +// template<typename OtherDerived> +// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other) +// { +// return *this; +// } + +// template<typename Sparse> +// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other) +// { +// return *this; +// } - EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? 1 : m_matrix.rows(); } - EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : 1; } + EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } + EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } protected: const typename MatrixType::Nested m_matrix; - int m_outer; + int m_outerStart; + const ei_int_if_dynamic<Size> m_outerSize; }; -template<typename MatrixType> -class SparseInnerVector<MatrixType>::InnerIterator : public MatrixType::InnerIterator +//---------- +// specialisation for DynamicSparseMatrix +//---------- + +template<typename _Scalar, int _Options, int Size> +class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size> + : public SparseMatrixBase<SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size> > { -public: - inline InnerIterator(const SparseInnerVector& xpr, int outer=0) - : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outer) - { - ei_assert(outer==0); - } + typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType; + enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor }; + public: + + EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet) + class InnerIterator: public MatrixType::InnerIterator + { + public: + inline InnerIterator(const SparseInnerVectorSet& xpr, int outer) + : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer) + {} + }; + + inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize) + : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize) + { + ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) ); + } + + inline SparseInnerVectorSet(const MatrixType& matrix, int outer) + : m_matrix(matrix), m_outerStart(outer) + { + ei_assert(Size==1); + ei_assert( (outer>=0) && (outer<matrix.outerSize()) ); + } + + template<typename OtherDerived> + inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other) + { + if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit)) + { + // need to transpose => perform a block evaluation followed by a big swap + DynamicSparseMatrix<Scalar,IsRowMajor?RowMajorBit:0> aux(other); + *this = aux.markAsRValue(); + } + else + { + // evaluate/copy vector per vector + for (int j=0; j<m_outerSize.value(); ++j) + { + SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j)); + m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data()); + } + } + return *this; + } + + inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other) + { + return operator=<SparseInnerVectorSet>(other); + } + +// template<typename Sparse> +// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other) +// { +// return *this; +// } + + EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } + EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } + + protected: + + const typename MatrixType::Nested m_matrix; + int m_outerStart; + const ei_int_if_dynamic<Size> m_outerSize; + }; + +//---------- + /** \returns the i-th row of the matrix \c *this. For row-major matrix only. */ template<typename Derived> -SparseInnerVector<Derived> SparseMatrixBase<Derived>::row(int i) +SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(int i) { EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); return innerVector(i); @@ -89,7 +182,7 @@ SparseInnerVector<Derived> SparseMatrixBase<Derived>::row(int i) /** \returns the i-th row of the matrix \c *this. For row-major matrix only. * (read-only version) */ template<typename Derived> -const SparseInnerVector<Derived> SparseMatrixBase<Derived>::row(int i) const +const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(int i) const { EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); return innerVector(i); @@ -97,18 +190,18 @@ const SparseInnerVector<Derived> SparseMatrixBase<Derived>::row(int i) const /** \returns the i-th column of the matrix \c *this. For column-major matrix only. */ template<typename Derived> -SparseInnerVector<Derived> SparseMatrixBase<Derived>::col(int i) +SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(int i) { - EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); + EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COL_MAJOR_MATRICES); return innerVector(i); } /** \returns the i-th column of the matrix \c *this. For column-major matrix only. * (read-only version) */ template<typename Derived> -const SparseInnerVector<Derived> SparseMatrixBase<Derived>::col(int i) const +const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(int i) const { - EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); + EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COL_MAJOR_MATRICES); return innerVector(i); } @@ -116,15 +209,65 @@ const SparseInnerVector<Derived> SparseMatrixBase<Derived>::col(int i) const * is col-major (resp. row-major). */ template<typename Derived> -SparseInnerVector<Derived> SparseMatrixBase<Derived>::innerVector(int outer) -{ return SparseInnerVector<Derived>(derived(), outer); } +SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(int outer) +{ return SparseInnerVectorSet<Derived,1>(derived(), outer); } + +/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this + * is col-major (resp. row-major). Read-only. + */ +template<typename Derived> +const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(int outer) const +{ return SparseInnerVectorSet<Derived,1>(derived(), outer); } + +//---------- + +/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */ +template<typename Derived> +SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(int start, int size) +{ + EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); + return innerVectors(start, size); +} + +/** \returns the i-th row of the matrix \c *this. For row-major matrix only. + * (read-only version) */ +template<typename Derived> +const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(int start, int size) const +{ + EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); + return innerVectors(start, size); +} + +/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */ +template<typename Derived> +SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(int start, int size) +{ + EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COL_MAJOR_MATRICES); + return innerVectors(start, size); +} + +/** \returns the i-th column of the matrix \c *this. For column-major matrix only. + * (read-only version) */ +template<typename Derived> +const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(int start, int size) const +{ + EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COL_MAJOR_MATRICES); + return innerVectors(start, size); +} + +/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this + * is col-major (resp. row-major). + */ +template<typename Derived> +SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(int outerStart, int outerSize) +{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); } /** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this * is col-major (resp. row-major). Read-only. */ template<typename Derived> -const SparseInnerVector<Derived> SparseMatrixBase<Derived>::innerVector(int outer) const -{ return SparseInnerVector<Derived>(derived(), outer); } +const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(int outerStart, int outerSize) const +{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); } # if 0 template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess> diff --git a/Eigen/src/Sparse/SparseCwiseBinaryOp.h b/Eigen/src/Sparse/SparseCwiseBinaryOp.h index 87fd429be..a061368ab 100644 --- a/Eigen/src/Sparse/SparseCwiseBinaryOp.h +++ b/Eigen/src/Sparse/SparseCwiseBinaryOp.h @@ -86,6 +86,8 @@ class SparseCwiseBinaryOp : ei_no_assignment_operator, EIGEN_STRONG_INLINE SparseCwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp()) : m_lhs(lhs), m_rhs(rhs), m_functor(func) { + EIGEN_STATIC_ASSERT((_LhsNested::Flags&RowMajorBit)==(_RhsNested::Flags&RowMajorBit), + BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER) EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex<BinaryOp>::ret ? int(ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret) : int(ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)), diff --git a/Eigen/src/Sparse/SparseMatrixBase.h b/Eigen/src/Sparse/SparseMatrixBase.h index 46c0c546a..468bc9e22 100644 --- a/Eigen/src/Sparse/SparseMatrixBase.h +++ b/Eigen/src/Sparse/SparseMatrixBase.h @@ -327,18 +327,21 @@ template<typename Derived> class SparseMatrixBase // void transposeInPlace(); const AdjointReturnType adjoint() const { return conjugate()/*.nestByValue()*/; } - SparseInnerVector<Derived> row(int i); - const SparseInnerVector<Derived> row(int i) const; - SparseInnerVector<Derived> col(int j); - const SparseInnerVector<Derived> col(int j) const; - SparseInnerVector<Derived> innerVector(int outer); - const SparseInnerVector<Derived> innerVector(int outer) const; - -// RowXpr row(int i); -// const RowXpr row(int i) const; - -// ColXpr col(int i); -// const ColXpr col(int i) const; + // sub-vector + SparseInnerVectorSet<Derived,1> row(int i); + const SparseInnerVectorSet<Derived,1> row(int i) const; + SparseInnerVectorSet<Derived,1> col(int j); + const SparseInnerVectorSet<Derived,1> col(int j) const; + SparseInnerVectorSet<Derived,1> innerVector(int outer); + const SparseInnerVectorSet<Derived,1> innerVector(int outer) const; + + // set of sub-vectors + SparseInnerVectorSet<Derived,Dynamic> subrows(int start, int size); + const SparseInnerVectorSet<Derived,Dynamic> subrows(int start, int size) const; + SparseInnerVectorSet<Derived,Dynamic> subcols(int start, int size); + const SparseInnerVectorSet<Derived,Dynamic> subcols(int start, int size) const; + SparseInnerVectorSet<Derived,Dynamic> innerVectors(int outerStart, int outerSize); + const SparseInnerVectorSet<Derived,Dynamic> innerVectors(int outerStart, int outerSize) const; // typename BlockReturnType<Derived>::Type block(int startRow, int startCol, int blockRows, int blockCols); // const typename BlockReturnType<Derived>::Type diff --git a/Eigen/src/Sparse/SparseUtil.h b/Eigen/src/Sparse/SparseUtil.h index 18d0ee238..0ab7dda41 100644 --- a/Eigen/src/Sparse/SparseUtil.h +++ b/Eigen/src/Sparse/SparseUtil.h @@ -107,7 +107,7 @@ template<typename _Scalar, int _Flags = 0> class SparseVector; template<typename _Scalar, int _Flags = 0> class MappedSparseMatrix; template<typename MatrixType> class SparseTranspose; -template<typename MatrixType> class SparseInnerVector; +template<typename MatrixType, int Size> class SparseInnerVectorSet; template<typename Derived> class SparseCwise; template<typename UnaryOp, typename MatrixType> class SparseCwiseUnaryOp; template<typename BinaryOp, typename Lhs, typename Rhs> class SparseCwiseBinaryOp; diff --git a/Eigen/src/Sparse/SparseVector.h b/Eigen/src/Sparse/SparseVector.h index 457984cad..a5100150b 100644 --- a/Eigen/src/Sparse/SparseVector.h +++ b/Eigen/src/Sparse/SparseVector.h @@ -59,6 +59,7 @@ class SparseVector EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseVector) EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=) EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=) +// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, =) protected: public: @@ -68,6 +69,9 @@ class SparseVector CompressedStorage<Scalar> m_data; int m_size; + + CompressedStorage<Scalar>& _data() { return m_data; } + CompressedStorage<Scalar>& _data() const { return m_data; } public: @@ -198,6 +202,13 @@ class SparseVector { *this = other.derived(); } + + template<typename OtherDerived> + inline SparseVector(const SparseMatrixBase<OtherDerived>& other) + : m_size(0) + { + *this = other.derived(); + } inline SparseVector(const SparseVector& other) : m_size(0) @@ -225,9 +236,12 @@ class SparseVector return *this; } -// template<typename OtherDerived> -// inline SparseVector& operator=(const MatrixBase<OtherDerived>& other) -// { + template<typename OtherDerived> + inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other) + { + return Base::operator=(other); + } + // const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); // if (needToTranspose) // { diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 439458128..08f19d7e4 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -254,6 +254,24 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re int j1 = ei_random(0,rows-1); VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0)); VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1)); + //m2.innerVector(j0) = 2*m2.innerVector(j1); + //refMat2.col(j0) = 2*refMat2.col(j1); + //VERIFY_IS_APPROX(m2, refMat2); + } + + // test innerVectors() + { + DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); + SparseMatrixType m2(rows, rows); + initSparse<Scalar>(density, refMat2, m2); + int j0 = ei_random(0,rows-2); + int j1 = ei_random(0,rows-2); + int n0 = ei_random<int>(1,rows-std::max(j0,j1)); + VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0)); + VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0), + refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0)); + //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0); + //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0); } // test transpose |