diff options
author | Gael Guennebaud <g.gael@free.fr> | 2016-12-14 17:05:26 +0100 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2016-12-14 17:05:26 +0100 |
commit | e67397bfa7cc1662774c4586f7532bbe3e69e0fd (patch) | |
tree | 18700af83e6f63ee0838c750c9cdeed343ed6da1 | |
parent | 98d74582751f65af99f94e9234b0817fa79f7fb9 (diff) |
bug #1359: fix compilation of col_major_sparse.row() *= scalar
(used to work in 3.2.9 though the expression is not really writable)
-rw-r--r-- | Eigen/src/SparseCore/SparseBlock.h | 29 | ||||
-rw-r--r-- | test/sparse_block.cpp | 53 |
2 files changed, 59 insertions, 23 deletions
diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h index c3ea7e0e2..511e92b2f 100644 --- a/Eigen/src/SparseCore/SparseBlock.h +++ b/Eigen/src/SparseCore/SparseBlock.h @@ -531,22 +531,24 @@ class unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBas enum { IsRowMajor = unary_evaluator::IsRowMajor }; const unary_evaluator& m_eval; Index m_outerPos; - Index m_innerIndex; - Scalar m_value; + const Index m_innerIndex; Index m_end; + EvalIterator m_it; public: EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer) : m_eval(aEval), - m_outerPos( (IsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry + m_outerPos( (IsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) ), m_innerIndex(IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()), - m_value(0), - m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) + m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()), + m_it(m_eval.m_argImpl, m_outerPos) { EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); - ++(*this); + while(m_it && m_it.index() < m_innerIndex) ++m_it; + if((!m_it) || (m_it.index()!=m_innerIndex)) + ++(*this); } inline StorageIndex index() const { return convert_index<StorageIndex>(m_outerPos - (IsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow())); } @@ -554,21 +556,20 @@ public: inline Index row() const { return IsRowMajor ? 0 : index(); } inline Index col() const { return IsRowMajor ? index() : 0; } - inline Scalar value() const { return m_value; } + inline Scalar value() const { return m_it.value(); } + inline Scalar& valueRef() { return m_it.valueRef(); } inline OuterVectorInnerIterator& operator++() { // search next non-zero entry while(++m_outerPos<m_end) { - EvalIterator it(m_eval.m_argImpl, m_outerPos); + // Restart iterator at the next inner-vector: + m_it.~EvalIterator(); + ::new (&m_it) EvalIterator(m_eval.m_argImpl, m_outerPos); // search for the key m_innerIndex in the current outer-vector - while(it && it.index() < m_innerIndex) ++it; - if(it && it.index()==m_innerIndex) - { - m_value = it.value(); - break; - } + while(m_it && m_it.index() < m_innerIndex) ++m_it; + if(m_it && m_it.index()==m_innerIndex) break; } return *this; } diff --git a/test/sparse_block.cpp b/test/sparse_block.cpp index cb5213ade..2a0b3b617 100644 --- a/test/sparse_block.cpp +++ b/test/sparse_block.cpp @@ -9,6 +9,20 @@ #include "sparse.h" +template<typename T> +typename Eigen::internal::enable_if<(T::Flags&RowMajorBit)==RowMajorBit, typename T::RowXpr>::type +innervec(T& A, Index i) +{ + return A.row(i); +} + +template<typename T> +typename Eigen::internal::enable_if<(T::Flags&RowMajorBit)==0, typename T::ColXpr>::type +innervec(T& A, Index i) +{ + return A.col(i); +} + template<typename SparseMatrixType> void sparse_block(const SparseMatrixType& ref) { const Index rows = ref.rows(); @@ -20,9 +34,10 @@ template<typename SparseMatrixType> void sparse_block(const SparseMatrixType& re typedef typename SparseMatrixType::StorageIndex StorageIndex; double density = (std::max)(8./(rows*cols), 0.01); - typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; + typedef Matrix<Scalar,Dynamic,Dynamic,SparseMatrixType::IsRowMajor?RowMajor:ColMajor> DenseMatrix; typedef Matrix<Scalar,Dynamic,1> DenseVector; typedef Matrix<Scalar,1,Dynamic> RowDenseVector; + typedef SparseVector<Scalar> SparseVectorType; Scalar s1 = internal::random<Scalar>(); { @@ -110,15 +125,35 @@ template<typename SparseMatrixType> void sparse_block(const SparseMatrixType& re initSparse<Scalar>(density, refMat2, m2); Index j0 = internal::random<Index>(0,outer-1); Index j1 = internal::random<Index>(0,outer-1); - if(SparseMatrixType::IsRowMajor) - VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.row(j0)); - else - VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0)); + Index r0 = internal::random<Index>(0,rows-1); + Index c0 = internal::random<Index>(0,cols-1); - if(SparseMatrixType::IsRowMajor) - VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.row(j0)+refMat2.row(j1)); - else - VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1)); + VERIFY_IS_APPROX(m2.innerVector(j0), innervec(refMat2,j0)); + VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), innervec(refMat2,j0)+innervec(refMat2,j1)); + + m2.innerVector(j0) *= Scalar(2); + innervec(refMat2,j0) *= Scalar(2); + VERIFY_IS_APPROX(m2, refMat2); + + m2.row(r0) *= Scalar(3); + refMat2.row(r0) *= Scalar(3); + VERIFY_IS_APPROX(m2, refMat2); + + m2.col(c0) *= Scalar(4); + refMat2.col(c0) *= Scalar(4); + VERIFY_IS_APPROX(m2, refMat2); + + m2.row(r0) /= Scalar(3); + refMat2.row(r0) /= Scalar(3); + VERIFY_IS_APPROX(m2, refMat2); + + m2.col(c0) /= Scalar(4); + refMat2.col(c0) /= Scalar(4); + VERIFY_IS_APPROX(m2, refMat2); + + SparseVectorType v1; + VERIFY_IS_APPROX(v1 = m2.col(c0) * 4, refMat2.col(c0)*4); + VERIFY_IS_APPROX(v1 = m2.row(r0) * 4, refMat2.row(r0).transpose()*4); SparseMatrixType m3(rows,cols); m3.reserve(VectorXi::Constant(outer,int(inner/2))); |