slice_sorted.cpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 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. #include "slice_sorted.h"
  9. #include <vector>
  10. // TODO: Write a version that works for row-major sparse matrices as well.
  11. template <typename TX, typename TY, typename DerivedR, typename DerivedC>
  12. IGL_INLINE void igl::slice_sorted(const Eigen::SparseMatrix<TX> &X,
  13. const Eigen::DenseBase<DerivedR> &R,
  14. const Eigen::DenseBase<DerivedC> &C,
  15. Eigen::SparseMatrix<TY> &Y)
  16. {
  17. int xm = X.rows();
  18. int xn = X.cols();
  19. int ym = R.size();
  20. int yn = C.size();
  21. // Special case when R or C is empty
  22. if (ym == 0 || yn == 0)
  23. {
  24. Y.resize(ym, yn);
  25. return;
  26. }
  27. assert(R.minCoeff() >= 0);
  28. assert(R.maxCoeff() < xm);
  29. assert(C.minCoeff() >= 0);
  30. assert(C.maxCoeff() < xn);
  31. // Multiplicity count for each row/col
  32. using RowIndexType = typename DerivedR::Scalar;
  33. using ColIndexType = typename DerivedC::Scalar;
  34. std::vector<RowIndexType> slicedRowStart(xm);
  35. std::vector<RowIndexType> rowRepeat(xm, 0);
  36. for (int i = 0; i < ym; ++i)
  37. {
  38. if (rowRepeat[R(i)] == 0)
  39. {
  40. slicedRowStart[R(i)] = i;
  41. }
  42. rowRepeat[R(i)]++;
  43. }
  44. std::vector<ColIndexType> columnRepeat(xn, 0);
  45. for (int i = 0; i < yn; i++)
  46. {
  47. columnRepeat[C(i)]++;
  48. }
  49. // Count number of nnz per outer row/col
  50. Eigen::VectorXi nnz(yn);
  51. for (int k = 0, c = 0; k < X.outerSize(); ++k)
  52. {
  53. int cnt = 0;
  54. for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
  55. {
  56. cnt += rowRepeat[it.row()];
  57. }
  58. for (int i = 0; i < columnRepeat[k]; ++i, ++c)
  59. {
  60. nnz(c) = cnt;
  61. }
  62. }
  63. Y.resize(ym, yn);
  64. Y.reserve(nnz);
  65. // Insert values
  66. for (int k = 0, c = 0; k < X.outerSize(); ++k)
  67. {
  68. for (int i = 0; i < columnRepeat[k]; ++i, ++c)
  69. {
  70. for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
  71. {
  72. for (int j = 0, r = slicedRowStart[it.row()]; j < rowRepeat[it.row()]; ++j, ++r)
  73. {
  74. Y.insert(r, c) = it.value();
  75. }
  76. }
  77. }
  78. }
  79. }
  80. #ifdef IGL_STATIC_LIBRARY
  81. template void igl::slice_sorted<double, double, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int>&);
  82. #endif