repdiag.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  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 "repdiag.h"
  9. #ifndef IGL_NO_OPENGL
  10. // Bug in unsupported/Eigen/SparseExtra needs iostream first
  11. #include <iostream>
  12. #include <unsupported/Eigen/SparseExtra>
  13. template <typename T>
  14. IGL_INLINE void igl::repdiag(
  15. const Eigen::SparseMatrix<T>& A,
  16. const int d,
  17. Eigen::SparseMatrix<T>& B)
  18. {
  19. int m = A.rows();
  20. int n = A.cols();
  21. // Should be able to *easily* do this in coherent order without
  22. // dynamicsparsematrix
  23. Eigen::DynamicSparseMatrix<T, Eigen::RowMajor>
  24. dyn_B(m*d,n*d);
  25. // Reserve enough space for new non zeros
  26. dyn_B.reserve(d*A.nonZeros());
  27. // loop over reps
  28. for(int i=0;i<d;i++)
  29. {
  30. // Loop outer level
  31. for (int k=0; k<A.outerSize(); ++k)
  32. {
  33. // loop inner level
  34. for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
  35. {
  36. dyn_B.coeffRef(i*m+it.row(),i*n+it.col()) += it.value();
  37. }
  38. }
  39. }
  40. B = Eigen::SparseMatrix<T>(dyn_B);
  41. }
  42. template <typename T>
  43. IGL_INLINE void igl::repdiag(
  44. const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & A,
  45. const int d,
  46. Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & B)
  47. {
  48. int m = A.rows();
  49. int n = A.cols();
  50. B.resize(m*d,n*d);
  51. B.array() *= 0;
  52. for(int i = 0;i<d;i++)
  53. {
  54. B.block(i*m,i*n,m,n) = A;
  55. }
  56. }
  57. // Wrapper with B as output
  58. template <class Mat>
  59. IGL_INLINE Mat igl::repdiag(const Mat & A, const int d)
  60. {
  61. Mat B;
  62. repdiag(A,d,B);
  63. return B;
  64. }
  65. #ifndef IGL_HEADER_ONLY
  66. // Explicit template specialization
  67. // generated by autoexplicit.sh
  68. template void igl::repdiag<double>(Eigen::SparseMatrix<double, 0, int> const&, int, Eigen::SparseMatrix<double, 0, int>&);
  69. // generated by autoexplicit.sh
  70. template Eigen::SparseMatrix<double, 0, int> igl::repdiag<Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, int);
  71. #endif
  72. #endif