blob: 2e532f7a599fbfbb9565cdc5bd22604362a3254c [file] [log] [blame]
Brian Silverman72890c22015-09-19 14:37:37 -04001// 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
12#include "main.h"
13
14template<typename MatrixType> void basicStuff(const MatrixType& m)
15{
Brian Silverman72890c22015-09-19 14:37:37 -040016 typedef typename MatrixType::Scalar Scalar;
17 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
18 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
19
20 Index rows = m.rows();
21 Index cols = m.cols();
22
23 // this test relies a lot on Random.h, and there's not much more that we can do
24 // to test it, hence I consider that we will have tested Random.h
25 MatrixType m1 = MatrixType::Random(rows, cols),
26 m2 = MatrixType::Random(rows, cols),
27 m3(rows, cols),
28 mzero = MatrixType::Zero(rows, cols),
29 square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows);
30 VectorType v1 = VectorType::Random(rows),
31 vzero = VectorType::Zero(rows);
32 SquareMatrixType sm1 = SquareMatrixType::Random(rows,rows), sm2(rows,rows);
33
34 Scalar x = 0;
35 while(x == Scalar(0)) x = internal::random<Scalar>();
36
37 Index r = internal::random<Index>(0, rows-1),
38 c = internal::random<Index>(0, cols-1);
39
40 m1.coeffRef(r,c) = x;
41 VERIFY_IS_APPROX(x, m1.coeff(r,c));
42 m1(r,c) = x;
43 VERIFY_IS_APPROX(x, m1(r,c));
44 v1.coeffRef(r) = x;
45 VERIFY_IS_APPROX(x, v1.coeff(r));
46 v1(r) = x;
47 VERIFY_IS_APPROX(x, v1(r));
48 v1[r] = x;
49 VERIFY_IS_APPROX(x, v1[r]);
50
51 VERIFY_IS_APPROX( v1, v1);
52 VERIFY_IS_NOT_APPROX( v1, 2*v1);
53 VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1);
54 VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.squaredNorm());
55 VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1, v1);
56 VERIFY_IS_APPROX( vzero, v1-v1);
57 VERIFY_IS_APPROX( m1, m1);
58 VERIFY_IS_NOT_APPROX( m1, 2*m1);
59 VERIFY_IS_MUCH_SMALLER_THAN( mzero, m1);
60 VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1, m1);
61 VERIFY_IS_APPROX( mzero, m1-m1);
62
63 // always test operator() on each read-only expression class,
64 // in order to check const-qualifiers.
65 // indeed, if an expression class (here Zero) is meant to be read-only,
66 // hence has no _write() method, the corresponding MatrixBase method (here zero())
67 // should return a const-qualified object so that it is the const-qualified
68 // operator() that gets called, which in turn calls _read().
69 VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1));
70
71 // now test copying a row-vector into a (column-)vector and conversely.
72 square.col(r) = square.row(r).eval();
73 Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows);
74 Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows);
75 rv = square.row(r);
76 cv = square.col(r);
77
78 VERIFY_IS_APPROX(rv, cv.transpose());
79
80 if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic)
81 {
82 VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1)));
83 }
84
85 if(cols!=1 && rows!=1)
86 {
87 VERIFY_RAISES_ASSERT(m1[0]);
88 VERIFY_RAISES_ASSERT((m1+m1)[0]);
89 }
90
91 VERIFY_IS_APPROX(m3 = m1,m1);
92 MatrixType m4;
93 VERIFY_IS_APPROX(m4 = m1,m1);
94
95 m3.real() = m1.real();
96 VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real());
97 VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real());
98
99 // check == / != operators
100 VERIFY(m1==m1);
101 VERIFY(m1!=m2);
102 VERIFY(!(m1==m2));
103 VERIFY(!(m1!=m1));
104 m1 = m2;
105 VERIFY(m1==m2);
106 VERIFY(!(m1!=m2));
107
108 // check automatic transposition
109 sm2.setZero();
110 for(typename MatrixType::Index i=0;i<rows;++i)
111 sm2.col(i) = sm1.row(i);
112 VERIFY_IS_APPROX(sm2,sm1.transpose());
113
114 sm2.setZero();
115 for(typename MatrixType::Index i=0;i<rows;++i)
116 sm2.col(i).noalias() = sm1.row(i);
117 VERIFY_IS_APPROX(sm2,sm1.transpose());
118
119 sm2.setZero();
120 for(typename MatrixType::Index i=0;i<rows;++i)
121 sm2.col(i).noalias() += sm1.row(i);
122 VERIFY_IS_APPROX(sm2,sm1.transpose());
123
124 sm2.setZero();
125 for(typename MatrixType::Index i=0;i<rows;++i)
126 sm2.col(i).noalias() -= sm1.row(i);
127 VERIFY_IS_APPROX(sm2,-sm1.transpose());
Austin Schuh189376f2018-12-20 22:11:15 +1100128
129 // check ternary usage
130 {
131 bool b = internal::random<int>(0,10)>5;
132 m3 = b ? m1 : m2;
133 if(b) VERIFY_IS_APPROX(m3,m1);
134 else VERIFY_IS_APPROX(m3,m2);
135 m3 = b ? -m1 : m2;
136 if(b) VERIFY_IS_APPROX(m3,-m1);
137 else VERIFY_IS_APPROX(m3,m2);
138 m3 = b ? m1 : -m2;
139 if(b) VERIFY_IS_APPROX(m3,m1);
140 else VERIFY_IS_APPROX(m3,-m2);
141 }
Brian Silverman72890c22015-09-19 14:37:37 -0400142}
143
144template<typename MatrixType> void basicStuffComplex(const MatrixType& m)
145{
Brian Silverman72890c22015-09-19 14:37:37 -0400146 typedef typename MatrixType::Scalar Scalar;
147 typedef typename NumTraits<Scalar>::Real RealScalar;
148 typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> RealMatrixType;
149
150 Index rows = m.rows();
151 Index cols = m.cols();
152
153 Scalar s1 = internal::random<Scalar>(),
154 s2 = internal::random<Scalar>();
155
156 VERIFY(numext::real(s1)==numext::real_ref(s1));
157 VERIFY(numext::imag(s1)==numext::imag_ref(s1));
158 numext::real_ref(s1) = numext::real(s2);
159 numext::imag_ref(s1) = numext::imag(s2);
160 VERIFY(internal::isApprox(s1, s2, NumTraits<RealScalar>::epsilon()));
161 // extended precision in Intel FPUs means that s1 == s2 in the line above is not guaranteed.
162
163 RealMatrixType rm1 = RealMatrixType::Random(rows,cols),
164 rm2 = RealMatrixType::Random(rows,cols);
165 MatrixType cm(rows,cols);
166 cm.real() = rm1;
167 cm.imag() = rm2;
168 VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).real(), rm1);
169 VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).imag(), rm2);
170 rm1.setZero();
171 rm2.setZero();
172 rm1 = cm.real();
173 rm2 = cm.imag();
174 VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).real(), rm1);
175 VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).imag(), rm2);
176 cm.real().setZero();
177 VERIFY(static_cast<const MatrixType&>(cm).real().isZero());
178 VERIFY(!static_cast<const MatrixType&>(cm).imag().isZero());
179}
180
181#ifdef EIGEN_TEST_PART_2
182void casting()
183{
184 Matrix4f m = Matrix4f::Random(), m2;
185 Matrix4d n = m.cast<double>();
186 VERIFY(m.isApprox(n.cast<float>()));
187 m2 = m.cast<float>(); // check the specialization when NewType == Type
188 VERIFY(m.isApprox(m2));
189}
190#endif
191
192template <typename Scalar>
193void fixedSizeMatrixConstruction()
194{
Austin Schuh189376f2018-12-20 22:11:15 +1100195 Scalar raw[4];
196 for(int k=0; k<4; ++k)
197 raw[k] = internal::random<Scalar>();
198
199 {
200 Matrix<Scalar,4,1> m(raw);
201 Array<Scalar,4,1> a(raw);
202 for(int k=0; k<4; ++k) VERIFY(m(k) == raw[k]);
203 for(int k=0; k<4; ++k) VERIFY(a(k) == raw[k]);
204 VERIFY_IS_EQUAL(m,(Matrix<Scalar,4,1>(raw[0],raw[1],raw[2],raw[3])));
205 VERIFY((a==(Array<Scalar,4,1>(raw[0],raw[1],raw[2],raw[3]))).all());
206 }
207 {
208 Matrix<Scalar,3,1> m(raw);
209 Array<Scalar,3,1> a(raw);
210 for(int k=0; k<3; ++k) VERIFY(m(k) == raw[k]);
211 for(int k=0; k<3; ++k) VERIFY(a(k) == raw[k]);
212 VERIFY_IS_EQUAL(m,(Matrix<Scalar,3,1>(raw[0],raw[1],raw[2])));
213 VERIFY((a==Array<Scalar,3,1>(raw[0],raw[1],raw[2])).all());
214 }
215 {
216 Matrix<Scalar,2,1> m(raw), m2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) );
217 Array<Scalar,2,1> a(raw), a2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) );
218 for(int k=0; k<2; ++k) VERIFY(m(k) == raw[k]);
219 for(int k=0; k<2; ++k) VERIFY(a(k) == raw[k]);
220 VERIFY_IS_EQUAL(m,(Matrix<Scalar,2,1>(raw[0],raw[1])));
221 VERIFY((a==Array<Scalar,2,1>(raw[0],raw[1])).all());
222 for(int k=0; k<2; ++k) VERIFY(m2(k) == DenseIndex(raw[k]));
223 for(int k=0; k<2; ++k) VERIFY(a2(k) == DenseIndex(raw[k]));
224 }
225 {
226 Matrix<Scalar,1,2> m(raw),
227 m2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) ),
228 m3( (int(raw[0])), (int(raw[1])) ),
229 m4( (float(raw[0])), (float(raw[1])) );
230 Array<Scalar,1,2> a(raw), a2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) );
231 for(int k=0; k<2; ++k) VERIFY(m(k) == raw[k]);
232 for(int k=0; k<2; ++k) VERIFY(a(k) == raw[k]);
233 VERIFY_IS_EQUAL(m,(Matrix<Scalar,1,2>(raw[0],raw[1])));
234 VERIFY((a==Array<Scalar,1,2>(raw[0],raw[1])).all());
235 for(int k=0; k<2; ++k) VERIFY(m2(k) == DenseIndex(raw[k]));
236 for(int k=0; k<2; ++k) VERIFY(a2(k) == DenseIndex(raw[k]));
237 for(int k=0; k<2; ++k) VERIFY(m3(k) == int(raw[k]));
238 for(int k=0; k<2; ++k) VERIFY((m4(k)) == Scalar(float(raw[k])));
239 }
240 {
241 Matrix<Scalar,1,1> m(raw), m1(raw[0]), m2( (DenseIndex(raw[0])) ), m3( (int(raw[0])) );
242 Array<Scalar,1,1> a(raw), a1(raw[0]), a2( (DenseIndex(raw[0])) );
243 VERIFY(m(0) == raw[0]);
244 VERIFY(a(0) == raw[0]);
245 VERIFY(m1(0) == raw[0]);
246 VERIFY(a1(0) == raw[0]);
247 VERIFY(m2(0) == DenseIndex(raw[0]));
248 VERIFY(a2(0) == DenseIndex(raw[0]));
249 VERIFY(m3(0) == int(raw[0]));
250 VERIFY_IS_EQUAL(m,(Matrix<Scalar,1,1>(raw[0])));
251 VERIFY((a==Array<Scalar,1,1>(raw[0])).all());
252 }
Brian Silverman72890c22015-09-19 14:37:37 -0400253}
254
255void test_basicstuff()
256{
257 for(int i = 0; i < g_repeat; i++) {
258 CALL_SUBTEST_1( basicStuff(Matrix<float, 1, 1>()) );
259 CALL_SUBTEST_2( basicStuff(Matrix4d()) );
260 CALL_SUBTEST_3( basicStuff(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
261 CALL_SUBTEST_4( basicStuff(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
262 CALL_SUBTEST_5( basicStuff(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
263 CALL_SUBTEST_6( basicStuff(Matrix<float, 100, 100>()) );
264 CALL_SUBTEST_7( basicStuff(Matrix<long double,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
265
266 CALL_SUBTEST_3( basicStuffComplex(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
267 CALL_SUBTEST_5( basicStuffComplex(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
268 }
269
270 CALL_SUBTEST_1(fixedSizeMatrixConstruction<unsigned char>());
Austin Schuh189376f2018-12-20 22:11:15 +1100271 CALL_SUBTEST_1(fixedSizeMatrixConstruction<float>());
Brian Silverman72890c22015-09-19 14:37:37 -0400272 CALL_SUBTEST_1(fixedSizeMatrixConstruction<double>());
Austin Schuh189376f2018-12-20 22:11:15 +1100273 CALL_SUBTEST_1(fixedSizeMatrixConstruction<int>());
274 CALL_SUBTEST_1(fixedSizeMatrixConstruction<long int>());
275 CALL_SUBTEST_1(fixedSizeMatrixConstruction<std::ptrdiff_t>());
Brian Silverman72890c22015-09-19 14:37:37 -0400276
277 CALL_SUBTEST_2(casting());
278}