Skip to content

Inner Iterator Incorrect for Block of Sparse Matrix

Summary

Iterating the non-zeros of a column of a sparse matrix gives the wrong results. The number of non-zeros is detected properly, but the corresponding indices are wrong.

Environment 1

  • Operating System : Ubuntu 20.04.4 LTS
  • Architecture : x64
  • Eigen Version : 3.4.90
  • Compiler Version : Gcc9.4.0
  • Compile Flags : -g
  • Vector Extension : SSE, AVX (Intel Tiger Lake)

Environment 2

  • Operating System : macOS 11.6.2
  • Architecture : x64
  • Eigen Version : 3.4.0
  • Compiler Version : clang13.0.0
  • Compile Flags : -g
  • Vector Extension : SSE, AVX (Intel Coffee Lake U)

Minimal Example

https://godbolt.org/z/98G8G7PPb

#include <iostream>
#include <Eigen/SparseCore>

int main() {
    using Scalar = int;
    using Matrix = Eigen::SparseMatrix<Scalar>;
    using Index = Matrix::Index;
    using std::cout, std::endl;

    // Assemble sparse matrix:
    Matrix A(4, 4);
    Scalar v = 1;
    std::vector<Eigen::Triplet<Scalar>> entries {
            {0, 1, v},
            {1, 3, v},
            {3, 3, v},
    };
    A.setFromTriplets(entries.begin(), entries.end());
    cout << A << endl;

    // Print last column
    Index c = 3;
    auto adj = A.col(c);
    cout << "Column:" << endl;
    cout << adj << endl;

    cout << "Broken Indices:" << endl;
    for (decltype(adj)::InnerIterator it(adj); it; ++it) {
        cout << it.index() << endl;
    }
    cout << endl;
    // `it.m_indices` points to first column of A, it is hence off by -1 in this case.

    cout << "Expected Indices:" << endl;
    for (decltype(A)::InnerIterator it(A, c); it; ++it) {
      cout << it.index() << endl;
    }
}

Steps to reproduce

  1. Compile
  2. Run

What is the current bug behavior?

Broken Indices:
0
1

What is the expected correct behavior?

Expected Indices:
1
3

Anything else that might help

It seems as if the it.m_indices field has the same value as the parent Block, which is the start of the first column of the matrix in this case. IIUC, it should instead point to the first element of the select column (column c=3 in the example above). I don't know what to do if the sparse matrix is stored row-major. Either way, I would expect it.index() to return 1 and 3.