1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
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/.
12 #include <Eigen/Eigenvalues>
14 template<typename MatrixType
> void verifyIsQuasiTriangular(const MatrixType
& T
)
16 typedef typename
MatrixType::Index Index
;
18 const Index size
= T
.cols();
19 typedef typename
MatrixType::Scalar Scalar
;
21 // Check T is lower Hessenberg
22 for(int row
= 2; row
< size
; ++row
) {
23 for(int col
= 0; col
< row
- 1; ++col
) {
24 VERIFY(T(row
,col
) == Scalar(0));
28 // Check that any non-zero on the subdiagonal is followed by a zero and is
29 // part of a 2x2 diagonal block with imaginary eigenvalues.
30 for(int row
= 1; row
< size
; ++row
) {
31 if (T(row
,row
-1) != Scalar(0)) {
32 VERIFY(row
== size
-1 || T(row
+1,row
) == 0);
33 Scalar tr
= T(row
-1,row
-1) + T(row
,row
);
34 Scalar det
= T(row
-1,row
-1) * T(row
,row
) - T(row
-1,row
) * T(row
,row
-1);
35 VERIFY(4 * det
> tr
* tr
);
40 template<typename MatrixType
> void schur(int size
= MatrixType::ColsAtCompileTime
)
42 // Test basic functionality: T is quasi-triangular and A = U T U*
43 for(int counter
= 0; counter
< g_repeat
; ++counter
) {
44 MatrixType A
= MatrixType::Random(size
, size
);
45 RealSchur
<MatrixType
> schurOfA(A
);
46 VERIFY_IS_EQUAL(schurOfA
.info(), Success
);
47 MatrixType U
= schurOfA
.matrixU();
48 MatrixType T
= schurOfA
.matrixT();
49 verifyIsQuasiTriangular(T
);
50 VERIFY_IS_APPROX(A
, U
* T
* U
.transpose());
53 // Test asserts when not initialized
54 RealSchur
<MatrixType
> rsUninitialized
;
55 VERIFY_RAISES_ASSERT(rsUninitialized
.matrixT());
56 VERIFY_RAISES_ASSERT(rsUninitialized
.matrixU());
57 VERIFY_RAISES_ASSERT(rsUninitialized
.info());
59 // Test whether compute() and constructor returns same result
60 MatrixType A
= MatrixType::Random(size
, size
);
61 RealSchur
<MatrixType
> rs1
;
63 RealSchur
<MatrixType
> rs2(A
);
64 VERIFY_IS_EQUAL(rs1
.info(), Success
);
65 VERIFY_IS_EQUAL(rs2
.info(), Success
);
66 VERIFY_IS_EQUAL(rs1
.matrixT(), rs2
.matrixT());
67 VERIFY_IS_EQUAL(rs1
.matrixU(), rs2
.matrixU());
69 // Test maximum number of iterations
70 RealSchur
<MatrixType
> rs3
;
71 rs3
.setMaxIterations(RealSchur
<MatrixType
>::m_maxIterationsPerRow
* size
).compute(A
);
72 VERIFY_IS_EQUAL(rs3
.info(), Success
);
73 VERIFY_IS_EQUAL(rs3
.matrixT(), rs1
.matrixT());
74 VERIFY_IS_EQUAL(rs3
.matrixU(), rs1
.matrixU());
76 rs3
.setMaxIterations(1).compute(A
);
77 VERIFY_IS_EQUAL(rs3
.info(), NoConvergence
);
78 VERIFY_IS_EQUAL(rs3
.getMaxIterations(), 1);
81 MatrixType Atriangular
= A
;
82 Atriangular
.template triangularView
<StrictlyLower
>().setZero();
83 rs3
.setMaxIterations(1).compute(Atriangular
); // triangular matrices do not need any iterations
84 VERIFY_IS_EQUAL(rs3
.info(), Success
);
85 VERIFY_IS_APPROX(rs3
.matrixT(), Atriangular
); // approx because of scaling...
86 VERIFY_IS_EQUAL(rs3
.matrixU(), MatrixType::Identity(size
, size
));
88 // Test computation of only T, not U
89 RealSchur
<MatrixType
> rsOnlyT(A
, false);
90 VERIFY_IS_EQUAL(rsOnlyT
.info(), Success
);
91 VERIFY_IS_EQUAL(rs1
.matrixT(), rsOnlyT
.matrixT());
92 VERIFY_RAISES_ASSERT(rsOnlyT
.matrixU());
94 if (size
> 2 && size
< 20)
96 // Test matrix with NaN
97 A(0,0) = std::numeric_limits
<typename
MatrixType::Scalar
>::quiet_NaN();
98 RealSchur
<MatrixType
> rsNaN(A
);
99 VERIFY_IS_EQUAL(rsNaN
.info(), NoConvergence
);
103 void test_schur_real()
105 CALL_SUBTEST_1(( schur
<Matrix4f
>() ));
106 CALL_SUBTEST_2(( schur
<MatrixXd
>(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/4)) ));
107 CALL_SUBTEST_3(( schur
<Matrix
<float, 1, 1> >() ));
108 CALL_SUBTEST_4(( schur
<Matrix
<double, 3, 3, Eigen::RowMajor
> >() ));
110 // Test problem size constructors
111 CALL_SUBTEST_5(RealSchur
<MatrixXf
>(10));