The call to nonZeros() on a SparseSparseProduct object leads to an infinite recursion smacking the stack. This can be seen by running valgrind with the verbose "-v" parameter on the following example:
using namespace Eigen;
typedef SparseMatrix<double, ColMajor> SpMat;
int main(int argc, char **argv)
const int m = 3;
A.insert(0,0) = 1.0;
A.insert(1,1) = 2.0;
A.insert(2,2) = 3.0;
B.insert(0,0) = 1.0;
B.insert(1,1) = 2.0;
B.insert(2,2) = 3.0;
int nnz = (A * B).nonZeros();
std::cout << nnz << std::endl;
Another thing that is broken is TriangularView<SparseMatrix>.
This leads to an infinite recursion in many sparse_product unit tests.
Strangely, clang++ optimizes away the recursion if compiled with optimization enabled and returns -1 (maybe that value is just by accident). With optimization, g++ generates a trivial infinite loop, leading to a time-out in the unit-tests.
Are there any cases except SparseMatrix<>, (and maybe Map<SparseMatrix>, Transpose<SparseMatrix>) where nonZeros() can be determined directly? I.e. does it make sense to provide a nonZeros() from SparseMatrixBase?
I pushed a work-around to avoid the infinite recursion:
This make the sparse_product unit tests pass again.
We still need to decide if it makes sense to provide nonZeros() for other than "direct access" sparse matrices.
Having an estimate of the nnz is really useful in sparse algorithms, even if it is not 100% accurate. Having nonZeros() be sometimes accurate and sometimes only an approximation is probably not very good. So, since this is essentially needed for evaluation purposes, this information could be carried out by evaluators. Evaluators should also be able to return a more accurate information when some sub-expressions are evaluated into temporaries.
Would it be too late to remove nonZeros() from SparseMatrixBase and only implement it for SparseMatrix (and Map<SparseMatrix>) directly (or maybe a common base class of them)?
I guess for all (?) other cases the only way to get the exact number of nonZeros basically requires to evaluate the expression.
nonZeros() has been in SparseMatrixBase at least since 2010, however it likely never worked correctly, other than for the "direct access" matrices.
Alternatively, we could deprecate it and/or let it static_assert if it is not implemented.
Regarding the approximated nnz, I guess we don't need to expose an estimateNonZeros() to the public interface, so implementing this as internal evaluator functionality sounds good to me.
Removing the broken nonZeros() method from SparseMatrixBase is the only reasonable option.
Summary: Bug 875: remove broken SparseMatrixBase::nonZeros and introduce a nonZerosEstimate() method to sparse evaluators for internal uses.
Factorize some code in SparseCompressedBase.