From e75b1eb883bd65f8f34b1ca2ca13cd28744ab13a Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 25 Jul 2012 09:33:50 +0200 Subject: [PATCH] Fix aliasing issue in sparse matrix assignment. (m=-m; or m=m.transpose(); with m sparse work again) --- Eigen/src/SparseCore/SparseMatrix.h | 26 +++++++++++++++----------- test/sparse_basic.cpp | 6 ++++++ test/sparse_vector.cpp | 5 +++++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index faed115ea..0a53ecbea 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -688,7 +688,6 @@ class SparseMatrix template EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase& other) { - initAssignment(other.derived()); const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); if (needToTranspose) { @@ -700,40 +699,45 @@ class SparseMatrix typedef typename internal::remove_all::type _OtherCopy; OtherCopy otherCopy(other.derived()); - Eigen::Map > (m_outerIndex,outerSize()).setZero(); + SparseMatrix dest(other.rows(),other.cols()); + Eigen::Map > (dest.m_outerIndex,dest.outerSize()).setZero(); + // pass 1 // FIXME the above copy could be merged with that pass for (Index j=0; jswap(dest); return *this; } else { + if(other.isRValue()) + initAssignment(other.derived()); // there is no special optimization return Base::operator=(other.derived()); } diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 767451450..4566de9f2 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -193,6 +193,12 @@ template void sparse_basic(const SparseMatrixType& re // sparse cwise* dense VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4)); // VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4); + + // test aliasing + VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1)); + VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval())); + VERIFY_IS_APPROX((m1 = -m1.transpose()), (refM1 = -refM1.transpose().eval())); + VERIFY_IS_APPROX((m1 += -m1), (refM1 += -refM1)); } // test transpose diff --git a/test/sparse_vector.cpp b/test/sparse_vector.cpp index 7201afe5b..9d559f5bf 100644 --- a/test/sparse_vector.cpp +++ b/test/sparse_vector.cpp @@ -78,6 +78,11 @@ template void sparse_vector(int rows, int cols) VERIFY_IS_APPROX(v1.squaredNorm(), refV1.squaredNorm()); + // test aliasing + VERIFY_IS_APPROX((v1 = -v1), (refV1 = -refV1)); + VERIFY_IS_APPROX((v1 = v1.transpose()), (refV1 = refV1.transpose().eval())); + VERIFY_IS_APPROX((v1 += -v1), (refV1 += -refV1)); + } void test_sparse_vector()