Search code examples
c++sparse-matrixeigen

Add scalar to every non-zero entry of an Eigen::SparseMatrix


I have a huge Eigen::SparseMatrix, and I would like to add a scalar to the nonzero entries in the matrix.

That is, if I had a matrix A with the values _ signifies a 0 entry in the sparse matrix, i.e. it was never inserted.

    1 _ 2
A = _ 3 _
    4 5 6

I would like to do something like A += 1 and arrive at

    2 _ 3
A = _ 4 _
    5 6 7

Where the zero entries are unaffected.

Is there any efficient way to do this?


Solution

  • I am aware of three different approaches:

    1. Loop over all the non-zero values using an InnerIterator

      for (int k=0; k<A.outerSize(); ++k)
        for (SparseMatrix<double>::InnerIterator it(A,k); it; ++it)
          it.valueRef() += 1;
      

      This is a general method, which works in all cases, but may be slower than the other methods.

    2. Using the coeffs operator to obtain a 1D vector containing all the non-zero elements

      A.makeCompressed();
      A.coeffs() += 1;
      

      This method may be faster if the matrix was already in compressed form or you need the compressed format.

    3. Accessing the raw data using valuePtr

      typedef Map<const Array<double,Dynamic,1> > CoeffMap;
      CoeffMap coeffs(A.valuePtr(), A.outerIndexPtr()[A.outerSize()]);
      coeffs += 1;
      

      This method is probably the fastest method, but also the trickiest one and may be even slower on some machines due to performing a floating base operation on uninitialised data (see comment of chtz). If A is in compressed format, this approach is equivalent to method 2.

    Note that I have not benchmarked the different approaches. The performance information is purely based on intuition. If you want to do it, be sure to use real sized matrices.