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