| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | // This file is part of Eigen, a lightweight C++ template library
 | 
					
						
							| 
									
										
										
										
											2009-05-23 02:25:33 +08:00
										 |  |  | // for linear algebra.
 | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-06-25 05:21:58 +08:00
										 |  |  | // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
 | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2012-07-14 02:42:47 +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/.
 | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "main.h"
 | 
					
						
							|  |  |  | #include <Eigen/QR>
 | 
					
						
							| 
									
										
										
										
											2019-01-17 08:17:39 +08:00
										 |  |  | #include "solverbase.h"
 | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | template <typename MatrixType> | 
					
						
							|  |  |  | void qr(const MatrixType& m) { | 
					
						
							| 
									
										
										
										
											2010-06-20 23:37:56 +08:00
										 |  |  |   Index rows = m.rows(); | 
					
						
							|  |  |  |   Index cols = m.cols(); | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   typedef typename MatrixType::Scalar Scalar; | 
					
						
							| 
									
										
										
										
											2009-10-13 10:33:51 +08:00
										 |  |  |   typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType; | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-21 08:34:46 +08:00
										 |  |  |   MatrixType a = MatrixType::Random(rows, cols); | 
					
						
							| 
									
										
										
										
											2009-07-06 23:12:10 +08:00
										 |  |  |   HouseholderQR<MatrixType> qrOfA(a); | 
					
						
							| 
									
										
										
										
											2010-06-18 00:30:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-03 00:11:09 +08:00
										 |  |  |   MatrixQType q = qrOfA.householderQ(); | 
					
						
							| 
									
										
										
										
											2009-10-13 10:33:51 +08:00
										 |  |  |   VERIFY_IS_UNITARY(q); | 
					
						
							| 
									
										
										
										
											2010-06-18 00:30:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 21:48:39 +08:00
										 |  |  |   MatrixType r = qrOfA.matrixQR().template triangularView<Upper>(); | 
					
						
							| 
									
										
										
										
											2009-12-03 00:11:09 +08:00
										 |  |  |   VERIFY_IS_APPROX(a, qrOfA.householderQ() * r); | 
					
						
							| 
									
										
										
										
											2009-09-28 22:49:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-06-08 23:03:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-28 22:49:55 +08:00
										 |  |  | template <typename MatrixType, int Cols2> | 
					
						
							|  |  |  | void qr_fixedsize() { | 
					
						
							|  |  |  |   enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime }; | 
					
						
							|  |  |  |   typedef typename MatrixType::Scalar Scalar; | 
					
						
							|  |  |  |   Matrix<Scalar, Rows, Cols> m1 = Matrix<Scalar, Rows, Cols>::Random(); | 
					
						
							|  |  |  |   HouseholderQR<Matrix<Scalar, Rows, Cols> > qr(m1); | 
					
						
							| 
									
										
										
										
											2008-06-08 23:03:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-28 22:49:55 +08:00
										 |  |  |   Matrix<Scalar, Rows, Cols> r = qr.matrixQR(); | 
					
						
							|  |  |  |   // FIXME need better way to construct trapezoid
 | 
					
						
							|  |  |  |   for (int i = 0; i < Rows; i++) | 
					
						
							|  |  |  |     for (int j = 0; j < Cols; j++) | 
					
						
							|  |  |  |       if (i > j) r(i, j) = Scalar(0); | 
					
						
							| 
									
										
										
										
											2008-06-08 23:03:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-03 00:11:09 +08:00
										 |  |  |   VERIFY_IS_APPROX(m1, qr.householderQ() * r); | 
					
						
							| 
									
										
										
										
											2009-09-28 22:49:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 08:17:39 +08:00
										 |  |  |   check_solverbase<Matrix<Scalar, Cols, Cols2>, Matrix<Scalar, Rows, Cols2> >(m1, qr, Rows, Cols, Cols2); | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  | template <typename MatrixType> | 
					
						
							|  |  |  | void qr_invertible() { | 
					
						
							| 
									
										
										
										
											2012-11-06 22:25:50 +08:00
										 |  |  |   using std::abs; | 
					
						
							| 
									
										
										
										
											2014-02-14 16:58:30 +08:00
										 |  |  |   using std::log; | 
					
						
							|  |  |  |   using std::max; | 
					
						
							|  |  |  |   using std::pow; | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  |   typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; | 
					
						
							| 
									
										
										
										
											2009-08-25 01:46:14 +08:00
										 |  |  |   typedef typename MatrixType::Scalar Scalar; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 08:17:39 +08:00
										 |  |  |   STATIC_CHECK((internal::is_same<typename HouseholderQR<MatrixType>::StorageIndex, int>::value)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-25 22:15:22 +08:00
										 |  |  |   int size = internal::random<int>(10, 50); | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   MatrixType m1(size, size), m2(size, size), m3(size, size); | 
					
						
							|  |  |  |   m1 = MatrixType::Random(size, size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-26 04:13:49 +08:00
										 |  |  |   if (internal::is_same<RealScalar, float>::value) { | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  |     // let's build a matrix more stable to inverse
 | 
					
						
							| 
									
										
										
										
											2014-02-14 16:58:30 +08:00
										 |  |  |     MatrixType a = MatrixType::Random(size, size * 4); | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  |     m1 += a * a.adjoint(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 23:12:10 +08:00
										 |  |  |   HouseholderQR<MatrixType> qr(m1); | 
					
						
							| 
									
										
										
										
											2019-01-17 08:17:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   check_solverbase<MatrixType, MatrixType>(m1, qr, size, size, size); | 
					
						
							| 
									
										
										
										
											2009-09-16 20:35:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-25 01:46:14 +08:00
										 |  |  |   // now construct a matrix with prescribed determinant
 | 
					
						
							|  |  |  |   m1.setZero(); | 
					
						
							| 
									
										
										
										
											2010-10-25 22:15:22 +08:00
										 |  |  |   for (int i = 0; i < size; i++) m1(i, i) = internal::random<Scalar>(); | 
					
						
							| 
									
										
										
										
											2022-07-30 02:24:14 +08:00
										 |  |  |   Scalar det = m1.diagonal().prod(); | 
					
						
							|  |  |  |   RealScalar absdet = abs(det); | 
					
						
							| 
									
										
										
										
											2009-12-03 00:11:09 +08:00
										 |  |  |   m3 = qr.householderQ();  // get a unitary
 | 
					
						
							| 
									
										
										
										
											2022-07-30 02:24:14 +08:00
										 |  |  |   m1 = m3 * m1 * m3.adjoint(); | 
					
						
							| 
									
										
										
										
											2009-08-25 01:46:14 +08:00
										 |  |  |   qr.compute(m1); | 
					
						
							| 
									
										
										
										
											2012-11-06 22:25:50 +08:00
										 |  |  |   VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant()); | 
					
						
							| 
									
										
										
										
											2014-02-14 16:58:30 +08:00
										 |  |  |   // This test is tricky if the determinant becomes too small.
 | 
					
						
							| 
									
										
										
										
											2018-04-15 16:15:28 +08:00
										 |  |  |   // Since we generate random numbers with magnitude range [0,1], the average determinant is 0.5^size
 | 
					
						
							| 
									
										
										
										
											2022-07-30 02:24:14 +08:00
										 |  |  |   RealScalar tol = | 
					
						
							|  |  |  |       numext::maxi(RealScalar(pow(0.5, size)), numext::maxi<RealScalar>(abs(absdet), abs(qr.absDeterminant()))); | 
					
						
							|  |  |  |   VERIFY_IS_MUCH_SMALLER_THAN(abs(det - qr.determinant()), tol); | 
					
						
							|  |  |  |   VERIFY_IS_MUCH_SMALLER_THAN(abs(absdet - qr.absDeterminant()), tol); | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-22 20:27:58 +08:00
										 |  |  | template <typename MatrixType> | 
					
						
							|  |  |  | void qr_verify_assert() { | 
					
						
							|  |  |  |   MatrixType tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 23:12:10 +08:00
										 |  |  |   HouseholderQR<MatrixType> qr; | 
					
						
							| 
									
										
										
										
											2009-08-25 01:46:14 +08:00
										 |  |  |   VERIFY_RAISES_ASSERT(qr.matrixQR()) | 
					
						
							| 
									
										
										
										
											2009-11-08 23:21:26 +08:00
										 |  |  |   VERIFY_RAISES_ASSERT(qr.solve(tmp)) | 
					
						
							| 
									
										
										
										
											2019-01-17 08:17:39 +08:00
										 |  |  |   VERIFY_RAISES_ASSERT(qr.transpose().solve(tmp)) | 
					
						
							|  |  |  |   VERIFY_RAISES_ASSERT(qr.adjoint().solve(tmp)) | 
					
						
							| 
									
										
										
										
											2009-12-03 00:11:09 +08:00
										 |  |  |   VERIFY_RAISES_ASSERT(qr.householderQ()) | 
					
						
							| 
									
										
										
										
											2022-07-30 02:24:14 +08:00
										 |  |  |   VERIFY_RAISES_ASSERT(qr.determinant()) | 
					
						
							| 
									
										
										
										
											2009-08-25 01:46:14 +08:00
										 |  |  |   VERIFY_RAISES_ASSERT(qr.absDeterminant()) | 
					
						
							|  |  |  |   VERIFY_RAISES_ASSERT(qr.logAbsDeterminant()) | 
					
						
							| 
									
										
										
										
											2009-05-22 20:27:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 20:46:15 +08:00
										 |  |  | EIGEN_DECLARE_TEST(qr) { | 
					
						
							| 
									
										
										
										
											2010-01-11 21:48:39 +08:00
										 |  |  |   for (int i = 0; i < g_repeat; i++) { | 
					
						
							| 
									
										
										
										
											2011-07-12 20:41:00 +08:00
										 |  |  |     CALL_SUBTEST_1( | 
					
						
							|  |  |  |         qr(MatrixXf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE)))); | 
					
						
							|  |  |  |     CALL_SUBTEST_2(qr(MatrixXcd(internal::random<int>(1, EIGEN_TEST_MAX_SIZE / 2), | 
					
						
							|  |  |  |                                 internal::random<int>(1, EIGEN_TEST_MAX_SIZE / 2)))); | 
					
						
							| 
									
										
										
										
											2009-10-29 06:19:29 +08:00
										 |  |  |     CALL_SUBTEST_3((qr_fixedsize<Matrix<float, 3, 4>, 2>())); | 
					
						
							|  |  |  |     CALL_SUBTEST_4((qr_fixedsize<Matrix<double, 6, 2>, 4>())); | 
					
						
							|  |  |  |     CALL_SUBTEST_5((qr_fixedsize<Matrix<double, 2, 5>, 7>())); | 
					
						
							| 
									
										
										
										
											2010-03-01 21:46:41 +08:00
										 |  |  |     CALL_SUBTEST_11(qr(Matrix<float, 1, 1>())); | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-02-04 23:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 17:45:53 +08:00
										 |  |  |   for (int i = 0; i < g_repeat; i++) { | 
					
						
							| 
									
										
										
										
											2009-10-29 06:19:29 +08:00
										 |  |  |     CALL_SUBTEST_1(qr_invertible<MatrixXf>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_6(qr_invertible<MatrixXd>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_7(qr_invertible<MatrixXcf>()); | 
					
						
							|  |  |  |     CALL_SUBTEST_8(qr_invertible<MatrixXcd>()); | 
					
						
							| 
									
										
										
										
											2009-01-20 18:38:56 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-22 20:27:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-29 06:19:29 +08:00
										 |  |  |   CALL_SUBTEST_9(qr_verify_assert<Matrix3f>()); | 
					
						
							|  |  |  |   CALL_SUBTEST_10(qr_verify_assert<Matrix3d>()); | 
					
						
							|  |  |  |   CALL_SUBTEST_1(qr_verify_assert<MatrixXf>()); | 
					
						
							|  |  |  |   CALL_SUBTEST_6(qr_verify_assert<MatrixXd>()); | 
					
						
							|  |  |  |   CALL_SUBTEST_7(qr_verify_assert<MatrixXcf>()); | 
					
						
							|  |  |  |   CALL_SUBTEST_8(qr_verify_assert<MatrixXcd>()); | 
					
						
							| 
									
										
										
										
											2010-04-21 23:15:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Test problem size constructors
 | 
					
						
							|  |  |  |   CALL_SUBTEST_12(HouseholderQR<MatrixXf>(10, 20)); | 
					
						
							| 
									
										
										
										
											2008-05-27 17:16:27 +08:00
										 |  |  | } |