redux.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2023 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #ifndef IGL_REDUX_H
  9. #define IGL_REDUX_H
  10. #include <Eigen/Core>
  11. #include <Eigen/Sparse>
  12. namespace igl
  13. {
  14. /// Perform reductions on the rows or columns of a SparseMatrix. This is
  15. /// _similar_ to DenseBase::redux, but different in two important ways:
  16. /// 1. (unstored) Zeros are **not** "visited", however if the first element
  17. /// in the column/row does not appear in the first row/column then the
  18. /// reduction is assumed to start with zero. In this way, "any", "all",
  19. /// "count"(non-zeros) work as expected. This means it is **not** possible
  20. /// to use this to count (implicit) zeros.
  21. /// 2. This redux is more powerful in the sense that A and B may have
  22. /// different types. This makes it possible to count the number of
  23. /// non-zeros in a SparseMatrix<bool> A into a VectorXi B.
  24. ///
  25. /// @param[in] A m by n sparse matrix
  26. /// @param[in] dim dimension along which to sum (1 or 2)
  27. /// @param[in] func function handle with the prototype `X(Y a, I i, J j, Z b)` where a
  28. /// is the running value, b is A(i,j)
  29. /// @param[out] S n-long sparse vector (if dim == 1) or m-long sparse vector
  30. /// (if dim == 2)
  31. ///
  32. /// \see for_each
  33. template <typename AType, typename Func, typename DerivedB>
  34. inline void redux(
  35. const Eigen::SparseMatrix<AType> & A,
  36. const int dim,
  37. const Func & func,
  38. Eigen::PlainObjectBase<DerivedB> & B);
  39. }
  40. // Implementation
  41. #include "for_each.h"
  42. template <typename AType, typename Func, typename DerivedB>
  43. inline void igl::redux(
  44. const Eigen::SparseMatrix<AType> & A,
  45. const int dim,
  46. const Func & func,
  47. Eigen::PlainObjectBase<DerivedB> & B)
  48. {
  49. typedef typename Eigen::SparseMatrix<AType>::StorageIndex Index;
  50. assert((dim == 1 || dim == 2) && "dim must be 2 or 1");
  51. // Get size of input
  52. int m = A.rows();
  53. int n = A.cols();
  54. // resize output
  55. B = DerivedB::Zero(dim==1?n:m);
  56. const auto func_wrap = [&func,&B,&dim](const Index i, const Index j, const AType v)
  57. {
  58. if(dim == 1)
  59. {
  60. B(j) = i == 0? v : func(B(j),v);
  61. }else
  62. {
  63. B(i) = j == 0? v : func(B(i),v);
  64. }
  65. };
  66. for_each(A,func_wrap);
  67. }
  68. //#ifndef IGL_STATIC_LIBRARY
  69. //# include "redux.cpp"
  70. //#endif
  71. #endif