1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
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/.
13 template<typename MatrixType
> void qr(const MatrixType
& m
)
15 typedef typename
MatrixType::Index Index
;
17 Index rows
= m
.rows();
18 Index cols
= m
.cols();
20 typedef typename
MatrixType::Scalar Scalar
;
21 typedef Matrix
<Scalar
, MatrixType::RowsAtCompileTime
, MatrixType::RowsAtCompileTime
> MatrixQType
;
23 MatrixType a
= MatrixType::Random(rows
,cols
);
24 HouseholderQR
<MatrixType
> qrOfA(a
);
26 MatrixQType q
= qrOfA
.householderQ();
29 MatrixType r
= qrOfA
.matrixQR().template triangularView
<Upper
>();
30 VERIFY_IS_APPROX(a
, qrOfA
.householderQ() * r
);
33 template<typename MatrixType
, int Cols2
> void qr_fixedsize()
35 enum { Rows
= MatrixType::RowsAtCompileTime
, Cols
= MatrixType::ColsAtCompileTime
};
36 typedef typename
MatrixType::Scalar Scalar
;
37 Matrix
<Scalar
,Rows
,Cols
> m1
= Matrix
<Scalar
,Rows
,Cols
>::Random();
38 HouseholderQR
<Matrix
<Scalar
,Rows
,Cols
> > qr(m1
);
40 Matrix
<Scalar
,Rows
,Cols
> r
= qr
.matrixQR();
41 // FIXME need better way to construct trapezoid
42 for(int i
= 0; i
< Rows
; i
++) for(int j
= 0; j
< Cols
; j
++) if(i
>j
) r(i
,j
) = Scalar(0);
44 VERIFY_IS_APPROX(m1
, qr
.householderQ() * r
);
46 Matrix
<Scalar
,Cols
,Cols2
> m2
= Matrix
<Scalar
,Cols
,Cols2
>::Random(Cols
,Cols2
);
47 Matrix
<Scalar
,Rows
,Cols2
> m3
= m1
*m2
;
48 m2
= Matrix
<Scalar
,Cols
,Cols2
>::Random(Cols
,Cols2
);
50 VERIFY_IS_APPROX(m3
, m1
*m2
);
53 template<typename MatrixType
> void qr_invertible()
59 typedef typename NumTraits
<typename
MatrixType::Scalar
>::Real RealScalar
;
60 typedef typename
MatrixType::Scalar Scalar
;
62 int size
= internal::random
<int>(10,50);
64 MatrixType
m1(size
, size
), m2(size
, size
), m3(size
, size
);
65 m1
= MatrixType::Random(size
,size
);
67 if (internal::is_same
<RealScalar
,float>::value
)
69 // let's build a matrix more stable to inverse
70 MatrixType a
= MatrixType::Random(size
,size
*4);
71 m1
+= a
* a
.adjoint();
74 HouseholderQR
<MatrixType
> qr(m1
);
75 m3
= MatrixType::Random(size
,size
);
77 VERIFY_IS_APPROX(m3
, m1
*m2
);
79 // now construct a matrix with prescribed determinant
81 for(int i
= 0; i
< size
; i
++) m1(i
,i
) = internal::random
<Scalar
>();
82 RealScalar absdet
= abs(m1
.diagonal().prod());
83 m3
= qr
.householderQ(); // get a unitary
86 VERIFY_IS_APPROX(log(absdet
), qr
.logAbsDeterminant());
87 // This test is tricky if the determinant becomes too small.
88 // Since we generate random numbers with magnitude rrange [0,1], the average determinant is 0.5^size
89 VERIFY_IS_MUCH_SMALLER_THAN( abs(absdet
-qr
.absDeterminant()), numext::maxi(RealScalar(pow(0.5,size
)),numext::maxi
<RealScalar
>(abs(absdet
),abs(qr
.absDeterminant()))) );
93 template<typename MatrixType
> void qr_verify_assert()
97 HouseholderQR
<MatrixType
> qr
;
98 VERIFY_RAISES_ASSERT(qr
.matrixQR())
99 VERIFY_RAISES_ASSERT(qr
.solve(tmp
))
100 VERIFY_RAISES_ASSERT(qr
.householderQ())
101 VERIFY_RAISES_ASSERT(qr
.absDeterminant())
102 VERIFY_RAISES_ASSERT(qr
.logAbsDeterminant())
107 for(int i
= 0; i
< g_repeat
; i
++) {
108 CALL_SUBTEST_1( qr(MatrixXf(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
),internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
))) );
109 CALL_SUBTEST_2( qr(MatrixXcd(internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2),internal::random
<int>(1,EIGEN_TEST_MAX_SIZE
/2))) );
110 CALL_SUBTEST_3(( qr_fixedsize
<Matrix
<float,3,4>, 2 >() ));
111 CALL_SUBTEST_4(( qr_fixedsize
<Matrix
<double,6,2>, 4 >() ));
112 CALL_SUBTEST_5(( qr_fixedsize
<Matrix
<double,2,5>, 7 >() ));
113 CALL_SUBTEST_11( qr(Matrix
<float,1,1>()) );
116 for(int i
= 0; i
< g_repeat
; i
++) {
117 CALL_SUBTEST_1( qr_invertible
<MatrixXf
>() );
118 CALL_SUBTEST_6( qr_invertible
<MatrixXd
>() );
119 CALL_SUBTEST_7( qr_invertible
<MatrixXcf
>() );
120 CALL_SUBTEST_8( qr_invertible
<MatrixXcd
>() );
123 CALL_SUBTEST_9(qr_verify_assert
<Matrix3f
>());
124 CALL_SUBTEST_10(qr_verify_assert
<Matrix3d
>());
125 CALL_SUBTEST_1(qr_verify_assert
<MatrixXf
>());
126 CALL_SUBTEST_6(qr_verify_assert
<MatrixXd
>());
127 CALL_SUBTEST_7(qr_verify_assert
<MatrixXcf
>());
128 CALL_SUBTEST_8(qr_verify_assert
<MatrixXcd
>());
130 // Test problem size constructors
131 CALL_SUBTEST_12(HouseholderQR
<MatrixXf
>(10, 20));