// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2023 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_REDUX_H #define IGL_REDUX_H #include #include namespace igl { /// 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. /// /// @param[in] A m by n sparse matrix /// @param[in] dim dimension along which to sum (1 or 2) /// @param[in] 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) /// @param[out] S n-long sparse vector (if dim == 1) or m-long sparse vector /// (if dim == 2) /// /// \see for_each 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