You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
9.5 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #define EIGEN_NO_STATIC_ASSERT
  10. #include "product.h"
  11. #include <Eigen/LU>
  12. // regression test for bug 447
  13. void product1x1()
  14. {
  15. Matrix<float,1,3> matAstatic;
  16. Matrix<float,3,1> matBstatic;
  17. matAstatic.setRandom();
  18. matBstatic.setRandom();
  19. VERIFY_IS_APPROX( (matAstatic * matBstatic).coeff(0,0),
  20. matAstatic.cwiseProduct(matBstatic.transpose()).sum() );
  21. MatrixXf matAdynamic(1,3);
  22. MatrixXf matBdynamic(3,1);
  23. matAdynamic.setRandom();
  24. matBdynamic.setRandom();
  25. VERIFY_IS_APPROX( (matAdynamic * matBdynamic).coeff(0,0),
  26. matAdynamic.cwiseProduct(matBdynamic.transpose()).sum() );
  27. }
  28. template<typename TC, typename TA, typename TB>
  29. const TC& ref_prod(TC &C, const TA &A, const TB &B)
  30. {
  31. for(Index i=0;i<C.rows();++i)
  32. for(Index j=0;j<C.cols();++j)
  33. for(Index k=0;k<A.cols();++k)
  34. C.coeffRef(i,j) += A.coeff(i,k) * B.coeff(k,j);
  35. return C;
  36. }
  37. template<typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB>
  38. typename internal::enable_if<! ( (Rows ==1&&Depth!=1&&OA==ColMajor)
  39. || (Depth==1&&Rows !=1&&OA==RowMajor)
  40. || (Cols ==1&&Depth!=1&&OB==RowMajor)
  41. || (Depth==1&&Cols !=1&&OB==ColMajor)
  42. || (Rows ==1&&Cols !=1&&OC==ColMajor)
  43. || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type
  44. test_lazy_single(int rows, int cols, int depth)
  45. {
  46. Matrix<T,Rows,Depth,OA> A(rows,depth); A.setRandom();
  47. Matrix<T,Depth,Cols,OB> B(depth,cols); B.setRandom();
  48. Matrix<T,Rows,Cols,OC> C(rows,cols); C.setRandom();
  49. Matrix<T,Rows,Cols,OC> D(C);
  50. VERIFY_IS_APPROX(C+=A.lazyProduct(B), ref_prod(D,A,B));
  51. }
  52. template<typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB>
  53. typename internal::enable_if< ( (Rows ==1&&Depth!=1&&OA==ColMajor)
  54. || (Depth==1&&Rows !=1&&OA==RowMajor)
  55. || (Cols ==1&&Depth!=1&&OB==RowMajor)
  56. || (Depth==1&&Cols !=1&&OB==ColMajor)
  57. || (Rows ==1&&Cols !=1&&OC==ColMajor)
  58. || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type
  59. test_lazy_single(int, int, int)
  60. {
  61. }
  62. template<typename T, int Rows, int Cols, int Depth>
  63. void test_lazy_all_layout(int rows=Rows, int cols=Cols, int depth=Depth)
  64. {
  65. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,ColMajor,ColMajor>(rows,cols,depth) ));
  66. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,ColMajor,ColMajor>(rows,cols,depth) ));
  67. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,RowMajor,ColMajor>(rows,cols,depth) ));
  68. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,RowMajor,ColMajor>(rows,cols,depth) ));
  69. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,ColMajor,RowMajor>(rows,cols,depth) ));
  70. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,ColMajor,RowMajor>(rows,cols,depth) ));
  71. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,RowMajor,RowMajor>(rows,cols,depth) ));
  72. CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,RowMajor,RowMajor>(rows,cols,depth) ));
  73. }
  74. template<typename T>
  75. void test_lazy_l1()
  76. {
  77. int rows = internal::random<int>(1,12);
  78. int cols = internal::random<int>(1,12);
  79. int depth = internal::random<int>(1,12);
  80. // Inner
  81. CALL_SUBTEST(( test_lazy_all_layout<T,1,1,1>() ));
  82. CALL_SUBTEST(( test_lazy_all_layout<T,1,1,2>() ));
  83. CALL_SUBTEST(( test_lazy_all_layout<T,1,1,3>() ));
  84. CALL_SUBTEST(( test_lazy_all_layout<T,1,1,8>() ));
  85. CALL_SUBTEST(( test_lazy_all_layout<T,1,1,9>() ));
  86. CALL_SUBTEST(( test_lazy_all_layout<T,1,1,-1>(1,1,depth) ));
  87. // Outer
  88. CALL_SUBTEST(( test_lazy_all_layout<T,2,1,1>() ));
  89. CALL_SUBTEST(( test_lazy_all_layout<T,1,2,1>() ));
  90. CALL_SUBTEST(( test_lazy_all_layout<T,2,2,1>() ));
  91. CALL_SUBTEST(( test_lazy_all_layout<T,3,3,1>() ));
  92. CALL_SUBTEST(( test_lazy_all_layout<T,4,4,1>() ));
  93. CALL_SUBTEST(( test_lazy_all_layout<T,4,8,1>() ));
  94. CALL_SUBTEST(( test_lazy_all_layout<T,4,-1,1>(4,cols) ));
  95. CALL_SUBTEST(( test_lazy_all_layout<T,7,-1,1>(7,cols) ));
  96. CALL_SUBTEST(( test_lazy_all_layout<T,-1,8,1>(rows) ));
  97. CALL_SUBTEST(( test_lazy_all_layout<T,-1,3,1>(rows) ));
  98. CALL_SUBTEST(( test_lazy_all_layout<T,-1,-1,1>(rows,cols) ));
  99. }
  100. template<typename T>
  101. void test_lazy_l2()
  102. {
  103. int rows = internal::random<int>(1,12);
  104. int cols = internal::random<int>(1,12);
  105. int depth = internal::random<int>(1,12);
  106. // mat-vec
  107. CALL_SUBTEST(( test_lazy_all_layout<T,2,1,2>() ));
  108. CALL_SUBTEST(( test_lazy_all_layout<T,2,1,4>() ));
  109. CALL_SUBTEST(( test_lazy_all_layout<T,4,1,2>() ));
  110. CALL_SUBTEST(( test_lazy_all_layout<T,4,1,4>() ));
  111. CALL_SUBTEST(( test_lazy_all_layout<T,5,1,4>() ));
  112. CALL_SUBTEST(( test_lazy_all_layout<T,4,1,5>() ));
  113. CALL_SUBTEST(( test_lazy_all_layout<T,4,1,6>() ));
  114. CALL_SUBTEST(( test_lazy_all_layout<T,6,1,4>() ));
  115. CALL_SUBTEST(( test_lazy_all_layout<T,8,1,8>() ));
  116. CALL_SUBTEST(( test_lazy_all_layout<T,-1,1,4>(rows) ));
  117. CALL_SUBTEST(( test_lazy_all_layout<T,4,1,-1>(4,1,depth) ));
  118. CALL_SUBTEST(( test_lazy_all_layout<T,-1,1,-1>(rows,1,depth) ));
  119. // vec-mat
  120. CALL_SUBTEST(( test_lazy_all_layout<T,1,2,2>() ));
  121. CALL_SUBTEST(( test_lazy_all_layout<T,1,2,4>() ));
  122. CALL_SUBTEST(( test_lazy_all_layout<T,1,4,2>() ));
  123. CALL_SUBTEST(( test_lazy_all_layout<T,1,4,4>() ));
  124. CALL_SUBTEST(( test_lazy_all_layout<T,1,5,4>() ));
  125. CALL_SUBTEST(( test_lazy_all_layout<T,1,4,5>() ));
  126. CALL_SUBTEST(( test_lazy_all_layout<T,1,4,6>() ));
  127. CALL_SUBTEST(( test_lazy_all_layout<T,1,6,4>() ));
  128. CALL_SUBTEST(( test_lazy_all_layout<T,1,8,8>() ));
  129. CALL_SUBTEST(( test_lazy_all_layout<T,1,-1, 4>(1,cols) ));
  130. CALL_SUBTEST(( test_lazy_all_layout<T,1, 4,-1>(1,4,depth) ));
  131. CALL_SUBTEST(( test_lazy_all_layout<T,1,-1,-1>(1,cols,depth) ));
  132. }
  133. template<typename T>
  134. void test_lazy_l3()
  135. {
  136. int rows = internal::random<int>(1,12);
  137. int cols = internal::random<int>(1,12);
  138. int depth = internal::random<int>(1,12);
  139. // mat-mat
  140. CALL_SUBTEST(( test_lazy_all_layout<T,2,4,2>() ));
  141. CALL_SUBTEST(( test_lazy_all_layout<T,2,6,4>() ));
  142. CALL_SUBTEST(( test_lazy_all_layout<T,4,3,2>() ));
  143. CALL_SUBTEST(( test_lazy_all_layout<T,4,8,4>() ));
  144. CALL_SUBTEST(( test_lazy_all_layout<T,5,6,4>() ));
  145. CALL_SUBTEST(( test_lazy_all_layout<T,4,2,5>() ));
  146. CALL_SUBTEST(( test_lazy_all_layout<T,4,7,6>() ));
  147. CALL_SUBTEST(( test_lazy_all_layout<T,6,8,4>() ));
  148. CALL_SUBTEST(( test_lazy_all_layout<T,8,3,8>() ));
  149. CALL_SUBTEST(( test_lazy_all_layout<T,-1,6,4>(rows) ));
  150. CALL_SUBTEST(( test_lazy_all_layout<T,4,3,-1>(4,3,depth) ));
  151. CALL_SUBTEST(( test_lazy_all_layout<T,-1,6,-1>(rows,6,depth) ));
  152. CALL_SUBTEST(( test_lazy_all_layout<T,8,2,2>() ));
  153. CALL_SUBTEST(( test_lazy_all_layout<T,5,2,4>() ));
  154. CALL_SUBTEST(( test_lazy_all_layout<T,4,4,2>() ));
  155. CALL_SUBTEST(( test_lazy_all_layout<T,8,4,4>() ));
  156. CALL_SUBTEST(( test_lazy_all_layout<T,6,5,4>() ));
  157. CALL_SUBTEST(( test_lazy_all_layout<T,4,4,5>() ));
  158. CALL_SUBTEST(( test_lazy_all_layout<T,3,4,6>() ));
  159. CALL_SUBTEST(( test_lazy_all_layout<T,2,6,4>() ));
  160. CALL_SUBTEST(( test_lazy_all_layout<T,7,8,8>() ));
  161. CALL_SUBTEST(( test_lazy_all_layout<T,8,-1, 4>(8,cols) ));
  162. CALL_SUBTEST(( test_lazy_all_layout<T,3, 4,-1>(3,4,depth) ));
  163. CALL_SUBTEST(( test_lazy_all_layout<T,4,-1,-1>(4,cols,depth) ));
  164. }
  165. void test_product_small()
  166. {
  167. for(int i = 0; i < g_repeat; i++) {
  168. CALL_SUBTEST_1( product(Matrix<float, 3, 2>()) );
  169. CALL_SUBTEST_2( product(Matrix<int, 3, 5>()) );
  170. CALL_SUBTEST_3( product(Matrix3d()) );
  171. CALL_SUBTEST_4( product(Matrix4d()) );
  172. CALL_SUBTEST_5( product(Matrix4f()) );
  173. CALL_SUBTEST_6( product1x1() );
  174. CALL_SUBTEST_11( test_lazy_l1<float>() );
  175. CALL_SUBTEST_12( test_lazy_l2<float>() );
  176. CALL_SUBTEST_13( test_lazy_l3<float>() );
  177. CALL_SUBTEST_21( test_lazy_l1<double>() );
  178. CALL_SUBTEST_22( test_lazy_l2<double>() );
  179. CALL_SUBTEST_23( test_lazy_l3<double>() );
  180. CALL_SUBTEST_31( test_lazy_l1<std::complex<float> >() );
  181. CALL_SUBTEST_32( test_lazy_l2<std::complex<float> >() );
  182. CALL_SUBTEST_33( test_lazy_l3<std::complex<float> >() );
  183. CALL_SUBTEST_41( test_lazy_l1<std::complex<double> >() );
  184. CALL_SUBTEST_42( test_lazy_l2<std::complex<double> >() );
  185. CALL_SUBTEST_43( test_lazy_l3<std::complex<double> >() );
  186. }
  187. #ifdef EIGEN_TEST_PART_6
  188. {
  189. // test compilation of (outer_product) * vector
  190. Vector3f v = Vector3f::Random();
  191. VERIFY_IS_APPROX( (v * v.transpose()) * v, (v * v.transpose()).eval() * v);
  192. }
  193. {
  194. // regression test for pull-request #93
  195. StormEigen::Matrix<double, 1, 1> A; A.setRandom();
  196. StormEigen::Matrix<double, 18, 1> B; B.setRandom();
  197. StormEigen::Matrix<double, 1, 18> C; C.setRandom();
  198. VERIFY_IS_APPROX(B * A.inverse(), B * A.inverse()[0]);
  199. VERIFY_IS_APPROX(A.inverse() * C, A.inverse()[0] * C);
  200. }
  201. {
  202. StormEigen::Matrix<double, 10, 10> A, B, C;
  203. A.setRandom();
  204. C = A;
  205. for(int k=0; k<79; ++k)
  206. C = C * A;
  207. B.noalias() = (((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)) * ((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)))
  208. * (((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)) * ((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)));
  209. VERIFY_IS_APPROX(B,C);
  210. }
  211. #endif
  212. }