repdiag.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. }
  35. // Implementation
  36. template <typename T>
  37. inline void igl::repdiag(
  38. const Eigen::SparseMatrix<T>& A,
  39. const int d,
  40. Eigen::SparseMatrix<T>& B)
  41. {
  42. int m = A.rows();
  43. int n = A.cols();
  44. // Should be able to *easily* do this in coherent order without
  45. // dynamicsparsematrix
  46. Eigen::DynamicSparseMatrix<T, Eigen::RowMajor>
  47. dyn_B(m*d,n*d);
  48. // Reserve enough space for new non zeros
  49. dyn_B.reserve(d*A.nonZeros());
  50. // loop over reps
  51. for(int i=0;i<d;i++)
  52. {
  53. // Loop outer level
  54. for (int k=0; k<A.outerSize(); ++k)
  55. {
  56. // loop inner level
  57. for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
  58. {
  59. dyn_B.coeffRef(i*m+it.row(),i*n+it.col()) += it.value();
  60. }
  61. }
  62. }
  63. B = Eigen::SparseMatrix<T>(dyn_B);
  64. }
  65. template <typename T>
  66. inline void igl::repdiag(
  67. const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & A,
  68. const int d,
  69. Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & B)
  70. {
  71. int m = A.rows();
  72. int n = A.cols();
  73. B.resize(m*d,n*d);
  74. B.array() *= 0;
  75. for(int i = 0;i<d;i++)
  76. {
  77. B.block(i*m,i*n,m,n) = A;
  78. }
  79. }
  80. #endif