repdiag.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #ifndef IGL_REPDIAG_H
  2. #define IGL_REPDIAG_H
  3. #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
  4. #include <Eigen/Dense>
  5. #include <Eigen/Sparse>
  6. namespace igl
  7. {
  8. // REPDIAG repeat a matrix along the diagonal a certain number of times, so
  9. // that if A is a m by n matrix and we want to repeat along the diagonal d
  10. // times, we get a m*d by n*d matrix B such that:
  11. // B( (k*m+1):(k*m+1+m-1), (k*n+1):(k*n+1+n-1)) = A
  12. // for k from 0 to d-1
  13. //
  14. // Inputs:
  15. // A m by n matrix we are repeating along the diagonal. May be dense or
  16. // sparse
  17. // d number of times to repeat A along the diagonal
  18. // Outputs:
  19. // B m*d by n*d matrix with A repeated d times along the diagonal,
  20. // will be dense or sparse to match A
  21. //
  22. // Sparse version
  23. template <typename T>
  24. inline void repdiag(
  25. const Eigen::SparseMatrix<T>& A,
  26. const int d,
  27. Eigen::SparseMatrix<T>& B);
  28. // Dense version
  29. template <typename T>
  30. inline void repdiag(
  31. const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & A,
  32. const int d,
  33. Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & B);
  34. // Wrapper with B as output
  35. template <class Mat>
  36. inline Mat repdiag(const Mat & A, const int d);
  37. }
  38. // Implementation
  39. template <typename T>
  40. inline void igl::repdiag(
  41. const Eigen::SparseMatrix<T>& A,
  42. const int d,
  43. Eigen::SparseMatrix<T>& B)
  44. {
  45. int m = A.rows();
  46. int n = A.cols();
  47. // Should be able to *easily* do this in coherent order without
  48. // dynamicsparsematrix
  49. Eigen::DynamicSparseMatrix<T, Eigen::RowMajor>
  50. dyn_B(m*d,n*d);
  51. // Reserve enough space for new non zeros
  52. dyn_B.reserve(d*A.nonZeros());
  53. // loop over reps
  54. for(int i=0;i<d;i++)
  55. {
  56. // Loop outer level
  57. for (int k=0; k<A.outerSize(); ++k)
  58. {
  59. // loop inner level
  60. for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
  61. {
  62. dyn_B.coeffRef(i*m+it.row(),i*n+it.col()) += it.value();
  63. }
  64. }
  65. }
  66. B = Eigen::SparseMatrix<T>(dyn_B);
  67. }
  68. template <typename T>
  69. inline void igl::repdiag(
  70. const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & A,
  71. const int d,
  72. Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & B)
  73. {
  74. int m = A.rows();
  75. int n = A.cols();
  76. B.resize(m*d,n*d);
  77. B.array() *= 0;
  78. for(int i = 0;i<d;i++)
  79. {
  80. B.block(i*m,i*n,m,n) = A;
  81. }
  82. }
  83. // Wrapper with B as output
  84. template <class Mat>
  85. inline Mat igl::repdiag(const Mat & A, const int d)
  86. {
  87. Mat B;
  88. repdiag(A,d,B);
  89. return B;
  90. }
  91. #endif