Discussion:
[eigen] SparseMatrix StorageIndex issue
Gerard Bahi
2017-12-21 14:08:49 UTC
Permalink
Hi,
I am using Eigen 3.3.4, on clang 4.0
I was changing the StorageIndex type and I noticed something that might be
a problem with my Eigen configuration or a bug.

Given the following code:

#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#include <Eigen/Eigen>

using StorageIndexType = long;
Eigen::SparseMatrix<double, Eigen::ColMajor, StorageIndexType> A(10,10);

When adding for(int i=0; i<10; ++i) A.insert(i,i) = 1; or A.setIdentity(); I
get a bad_alloc exception.
However running:
A.resize(10, 10);
for(int i=0; i<10; ++i) A.insert(i,i) = 1;

Does not cause the throw. It will throw if using *setIdentity* instead of
insert even with the resize though.
I have also noticed that printing the matrix like this:
std::cerr << "A =\n" << A << std::endl;
Causes the bad_alloc throw as well on (SparseMatrix.h:829) // s <<
static_cast<const SparseMatrixBase<SparseMatrix>&>(m)

The streaming with Eigen debug ON print shows the following (before
crashing):
Nonzero entries:
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8) (1,9) (_,_) (_,_)
(_,_) (_,_) (_,_) (_,_) (_,_) (_,_) (_,_) (_,_)

Outer pointers:
0 1 2 3 4 5 6 7 8 9 $
Inner non zeros:
1 1 1 1 1 1 1 1 1 1 $

I have tried making all combinations of int and long of
EIGEN_DEFAULT_DENSE_INDEX_TYPE
and StorageIndexType, only this combination crashes.

Trying to use the matrix with SPQR also crashes (which was my initial
intention):
Eigen::SPQR<Eigen::SparseMatrix<double, Eigen::ColMajor, StorageIndexType>
solver;
solver.compute(A);

Kind regards,
Gerard
Gael Guennebaud
2017-12-31 14:20:46 UTC
Permalink
Hi,
Post by Gerard Bahi
Hi,
I am using Eigen 3.3.4, on clang 4.0
I was changing the StorageIndex type and I noticed something that might be
a problem with my Eigen configuration or a bug.
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#include <Eigen/Eigen>
using StorageIndexType = long;
Eigen::SparseMatrix<double, Eigen::ColMajor, StorageIndexType> A(10,10);
We've never tested such a configuration because it makes no sense. We
should probably prohibit it as it is doom to fail. In your case the problem
lies in this line:

Index realloc_size = (std::min<Index>)(NumTraits<StorageIndex>::highest(),
size + Index(reserveSizeFactor*double(size)));

where NumTraits<long>::highest() is wrongly converted to int as -1. Of
course this line is easy to fix, there will be many other not-fixable
issues. So better statically assert IMO.

gael
Post by Gerard Bahi
When adding for(int i=0; i<10; ++i) A.insert(i,i) = 1; or
A.setIdentity(); I get a bad_alloc exception.
A.resize(10, 10);
for(int i=0; i<10; ++i) A.insert(i,i) = 1;
Does not cause the throw. It will throw if using *setIdentity* instead of
insert even with the resize though.
std::cerr << "A =\n" << A << std::endl;
Causes the bad_alloc throw as well on (SparseMatrix.h:829) // s <<
static_cast<const SparseMatrixBase<SparseMatrix>&>(m)
The streaming with Eigen debug ON print shows the following (before
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8) (1,9) (_,_) (_,_)
(_,_) (_,_) (_,_) (_,_) (_,_) (_,_) (_,_) (_,_)
0 1 2 3 4 5 6 7 8 9 $
1 1 1 1 1 1 1 1 1 1 $
I have tried making all combinations of int and long of EIGEN_DEFAULT_DENSE_INDEX_TYPE
and StorageIndexType, only this combination crashes.
Trying to use the matrix with SPQR also crashes (which was my initial
Eigen::SPQR<Eigen::SparseMatrix<double, Eigen::ColMajor,
StorageIndexType> > solver;
solver.compute(A);
Kind regards,
Gerard
Gerard Bahi
2017-12-31 17:49:16 UTC
Permalink
Hi Gael,
Thanks for your answer.
I think an assert is a good idea. Otherwise one gets crashes when using
SPQR as it forces long for storage index type.

Kind Regards,
Gerard
Post by Gael Guennebaud
Hi,
Post by Gerard Bahi
Hi,
I am using Eigen 3.3.4, on clang 4.0
I was changing the StorageIndex type and I noticed something that might
be a problem with my Eigen configuration or a bug.
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#include <Eigen/Eigen>
using StorageIndexType = long;
Eigen::SparseMatrix<double, Eigen::ColMajor, StorageIndexType> A(10,10);
We've never tested such a configuration because it makes no sense. We
should probably prohibit it as it is doom to fail. In your case the problem
Index realloc_size = (std::min<Index>)(NumTraits<StorageIndex>::highest(),
size + Index(reserveSizeFactor*double(size)));
where NumTraits<long>::highest() is wrongly converted to int as -1. Of
course this line is easy to fix, there will be many other not-fixable
issues. So better statically assert IMO.
gael
Post by Gerard Bahi
When adding for(int i=0; i<10; ++i) A.insert(i,i) = 1; or
A.setIdentity(); I get a bad_alloc exception.
A.resize(10, 10);
for(int i=0; i<10; ++i) A.insert(i,i) = 1;
Does not cause the throw. It will throw if using *setIdentity* instead
of insert even with the resize though.
std::cerr << "A =\n" << A << std::endl;
Causes the bad_alloc throw as well on (SparseMatrix.h:829) // s <<
static_cast<const SparseMatrixBase<SparseMatrix>&>(m)
The streaming with Eigen debug ON print shows the following (before
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8) (1,9) (_,_) (_,_)
(_,_) (_,_) (_,_) (_,_) (_,_) (_,_) (_,_) (_,_)
0 1 2 3 4 5 6 7 8 9 $
1 1 1 1 1 1 1 1 1 1 $
I have tried making all combinations of int and long of EIGEN_DEFAULT_DENSE_INDEX_TYPE
and StorageIndexType, only this combination crashes.
Trying to use the matrix with SPQR also crashes (which was my initial
Eigen::SPQR<Eigen::SparseMatrix<double, Eigen::ColMajor,
StorageIndexType> > solver;
solver.compute(A);
Kind regards,
Gerard
Loading...