[eigen] [Patch] Bug in Sparse module |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: [eigen] [Patch] Bug in Sparse module
- From: David Luitz <tux008@xxxxxxxxxxxxxx>
- Date: Wed, 29 Dec 2010 00:55:50 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:content-type; bh=V2ml461Pf7qkAIiJykHIY25xrLEdmQgYkBhSzMVphYo=; b=K2+j55ArdIjZItGr48YF8ql5PvEFSW/P5bLuBvQltKoejFU9jxIVLNeQpfOCGMJ6qG sPJAV9oqgraXigp8Zh3QTJGFZ4+Vn7hDsG2jvDs15M/Mbc96hfp9fkLLZ2bAnx5+D7t9 /mn4xgEXzriPK0KNWovDunwojr/9etKBuoCqw=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject :content-type; b=kE8oMzNb8OYB2wEzfVhOAz71iGbSP7nrgW5G1Rd8KyBvsFZHPJXHxZemLzWKZVe5U/ ya3dj8xaofJT+PkpKXKnmZi6bEYarq8DGJDZ/4vVGCMi16yWsKNhlxaWE0jkHzHI038t TzVZS2PqUyXe8Mu79aStOdDcesHKq82bZlWX4=
Hi all,
There is a bug in the Sparse Module, in
Eigen/src/Sparse/SparseDenseProduct.h class SparseTimeDenseProduct.
The problem is, that j runs from 0 to lhs.outerSize(), and coeff(j,0)
may be out of range if lhs is Row major. This results in a segmentation
fault, which is illustrated by the piece of code attached in the file
sparse2.cc. (Change the commented line to compare both cases.)
I have written a patch that solves this problem by changing the order of
the existing code. The new code also eliminates the temporary variables
dest_j and rhs_j in the cases where they are not needed.
The patch should work against mercurial revision 3604:537b5d33b440
Greetings,
David J. Luitz
#include<iostream>
#include <Eigen/Eigen>
int main(){
Eigen::SparseMatrix<double, Eigen::RowMajor> m1(10000, 2);// segfaults
// Eigen::SparseMatrix<double, Eigen::ColMajor> m1(10000, 2);// works
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> m2(2, 2);
m1.setZero();
m2.setZero(2,2);
Eigen::Matrix<double,Eigen::Dynamic, Eigen::Dynamic> res( m1*m2 );
std::cout << res(0,0) << std::endl;
}
diff -r 537b5d33b440 Eigen/src/Sparse/SparseDenseProduct.h
--- a/Eigen/src/Sparse/SparseDenseProduct.h Tue Dec 28 13:46:39 2010 +0100
+++ b/Eigen/src/Sparse/SparseDenseProduct.h Wed Dec 29 00:41:17 2010 +0100
@@ -169,14 +169,30 @@
enum { LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit };
for(Index j=0; j<m_lhs.outerSize(); ++j)
{
- typename Rhs::Scalar rhs_j = alpha * m_rhs.coeff(j,0);
- Block<Dest,1,Dest::ColsAtCompileTime> dest_j(dest.row(LhsIsRowMajor ? j : 0));
- for(LhsInnerIterator it(m_lhs,j); it ;++it)
- {
- if(LhsIsRowMajor) dest_j += (alpha*it.value()) * m_rhs.row(it.index());
- else if(Rhs::ColsAtCompileTime==1) dest.coeffRef(it.index()) += it.value() * rhs_j;
- else dest.row(it.index()) += (alpha*it.value()) * m_rhs.row(j);
- }
+ if(LhsIsRowMajor)
+ {
+ Block<Dest,1,Dest::ColsAtCompileTime> dest_j(dest.row(LhsIsRowMajor ? j : 0));
+ for(LhsInnerIterator it(m_lhs,j); it ;++it)
+ {
+ dest_j += (alpha*it.value()) * m_rhs.row(it.index());
+ }
+ }
+ else if(Rhs::ColsAtCompileTime==1)
+ {
+ typename Rhs::Scalar rhs_j = alpha * m_rhs.coeff(j,0);
+ for(LhsInnerIterator it(m_lhs,j); it ;++it)
+ {
+ dest.coeffRef(it.index()) += it.value() * rhs_j;
+ }
+ }
+ else
+ {
+ for(LhsInnerIterator it(m_lhs,j); it ;++it)
+ {
+ dest.row(it.index()) += (alpha*it.value()) * m_rhs.row(j);
+ }
+ }
+
}
}
@@ -187,8 +203,8 @@
// dense = dense * sparse
namespace internal {
-template<typename Lhs, typename Rhs>
-struct traits<DenseTimeSparseProduct<Lhs,Rhs> >
+ template<typename Lhs, typename Rhs>
+ struct traits<DenseTimeSparseProduct<Lhs,Rhs> >
: traits<ProductBase<DenseTimeSparseProduct<Lhs,Rhs>, Lhs, Rhs> >
{
typedef Dense StorageKind;