example.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Make an effort to verify bugs/gotchas for column and row major
  2. //#define EIGEN_DEFAULT_TO_ROW_MAJOR
  3. #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
  4. #define EIGEN_IM_MAD_AS_HELL_AND_IM_NOT_GOING_TO_TAKE_IT_ANYMORE
  5. #include <Eigen/Sparse>
  6. #include <Eigen/SparseExtra>
  7. using namespace Eigen;
  8. #include <cstdio>
  9. #include <iostream>
  10. using namespace std;
  11. #include <igl/print_ijv.h>
  12. using namespace igl;
  13. // Eigen fails to notice at compile time that the inneriterator used to loop
  14. // over the contents of a sparsematrix of type T is a different type
  15. //
  16. // http://www.alecjacobson.com/weblog/?p=2216
  17. void wrong_sparsematrix_inner_iterator_type()
  18. {
  19. // Fill 10 by 10 matrix with 0.5*(1:10) along the diagonal
  20. SparseMatrix<double> A(10,10);
  21. A.reserve(10);
  22. for(int i = 0;i<10;i++)
  23. {
  24. A.insert(i,i) = (double)i/2.0;
  25. }
  26. A.finalize();
  27. cout<<"AIJV=["<<endl;print_ijv(A,1);cout<<endl<<"];"<<endl<<
  28. "A=sparse(AIJV(:,1),AIJV(:,2),AIJV(:,3),"<<
  29. A.rows()<<","<<A.cols()<<");"<<endl;
  30. // Traverse A as *int*
  31. for(int k = 0;k<A.outerSize();k++)
  32. {
  33. // Each entry seems to be cast to int and if it's cast to zero then it's as
  34. // if it wasn't even there
  35. for (SparseMatrix<int>::InnerIterator it(A,k); it; ++it)
  36. {
  37. printf("A(%d,%d) = %d\n",it.row(),it.col(),it.value());
  38. }
  39. }
  40. }
  41. // Eigen can't handle .transpose within expression on right hand side of =
  42. // operator
  43. //
  44. // Temporary solution: Never use Something.transpose() in expression. Always
  45. // first compute Something into a matrix:
  46. // SparseMatrix S = Something;
  47. // then compute tranpose
  48. // SparseMatrix ST = Something.transpose();
  49. // then continue
  50. void sparsematrix_transpose_in_rhs_aliasing()
  51. {
  52. SparseMatrix<double> A(7,2);
  53. A.reserve(4);
  54. A.insert(0,0) = -0.5;
  55. A.insert(2,0) = -0.5;
  56. A.insert(4,1) = -0.5;
  57. A.insert(6,1) = -0.5;
  58. A.finalize();
  59. cout<<"AIJV=["<<endl;print_ijv(A,1);cout<<endl<<"];"<<endl<<
  60. "A=sparse(AIJV(:,1),AIJV(:,2),AIJV(:,3),"<<
  61. A.rows()<<","<<A.cols()<<");"<<endl;
  62. SparseMatrix<double> B(2,7);
  63. B.reserve(4);
  64. B.insert(0,0) = -0.5;
  65. B.insert(0,2) = -0.5;
  66. B.insert(1,4) = -0.5;
  67. B.insert(1,6) = -0.5;
  68. B.finalize();
  69. cout<<"BIJV=["<<endl;print_ijv(B,1);cout<<endl<<"];"<<endl<<
  70. "B=sparse(BIJV(:,1),BIJV(:,2),BIJV(:,3),"<<
  71. B.rows()<<","<<B.cols()<<");"<<endl;
  72. SparseMatrix<double> C;
  73. // Should be empty but isn't
  74. C = A-B.transpose();
  75. cout<<"C = A - B.transpose();"<<endl;
  76. cout<<"CIJV=["<<endl;print_ijv(C,1);cout<<endl<<"];"<<endl<<
  77. "C=sparse(CIJV(:,1),CIJV(:,2),CIJV(:,3),"<<
  78. C.rows()<<","<<C.cols()<<");"<<endl;
  79. // Should be empty but isn't
  80. C = A-B.transpose().eval();
  81. cout<<"C = A - B.transpose().eval();"<<endl;
  82. cout<<"CIJV=["<<endl;print_ijv(C,1);cout<<endl<<"];"<<endl<<
  83. "C=sparse(CIJV(:,1),CIJV(:,2),CIJV(:,3),"<<
  84. C.rows()<<","<<C.cols()<<");"<<endl;
  85. // This works
  86. SparseMatrix<double> BT = B.transpose();
  87. C = A-BT;
  88. cout<<"C = A - BT;"<<endl;
  89. cout<<"CIJV=["<<endl;print_ijv(C,1);cout<<endl<<"];"<<endl<<
  90. "C=sparse(CIJV(:,1),CIJV(:,2),CIJV(:,3),"<<
  91. C.rows()<<","<<C.cols()<<");"<<endl;
  92. }
  93. // Eigen claims the sparseLLT can be constructed using a SparseMatrix but
  94. // at runtime crashes unless it is given exclusively the lower triangle
  95. //
  96. // Temporary solution, replace:
  97. // SparseLLT<SparseMatrix<T> > A_LLT(A);
  98. // with:
  99. // SparseLLT<SparseMatrix<T> > A_LLT(A.template triangularView<Eigen::Lower>());
  100. //
  101. void sparsellt_needs_triangular_view()
  102. {
  103. // Succeeds
  104. SparseMatrix<double> A(2,2);
  105. A.reserve(4);
  106. A.insert(0,0) = 1;
  107. A.insert(0,1) = -0.5;
  108. A.insert(1,0) = -0.5;
  109. A.insert(1,1) = 1;
  110. A.finalize();
  111. cout<<"AIJV=["<<endl;print_ijv(A,1);cout<<endl<<"];"<<endl<<
  112. "A=sparse(AIJV(:,1),AIJV(:,2),AIJV(:,3),"<<
  113. A.rows()<<","<<A.cols()<<");"<<endl;
  114. SparseLLT<SparseMatrix<double> > A_LLT(A.triangularView<Eigen::Lower>());
  115. SparseMatrix<double> A_L = A_LLT.matrixL();
  116. cout<<"A_LIJV=["<<endl;print_ijv(A_L,1);cout<<endl<<"];"<<endl<<
  117. "A_L=sparse(A_LIJV(:,1),A_LIJV(:,2),A_LIJV(:,3),"<<
  118. A_L.rows()<<","<<A_L.cols()<<");"<<endl;
  119. //Crashes
  120. SparseMatrix<double> B(2,2);
  121. B.reserve(4);
  122. B.insert(0,0) = 1;
  123. B.insert(0,1) = -0.5;
  124. B.insert(1,0) = -0.5;
  125. B.insert(1,1) = 1;
  126. B.finalize();
  127. cout<<"BIJV=["<<endl;print_ijv(B,1);cout<<endl<<"];"<<endl<<
  128. "B=sparse(BIJV(:,1),BIJV(:,2),BIJV(:,3),"<<
  129. B.rows()<<","<<B.cols()<<");"<<endl;
  130. SparseLLT<SparseMatrix<double> > B_LLT(B);
  131. }
  132. void sparsematrix_nonzeros_after_expression()
  133. {
  134. SparseMatrix<double> A(2,2);
  135. A.reserve(4);
  136. A.insert(0,0) = 1;
  137. A.insert(0,1) = -0.5;
  138. A.insert(1,0) = -0.5;
  139. A.insert(1,1) = 1;
  140. A.finalize();
  141. cout<<"AIJV=["<<endl;print_ijv(A,1);cout<<endl<<"];"<<endl<<
  142. "A=sparse(AIJV(:,1),AIJV(:,2),AIJV(:,3),"<<
  143. A.rows()<<","<<A.cols()<<");"<<endl;
  144. // Succeeds
  145. SparseMatrix<double> AmA = A-A;
  146. cout<<"(AmA).nonZeros(): "<<AmA.nonZeros()<<endl;
  147. // Succeeds
  148. cout<<"(A-A).eval().nonZeros(): "<<(A-A).eval().nonZeros()<<endl;
  149. // Crashes
  150. cout<<"(A-A).nonZeros(): "<<(A-A).nonZeros()<<endl;
  151. }
  152. // Eigen's SparseLLT's succeeded() method claims to return whether LLT
  153. // computation was successful. Instead it seems its value is meaningless
  154. //
  155. // Temporary solution: Check for presence NaNs in matrixL()
  156. // bool succeeded = (A_LLT.matrixL()*0).eval().nonZeros() == 0;
  157. void sparsellt_succeeded_is_meaningless()
  158. {
  159. // Should succeed
  160. SparseMatrix<double> A(2,2);
  161. A.reserve(4);
  162. A.insert(0,0) = 1;
  163. A.insert(0,1) = -0.5;
  164. A.insert(1,0) = -0.5;
  165. A.insert(1,1) = 1;
  166. A.finalize();
  167. cout<<"AIJV=["<<endl;print_ijv(A,1);cout<<endl<<"];"<<endl<<
  168. "A=sparse(AIJV(:,1),AIJV(:,2),AIJV(:,3),"<<
  169. A.rows()<<","<<A.cols()<<");"<<endl;
  170. SparseLLT<SparseMatrix<double> > A_LLT(A.triangularView<Eigen::Lower>());
  171. cout<<"A_LLT.succeeded(): "<<(A_LLT.succeeded()?"TRUE":"FALSE")<<endl;
  172. SparseMatrix<double> A_L = A_LLT.matrixL();
  173. // See sparsematrix_nonzeros_after_expression
  174. cout<<"(A_L*0).eval().nonZeros(): "<<(A_L*0).eval().nonZeros()<<endl;
  175. cout<<"A_LIJV=["<<endl;print_ijv(A_L,1);cout<<endl<<"];"<<endl<<
  176. "A_L=sparse(A_LIJV(:,1),A_LIJV(:,2),A_LIJV(:,3),"<<
  177. A_L.rows()<<","<<A_L.cols()<<");"<<endl;
  178. // Should not succeed
  179. SparseMatrix<double> B(2,2);
  180. B.reserve(4);
  181. B.insert(0,0) = -1;
  182. B.insert(0,1) = 0.5;
  183. B.insert(1,0) = 0.5;
  184. B.insert(1,1) = -1;
  185. B.finalize();
  186. cout<<"BIJV=["<<endl;print_ijv(B,1);cout<<endl<<"];"<<endl<<
  187. "B=sparse(BIJV(:,1),BIJV(:,2),BIJV(:,3),"<<
  188. B.rows()<<","<<B.cols()<<");"<<endl;
  189. SparseLLT<SparseMatrix<double> > B_LLT(B.triangularView<Eigen::Lower>());
  190. cout<<"B_LLT.succeeded(): "<<(B_LLT.succeeded()?"TRUE":"FALSE")<<endl;
  191. SparseMatrix<double> B_L = B_LLT.matrixL();
  192. // See sparsematrix_nonzeros_after_expression
  193. cout<<"(B_L*0).eval().nonZeros(): "<<(B_L*0).eval().nonZeros()<<endl;
  194. cout<<"B_LIJV=["<<endl;print_ijv(B_L,1);cout<<endl<<"];"<<endl<<
  195. "B_L=sparse(B_LIJV(:,1),B_LIJV(:,2),B_LIJV(:,3),"<<
  196. B_L.rows()<<","<<B_L.cols()<<");"<<endl;
  197. }
  198. int main(int argc, char * argv[])
  199. {
  200. //wrong_sparsematrix_inner_iterator_type();
  201. //sparsematrix_transpose_in_rhs_aliasing();
  202. //sparsellt_needs_triangular_view();
  203. //sparsematrix_nonzeros_after_expression();
  204. //sparsellt_succeeded_is_meaningless();
  205. return 0;
  206. }