| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  | // This file is part of Eigen, a lightweight C++ template library
 | 
					
						
							|  |  |  | // for linear algebra.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Copyright (C) 2012 Alexey Korepanov <kaikaikai@yandex.ru>
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2012-07-25 00:11:41 +08:00
										 |  |  | // This Source Code Form is subject to the terms of the Mozilla
 | 
					
						
							|  |  |  | // Public License v. 2.0. If a copy of the MPL was not distributed
 | 
					
						
							|  |  |  | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 17:08:44 +08:00
										 |  |  | #define EIGEN_RUNTIME_NO_MALLOC
 | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  | #include "main.h"
 | 
					
						
							|  |  |  | #include <limits>
 | 
					
						
							|  |  |  | #include <Eigen/Eigenvalues>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename MatrixType> | 
					
						
							|  |  |  | void real_qz(const MatrixType& m) { | 
					
						
							|  |  |  |   /* this test covers the following files:
 | 
					
						
							|  |  |  |      RealQZ.h | 
					
						
							|  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2012-11-06 22:25:50 +08:00
										 |  |  |   using std::abs; | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |   Index dim = m.cols(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MatrixType A = MatrixType::Random(dim, dim), B = MatrixType::Random(dim, dim); | 
					
						
							| 
									
										
										
										
											2015-03-31 05:56:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Regression test for bug 985: Randomly set rows or columns to zero
 | 
					
						
							| 
									
										
										
										
											2015-03-31 06:42:14 +08:00
										 |  |  |   Index k = internal::random<Index>(0, dim - 1); | 
					
						
							| 
									
										
										
										
											2015-03-31 05:56:20 +08:00
										 |  |  |   switch (internal::random<int>(0, 10)) { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |       A.row(k).setZero(); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       A.col(k).setZero(); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |       B.row(k).setZero(); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |       B.col(k).setZero(); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 17:08:44 +08:00
										 |  |  |   RealQZ<MatrixType> qz(dim); | 
					
						
							|  |  |  |   // TODO enable full-prealocation of required memory, this probably requires an in-place mode for
 | 
					
						
							|  |  |  |   // HessenbergDecomposition
 | 
					
						
							|  |  |  |   // Eigen::internal::set_is_malloc_allowed(false);
 | 
					
						
							|  |  |  |   qz.compute(A, B); | 
					
						
							|  |  |  |   // Eigen::internal::set_is_malloc_allowed(true);
 | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |   VERIFY_IS_EQUAL(qz.info(), Success); | 
					
						
							|  |  |  |   // check for zeros
 | 
					
						
							|  |  |  |   bool all_zeros = true; | 
					
						
							|  |  |  |   for (Index i = 0; i < A.cols(); i++) | 
					
						
							|  |  |  |     for (Index j = 0; j < i; j++) { | 
					
						
							| 
									
										
										
										
											2022-01-27 02:16:19 +08:00
										 |  |  |       if (!numext::is_exactly_zero(abs(qz.matrixT()(i, j)))) { | 
					
						
							| 
									
										
										
										
											2016-06-11 20:41:53 +08:00
										 |  |  |         std::cerr << "Error: T(" << i << "," << j << ") = " << qz.matrixT()(i, j) << std::endl; | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |         all_zeros = false; | 
					
						
							| 
									
										
										
										
											2016-06-11 20:41:53 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-01-27 02:16:19 +08:00
										 |  |  |       if (j < i - 1 && !numext::is_exactly_zero(abs(qz.matrixS()(i, j)))) { | 
					
						
							| 
									
										
										
										
											2016-06-11 20:41:53 +08:00
										 |  |  |         std::cerr << "Error: S(" << i << "," << j << ") = " << qz.matrixS()(i, j) << std::endl; | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |         all_zeros = false; | 
					
						
							| 
									
										
										
										
											2016-06-11 20:41:53 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-01-27 02:16:19 +08:00
										 |  |  |       if (j == i - 1 && j > 0 && !numext::is_exactly_zero(abs(qz.matrixS()(i, j))) && | 
					
						
							|  |  |  |           !numext::is_exactly_zero(abs(qz.matrixS()(i - 1, j - 1)))) { | 
					
						
							| 
									
										
										
										
											2016-06-11 20:41:53 +08:00
										 |  |  |         std::cerr << "Error: S(" << i << "," << j << ") = " << qz.matrixS()(i, j) << " && S(" << i - 1 << "," << j - 1 | 
					
						
							|  |  |  |                   << ") = " << qz.matrixS()(i - 1, j - 1) << std::endl; | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |         all_zeros = false; | 
					
						
							| 
									
										
										
										
											2016-06-11 20:41:53 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   VERIFY_IS_EQUAL(all_zeros, true); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixS() * qz.matrixZ(), A); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixT() * qz.matrixZ(), B); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixQ().adjoint(), MatrixType::Identity(dim, dim)); | 
					
						
							|  |  |  |   VERIFY_IS_APPROX(qz.matrixZ() * qz.matrixZ().adjoint(), MatrixType::Identity(dim, dim)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 20:46:15 +08:00
										 |  |  | EIGEN_DECLARE_TEST(real_qz) { | 
					
						
							| 
									
										
										
										
											2013-06-24 01:11:32 +08:00
										 |  |  |   int s = 0; | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  |   for (int i = 0; i < g_repeat; i++) { | 
					
						
							|  |  |  |     CALL_SUBTEST_1(real_qz(Matrix4f())); | 
					
						
							|  |  |  |     s = internal::random<int>(1, EIGEN_TEST_MAX_SIZE / 4); | 
					
						
							|  |  |  |     CALL_SUBTEST_2(real_qz(MatrixXd(s, s))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // some trivial but implementation-wise tricky cases
 | 
					
						
							|  |  |  |     CALL_SUBTEST_2(real_qz(MatrixXd(1, 1))); | 
					
						
							|  |  |  |     CALL_SUBTEST_2(real_qz(MatrixXd(2, 2))); | 
					
						
							|  |  |  |     CALL_SUBTEST_3(real_qz(Matrix<double, 1, 1>())); | 
					
						
							|  |  |  |     CALL_SUBTEST_4(real_qz(Matrix2d())); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-12-06 05:22:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 17:42:04 +08:00
										 |  |  |   TEST_SET_BUT_UNUSED_VARIABLE(s) | 
					
						
							| 
									
										
										
										
											2012-07-12 05:38:03 +08:00
										 |  |  | } |