1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 template<typename MatrixType
> void qr()
16 typedef typename
MatrixType::Index Index
;
18 Index rows
= internal::random
<Index
>(20,200), cols
= internal::random
<int>(20,200), cols2
= internal::random
<int>(20,200);
19 Index rank
= internal::random
<Index
>(1, (std::min
)(rows
, cols
)-1);
21 typedef typename
MatrixType::Scalar Scalar
;
22 typedef Matrix
<Scalar
, MatrixType::RowsAtCompileTime
, MatrixType::RowsAtCompileTime
> MatrixQType
;
24 createRandomPIMatrixOfRank(rank
,rows
,cols
,m1
);
25 FullPivHouseholderQR
<MatrixType
> qr(m1
);
26 VERIFY(rank
== qr
.rank());
27 VERIFY(cols
- qr
.rank() == qr
.dimensionOfKernel());
28 VERIFY(!qr
.isInjective());
29 VERIFY(!qr
.isInvertible());
30 VERIFY(!qr
.isSurjective());
32 MatrixType r
= qr
.matrixQR();
34 MatrixQType q
= qr
.matrixQ();
37 // FIXME need better way to construct trapezoid
38 for(int i
= 0; i
< rows
; i
++) for(int j
= 0; j
< cols
; j
++) if(i
>j
) r(i
,j
) = Scalar(0);
40 MatrixType c
= qr
.matrixQ() * r
* qr
.colsPermutation().inverse();
42 VERIFY_IS_APPROX(m1
, c
);
44 MatrixType m2
= MatrixType::Random(cols
,cols2
);
45 MatrixType m3
= m1
*m2
;
46 m2
= MatrixType::Random(cols
,cols2
);
48 VERIFY_IS_APPROX(m3
, m1
*m2
);
51 template<typename MatrixType
> void qr_invertible()
55 typedef typename NumTraits
<typename
MatrixType::Scalar
>::Real RealScalar
;
56 typedef typename
MatrixType::Scalar Scalar
;
58 int size
= internal::random
<int>(10,50);
60 MatrixType
m1(size
, size
), m2(size
, size
), m3(size
, size
);
61 m1
= MatrixType::Random(size
,size
);
63 if (internal::is_same
<RealScalar
,float>::value
)
65 // let's build a matrix more stable to inverse
66 MatrixType a
= MatrixType::Random(size
,size
*2);
67 m1
+= a
* a
.adjoint();
70 FullPivHouseholderQR
<MatrixType
> qr(m1
);
71 VERIFY(qr
.isInjective());
72 VERIFY(qr
.isInvertible());
73 VERIFY(qr
.isSurjective());
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
.matrixQ(); // get a unitary
86 VERIFY_IS_APPROX(absdet
, qr
.absDeterminant());
87 VERIFY_IS_APPROX(log(absdet
), qr
.logAbsDeterminant());
90 template<typename MatrixType
> void qr_verify_assert()
94 FullPivHouseholderQR
<MatrixType
> qr
;
95 VERIFY_RAISES_ASSERT(qr
.matrixQR())
96 VERIFY_RAISES_ASSERT(qr
.solve(tmp
))
97 VERIFY_RAISES_ASSERT(qr
.matrixQ())
98 VERIFY_RAISES_ASSERT(qr
.dimensionOfKernel())
99 VERIFY_RAISES_ASSERT(qr
.isInjective())
100 VERIFY_RAISES_ASSERT(qr
.isSurjective())
101 VERIFY_RAISES_ASSERT(qr
.isInvertible())
102 VERIFY_RAISES_ASSERT(qr
.inverse())
103 VERIFY_RAISES_ASSERT(qr
.absDeterminant())
104 VERIFY_RAISES_ASSERT(qr
.logAbsDeterminant())
107 void test_qr_fullpivoting()
109 for(int i
= 0; i
< 1; i
++) {
110 // FIXME : very weird bug here
111 // CALL_SUBTEST(qr(Matrix2f()) );
112 CALL_SUBTEST_1( qr
<MatrixXf
>() );
113 CALL_SUBTEST_2( qr
<MatrixXd
>() );
114 CALL_SUBTEST_3( qr
<MatrixXcd
>() );
117 for(int i
= 0; i
< g_repeat
; i
++) {
118 CALL_SUBTEST_1( qr_invertible
<MatrixXf
>() );
119 CALL_SUBTEST_2( qr_invertible
<MatrixXd
>() );
120 CALL_SUBTEST_4( qr_invertible
<MatrixXcf
>() );
121 CALL_SUBTEST_3( qr_invertible
<MatrixXcd
>() );
124 CALL_SUBTEST_5(qr_verify_assert
<Matrix3f
>());
125 CALL_SUBTEST_6(qr_verify_assert
<Matrix3d
>());
126 CALL_SUBTEST_1(qr_verify_assert
<MatrixXf
>());
127 CALL_SUBTEST_2(qr_verify_assert
<MatrixXd
>());
128 CALL_SUBTEST_4(qr_verify_assert
<MatrixXcf
>());
129 CALL_SUBTEST_3(qr_verify_assert
<MatrixXcd
>());
131 // Test problem size constructors
132 CALL_SUBTEST_7(FullPivHouseholderQR
<MatrixXf
>(10, 20));
133 CALL_SUBTEST_7((FullPivHouseholderQR
<Matrix
<float,10,20> >(10,20)));
134 CALL_SUBTEST_7((FullPivHouseholderQR
<Matrix
<float,10,20> >(Matrix
<float,10,20>::Random())));
135 CALL_SUBTEST_7((FullPivHouseholderQR
<Matrix
<float,20,10> >(20,10)));
136 CALL_SUBTEST_7((FullPivHouseholderQR
<Matrix
<float,20,10> >(Matrix
<float,20,10>::Random())));