1 // This file is triangularView of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2009 Gael Guennebaud <[email protected]>
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 #ifdef EIGEN_TEST_PART_100
11 # define EIGEN_NO_DEPRECATED_WARNING
12 #endif
13
14 #include "main.h"
15
16
triangular_deprecated(const MatrixType & m)17 template<typename MatrixType> void triangular_deprecated(const MatrixType &m)
18 {
19 Index rows = m.rows();
20 Index cols = m.cols();
21 MatrixType m1, m2, m3, m4;
22 m1.setRandom(rows,cols);
23 m2.setRandom(rows,cols);
24 m3 = m1; m4 = m2;
25 // deprecated method:
26 m1.template triangularView<Eigen::Upper>().swap(m2);
27 // use this method instead:
28 m3.template triangularView<Eigen::Upper>().swap(m4.template triangularView<Eigen::Upper>());
29 VERIFY_IS_APPROX(m1,m3);
30 VERIFY_IS_APPROX(m2,m4);
31 // deprecated method:
32 m1.template triangularView<Eigen::Lower>().swap(m4);
33 // use this method instead:
34 m3.template triangularView<Eigen::Lower>().swap(m2.template triangularView<Eigen::Lower>());
35 VERIFY_IS_APPROX(m1,m3);
36 VERIFY_IS_APPROX(m2,m4);
37 }
38
39
triangular_square(const MatrixType & m)40 template<typename MatrixType> void triangular_square(const MatrixType& m)
41 {
42 typedef typename MatrixType::Scalar Scalar;
43 typedef typename NumTraits<Scalar>::Real RealScalar;
44 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
45
46 RealScalar largerEps = 10*test_precision<RealScalar>();
47
48 Index rows = m.rows();
49 Index cols = m.cols();
50
51 MatrixType m1 = MatrixType::Random(rows, cols),
52 m2 = MatrixType::Random(rows, cols),
53 m3(rows, cols),
54 m4(rows, cols),
55 r1(rows, cols),
56 r2(rows, cols);
57 VectorType v2 = VectorType::Random(rows);
58
59 MatrixType m1up = m1.template triangularView<Upper>();
60 MatrixType m2up = m2.template triangularView<Upper>();
61
62 if (rows*cols>1)
63 {
64 VERIFY(m1up.isUpperTriangular());
65 VERIFY(m2up.transpose().isLowerTriangular());
66 VERIFY(!m2.isLowerTriangular());
67 }
68
69 // VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);
70
71 // test overloaded operator+=
72 r1.setZero();
73 r2.setZero();
74 r1.template triangularView<Upper>() += m1;
75 r2 += m1up;
76 VERIFY_IS_APPROX(r1,r2);
77
78 // test overloaded operator=
79 m1.setZero();
80 m1.template triangularView<Upper>() = m2.transpose() + m2;
81 m3 = m2.transpose() + m2;
82 VERIFY_IS_APPROX(m3.template triangularView<Lower>().transpose().toDenseMatrix(), m1);
83
84 // test overloaded operator=
85 m1.setZero();
86 m1.template triangularView<Lower>() = m2.transpose() + m2;
87 VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);
88
89 VERIFY_IS_APPROX(m3.template triangularView<Lower>().conjugate().toDenseMatrix(),
90 m3.conjugate().template triangularView<Lower>().toDenseMatrix());
91
92 m1 = MatrixType::Random(rows, cols);
93 for (int i=0; i<rows; ++i)
94 while (numext::abs2(m1(i,i))<RealScalar(1e-1)) m1(i,i) = internal::random<Scalar>();
95
96 Transpose<MatrixType> trm4(m4);
97 // test back and forward substitution with a vector as the rhs
98 m3 = m1.template triangularView<Upper>();
99 VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(v2)), largerEps));
100 m3 = m1.template triangularView<Lower>();
101 VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(v2)), largerEps));
102 m3 = m1.template triangularView<Upper>();
103 VERIFY(v2.isApprox(m3 * (m1.template triangularView<Upper>().solve(v2)), largerEps));
104 m3 = m1.template triangularView<Lower>();
105 VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(v2)), largerEps));
106
107 // test back and forward substitution with a matrix as the rhs
108 m3 = m1.template triangularView<Upper>();
109 VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(m2)), largerEps));
110 m3 = m1.template triangularView<Lower>();
111 VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(m2)), largerEps));
112 m3 = m1.template triangularView<Upper>();
113 VERIFY(m2.isApprox(m3 * (m1.template triangularView<Upper>().solve(m2)), largerEps));
114 m3 = m1.template triangularView<Lower>();
115 VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(m2)), largerEps));
116
117 // check M * inv(L) using in place API
118 m4 = m3;
119 m1.transpose().template triangularView<Eigen::Upper>().solveInPlace(trm4);
120 VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Lower>(), m3);
121
122 // check M * inv(U) using in place API
123 m3 = m1.template triangularView<Upper>();
124 m4 = m3;
125 m3.transpose().template triangularView<Eigen::Lower>().solveInPlace(trm4);
126 VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Upper>(), m3);
127
128 // check solve with unit diagonal
129 m3 = m1.template triangularView<UnitUpper>();
130 VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpper>().solve(m2)), largerEps));
131
132 // VERIFY(( m1.template triangularView<Upper>()
133 // * m2.template triangularView<Upper>()).isUpperTriangular());
134
135 // test swap
136 m1.setOnes();
137 m2.setZero();
138 m2.template triangularView<Upper>().swap(m1.template triangularView<Eigen::Upper>());
139 m3.setZero();
140 m3.template triangularView<Upper>().setOnes();
141 VERIFY_IS_APPROX(m2,m3);
142 VERIFY_RAISES_STATIC_ASSERT(m1.template triangularView<Eigen::Lower>().swap(m2.template triangularView<Eigen::Upper>()));
143
144 m1.setRandom();
145 m3 = m1.template triangularView<Upper>();
146 Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic> m5(cols, internal::random<int>(1,20)); m5.setRandom();
147 Matrix<Scalar, Dynamic, MatrixType::RowsAtCompileTime> m6(internal::random<int>(1,20), rows); m6.setRandom();
148 VERIFY_IS_APPROX(m1.template triangularView<Upper>() * m5, m3*m5);
149 VERIFY_IS_APPROX(m6*m1.template triangularView<Upper>(), m6*m3);
150
151 m1up = m1.template triangularView<Upper>();
152 VERIFY_IS_APPROX(m1.template selfadjointView<Upper>().template triangularView<Upper>().toDenseMatrix(), m1up);
153 VERIFY_IS_APPROX(m1up.template selfadjointView<Upper>().template triangularView<Upper>().toDenseMatrix(), m1up);
154 VERIFY_IS_APPROX(m1.template selfadjointView<Upper>().template triangularView<Lower>().toDenseMatrix(), m1up.adjoint());
155 VERIFY_IS_APPROX(m1up.template selfadjointView<Upper>().template triangularView<Lower>().toDenseMatrix(), m1up.adjoint());
156
157 VERIFY_IS_APPROX(m1.template selfadjointView<Upper>().diagonal(), m1.diagonal());
158
159 m3.setRandom();
160 const MatrixType& m3c(m3);
161 VERIFY( is_same_type(m3c.template triangularView<Lower>(),m3.template triangularView<Lower>().template conjugateIf<false>()) );
162 VERIFY( is_same_type(m3c.template triangularView<Lower>().conjugate(),m3.template triangularView<Lower>().template conjugateIf<true>()) );
163 VERIFY_IS_APPROX(m3.template triangularView<Lower>().template conjugateIf<true>().toDenseMatrix(),
164 m3.conjugate().template triangularView<Lower>().toDenseMatrix());
165 VERIFY_IS_APPROX(m3.template triangularView<Lower>().template conjugateIf<false>().toDenseMatrix(),
166 m3.template triangularView<Lower>().toDenseMatrix());
167
168 VERIFY( is_same_type(m3c.template selfadjointView<Lower>(),m3.template selfadjointView<Lower>().template conjugateIf<false>()) );
169 VERIFY( is_same_type(m3c.template selfadjointView<Lower>().conjugate(),m3.template selfadjointView<Lower>().template conjugateIf<true>()) );
170 VERIFY_IS_APPROX(m3.template selfadjointView<Lower>().template conjugateIf<true>().toDenseMatrix(),
171 m3.conjugate().template selfadjointView<Lower>().toDenseMatrix());
172 VERIFY_IS_APPROX(m3.template selfadjointView<Lower>().template conjugateIf<false>().toDenseMatrix(),
173 m3.template selfadjointView<Lower>().toDenseMatrix());
174
175 }
176
177
triangular_rect(const MatrixType & m)178 template<typename MatrixType> void triangular_rect(const MatrixType& m)
179 {
180 typedef typename MatrixType::Scalar Scalar;
181 typedef typename NumTraits<Scalar>::Real RealScalar;
182 enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
183
184 Index rows = m.rows();
185 Index cols = m.cols();
186
187 MatrixType m1 = MatrixType::Random(rows, cols),
188 m2 = MatrixType::Random(rows, cols),
189 m3(rows, cols),
190 m4(rows, cols),
191 r1(rows, cols),
192 r2(rows, cols);
193
194 MatrixType m1up = m1.template triangularView<Upper>();
195 MatrixType m2up = m2.template triangularView<Upper>();
196
197 if (rows>1 && cols>1)
198 {
199 VERIFY(m1up.isUpperTriangular());
200 VERIFY(m2up.transpose().isLowerTriangular());
201 VERIFY(!m2.isLowerTriangular());
202 }
203
204 // test overloaded operator+=
205 r1.setZero();
206 r2.setZero();
207 r1.template triangularView<Upper>() += m1;
208 r2 += m1up;
209 VERIFY_IS_APPROX(r1,r2);
210
211 // test overloaded operator=
212 m1.setZero();
213 m1.template triangularView<Upper>() = 3 * m2;
214 m3 = 3 * m2;
215 VERIFY_IS_APPROX(m3.template triangularView<Upper>().toDenseMatrix(), m1);
216
217
218 m1.setZero();
219 m1.template triangularView<Lower>() = 3 * m2;
220 VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);
221
222 m1.setZero();
223 m1.template triangularView<StrictlyUpper>() = 3 * m2;
224 VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpper>().toDenseMatrix(), m1);
225
226
227 m1.setZero();
228 m1.template triangularView<StrictlyLower>() = 3 * m2;
229 VERIFY_IS_APPROX(m3.template triangularView<StrictlyLower>().toDenseMatrix(), m1);
230 m1.setRandom();
231 m2 = m1.template triangularView<Upper>();
232 VERIFY(m2.isUpperTriangular());
233 VERIFY(!m2.isLowerTriangular());
234 m2 = m1.template triangularView<StrictlyUpper>();
235 VERIFY(m2.isUpperTriangular());
236 VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
237 m2 = m1.template triangularView<UnitUpper>();
238 VERIFY(m2.isUpperTriangular());
239 m2.diagonal().array() -= Scalar(1);
240 VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
241 m2 = m1.template triangularView<Lower>();
242 VERIFY(m2.isLowerTriangular());
243 VERIFY(!m2.isUpperTriangular());
244 m2 = m1.template triangularView<StrictlyLower>();
245 VERIFY(m2.isLowerTriangular());
246 VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
247 m2 = m1.template triangularView<UnitLower>();
248 VERIFY(m2.isLowerTriangular());
249 m2.diagonal().array() -= Scalar(1);
250 VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
251 // test swap
252 m1.setOnes();
253 m2.setZero();
254 m2.template triangularView<Upper>().swap(m1.template triangularView<Eigen::Upper>());
255 m3.setZero();
256 m3.template triangularView<Upper>().setOnes();
257 VERIFY_IS_APPROX(m2,m3);
258 }
259
bug_159()260 void bug_159()
261 {
262 Matrix3d m = Matrix3d::Random().triangularView<Lower>();
263 EIGEN_UNUSED_VARIABLE(m)
264 }
265
EIGEN_DECLARE_TEST(triangular)266 EIGEN_DECLARE_TEST(triangular)
267 {
268 int maxsize = (std::min)(EIGEN_TEST_MAX_SIZE,20);
269 for(int i = 0; i < g_repeat ; i++)
270 {
271 int r = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(r)
272 int c = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(c)
273
274 CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
275 CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
276 CALL_SUBTEST_3( triangular_square(Matrix3d()) );
277 CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) );
278 CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) );
279 CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) );
280
281 CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) );
282 CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) );
283 CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) );
284 CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) );
285 CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) );
286
287 CALL_SUBTEST_100( triangular_deprecated(Matrix<float, 5, 7>()) );
288 CALL_SUBTEST_100( triangular_deprecated(MatrixXd(r,c)) );
289 }
290
291 CALL_SUBTEST_1( bug_159() );
292 }
293