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

Time:10-06

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)?

CodePudding user response:

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;
}

CodePudding user response:

Using a temporary std::vector makes it possible to apply the push_back method for storing the non-zero values. The content of the std::vector can then be Mapped to an Eigen::Vector.

VectorXf get_non_zero_values(const MatrixXf& m) {
  std::vector<float> nzv;
  for (int i = 0; i < m.size();   i) {
    if (m(i)) nzv.push_back(m(i));    
  }
Map<VectorXf> nzm(nzv.data(), nzv.size());
return nzm; 
}
  • Related