Enrico Borba
Enrico Borba

Reputation: 2137

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?

Upvotes: 2

Views: 798

Answers (2)

JackieLam
JackieLam

Reputation: 668

As a supplement to @m7913d's second answer: coeffs() is a very useful function in processing coefficient-wise math functions. Eigen documents only provided dense matrix based math calculation -> https://eigen.tuxfamily.org/dox/group__CoeffwiseMathFunctions.html

For example, you can do sth like:

A.coeffs() = A.coeffs.exp();

Upvotes: 0

m7913d
m7913d

Reputation: 11072

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.

Upvotes: 6

Related Questions