product_small.cpp
Go to the documentation of this file.
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 
10 #define EIGEN_NO_STATIC_ASSERT
11 #include "product.h"
12 #include <Eigen/LU>
13 
14 // regression test for bug 447
15 template<int>
16 void product1x1()
17 {
18  Matrix<float,1,3> matAstatic;
19  Matrix<float,3,1> matBstatic;
20  matAstatic.setRandom();
21  matBstatic.setRandom();
22  VERIFY_IS_APPROX( (matAstatic * matBstatic).coeff(0,0),
23  matAstatic.cwiseProduct(matBstatic.transpose()).sum() );
24 
25  MatrixXf matAdynamic(1,3);
26  MatrixXf matBdynamic(3,1);
27  matAdynamic.setRandom();
28  matBdynamic.setRandom();
29  VERIFY_IS_APPROX( (matAdynamic * matBdynamic).coeff(0,0),
30  matAdynamic.cwiseProduct(matBdynamic.transpose()).sum() );
31 }
32 
33 template<typename TC, typename TA, typename TB>
34 const TC& ref_prod(TC &C, const TA &A, const TB &B)
35 {
36  for(Index i=0;i<C.rows();++i)
37  for(Index j=0;j<C.cols();++j)
38  for(Index k=0;k<A.cols();++k)
39  C.coeffRef(i,j) += A.coeff(i,k) * B.coeff(k,j);
40  return C;
41 }
42 
43 template<typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB>
44 typename internal::enable_if<! ( (Rows ==1&&Depth!=1&&OA==ColMajor)
45  || (Depth==1&&Rows !=1&&OA==RowMajor)
46  || (Cols ==1&&Depth!=1&&OB==RowMajor)
47  || (Depth==1&&Cols !=1&&OB==ColMajor)
48  || (Rows ==1&&Cols !=1&&OC==ColMajor)
49  || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type
51 {
52  Matrix<T,Rows,Depth,OA> A(rows,depth); A.setRandom();
53  Matrix<T,Depth,Cols,OB> B(depth,cols); B.setRandom();
54  Matrix<T,Rows,Cols,OC> C(rows,cols); C.setRandom();
56  VERIFY_IS_APPROX(C+=A.lazyProduct(B), ref_prod(D,A,B));
57 }
58 
60 {
61  int rows = internal::random<int>(1,64);
62  int cols = internal::random<int>(1,64);
63  int depth = internal::random<int>(1,65);
64 
65  typedef Matrix<bool,Dynamic,Dynamic> MatrixX;
66  MatrixX A(rows,depth); A.setRandom();
67  MatrixX B(depth,cols); B.setRandom();
68  MatrixX C(rows,cols); C.setRandom();
69  MatrixX D(C);
70  for(Index i=0;i<C.rows();++i)
71  for(Index j=0;j<C.cols();++j)
72  for(Index k=0;k<A.cols();++k)
73  D.coeffRef(i,j) |= A.coeff(i,k) & B.coeff(k,j);
74  C += A * B;
75  VERIFY_IS_EQUAL(C, D);
76 
77  MatrixX E = B.transpose();
78  for(Index i=0;i<B.rows();++i)
79  for(Index j=0;j<B.cols();++j)
80  VERIFY_IS_EQUAL(B(i,j), E(j,i));
81 }
82 
83 template<typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB>
84 typename internal::enable_if< ( (Rows ==1&&Depth!=1&&OA==ColMajor)
85  || (Depth==1&&Rows !=1&&OA==RowMajor)
86  || (Cols ==1&&Depth!=1&&OB==RowMajor)
87  || (Depth==1&&Cols !=1&&OB==ColMajor)
88  || (Rows ==1&&Cols !=1&&OC==ColMajor)
89  || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type
90 test_lazy_single(int, int, int)
91 {
92 }
93 
94 template<typename T, int Rows, int Cols, int Depth>
95 void test_lazy_all_layout(int rows=Rows, int cols=Cols, int depth=Depth)
96 {
97  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,ColMajor,ColMajor>(rows,cols,depth) ));
98  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,ColMajor,ColMajor>(rows,cols,depth) ));
99  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,RowMajor,ColMajor>(rows,cols,depth) ));
100  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,RowMajor,ColMajor>(rows,cols,depth) ));
101  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,ColMajor,RowMajor>(rows,cols,depth) ));
102  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,ColMajor,RowMajor>(rows,cols,depth) ));
103  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,RowMajor,RowMajor>(rows,cols,depth) ));
104  CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,RowMajor,RowMajor>(rows,cols,depth) ));
105 }
106 
107 template<typename T>
109 {
110  int rows = internal::random<int>(1,12);
111  int cols = internal::random<int>(1,12);
112  int depth = internal::random<int>(1,12);
113 
114  // Inner
115  CALL_SUBTEST(( test_lazy_all_layout<T,1,1,1>() ));
116  CALL_SUBTEST(( test_lazy_all_layout<T,1,1,2>() ));
117  CALL_SUBTEST(( test_lazy_all_layout<T,1,1,3>() ));
118  CALL_SUBTEST(( test_lazy_all_layout<T,1,1,8>() ));
119  CALL_SUBTEST(( test_lazy_all_layout<T,1,1,9>() ));
120  CALL_SUBTEST(( test_lazy_all_layout<T,1,1,-1>(1,1,depth) ));
121 
122  // Outer
123  CALL_SUBTEST(( test_lazy_all_layout<T,2,1,1>() ));
124  CALL_SUBTEST(( test_lazy_all_layout<T,1,2,1>() ));
125  CALL_SUBTEST(( test_lazy_all_layout<T,2,2,1>() ));
126  CALL_SUBTEST(( test_lazy_all_layout<T,3,3,1>() ));
127  CALL_SUBTEST(( test_lazy_all_layout<T,4,4,1>() ));
128  CALL_SUBTEST(( test_lazy_all_layout<T,4,8,1>() ));
129  CALL_SUBTEST(( test_lazy_all_layout<T,4,-1,1>(4,cols) ));
130  CALL_SUBTEST(( test_lazy_all_layout<T,7,-1,1>(7,cols) ));
131  CALL_SUBTEST(( test_lazy_all_layout<T,-1,8,1>(rows) ));
132  CALL_SUBTEST(( test_lazy_all_layout<T,-1,3,1>(rows) ));
133  CALL_SUBTEST(( test_lazy_all_layout<T,-1,-1,1>(rows,cols) ));
134 }
135 
136 template<typename T>
138 {
139  int rows = internal::random<int>(1,12);
140  int cols = internal::random<int>(1,12);
141  int depth = internal::random<int>(1,12);
142 
143  // mat-vec
144  CALL_SUBTEST(( test_lazy_all_layout<T,2,1,2>() ));
145  CALL_SUBTEST(( test_lazy_all_layout<T,2,1,4>() ));
146  CALL_SUBTEST(( test_lazy_all_layout<T,4,1,2>() ));
147  CALL_SUBTEST(( test_lazy_all_layout<T,4,1,4>() ));
148  CALL_SUBTEST(( test_lazy_all_layout<T,5,1,4>() ));
149  CALL_SUBTEST(( test_lazy_all_layout<T,4,1,5>() ));
150  CALL_SUBTEST(( test_lazy_all_layout<T,4,1,6>() ));
151  CALL_SUBTEST(( test_lazy_all_layout<T,6,1,4>() ));
152  CALL_SUBTEST(( test_lazy_all_layout<T,8,1,8>() ));
153  CALL_SUBTEST(( test_lazy_all_layout<T,-1,1,4>(rows) ));
154  CALL_SUBTEST(( test_lazy_all_layout<T,4,1,-1>(4,1,depth) ));
155  CALL_SUBTEST(( test_lazy_all_layout<T,-1,1,-1>(rows,1,depth) ));
156 
157  // vec-mat
158  CALL_SUBTEST(( test_lazy_all_layout<T,1,2,2>() ));
159  CALL_SUBTEST(( test_lazy_all_layout<T,1,2,4>() ));
160  CALL_SUBTEST(( test_lazy_all_layout<T,1,4,2>() ));
161  CALL_SUBTEST(( test_lazy_all_layout<T,1,4,4>() ));
162  CALL_SUBTEST(( test_lazy_all_layout<T,1,5,4>() ));
163  CALL_SUBTEST(( test_lazy_all_layout<T,1,4,5>() ));
164  CALL_SUBTEST(( test_lazy_all_layout<T,1,4,6>() ));
165  CALL_SUBTEST(( test_lazy_all_layout<T,1,6,4>() ));
166  CALL_SUBTEST(( test_lazy_all_layout<T,1,8,8>() ));
167  CALL_SUBTEST(( test_lazy_all_layout<T,1,-1, 4>(1,cols) ));
168  CALL_SUBTEST(( test_lazy_all_layout<T,1, 4,-1>(1,4,depth) ));
169  CALL_SUBTEST(( test_lazy_all_layout<T,1,-1,-1>(1,cols,depth) ));
170 }
171 
172 template<typename T>
174 {
175  int rows = internal::random<int>(1,12);
176  int cols = internal::random<int>(1,12);
177  int depth = internal::random<int>(1,12);
178  // mat-mat
179  CALL_SUBTEST(( test_lazy_all_layout<T,2,4,2>() ));
180  CALL_SUBTEST(( test_lazy_all_layout<T,2,6,4>() ));
181  CALL_SUBTEST(( test_lazy_all_layout<T,4,3,2>() ));
182  CALL_SUBTEST(( test_lazy_all_layout<T,4,8,4>() ));
183  CALL_SUBTEST(( test_lazy_all_layout<T,5,6,4>() ));
184  CALL_SUBTEST(( test_lazy_all_layout<T,4,2,5>() ));
185  CALL_SUBTEST(( test_lazy_all_layout<T,4,7,6>() ));
186  CALL_SUBTEST(( test_lazy_all_layout<T,6,8,4>() ));
187  CALL_SUBTEST(( test_lazy_all_layout<T,8,3,8>() ));
188  CALL_SUBTEST(( test_lazy_all_layout<T,-1,6,4>(rows) ));
189  CALL_SUBTEST(( test_lazy_all_layout<T,4,3,-1>(4,3,depth) ));
190  CALL_SUBTEST(( test_lazy_all_layout<T,-1,6,-1>(rows,6,depth) ));
191  CALL_SUBTEST(( test_lazy_all_layout<T,8,2,2>() ));
192  CALL_SUBTEST(( test_lazy_all_layout<T,5,2,4>() ));
193  CALL_SUBTEST(( test_lazy_all_layout<T,4,4,2>() ));
194  CALL_SUBTEST(( test_lazy_all_layout<T,8,4,4>() ));
195  CALL_SUBTEST(( test_lazy_all_layout<T,6,5,4>() ));
196  CALL_SUBTEST(( test_lazy_all_layout<T,4,4,5>() ));
197  CALL_SUBTEST(( test_lazy_all_layout<T,3,4,6>() ));
198  CALL_SUBTEST(( test_lazy_all_layout<T,2,6,4>() ));
199  CALL_SUBTEST(( test_lazy_all_layout<T,7,8,8>() ));
200  CALL_SUBTEST(( test_lazy_all_layout<T,8,-1, 4>(8,cols) ));
201  CALL_SUBTEST(( test_lazy_all_layout<T,3, 4,-1>(3,4,depth) ));
202  CALL_SUBTEST(( test_lazy_all_layout<T,4,-1,-1>(4,cols,depth) ));
203 }
204 
205 template<typename T,int N,int M,int K>
207 {
208  // Check tricky cases for which the result of the product is a vector and thus must exhibit the LinearBit flag,
209  // but is not vectorizable along the linear dimension.
210  Index n = N==Dynamic ? internal::random<Index>(1,32) : N;
211  Index m = M==Dynamic ? internal::random<Index>(1,32) : M;
212  Index k = K==Dynamic ? internal::random<Index>(1,32) : K;
213 
214  {
215  Matrix<T,N,M+1> A; A.setRandom(n,m+1);
216  Matrix<T,M*2,K> B; B.setRandom(m*2,k);
219 
220  C.noalias() = A.template topLeftCorner<1,M>() * (B.template topRows<M>()+B.template bottomRows<M>());
221  R.noalias() = A.template topLeftCorner<1,M>() * (B.template topRows<M>()+B.template bottomRows<M>()).eval();
222  VERIFY_IS_APPROX(C,R);
223  }
224 
225  {
230 
231  C.noalias() = (B.template leftCols<M>()+B.template rightCols<M>()) * A.template topLeftCorner<M,1>();
232  R.noalias() = (B.template leftCols<M>()+B.template rightCols<M>()).eval() * A.template topLeftCorner<M,1>();
233  VERIFY_IS_APPROX(C,R);
234  }
235 }
236 
237 template<int Rows>
238 void bug_1311()
239 {
241  Vector2d b = Vector2d::Random() ;
243  res.noalias() = 1. * (A * b);
244  VERIFY_IS_APPROX(res, A*b);
245  res.noalias() = 1.*A * b;
246  VERIFY_IS_APPROX(res, A*b);
247  res.noalias() = (1.*A).lazyProduct(b);
248  VERIFY_IS_APPROX(res, A*b);
249  res.noalias() = (1.*A).lazyProduct(1.*b);
250  VERIFY_IS_APPROX(res, A*b);
251  res.noalias() = (A).lazyProduct(1.*b);
252  VERIFY_IS_APPROX(res, A*b);
253 }
254 
255 template<int>
257 {
258  {
259  // test compilation of (outer_product) * vector
260  Vector3f v = Vector3f::Random();
261  VERIFY_IS_APPROX( (v * v.transpose()) * v, (v * v.transpose()).eval() * v);
262  }
263 
264  {
265  // regression test for pull-request #93
269  VERIFY_IS_APPROX(B * A.inverse(), B * A.inverse()[0]);
270  VERIFY_IS_APPROX(A.inverse() * C, A.inverse()[0] * C);
271  }
272 
273  {
275  A.setRandom();
276  C = A;
277  for(int k=0; k<79; ++k)
278  C = C * A;
279  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)))
280  * (((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)));
281  VERIFY_IS_APPROX(B,C);
282  }
283 }
284 
285 EIGEN_DECLARE_TEST(product_small)
286 {
287  for(int i = 0; i < g_repeat; i++) {
291  CALL_SUBTEST_3( product(Matrix3d()) );
292  CALL_SUBTEST_4( product(Matrix4d()) );
293  CALL_SUBTEST_5( product(Matrix4f()) );
294  CALL_SUBTEST_6( product1x1<0>() );
295 
296  CALL_SUBTEST_11( test_lazy_l1<float>() );
297  CALL_SUBTEST_12( test_lazy_l2<float>() );
298  CALL_SUBTEST_13( test_lazy_l3<float>() );
299 
300  CALL_SUBTEST_21( test_lazy_l1<double>() );
301  CALL_SUBTEST_22( test_lazy_l2<double>() );
302  CALL_SUBTEST_23( test_lazy_l3<double>() );
303 
304  CALL_SUBTEST_31( test_lazy_l1<std::complex<float> >() );
305  CALL_SUBTEST_32( test_lazy_l2<std::complex<float> >() );
306  CALL_SUBTEST_33( test_lazy_l3<std::complex<float> >() );
307 
308  CALL_SUBTEST_41( test_lazy_l1<std::complex<double> >() );
309  CALL_SUBTEST_42( test_lazy_l2<std::complex<double> >() );
310  CALL_SUBTEST_43( test_lazy_l3<std::complex<double> >() );
311 
312  CALL_SUBTEST_7(( test_linear_but_not_vectorizable<float,2,1,Dynamic>() ));
313  CALL_SUBTEST_7(( test_linear_but_not_vectorizable<float,3,1,Dynamic>() ));
314  CALL_SUBTEST_7(( test_linear_but_not_vectorizable<float,2,1,16>() ));
315 
316  CALL_SUBTEST_6( bug_1311<3>() );
317  CALL_SUBTEST_6( bug_1311<5>() );
318 
320  }
321 
322  CALL_SUBTEST_6( product_small_regressions<0>() );
323 }
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:49
Matrix3f m
#define CALL_SUBTEST_12(FUNC)
#define CALL_SUBTEST_9(FUNC)
#define CALL_SUBTEST_6(FUNC)
void test_lazy_all_layout(int rows=Rows, int cols=Cols, int depth=Depth)
#define CALL_SUBTEST_4(FUNC)
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51
void test_lazy_l1()
Scalar * b
Definition: benchVecAdd.cpp:17
EIGEN_DECLARE_TEST(product_small)
#define CALL_SUBTEST_33(FUNC)
#define CALL_SUBTEST_13(FUNC)
#define CALL_SUBTEST_3(FUNC)
static double depth
#define CALL_SUBTEST_7(FUNC)
int n
Rot2 R(Rot2::fromAngle(0.1))
#define CALL_SUBTEST_31(FUNC)
#define CALL_SUBTEST_11(FUNC)
static Cal3_S2 K(500, 500, 0.1, 640/2, 480/2)
void test_linear_but_not_vectorizable()
#define CALL_SUBTEST_22(FUNC)
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:48
#define N
Definition: gksort.c:12
void bug_1311()
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
#define CALL_SUBTEST_23(FUNC)
#define VERIFY_IS_APPROX(a, b)
#define CALL_SUBTEST_42(FUNC)
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:386
#define CALL_SUBTEST_1(FUNC)
#define CALL_SUBTEST_41(FUNC)
static int g_repeat
Definition: main.h:169
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:74
Array< int, Dynamic, 1 > v
#define CALL_SUBTEST_8(FUNC)
#define CALL_SUBTEST_21(FUNC)
static const int Cols
Matrix< Scalar, Dynamic, Dynamic > C
Definition: bench_gemm.cpp:50
void test_lazy_l2()
void product1x1()
DiscreteKey E(5, 2)
#define CALL_SUBTEST_5(FUNC)
#define CALL_SUBTEST(FUNC)
Definition: main.h:399
void test_dynamic_bool()
void product_small_regressions()
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 rows, int cols, int depth)
#define CALL_SUBTEST_2(FUNC)
internal::nested_eval< T, 1 >::type eval(const T &xpr)
#define CALL_SUBTEST_43(FUNC)
const int Dynamic
Definition: Constants.h:22
The matrix class, also used for vectors and row-vectors.
#define CALL_SUBTEST_32(FUNC)
Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > & setRandom(Index size)
Definition: Random.h:151
void test_lazy_l3()
std::ptrdiff_t j
const TC & ref_prod(TC &C, const TA &A, const TB &B)
void product(const MatrixType &m)
Definition: product.h:20


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:35:19