Search code examples
c++eigendata-manipulationeigen3

Get all non-zero values of a dense Eigen::Matrix object


Asuming you have a dynamic size Eigen::Matrix object and want to do some computation on only non-zero values, how can you get a vector or list representation of all non-zero values?

Matrix3f m;
m << 1, 0, 0,
     0, 5, 6,
     0, 0, 9;
VectorXf v = get_non_zero_values(m);
cout << v;

should give you

1 5 6 9

How can this be done with Eigen (most efficiently)?


Solution

  • After a lot of research in the web and inspired by this stackoverflow post I came up with my own solution

    template <typename T>
    Eigen::Matrix<T, Eigen::Dynamic, 1> get_non_zeros(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& _input)
    {
        Eigen::Matrix<T, Eigen::Dynamic, 1> reduced(Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1>>(_input.data(), _input.size()));
        Eigen::Matrix<bool, Eigen::Dynamic, 1> empty = (reduced.array() == 0).rowwise().all();
    
        size_t last = reduced.rows() - 1;
        for ( size_t i = 0; i < last + 1;) {
            if ( empty(i) ) {
                reduced.row(i).swap(reduced.row(last));
                empty.segment<1>(i).swap(empty.segment<1>(last));
                --last;
            }
            else {
                ++i;
            }
        }
    
        reduced.conservativeResize(last + 1, reduced.cols());
    
        return reduced;
    }