householder.cpp File Reference
#include "main.h"
#include <Eigen/QR>

Functions

template<typename MatrixType >
void householder (const MatrixType &m)
 
template<typename MatrixType >
void householder_update (const MatrixType &m)
 
 EIGEN_DECLARE_TEST (householder)
 

Function Documentation

◆ EIGEN_DECLARE_TEST()

EIGEN_DECLARE_TEST ( householder  )
216  {
217  for (int i = 0; i < g_repeat; i++) {
223  MatrixXd(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
225  MatrixXcf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
227  MatrixXf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
229 
233  MatrixXcf(internal::random<Index>(1, EIGEN_TEST_MAX_SIZE), internal::random<Index>(1, EIGEN_TEST_MAX_SIZE))));
234  }
235 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define EIGEN_TEST_MAX_SIZE
Definition: boostmultiprec.cpp:16
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
void householder_update(const MatrixType &m)
Definition: householder.cpp:137
void householder(const MatrixType &m)
Definition: householder.cpp:14
static int g_repeat
Definition: main.h:191
#define CALL_SUBTEST_6(FUNC)
Definition: split_test_helper.h:34
#define CALL_SUBTEST_3(FUNC)
Definition: split_test_helper.h:16
#define CALL_SUBTEST_1(FUNC)
Definition: split_test_helper.h:4
#define CALL_SUBTEST_8(FUNC)
Definition: split_test_helper.h:46
#define CALL_SUBTEST_5(FUNC)
Definition: split_test_helper.h:28
#define CALL_SUBTEST_2(FUNC)
Definition: split_test_helper.h:10
#define CALL_SUBTEST_7(FUNC)
Definition: split_test_helper.h:40
#define CALL_SUBTEST_4(FUNC)
Definition: split_test_helper.h:22
#define CALL_SUBTEST_9(FUNC)
Definition: split_test_helper.h:52

References CALL_SUBTEST_1, CALL_SUBTEST_2, CALL_SUBTEST_3, CALL_SUBTEST_4, CALL_SUBTEST_5, CALL_SUBTEST_6, CALL_SUBTEST_7, CALL_SUBTEST_8, CALL_SUBTEST_9, EIGEN_TEST_MAX_SIZE, Eigen::g_repeat, householder(), householder_update(), and i.

◆ householder()

template<typename MatrixType >
void householder ( const MatrixType m)
14  {
15  static bool even = true;
16  even = !even;
17  /* this test covers the following files:
18  Householder.h
19  */
20  Index rows = m.rows();
21  Index cols = m.cols();
22 
23  typedef typename MatrixType::Scalar Scalar;
24  typedef typename NumTraits<Scalar>::Real RealScalar;
29  typedef Matrix<Scalar, Dynamic, 1> HCoeffsVectorType;
30 
32 
33  Matrix<Scalar, internal::max_size_prefer_dynamic(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime), 1>
34  _tmp((std::max)(rows, cols));
35  Scalar* tmp = &_tmp.coeffRef(0, 0);
36 
37  Scalar beta;
39  EssentialVectorType essential;
40 
41  VectorType v1 = VectorType::Random(rows), v2;
42  v2 = v1;
43  v1.makeHouseholder(essential, beta, alpha);
44  v1.applyHouseholderOnTheLeft(essential, beta, tmp);
45  VERIFY_IS_APPROX(v1.norm(), v2.norm());
46  if (rows >= 2) VERIFY_IS_MUCH_SMALLER_THAN(v1.tail(rows - 1).norm(), v1.norm());
47  v1 = VectorType::Random(rows);
48  v2 = v1;
49  v1.applyHouseholderOnTheLeft(essential, beta, tmp);
50  VERIFY_IS_APPROX(v1.norm(), v2.norm());
51 
52  // reconstruct householder matrix:
53  SquareMatrixType id, H1, H2;
54  id.setIdentity(rows, rows);
55  H1 = H2 = id;
56  VectorType vv(rows);
57  vv << Scalar(1), essential;
58  H1.applyHouseholderOnTheLeft(essential, beta, tmp);
59  H2.applyHouseholderOnTheRight(essential, beta, tmp);
60  VERIFY_IS_APPROX(H1, H2);
61  VERIFY_IS_APPROX(H1, id - beta * vv * vv.adjoint());
62 
64 
65  v1 = VectorType::Random(rows);
66  if (even) v1.tail(rows - 1).setZero();
67  m1.colwise() = v1;
68  m2 = m1;
69  m1.col(0).makeHouseholder(essential, beta, alpha);
70  m1.applyHouseholderOnTheLeft(essential, beta, tmp);
71  VERIFY_IS_APPROX(m1.norm(), m2.norm());
72  if (rows >= 2) VERIFY_IS_MUCH_SMALLER_THAN(m1.block(1, 0, rows - 1, cols).norm(), m1.norm());
75 
76  v1 = VectorType::Random(rows);
77  if (even) v1.tail(rows - 1).setZero();
78  SquareMatrixType m3(rows, rows), m4(rows, rows);
79  m3.rowwise() = v1.transpose();
80  m4 = m3;
81  m3.row(0).makeHouseholder(essential, beta, alpha);
82  m3.applyHouseholderOnTheRight(essential.conjugate(), beta, tmp);
83  VERIFY_IS_APPROX(m3.norm(), m4.norm());
84  if (rows >= 2) VERIFY_IS_MUCH_SMALLER_THAN(m3.block(0, 1, rows, rows - 1).norm(), m3.norm());
87 
88  // test householder sequence on the left with a shift
89 
90  Index shift = internal::random<Index>(0, std::max<Index>(rows - 2, 0));
91  Index brows = rows - shift;
92  m1.setRandom(rows, cols);
93  HBlockMatrixType hbm = m1.block(shift, 0, brows, cols);
95  m2 = m1;
96  m2.block(shift, 0, brows, cols) = qr.matrixQR();
97  HCoeffsVectorType hc = qr.hCoeffs().conjugate();
99  hseq.setLength(hc.size()).setShift(shift);
100  VERIFY(hseq.length() == hc.size());
101  VERIFY(hseq.shift() == shift);
102 
103  MatrixType m5 = m2;
104  m5.block(shift, 0, brows, cols).template triangularView<StrictlyLower>().setZero();
105  VERIFY_IS_APPROX(hseq * m5, m1); // test applying hseq directly
106  m3 = hseq;
107  VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating hseq to a dense matrix, then applying
108 
109  SquareMatrixType hseq_mat = hseq;
110  SquareMatrixType hseq_mat_conj = hseq.conjugate();
111  SquareMatrixType hseq_mat_adj = hseq.adjoint();
112  SquareMatrixType hseq_mat_trans = hseq.transpose();
113  SquareMatrixType m6 = SquareMatrixType::Random(rows, rows);
114  VERIFY_IS_APPROX(hseq_mat.adjoint(), hseq_mat_adj);
115  VERIFY_IS_APPROX(hseq_mat.conjugate(), hseq_mat_conj);
116  VERIFY_IS_APPROX(hseq_mat.transpose(), hseq_mat_trans);
117  VERIFY_IS_APPROX(hseq * m6, hseq_mat * m6);
118  VERIFY_IS_APPROX(hseq.adjoint() * m6, hseq_mat_adj * m6);
119  VERIFY_IS_APPROX(hseq.conjugate() * m6, hseq_mat_conj * m6);
120  VERIFY_IS_APPROX(hseq.transpose() * m6, hseq_mat_trans * m6);
121  VERIFY_IS_APPROX(m6 * hseq, m6 * hseq_mat);
122  VERIFY_IS_APPROX(m6 * hseq.adjoint(), m6 * hseq_mat_adj);
123  VERIFY_IS_APPROX(m6 * hseq.conjugate(), m6 * hseq_mat_conj);
124  VERIFY_IS_APPROX(m6 * hseq.transpose(), m6 * hseq_mat_trans);
125 
126  // test householder sequence on the right with a shift
127 
128  TMatrixType tm2 = m2.transpose();
130  rhseq.setLength(hc.size()).setShift(shift);
131  VERIFY_IS_APPROX(rhseq * m5, m1); // test applying rhseq directly
132  m3 = rhseq;
133  VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating rhseq to a dense matrix, then applying
134 }
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
HouseholderQR< MatrixXf > qr(A)
Matrix3d m1
Definition: IOFormat.cpp:2
Vector3d hc
Definition: Tridiagonalization_householderCoefficients.cpp:5
MatrixType m2(n_dims)
Map< RowVectorXf > v2(M2.data(), M2.size())
M1<< 1, 2, 3, 4, 5, 6, 7, 8, 9;Map< RowVectorXf > v1(M1.data(), M1.size())
int rows
Definition: Tutorial_commainit_02.cpp:1
int cols
Definition: Tutorial_commainit_02.cpp:1
SCALAR Scalar
Definition: bench_gemm.cpp:45
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
Householder QR decomposition of a matrix.
Definition: HouseholderQR.h:59
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition: HouseholderSequence.h:117
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar & coeffRef(Index rowId, Index colId)
Definition: PlainObjectBase.h:217
float real
Definition: datatypes.h:10
#define max(a, b)
Definition: datatypes.h:23
#define VERIFY_IS_APPROX(a, b)
Definition: integer_types.cpp:13
RealScalar alpha
Definition: level1_cplx_impl.h:151
int * m
Definition: level2_cplx_impl.h:294
Scalar beta
Definition: level2_cplx_impl.h:36
Eigen::Matrix< Scalar, Dynamic, Dynamic, ColMajor > tmp
Definition: level3_impl.h:365
#define VERIFY(a)
Definition: main.h:362
#define VERIFY_IS_MUCH_SMALLER_THAN(a, b)
Definition: main.h:371
constexpr int max_size_prefer_dynamic(A a, B b)
Definition: Meta.h:695
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
Definition: fft_test_shared.h:66

References Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::adjoint(), alpha, beta, Eigen::Matrix< Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_ >::coeffRef(), cols, Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::conjugate(), hc, imag(), Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::length(), m, m1, m2(), max, Eigen::internal::max_size_prefer_dynamic(), qr(), rows, Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::setLength(), Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::setShift(), Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::shift(), tmp, Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::transpose(), v1(), v2(), VERIFY, VERIFY_IS_APPROX, and VERIFY_IS_MUCH_SMALLER_THAN.

Referenced by EIGEN_DECLARE_TEST().

◆ householder_update()

template<typename MatrixType >
void householder_update ( const MatrixType m)
137  {
138  // This test is covering the internal::householder_qr_inplace_update function.
139  // At time of writing, there is not public API that exposes this update behavior directly,
140  // so we are testing the internal implementation.
141 
142  const Index rows = m.rows();
143  const Index cols = m.cols();
144 
145  typedef typename MatrixType::Scalar Scalar;
147  typedef Matrix<Scalar, Dynamic, 1> HCoeffsVectorType;
148  typedef Matrix<Scalar, Dynamic, Dynamic> MatrixX;
150 
151  VectorX tmpOwner(cols);
152  Scalar* tmp = tmpOwner.data();
153 
154  // The matrix to factorize.
155  const MatrixType A = MatrixType::Random(rows, cols);
156 
157  // matQR and hCoeffs will hold the factorization of A,
158  // built by a sequence of calls to `update`.
159  MatrixType matQR(rows, cols);
160  HCoeffsVectorType hCoeffs(cols);
161 
162  // householder_qr_inplace_update should be able to build a QR factorization one column at a time.
163  // We verify this by starting with an empty factorization and 'updating' one column at a time.
164  // After each call to update, we should have a QR factorization of the columns presented so far.
165 
166  const Index size = (std::min)(rows, cols); // QR can only go up to 'size' b/c that's full rank.
167  for (Index k = 0; k != size; ++k) {
168  // Make a copy of the column to prevent any possibility of 'leaking' other parts of A.
169  const VectorType newColumn = A.col(k);
170  internal::householder_qr_inplace_update(matQR, hCoeffs, newColumn, k, tmp);
171 
172  // Verify Property:
173  // matQR.leftCols(k+1) and hCoeffs.head(k+1) hold
174  // a QR factorization of A.leftCols(k+1).
175  // This is the fundamental guarantee of householder_qr_inplace_update.
176  {
177  const MatrixX matQR_k = matQR.leftCols(k + 1);
178  const VectorX hCoeffs_k = hCoeffs.head(k + 1);
179  MatrixX R = matQR_k.template triangularView<Upper>();
180  MatrixX QxR = householderSequence(matQR_k, hCoeffs_k.conjugate()) * R;
181  VERIFY_IS_APPROX(QxR, A.leftCols(k + 1));
182  }
183 
184  // Verify Property:
185  // A sequence of calls to 'householder_qr_inplace_update'
186  // should produce the same result as 'householder_qr_inplace_unblocked'.
187  // This is a property of the current implementation.
188  // If these implementations diverge in the future,
189  // then simply delete the test of this property.
190  {
191  MatrixX QR_at_once = A.leftCols(k + 1);
192  VectorX hCoeffs_at_once(k + 1);
193  internal::householder_qr_inplace_unblocked(QR_at_once, hCoeffs_at_once, tmp);
194  VERIFY_IS_APPROX(QR_at_once, matQR.leftCols(k + 1));
195  VERIFY_IS_APPROX(hCoeffs_at_once, hCoeffs.head(k + 1));
196  }
197  }
198 
199  // Verify Property:
200  // We can go back and update any column to have a new value,
201  // and get a QR factorization of the columns up to that one.
202  {
203  const Index k = internal::random<Index>(0, size - 1);
204  VectorType newColumn = VectorType::Random(rows);
205  internal::householder_qr_inplace_update(matQR, hCoeffs, newColumn, k, tmp);
206 
207  const MatrixX matQR_k = matQR.leftCols(k + 1);
208  const VectorX hCoeffs_k = hCoeffs.head(k + 1);
209  MatrixX R = matQR_k.template triangularView<Upper>();
210  MatrixX QxR = householderSequence(matQR_k, hCoeffs_k.conjugate()) * R;
211  VERIFY_IS_APPROX(QxR.leftCols(k), A.leftCols(k));
212  VERIFY_IS_APPROX(QxR.col(k), newColumn);
213  }
214 }
@ R
Definition: StatisticsVector.h:21
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
constexpr EIGEN_DEVICE_FUNC const Scalar * data() const
Definition: PlainObjectBase.h:273
#define min(a, b)
Definition: datatypes.h:22
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition: HouseholderSequence.h:484
char char char int int * k
Definition: level2_impl.h:374
void householder_qr_inplace_unblocked(MatrixQR &mat, HCoeffs &hCoeffs, typename MatrixQR::Scalar *tempData=0)
Definition: HouseholderQR.h:346
void householder_qr_inplace_update(MatrixQR &mat, HCoeffs &hCoeffs, const VectorQR &newColumn, typename MatrixQR::Index k, typename MatrixQR::Scalar *tempData)
Definition: HouseholderQR.h:386
Matrix< Scalar, Dynamic, 1 > VectorX
Definition: sparse_lu.cpp:43

References cols, Eigen::PlainObjectBase< Derived >::data(), Eigen::internal::householder_qr_inplace_unblocked(), Eigen::internal::householder_qr_inplace_update(), Eigen::householderSequence(), k, m, min, R, rows, size, tmp, and VERIFY_IS_APPROX.

Referenced by EIGEN_DECLARE_TEST().