slice.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "slice.h"
  2. #include <vector>
  3. // Bug in unsupported/Eigen/SparseExtra needs iostream first
  4. #include <iostream>
  5. #include <unsupported/Eigen/SparseExtra>
  6. template <typename T>
  7. IGL_INLINE void igl::slice(
  8. const Eigen::SparseMatrix<T>& X,
  9. const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
  10. const Eigen::Matrix<int,Eigen::Dynamic,1> & C,
  11. Eigen::SparseMatrix<T>& Y)
  12. {
  13. int xm = X.rows();
  14. int xn = X.cols();
  15. int ym = R.size();
  16. int yn = C.size();
  17. // special case when R or C is empty
  18. if(ym == 0 || yn == 0)
  19. {
  20. Y.resize(ym,yn);
  21. return;
  22. }
  23. assert(R.minCoeff() >= 0);
  24. assert(R.maxCoeff() < xm);
  25. assert(C.minCoeff() >= 0);
  26. assert(C.maxCoeff() < xn);
  27. // Build reindexing maps for columns and rows, -1 means not in map
  28. std::vector<std::vector<int> > RI;
  29. RI.resize(xm);
  30. for(int i = 0;i<ym;i++)
  31. {
  32. RI[R(i)].push_back(i);
  33. }
  34. std::vector<std::vector<int> > CI;
  35. CI.resize(xn);
  36. // initialize to -1
  37. for(int i = 0;i<yn;i++)
  38. {
  39. CI[C(i)].push_back(i);
  40. }
  41. // Resize output
  42. Eigen::DynamicSparseMatrix<T, Eigen::RowMajor> dyn_Y(ym,yn);
  43. // Take a guess at the number of nonzeros (this assumes uniform distribution
  44. // not banded or heavily diagonal)
  45. dyn_Y.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn));
  46. // Iterate over outside
  47. for(int k=0; k<X.outerSize(); ++k)
  48. {
  49. // Iterate over inside
  50. for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
  51. {
  52. std::vector<int>::iterator rit, cit;
  53. for(rit = RI[it.row()].begin();rit != RI[it.row()].end(); rit++)
  54. {
  55. for(cit = CI[it.col()].begin();cit != CI[it.col()].end(); cit++)
  56. {
  57. dyn_Y.coeffRef(*rit,*cit) = it.value();
  58. }
  59. }
  60. }
  61. }
  62. Y = Eigen::SparseMatrix<T>(dyn_Y);
  63. }
  64. template <typename DerivedX>
  65. IGL_INLINE void igl::slice(
  66. const Eigen::PlainObjectBase<DerivedX> & X,
  67. const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
  68. const Eigen::Matrix<int,Eigen::Dynamic,1> & C,
  69. Eigen::PlainObjectBase<DerivedX> & Y)
  70. {
  71. #ifndef NDEBUG
  72. int xm = X.rows();
  73. int xn = X.cols();
  74. #endif
  75. int ym = R.size();
  76. int yn = C.size();
  77. // special case when R or C is empty
  78. if(ym == 0 || yn == 0)
  79. {
  80. Y.resize(ym,yn);
  81. return;
  82. }
  83. assert(R.minCoeff() >= 0);
  84. assert(R.maxCoeff() < xm);
  85. assert(C.minCoeff() >= 0);
  86. assert(C.maxCoeff() < xn);
  87. // Resize output
  88. Y.resize(ym,yn);
  89. // loop over output rows, then columns
  90. for(int i = 0;i<ym;i++)
  91. {
  92. for(int j = 0;j<yn;j++)
  93. {
  94. Y(i,j) = X(R(i),C(j));
  95. }
  96. }
  97. }
  98. template <typename DerivedX>
  99. IGL_INLINE void igl::slice(
  100. const Eigen::PlainObjectBase<DerivedX> & X,
  101. const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
  102. Eigen::PlainObjectBase<DerivedX> & Y)
  103. {
  104. // phony column indices
  105. Eigen::Matrix<int,Eigen::Dynamic,1> C;
  106. C.resize(1);
  107. C(0) = 0;
  108. return igl::slice(X,R,C,Y);
  109. }
  110. #ifndef IGL_HEADER_ONLY
  111. // Explicit template specialization
  112. // generated by autoexplicit.sh
  113. template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  114. // generated by autoexplicit.sh
  115. template void igl::slice<Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
  116. // generated by autoexplicit.sh
  117. template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  118. // generated by autoexplicit.sh
  119. template void igl::slice<Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
  120. // generated by autoexplicit.sh
  121. template void igl::slice<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<double, 0, int>&);
  122. template void igl::slice<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  123. #endif