From feaf76c00103df5f0ae2d7a365a91f70253922cd Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 9 Jun 2015 23:11:24 +0200 Subject: [PATCH] bug #910: add a StandardCompressedFormat option to Ref to enforce standard compressed storage format. If the input is not compressed, then this trigger a copy for a const Ref, and a runtime assert for non-const Ref. --- Eigen/src/SparseCore/SparseMatrix.h | 3 +++ Eigen/src/SparseCore/SparseRef.h | 30 ++++++++++++++++++++++++++++- test/sparse_ref.cpp | 18 +++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index d10880cb5..d9964d0f6 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -725,6 +725,9 @@ class SparseMatrix } else if(this!=&other) { + #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN + EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN + #endif initAssignment(other); if(other.isCompressed()) { diff --git a/Eigen/src/SparseCore/SparseRef.h b/Eigen/src/SparseCore/SparseRef.h index 2ca039323..8df62a119 100644 --- a/Eigen/src/SparseCore/SparseRef.h +++ b/Eigen/src/SparseCore/SparseRef.h @@ -12,6 +12,10 @@ namespace Eigen { +enum { + StandardCompressedFormat = 2 +}; + namespace internal { template class SparseRefBase; @@ -72,6 +76,19 @@ protected: } // namespace internal + +/** + * \ingroup Sparse_Module + * + * \brief A sparse matrix expression referencing an existing sparse expression + * + * \tparam PlainObjectType the equivalent sparse matrix type of the referenced data + * \tparam Options specifies whether the a standard compressed format is required \c Options is \c #StandardCompressedFormat, or \c 0. + * The default is \c 0. + * \tparam StrideType Only used for dense Ref + * + * \sa class Ref + */ template class Ref, Options, StrideType > : public internal::SparseRefBase, Options, StrideType > > @@ -93,6 +110,7 @@ class Ref, Options, StrideType > inline Ref(SparseMatrix& expr) { EIGEN_STATIC_ASSERT(bool(Traits::template match >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); + eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); Base::construct(expr.derived()); } @@ -100,6 +118,7 @@ class Ref, Options, StrideType > inline Ref(MappedSparseMatrix& expr) { EIGEN_STATIC_ASSERT(bool(Traits::template match >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); + eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); Base::construct(expr.derived()); } @@ -112,6 +131,7 @@ class Ref, Options, StrideType > { EIGEN_STATIC_ASSERT(bool(internal::is_lvalue::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); EIGEN_STATIC_ASSERT(bool(Traits::template match::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); + eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); Base::construct(expr.const_cast_derived()); } }; @@ -148,7 +168,15 @@ class Ref, Options, StrideType template void construct(const Expression& expr,internal::true_type) { - Base::construct(expr); + if((Options & int(StandardCompressedFormat)) && (!expr.isCompressed())) + { + m_object = expr; + Base::construct(m_object); + } + else + { + Base::construct(expr); + } } template diff --git a/test/sparse_ref.cpp b/test/sparse_ref.cpp index e7380ba21..d173ee658 100644 --- a/test/sparse_ref.cpp +++ b/test/sparse_ref.cpp @@ -47,12 +47,20 @@ EIGEN_DONT_INLINE void call_ref_1(Ref > a, const B &b) { VER template EIGEN_DONT_INLINE void call_ref_2(const Ref >& a, const B &b) { VERIFY_IS_EQUAL(a.toDense(),b.toDense()); } +template +EIGEN_DONT_INLINE void call_ref_3(const Ref, StandardCompressedFormat>& a, const B &b) { + VERIFY(a.isCompressed()); + VERIFY_IS_EQUAL(a.toDense(),b.toDense()); +} + void call_ref() { // SparseVector > ca = VectorXcf::Random(10).sparseView(); // SparseVector a = VectorXf::Random(10).sparseView(); SparseMatrix A = MatrixXf::Random(10,10).sparseView(0.5,1); SparseMatrix B = MatrixXf::Random(10,10).sparseView(0.5,1); + SparseMatrix C = MatrixXf::Random(10,10).sparseView(0.5,1); + C.reserve(VectorXi::Constant(C.outerSize(), 2)); const SparseMatrix& Ac(A); Block > Ab(A,0,1, 3,3); const Block > Abc(A,0,1,3,3); @@ -61,12 +69,22 @@ void call_ref() VERIFY_EVALUATION_COUNT( call_ref_1(A, A), 0); // VERIFY_EVALUATION_COUNT( call_ref_1(Ac, Ac), 0); // does not compile on purpose VERIFY_EVALUATION_COUNT( call_ref_2(A, A), 0); + VERIFY_EVALUATION_COUNT( call_ref_3(A, A), 0); VERIFY_EVALUATION_COUNT( call_ref_2(A.transpose(), A.transpose()), 1); + VERIFY_EVALUATION_COUNT( call_ref_3(A.transpose(), A.transpose()), 1); VERIFY_EVALUATION_COUNT( call_ref_2(Ac,Ac), 0); + VERIFY_EVALUATION_COUNT( call_ref_3(Ac,Ac), 0); VERIFY_EVALUATION_COUNT( call_ref_2(A+A,2*Ac), 1); + VERIFY_EVALUATION_COUNT( call_ref_3(A+A,2*Ac), 1); VERIFY_EVALUATION_COUNT( call_ref_2(B, B), 1); + VERIFY_EVALUATION_COUNT( call_ref_3(B, B), 1); VERIFY_EVALUATION_COUNT( call_ref_2(B.transpose(), B.transpose()), 0); + VERIFY_EVALUATION_COUNT( call_ref_3(B.transpose(), B.transpose()), 0); VERIFY_EVALUATION_COUNT( call_ref_2(A*A, A*A), 1); + VERIFY_EVALUATION_COUNT( call_ref_3(A*A, A*A), 1); + + VERIFY(!C.isCompressed()); + VERIFY_EVALUATION_COUNT( call_ref_3(C, C), 1); Ref > Ar(A); VERIFY_IS_APPROX(Ar+Ar, A+A);