| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  | // This file is part of Eigen, a lightweight C++ template library
 | 
					
						
							| 
									
										
										
										
											2009-05-23 02:25:33 +08:00
										 |  |  | // for linear algebra.
 | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2008-11-24 21:40:43 +08:00
										 |  |  | // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
 | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2012-07-14 02:42:47 +08:00
										 |  |  | // 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/.
 | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "product.h"
 | 
					
						
							| 
									
										
										
										
											2015-01-13 17:25:50 +08:00
										 |  |  | #include <Eigen/LU>
 | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 22:23:28 +08:00
										 |  |  | // regression test for bug 447
 | 
					
						
							| 
									
										
										
										
											2016-09-27 05:53:40 +08:00
										 |  |  | template <int> | 
					
						
							| 
									
										
										
										
											2012-04-18 22:23:28 +08:00
										 |  |  | void product1x1() { | 
					
						
							|  |  |  |   Matrix<float, 1, 3> matAstatic; | 
					
						
							|  |  |  |   Matrix<float, 3, 1> 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()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  | template <typename TC, typename TA, typename TB> | 
					
						
							|  |  |  | const TC &ref_prod(TC &C, const TA &A, const TB &B) { | 
					
						
							|  |  |  |   for (Index i = 0; i < C.rows(); ++i) | 
					
						
							|  |  |  |     for (Index j = 0; j < C.cols(); ++j) | 
					
						
							|  |  |  |       for (Index k = 0; k < A.cols(); ++k) C.coeffRef(i, j) += A.coeff(i, k) * B.coeff(k, j); | 
					
						
							|  |  |  |   return C; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB> | 
					
						
							| 
									
										
										
										
											2022-03-17 00:43:40 +08:00
										 |  |  | std::enable_if_t<!((Rows == 1 && Depth != 1 && OA == ColMajor) || (Depth == 1 && Rows != 1 && OA == RowMajor) || | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  |                    (Cols == 1 && Depth != 1 && OB == RowMajor) || (Depth == 1 && Cols != 1 && OB == ColMajor) || | 
					
						
							| 
									
										
										
										
											2022-03-17 00:43:40 +08:00
										 |  |  |                    (Rows == 1 && Cols != 1 && OC == ColMajor) || (Cols == 1 && Rows != 1 && OC == RowMajor)), | 
					
						
							|  |  |  |                  void> | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  | test_lazy_single(int rows, int cols, int depth) { | 
					
						
							|  |  |  |   Matrix<T, Rows, Depth, OA> A(rows, depth); | 
					
						
							|  |  |  |   A.setRandom(); | 
					
						
							|  |  |  |   Matrix<T, Depth, Cols, OB> B(depth, cols); | 
					
						
							|  |  |  |   B.setRandom(); | 
					
						
							|  |  |  |   Matrix<T, Rows, Cols, OC> C(rows, cols); | 
					
						
							|  |  |  |   C.setRandom(); | 
					
						
							|  |  |  |   Matrix<T, Rows, Cols, OC> D(C); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(C += A.lazyProduct(B), ref_prod(D, A, B)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 03:54:45 +08:00
										 |  |  | void test_dynamic_bool() { | 
					
						
							| 
									
										
										
										
											2020-04-25 08:29:25 +08:00
										 |  |  |   int rows = internal::random<int>(1, 64); | 
					
						
							|  |  |  |   int cols = internal::random<int>(1, 64); | 
					
						
							|  |  |  |   int depth = internal::random<int>(1, 65); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 03:54:45 +08:00
										 |  |  |   typedef Matrix<bool, Dynamic, Dynamic> MatrixX; | 
					
						
							| 
									
										
										
										
											2020-04-25 08:29:25 +08:00
										 |  |  |   MatrixX A(rows, depth); | 
					
						
							|  |  |  |   A.setRandom(); | 
					
						
							|  |  |  |   MatrixX B(depth, cols); | 
					
						
							|  |  |  |   B.setRandom(); | 
					
						
							| 
									
										
										
										
											2021-01-02 03:54:45 +08:00
										 |  |  |   MatrixX C(rows, cols); | 
					
						
							|  |  |  |   C.setRandom(); | 
					
						
							|  |  |  |   MatrixX D(C); | 
					
						
							| 
									
										
										
										
											2020-04-25 08:29:25 +08:00
										 |  |  |   for (Index i = 0; i < C.rows(); ++i) | 
					
						
							|  |  |  |     for (Index j = 0; j < C.cols(); ++j) | 
					
						
							| 
									
										
										
										
											2023-04-25 23:24:49 +08:00
										 |  |  |       for (Index k = 0; k < A.cols(); ++k) D.coeffRef(i, j) |= (A.coeff(i, k) && B.coeff(k, j)); | 
					
						
							| 
									
										
										
										
											2020-04-25 08:29:25 +08:00
										 |  |  |   C += A * B; | 
					
						
							|  |  |  |   VERIFY_IS_EQUAL(C, D); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MatrixX E = B.transpose(); | 
					
						
							|  |  |  |   for (Index i = 0; i < B.rows(); ++i) | 
					
						
							|  |  |  |     for (Index j = 0; j < B.cols(); ++j) VERIFY_IS_EQUAL(B(i, j), E(j, i)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  | template <typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB> | 
					
						
							| 
									
										
										
										
											2022-03-17 00:43:40 +08:00
										 |  |  | std::enable_if_t<((Rows == 1 && Depth != 1 && OA == ColMajor) || (Depth == 1 && Rows != 1 && OA == RowMajor) || | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  |                   (Cols == 1 && Depth != 1 && OB == RowMajor) || (Depth == 1 && Cols != 1 && OB == ColMajor) || | 
					
						
							| 
									
										
										
										
											2022-03-17 00:43:40 +08:00
										 |  |  |                   (Rows == 1 && Cols != 1 && OC == ColMajor) || (Cols == 1 && Rows != 1 && OC == RowMajor)), | 
					
						
							|  |  |  |                  void> | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  | test_lazy_single(int, int, int) {} | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  | template <typename T, int Rows, int Cols, int Depth> | 
					
						
							|  |  |  | void test_lazy_all_layout(int rows = Rows, int cols = Cols, int depth = Depth) { | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, ColMajor, ColMajor, ColMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, RowMajor, ColMajor, ColMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, ColMajor, RowMajor, ColMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, RowMajor, RowMajor, ColMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, ColMajor, ColMajor, RowMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, RowMajor, ColMajor, RowMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, ColMajor, RowMajor, RowMajor>(rows, cols, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_single<T, Rows, Cols, Depth, RowMajor, RowMajor, RowMajor>(rows, cols, depth))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | void test_lazy_l1() { | 
					
						
							|  |  |  |   int rows = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   int cols = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   int depth = internal::random<int>(1, 12); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Inner
 | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 1, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 1, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 1, 3>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 1, 8>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 1, 9>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 1, -1>(1, 1, depth))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Outer
 | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 1, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 2, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 2, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 3, 3, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 4, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 8, 1>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, -1, 1>(4, cols))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 7, -1, 1>(7, cols))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, 8, 1>(rows))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, 3, 1>(rows))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, -1, 1>(rows, cols))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | void test_lazy_l2() { | 
					
						
							|  |  |  |   int rows = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   int cols = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   int depth = internal::random<int>(1, 12); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // mat-vec
 | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 1, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 1, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 1, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 1, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 5, 1, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 1, 5>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 1, 6>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 6, 1, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 8, 1, 8>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, 1, 4>(rows))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 1, -1>(4, 1, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, 1, -1>(rows, 1, depth))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // vec-mat
 | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 2, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 2, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 4, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 4, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 5, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 4, 5>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 4, 6>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 6, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 8, 8>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, -1, 4>(1, cols))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, 4, -1>(1, 4, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 1, -1, -1>(1, cols, depth))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | void test_lazy_l3() { | 
					
						
							|  |  |  |   int rows = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   int cols = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   int depth = internal::random<int>(1, 12); | 
					
						
							|  |  |  |   // mat-mat
 | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 4, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 6, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 3, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 8, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 5, 6, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 2, 5>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 7, 6>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 6, 8, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 8, 3, 8>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, 6, 4>(rows))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 3, -1>(4, 3, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, -1, 6, -1>(rows, 6, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 8, 2, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 5, 2, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 4, 2>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 8, 4, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 6, 5, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, 4, 5>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 3, 4, 6>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 2, 6, 4>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 7, 8, 8>())); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 8, -1, 4>(8, cols))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 3, 4, -1>(3, 4, depth))); | 
					
						
							|  |  |  |   CALL_SUBTEST((test_lazy_all_layout<T, 4, -1, -1>(4, cols, depth))); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-04-18 22:23:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 21:20:22 +08:00
										 |  |  | template <typename T, int N, int M, int K> | 
					
						
							|  |  |  | 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<Index>(1, 32) : N; | 
					
						
							|  |  |  |   Index m = M == Dynamic ? internal::random<Index>(1, 32) : M; | 
					
						
							|  |  |  |   Index k = K == Dynamic ? internal::random<Index>(1, 32) : K; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Matrix<T, N, M + 1> A; | 
					
						
							|  |  |  |     A.setRandom(n, m + 1); | 
					
						
							|  |  |  |     Matrix<T, M * 2, K> B; | 
					
						
							|  |  |  |     B.setRandom(m * 2, k); | 
					
						
							|  |  |  |     Matrix<T, 1, K> C; | 
					
						
							|  |  |  |     Matrix<T, 1, K> R; | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 21:20:22 +08:00
										 |  |  |     C.noalias() = A.template topLeftCorner<1, M>() * (B.template topRows<M>() + B.template bottomRows<M>()); | 
					
						
							|  |  |  |     R.noalias() = A.template topLeftCorner<1, M>() * (B.template topRows<M>() + B.template bottomRows<M>()).eval(); | 
					
						
							|  |  |  |     VERIFY_IS_APPROX(C, R); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Matrix<T, M + 1, N, RowMajor> A; | 
					
						
							|  |  |  |     A.setRandom(m + 1, n); | 
					
						
							|  |  |  |     Matrix<T, K, M * 2, RowMajor> B; | 
					
						
							|  |  |  |     B.setRandom(k, m * 2); | 
					
						
							|  |  |  |     Matrix<T, K, 1> C; | 
					
						
							|  |  |  |     Matrix<T, K, 1> R; | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 21:20:22 +08:00
										 |  |  |     C.noalias() = (B.template leftCols<M>() + B.template rightCols<M>()) * A.template topLeftCorner<M, 1>(); | 
					
						
							|  |  |  |     R.noalias() = (B.template leftCols<M>() + B.template rightCols<M>()).eval() * A.template topLeftCorner<M, 1>(); | 
					
						
							|  |  |  |     VERIFY_IS_APPROX(C, R); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-27 05:53:40 +08:00
										 |  |  | template <int Rows> | 
					
						
							|  |  |  | void bug_1311() { | 
					
						
							|  |  |  |   Matrix<double, Rows, 2> A; | 
					
						
							|  |  |  |   A.setRandom(); | 
					
						
							|  |  |  |   Vector2d b = Vector2d::Random(); | 
					
						
							|  |  |  |   Matrix<double, Rows, 1> res; | 
					
						
							|  |  |  |   res.noalias() = 1. * (A * b); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(res, A * b); | 
					
						
							|  |  |  |   res.noalias() = 1. * A * b; | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(res, A * b); | 
					
						
							|  |  |  |   res.noalias() = (1. * A).lazyProduct(b); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(res, A * b); | 
					
						
							|  |  |  |   res.noalias() = (1. * A).lazyProduct(1. * b); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(res, A * b); | 
					
						
							|  |  |  |   res.noalias() = (A).lazyProduct(1. * b); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(res, A * b); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 21:52:58 +08:00
										 |  |  | template <int> | 
					
						
							|  |  |  | void product_small_regressions() { | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // test compilation of (outer_product) * vector
 | 
					
						
							|  |  |  |     Vector3f v = Vector3f::Random(); | 
					
						
							|  |  |  |     VERIFY_IS_APPROX((v * v.transpose()) * v, (v * v.transpose()).eval() * v); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 21:52:58 +08:00
										 |  |  |   { | 
					
						
							|  |  |  |     // regression test for pull-request #93
 | 
					
						
							|  |  |  |     Eigen::Matrix<double, 1, 1> A; | 
					
						
							|  |  |  |     A.setRandom(); | 
					
						
							|  |  |  |     Eigen::Matrix<double, 18, 1> B; | 
					
						
							|  |  |  |     B.setRandom(); | 
					
						
							|  |  |  |     Eigen::Matrix<double, 1, 18> 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<double, 10, 10> 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); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-20 04:46:44 +08:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | void product_sweep(int max_m, int max_k, int max_n) { | 
					
						
							|  |  |  |   using Matrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; | 
					
						
							|  |  |  |   for (int m = 1; m < max_m; ++m) { | 
					
						
							|  |  |  |     for (int n = 1; n < max_n; ++n) { | 
					
						
							|  |  |  |       Matrix C = Matrix::Zero(m, n); | 
					
						
							|  |  |  |       Matrix Cref = Matrix::Zero(m, n); | 
					
						
							|  |  |  |       for (int k = 1; k < max_k; ++k) { | 
					
						
							|  |  |  |         Matrix A = Matrix::Random(m, k); | 
					
						
							|  |  |  |         Matrix B = Matrix::Random(k, n); | 
					
						
							|  |  |  |         C = A * B; | 
					
						
							|  |  |  |         Cref.setZero(); | 
					
						
							|  |  |  |         ref_prod(Cref, A, B); | 
					
						
							|  |  |  |         VERIFY_IS_APPROX(C, Cref); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 20:46:15 +08:00
										 |  |  | EIGEN_DECLARE_TEST(product_small) { | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  |   for (int i = 0; i < g_repeat; i++) { | 
					
						
							| 
									
										
										
										
											2009-10-29 06:19:29 +08:00
										 |  |  |     CALL_SUBTEST_1(product(Matrix<float, 3, 2>())); | 
					
						
							| 
									
										
										
										
											2016-09-17 18:52:27 +08:00
										 |  |  |     CALL_SUBTEST_2(product(Matrix<int, 3, 17>())); | 
					
						
							|  |  |  |     CALL_SUBTEST_8(product(Matrix<double, 3, 17>())); | 
					
						
							| 
									
										
										
										
											2009-10-29 06:19:29 +08:00
										 |  |  |     CALL_SUBTEST_3(product(Matrix3d())); | 
					
						
							|  |  |  |     CALL_SUBTEST_4(product(Matrix4d())); | 
					
						
							|  |  |  |     CALL_SUBTEST_5(product(Matrix4f())); | 
					
						
							| 
									
										
										
										
											2022-12-20 04:46:44 +08:00
										 |  |  |     CALL_SUBTEST_10(product(Matrix<bfloat16, 3, 2>())); | 
					
						
							| 
									
										
										
										
											2016-09-27 05:53:40 +08:00
										 |  |  |     CALL_SUBTEST_6(product1x1<0>()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  |     CALL_SUBTEST_11(test_lazy_l1<float>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_12(test_lazy_l2<float>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_13(test_lazy_l3<float>()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  |     CALL_SUBTEST_21(test_lazy_l1<double>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_22(test_lazy_l2<double>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_23(test_lazy_l3<double>()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  |     CALL_SUBTEST_31(test_lazy_l1<std::complex<float> >()); | 
					
						
							|  |  |  |     CALL_SUBTEST_32(test_lazy_l2<std::complex<float> >()); | 
					
						
							|  |  |  |     CALL_SUBTEST_33(test_lazy_l3<std::complex<float> >()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 18:27:43 +08:00
										 |  |  |     CALL_SUBTEST_41(test_lazy_l1<std::complex<double> >()); | 
					
						
							|  |  |  |     CALL_SUBTEST_42(test_lazy_l2<std::complex<double> >()); | 
					
						
							|  |  |  |     CALL_SUBTEST_43(test_lazy_l3<std::complex<double> >()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 21:20:22 +08:00
										 |  |  |     CALL_SUBTEST_7((test_linear_but_not_vectorizable<float, 2, 1, Dynamic>())); | 
					
						
							|  |  |  |     CALL_SUBTEST_7((test_linear_but_not_vectorizable<float, 3, 1, Dynamic>())); | 
					
						
							|  |  |  |     CALL_SUBTEST_7((test_linear_but_not_vectorizable<float, 2, 1, 16>())); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-27 05:53:40 +08:00
										 |  |  |     CALL_SUBTEST_6(bug_1311<3>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_6(bug_1311<5>()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 03:54:45 +08:00
										 |  |  |     CALL_SUBTEST_9(test_dynamic_bool()); | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-20 04:46:44 +08:00
										 |  |  |     // Commonly specialized vectorized types.
 | 
					
						
							|  |  |  |     CALL_SUBTEST_50(product_sweep<float>(10, 10, 10)); | 
					
						
							|  |  |  |     CALL_SUBTEST_51(product_sweep<double>(10, 10, 10)); | 
					
						
							|  |  |  |     CALL_SUBTEST_52(product_sweep<Eigen::half>(10, 10, 10)); | 
					
						
							|  |  |  |     CALL_SUBTEST_53(product_sweep<Eigen::bfloat16>(10, 10, 10)); | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-10-01 19:27:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 21:52:58 +08:00
										 |  |  |   CALL_SUBTEST_6(product_small_regressions<0>()); | 
					
						
							| 
									
										
										
										
											2008-08-02 07:44:59 +08:00
										 |  |  | } |