1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #define EIGEN_SCALAR_BINARY_OP_PLUGIN { g_called |= (!internal::is_same<LhsScalar,RhsScalar>::value); }
16 template<typename MatrixType
> void linearStructure(const MatrixType
& m
)
19 /* this test covers the following files:
20 CwiseUnaryOp.h, CwiseBinaryOp.h, SelfCwiseBinaryOp.h
22 typedef typename
MatrixType::Index Index
;
23 typedef typename
MatrixType::Scalar Scalar
;
24 typedef typename
MatrixType::RealScalar RealScalar
;
26 Index rows
= m
.rows();
27 Index cols
= m
.cols();
29 // this test relies a lot on Random.h, and there's not much more that we can do
30 // to test it, hence I consider that we will have tested Random.h
31 MatrixType m1
= MatrixType::Random(rows
, cols
),
32 m2
= MatrixType::Random(rows
, cols
),
35 Scalar s1
= internal::random
<Scalar
>();
36 while (abs(s1
)<RealScalar(1e-3)) s1
= internal::random
<Scalar
>();
38 Index r
= internal::random
<Index
>(0, rows
-1),
39 c
= internal::random
<Index
>(0, cols
-1);
41 VERIFY_IS_APPROX(-(-m1
), m1
);
42 VERIFY_IS_APPROX(m1
+m1
, 2*m1
);
43 VERIFY_IS_APPROX(m1
+m2
-m1
, m2
);
44 VERIFY_IS_APPROX(-m2
+m1
+m2
, m1
);
45 VERIFY_IS_APPROX(m1
*s1
, s1
*m1
);
46 VERIFY_IS_APPROX((m1
+m2
)*s1
, s1
*m1
+s1
*m2
);
47 VERIFY_IS_APPROX((-m1
+m2
)*s1
, -s1
*m1
+s1
*m2
);
49 VERIFY_IS_APPROX(m3
, m1
+m2
);
51 VERIFY_IS_APPROX(m3
, m2
-m1
);
53 VERIFY_IS_APPROX(m3
, s1
*m2
);
54 if(!NumTraits
<Scalar
>::IsInteger
)
57 VERIFY_IS_APPROX(m3
, m2
/s1
);
60 // again, test operator() to check const-qualification
61 VERIFY_IS_APPROX((-m1
)(r
,c
), -(m1(r
,c
)));
62 VERIFY_IS_APPROX((m1
-m2
)(r
,c
), (m1(r
,c
))-(m2(r
,c
)));
63 VERIFY_IS_APPROX((m1
+m2
)(r
,c
), (m1(r
,c
))+(m2(r
,c
)));
64 VERIFY_IS_APPROX((s1
*m1
)(r
,c
), s1
*(m1(r
,c
)));
65 VERIFY_IS_APPROX((m1
*s1
)(r
,c
), (m1(r
,c
))*s1
);
66 if(!NumTraits
<Scalar
>::IsInteger
)
67 VERIFY_IS_APPROX((m1
/s1
)(r
,c
), (m1(r
,c
))/s1
);
69 // use .block to disable vectorization and compare to the vectorized version
70 VERIFY_IS_APPROX(m1
+m1
.block(0,0,rows
,cols
), m1
+m1
);
71 VERIFY_IS_APPROX(m1
.cwiseProduct(m1
.block(0,0,rows
,cols
)), m1
.cwiseProduct(m1
));
72 VERIFY_IS_APPROX(m1
- m1
.block(0,0,rows
,cols
), m1
- m1
);
73 VERIFY_IS_APPROX(m1
.block(0,0,rows
,cols
) * s1
, m1
* s1
);
76 // Make sure that complex * real and real * complex are properly optimized
77 template<typename MatrixType
> void real_complex(DenseIndex rows
= MatrixType::RowsAtCompileTime
, DenseIndex cols
= MatrixType::ColsAtCompileTime
)
79 typedef typename
MatrixType::Scalar Scalar
;
80 typedef typename
MatrixType::RealScalar RealScalar
;
82 RealScalar s
= internal::random
<RealScalar
>();
83 MatrixType m1
= MatrixType::Random(rows
, cols
);
86 VERIFY_IS_APPROX(s
*m1
, Scalar(s
)*m1
);
87 VERIFY(g_called
&& "real * matrix<complex> not properly optimized");
90 VERIFY_IS_APPROX(m1
*s
, m1
*Scalar(s
));
91 VERIFY(g_called
&& "matrix<complex> * real not properly optimized");
94 VERIFY_IS_APPROX(m1
/s
, m1
/Scalar(s
));
95 VERIFY(g_called
&& "matrix<complex> / real not properly optimized");
98 VERIFY_IS_APPROX(s
+m1
.array(), Scalar(s
)+m1
.array());
99 VERIFY(g_called
&& "real + matrix<complex> not properly optimized");
102 VERIFY_IS_APPROX(m1
.array()+s
, m1
.array()+Scalar(s
));
103 VERIFY(g_called
&& "matrix<complex> + real not properly optimized");
106 VERIFY_IS_APPROX(s
-m1
.array(), Scalar(s
)-m1
.array());
107 VERIFY(g_called
&& "real - matrix<complex> not properly optimized");
110 VERIFY_IS_APPROX(m1
.array()-s
, m1
.array()-Scalar(s
));
111 VERIFY(g_called
&& "matrix<complex> - real not properly optimized");
114 void test_linearstructure()
117 VERIFY(g_called
); // avoid `unneeded-internal-declaration` warning.
118 for(int i
= 0; i
< g_repeat
; i
++) {
119 CALL_SUBTEST_1( linearStructure(Matrix
<float, 1, 1>()) );
120 CALL_SUBTEST_2( linearStructure(Matrix2f()) );
121 CALL_SUBTEST_3( linearStructure(Vector3d()) );
122 CALL_SUBTEST_4( linearStructure(Matrix4d()) );
123 CALL_SUBTEST_5( linearStructure(MatrixXcf(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2))) );
124 CALL_SUBTEST_6( linearStructure(MatrixXf (internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
125 CALL_SUBTEST_7( linearStructure(MatrixXi (internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
126 CALL_SUBTEST_8( linearStructure(MatrixXcd(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2))) );
127 CALL_SUBTEST_9( linearStructure(ArrayXXf (internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
128 CALL_SUBTEST_10( linearStructure(ArrayXXcf (internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
), internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
130 CALL_SUBTEST_11( real_complex
<Matrix4cd
>() );
131 CALL_SUBTEST_11( real_complex
<MatrixXcf
>(10,10) );
132 CALL_SUBTEST_11( real_complex
<ArrayXXcf
>(10,10) );
135 #ifdef EIGEN_TEST_PART_4
137 // make sure that /=scalar and /scalar do not overflow
138 // rational: 1.0/4.94e-320 overflow, but m/4.94e-320 should not
140 m3
= m2
= Matrix4d::Random()*1e-20;
142 VERIFY_IS_APPROX(m2
.cwiseQuotient(m2
), Matrix4d::Ones());
144 VERIFY_IS_APPROX(m3
.cwiseQuotient(m3
), Matrix4d::Ones());