cat.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "cat.h"
  2. #include <cstdio>
  3. // Bug in unsupported/Eigen/SparseExtra needs iostream first
  4. #include <iostream>
  5. #include <unsupported/Eigen/SparseExtra>
  6. // Sparse matrices need to be handled carefully. Because C++ does not
  7. // Template:
  8. // Scalar sparse matrix scalar type, e.g. double
  9. template <typename Scalar>
  10. IGL_INLINE void igl::cat(
  11. const int dim,
  12. const Eigen::SparseMatrix<Scalar> & A,
  13. const Eigen::SparseMatrix<Scalar> & B,
  14. Eigen::SparseMatrix<Scalar> & C)
  15. {
  16. assert(dim == 1 || dim == 2);
  17. using namespace Eigen;
  18. // Special case if B or A is empty
  19. if(A.size() == 0)
  20. {
  21. C = B;
  22. return;
  23. }
  24. if(B.size() == 0)
  25. {
  26. C = A;
  27. return;
  28. }
  29. DynamicSparseMatrix<Scalar, RowMajor> dyn_C;
  30. if(dim == 1)
  31. {
  32. assert(A.cols() == B.cols());
  33. dyn_C.resize(A.rows()+B.rows(),A.cols());
  34. }else if(dim == 2)
  35. {
  36. assert(A.rows() == B.rows());
  37. dyn_C.resize(A.rows(),A.cols()+B.cols());
  38. }else
  39. {
  40. fprintf(stderr,"cat.h: Error: Unsupported dimension %d\n",dim);
  41. }
  42. dyn_C.reserve(A.nonZeros()+B.nonZeros());
  43. // Iterate over outside of A
  44. for(int k=0; k<A.outerSize(); ++k)
  45. {
  46. // Iterate over inside
  47. for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
  48. {
  49. dyn_C.coeffRef(it.row(),it.col()) += it.value();
  50. }
  51. }
  52. // Iterate over outside of B
  53. for(int k=0; k<B.outerSize(); ++k)
  54. {
  55. // Iterate over inside
  56. for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
  57. {
  58. int r = (dim == 1 ? A.rows()+it.row() : it.row());
  59. int c = (dim == 2 ? A.cols()+it.col() : it.col());
  60. dyn_C.coeffRef(r,c) += it.value();
  61. }
  62. }
  63. C = SparseMatrix<Scalar>(dyn_C);
  64. }
  65. template <typename Derived, class MatC>
  66. IGL_INLINE void igl::cat(
  67. const int dim,
  68. const Eigen::MatrixBase<Derived> & A,
  69. const Eigen::MatrixBase<Derived> & B,
  70. MatC & C)
  71. {
  72. assert(dim == 1 || dim == 2);
  73. // Special case if B or A is empty
  74. if(A.size() == 0)
  75. {
  76. C = B;
  77. return;
  78. }
  79. if(B.size() == 0)
  80. {
  81. C = A;
  82. return;
  83. }
  84. if(dim == 1)
  85. {
  86. assert(A.cols() == B.cols());
  87. C.resize(A.rows()+B.rows(),A.cols());
  88. C << A,B;
  89. }else if(dim == 2)
  90. {
  91. assert(A.rows() == B.rows());
  92. C.resize(A.rows(),A.cols()+B.cols());
  93. C << A,B;
  94. }else
  95. {
  96. fprintf(stderr,"cat.h: Error: Unsupported dimension %d\n",dim);
  97. }
  98. }
  99. template <class Mat>
  100. IGL_INLINE Mat igl::cat(const int dim, const Mat & A, const Mat & B)
  101. {
  102. assert(dim == 1 || dim == 2);
  103. Mat C;
  104. igl::cat(dim,A,B,C);
  105. return C;
  106. }
  107. template <class Mat>
  108. IGL_INLINE void cat(const std::vector<std::vector< Mat > > & A, Mat & C)
  109. {
  110. using namespace igl;
  111. using namespace std;
  112. // Start with empty matrix
  113. C.resize(0,0);
  114. for(typename vector<vector< Mat > >::const_iterator rit = A.begin(); rit != A.end(); rit++)
  115. {
  116. // Concatenate each row horizontally
  117. // Start with empty matrix
  118. Mat row(0,0);
  119. for(typename vector<vector< Mat > >::iterator cit = A.begin(); rit != A.end(); rit++)
  120. {
  121. row = cat(2,row,*cit);
  122. }
  123. // Concatenate rows vertically
  124. C = cat(1,C,row);
  125. }
  126. }
  127. #ifndef IGL_HEADER_ONLY
  128. // Explicit template specialization
  129. // generated by autoexplicit.sh
  130. template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::cat<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(int, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&);
  131. // generated by autoexplicit.sh
  132. template Eigen::SparseMatrix<double, 0, int> igl::cat<Eigen::SparseMatrix<double, 0, int> >(int, Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&);
  133. // generated by autoexplicit.sh
  134. template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::cat<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
  135. template void igl::cat<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(int, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
  136. template Eigen::Matrix<int, -1, 1, 0, -1, 1> igl::cat<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&);
  137. template Eigen::Matrix<double, -1, 1, 0, -1, 1> igl::cat<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(int, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&);
  138. #endif