// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2006-2008 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #define EIGEN_NO_STATIC_ASSERT #include "product.h" #include // regression test for bug 447 void product1x1() { Matrix matAstatic; Matrix matBstatic; matAstatic.setRandom(); matBstatic.setRandom(); VERIFY_IS_APPROX( (matAstatic * matBstatic).coeff(0,0), matAstatic.cwiseProduct(matBstatic.transpose()).sum() ); MatrixXf matAdynamic(1,3); MatrixXf matBdynamic(3,1); matAdynamic.setRandom(); matBdynamic.setRandom(); VERIFY_IS_APPROX( (matAdynamic * matBdynamic).coeff(0,0), matAdynamic.cwiseProduct(matBdynamic.transpose()).sum() ); } template const TC& ref_prod(TC &C, const TA &A, const TB &B) { for(Index i=0;i typename internal::enable_if::type test_lazy_single(int rows, int cols, int depth) { Matrix A(rows,depth); A.setRandom(); Matrix B(depth,cols); B.setRandom(); Matrix C(rows,cols); C.setRandom(); Matrix D(C); VERIFY_IS_APPROX(C+=A.lazyProduct(B), ref_prod(D,A,B)); } template typename internal::enable_if< ( (Rows ==1&&Depth!=1&&OA==ColMajor) || (Depth==1&&Rows !=1&&OA==RowMajor) || (Cols ==1&&Depth!=1&&OB==RowMajor) || (Depth==1&&Cols !=1&&OB==ColMajor) || (Rows ==1&&Cols !=1&&OC==ColMajor) || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type test_lazy_single(int, int, int) { } template void test_lazy_all_layout(int rows=Rows, int cols=Cols, int depth=Depth) { CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); CALL_SUBTEST(( test_lazy_single(rows,cols,depth) )); } template void test_lazy_l1() { int rows = internal::random(1,12); int cols = internal::random(1,12); int depth = internal::random(1,12); // Inner CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout(1,1,depth) )); // Outer CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout(4,cols) )); CALL_SUBTEST(( test_lazy_all_layout(7,cols) )); CALL_SUBTEST(( test_lazy_all_layout(rows) )); CALL_SUBTEST(( test_lazy_all_layout(rows) )); CALL_SUBTEST(( test_lazy_all_layout(rows,cols) )); } template void test_lazy_l2() { int rows = internal::random(1,12); int cols = internal::random(1,12); int depth = internal::random(1,12); // mat-vec CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout(rows) )); CALL_SUBTEST(( test_lazy_all_layout(4,1,depth) )); CALL_SUBTEST(( test_lazy_all_layout(rows,1,depth) )); // vec-mat CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout(1,cols) )); CALL_SUBTEST(( test_lazy_all_layout(1,4,depth) )); CALL_SUBTEST(( test_lazy_all_layout(1,cols,depth) )); } template void test_lazy_l3() { int rows = internal::random(1,12); int cols = internal::random(1,12); int depth = internal::random(1,12); // mat-mat CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout(rows) )); CALL_SUBTEST(( test_lazy_all_layout(4,3,depth) )); CALL_SUBTEST(( test_lazy_all_layout(rows,6,depth) )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout() )); CALL_SUBTEST(( test_lazy_all_layout(8,cols) )); CALL_SUBTEST(( test_lazy_all_layout(3,4,depth) )); CALL_SUBTEST(( test_lazy_all_layout(4,cols,depth) )); } template void test_linear_but_not_vectorizable() { // Check tricky cases for which the result of the product is a vector and thus must exhibit the LinearBit flag, // but is not vectorizable along the linear dimension. Index n = N==Dynamic ? internal::random(1,32) : N; Index m = M==Dynamic ? internal::random(1,32) : M; Index k = K==Dynamic ? internal::random(1,32) : K; { Matrix A; A.setRandom(n,m+1); Matrix B; B.setRandom(m*2,k); Matrix C; Matrix R; C.noalias() = A.template topLeftCorner<1,M>() * (B.template topRows()+B.template bottomRows()); R.noalias() = A.template topLeftCorner<1,M>() * (B.template topRows()+B.template bottomRows()).eval(); VERIFY_IS_APPROX(C,R); } { Matrix A; A.setRandom(m+1,n); Matrix B; B.setRandom(k,m*2); Matrix C; Matrix R; C.noalias() = (B.template leftCols()+B.template rightCols()) * A.template topLeftCorner(); R.noalias() = (B.template leftCols()+B.template rightCols()).eval() * A.template topLeftCorner(); VERIFY_IS_APPROX(C,R); } } void test_product_small() { for(int i = 0; i < g_repeat; i++) { CALL_SUBTEST_1( product(Matrix()) ); CALL_SUBTEST_2( product(Matrix()) ); CALL_SUBTEST_8( product(Matrix()) ); CALL_SUBTEST_3( product(Matrix3d()) ); CALL_SUBTEST_4( product(Matrix4d()) ); CALL_SUBTEST_5( product(Matrix4f()) ); CALL_SUBTEST_6( product1x1() ); CALL_SUBTEST_11( test_lazy_l1() ); CALL_SUBTEST_12( test_lazy_l2() ); CALL_SUBTEST_13( test_lazy_l3() ); CALL_SUBTEST_21( test_lazy_l1() ); CALL_SUBTEST_22( test_lazy_l2() ); CALL_SUBTEST_23( test_lazy_l3() ); CALL_SUBTEST_31( test_lazy_l1 >() ); CALL_SUBTEST_32( test_lazy_l2 >() ); CALL_SUBTEST_33( test_lazy_l3 >() ); CALL_SUBTEST_41( test_lazy_l1 >() ); CALL_SUBTEST_42( test_lazy_l2 >() ); CALL_SUBTEST_43( test_lazy_l3 >() ); CALL_SUBTEST_7(( test_linear_but_not_vectorizable() )); CALL_SUBTEST_7(( test_linear_but_not_vectorizable() )); CALL_SUBTEST_7(( test_linear_but_not_vectorizable() )); } #ifdef EIGEN_TEST_PART_6 { // test compilation of (outer_product) * vector Vector3f v = Vector3f::Random(); VERIFY_IS_APPROX( (v * v.transpose()) * v, (v * v.transpose()).eval() * v); } { // regression test for pull-request #93 Eigen::Matrix A; A.setRandom(); Eigen::Matrix B; B.setRandom(); Eigen::Matrix C; C.setRandom(); VERIFY_IS_APPROX(B * A.inverse(), B * A.inverse()[0]); VERIFY_IS_APPROX(A.inverse() * C, A.inverse()[0] * C); } { Eigen::Matrix A, B, C; A.setRandom(); C = A; for(int k=0; k<79; ++k) C = C * A; 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))) * (((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))); VERIFY_IS_APPROX(B,C); } #endif }