#ifndef IGL_REDUX_H #define IGL_REDUX_H #include #include namespace igl { // REDUX Perform reductions on the rows or columns of a SparseMatrix. This is // _similar_ to DenseBase::redux, but different in two important ways: // 1. (unstored) Zeros are **not** "visited", however if the first element // in the column/row does not appear in the first row/column then the // reduction is assumed to start with zero. In this way, "any", "all", // "count"(non-zeros) work as expected. This means it is **not** possible // to use this to count (implicit) zeros. // 2. This redux is more powerful in the sense that A and B may have // different types. This makes it possible to count the number of // non-zeros in a SparseMatrix A into a VectorXi B. // // Inputs: // A m by n sparse matrix // dim dimension along which to sum (1 or 2) // func function handle with the prototype `X(Y a, I i, J j, Z b)` where a // is the running value, b is A(i,j) // Output: // S n-long sparse vector (if dim == 1) // or // S m-long sparse vector (if dim == 2) template inline void redux( const Eigen::SparseMatrix & A, const int dim, const Func & func, Eigen::PlainObjectBase & B); } // Implementation #include "for_each.h" template inline void igl::redux( const Eigen::SparseMatrix & A, const int dim, const Func & func, Eigen::PlainObjectBase & B) { typedef typename Eigen::SparseMatrix::StorageIndex Index; assert((dim == 1 || dim == 2) && "dim must be 2 or 1"); // Get size of input int m = A.rows(); int n = A.cols(); // resize output B = DerivedB::Zero(dim==1?n:m); const auto func_wrap = [&func,&B,&dim](const Index i, const Index j, const AType v) { if(dim == 1) { B(j) = i == 0? v : func(B(j),v); }else { B(i) = j == 0? v : func(B(i),v); } }; for_each(A,func_wrap); } //#ifndef IGL_STATIC_LIBRARY //# include "redux.cpp" //#endif #endif