1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "main.h"
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/QR>
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> void qr()
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Index Index;
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), cols2 = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Scalar Scalar;
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m1;
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  createRandomPIMatrixOfRank(rank,rows,cols,m1);
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ColPivHouseholderQR<MatrixType> qr(m1);
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(rank == qr.rank());
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(cols - qr.rank() == qr.dimensionOfKernel());
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(!qr.isInjective());
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(!qr.isInvertible());
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(!qr.isSurjective());
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixQType q = qr.householderQ();
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_UNITARY(q);
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType r = qr.matrixQR().template triangularView<Upper>();
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType c = q * r * qr.colsPermutation().inverse();
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m1, c);
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m2 = MatrixType::Random(cols,cols2);
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m3 = m1*m2;
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2 = MatrixType::Random(cols,cols2);
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2 = qr.solve(m3);
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m3, m1*m2);
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, int Cols2> void qr_fixedsize()
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Scalar Scalar;
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int rank = internal::random<int>(1, (std::min)(int(Rows), int(Cols))-1);
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<Scalar,Rows,Cols> m1;
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  createRandomPIMatrixOfRank(rank,Rows,Cols,m1);
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ColPivHouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(rank == qr.rank());
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(Cols - qr.rank() == qr.dimensionOfKernel());
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(qr.isInjective() == (rank == Rows));
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(qr.isSurjective() == (rank == Cols));
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(qr.isInvertible() == (qr.isInjective() && qr.isSurjective()));
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<Scalar,Rows,Cols> r = qr.matrixQR().template triangularView<Upper>();
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<Scalar,Rows,Cols> c = qr.householderQ() * r * qr.colsPermutation().inverse();
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m1, c);
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2 = qr.solve(m3);
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m3, m1*m2);
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> void qr_invertible()
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  using std::log;
747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  using std::abs;
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Scalar Scalar;
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int size = internal::random<int>(10,50);
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m1(size, size), m2(size, size), m3(size, size);
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m1 = MatrixType::Random(size,size);
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (internal::is_same<RealScalar,float>::value)
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // let's build a matrix more stable to inverse
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MatrixType a = MatrixType::Random(size,size*2);
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m1 += a * a.adjoint();
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ColPivHouseholderQR<MatrixType> qr(m1);
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3 = MatrixType::Random(size,size);
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2 = qr.solve(m3);
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  //VERIFY_IS_APPROX(m3, m1*m2);
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // now construct a matrix with prescribed determinant
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m1.setZero();
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  RealScalar absdet = abs(m1.diagonal().prod());
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3 = qr.householderQ(); // get a unitary
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m1 = m3 * m1 * m3;
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  qr.compute(m1);
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(absdet, qr.absDeterminant());
1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> void qr_verify_assert()
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType tmp;
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ColPivHouseholderQR<MatrixType> qr;
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.matrixQR())
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.solve(tmp))
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.householderQ())
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.dimensionOfKernel())
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.isInjective())
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.isSurjective())
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.isInvertible())
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.inverse())
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.absDeterminant())
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid test_qr_colpivoting()
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for(int i = 0; i < g_repeat; i++) {
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_1( qr<MatrixXf>() );
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_2( qr<MatrixXd>() );
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_3( qr<MatrixXcd>() );
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_4(( qr_fixedsize<Matrix<float,3,5>, 4 >() ));
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,6,2>, 3 >() ));
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,1,1>, 1 >() ));
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for(int i = 0; i < g_repeat; i++) {
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_2( qr_invertible<MatrixXd>() );
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_6( qr_invertible<MatrixXcf>() );
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_3( qr_invertible<MatrixXcd>() );
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_7(qr_verify_assert<Matrix3f>());
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_8(qr_verify_assert<Matrix3d>());
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_2(qr_verify_assert<MatrixXd>());
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_6(qr_verify_assert<MatrixXcf>());
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_3(qr_verify_assert<MatrixXcd>());
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // Test problem size constructors
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST_9(ColPivHouseholderQR<MatrixXf>(10, 20));
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
151