Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
HouseholderSequence.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009 Gael Guennebaud <[email protected]>
5// Copyright (C) 2010 Benoit Jacob <[email protected]>
6//
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/.
10
11#ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
12#define EIGEN_HOUSEHOLDER_SEQUENCE_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
60namespace internal {
61
62template <typename VectorsType, typename CoeffsType, int Side>
63struct traits<HouseholderSequence<VectorsType, CoeffsType, Side> > {
64 typedef typename VectorsType::Scalar Scalar;
65 typedef typename VectorsType::StorageIndex StorageIndex;
66 typedef typename VectorsType::StorageKind StorageKind;
67 enum {
68 RowsAtCompileTime =
69 Side == OnTheLeft ? traits<VectorsType>::RowsAtCompileTime : traits<VectorsType>::ColsAtCompileTime,
70 ColsAtCompileTime = RowsAtCompileTime,
71 MaxRowsAtCompileTime =
72 Side == OnTheLeft ? traits<VectorsType>::MaxRowsAtCompileTime : traits<VectorsType>::MaxColsAtCompileTime,
73 MaxColsAtCompileTime = MaxRowsAtCompileTime,
74 Flags = 0
75 };
76};
77
78struct HouseholderSequenceShape {};
79
80template <typename VectorsType, typename CoeffsType, int Side>
81struct evaluator_traits<HouseholderSequence<VectorsType, CoeffsType, Side> >
82 : public evaluator_traits_base<HouseholderSequence<VectorsType, CoeffsType, Side> > {
83 typedef HouseholderSequenceShape Shape;
84};
85
86template <typename VectorsType, typename CoeffsType, int Side>
87struct hseq_side_dependent_impl {
88 typedef Block<const VectorsType, Dynamic, 1> EssentialVectorType;
89 typedef HouseholderSequence<VectorsType, CoeffsType, OnTheLeft> HouseholderSequenceType;
90 static EIGEN_DEVICE_FUNC inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k) {
91 Index start = k + 1 + h.m_shift;
92 return Block<const VectorsType, Dynamic, 1>(h.m_vectors, start, k, h.rows() - start, 1);
93 }
94};
95
96template <typename VectorsType, typename CoeffsType>
97struct hseq_side_dependent_impl<VectorsType, CoeffsType, OnTheRight> {
98 typedef Transpose<Block<const VectorsType, 1, Dynamic> > EssentialVectorType;
99 typedef HouseholderSequence<VectorsType, CoeffsType, OnTheRight> HouseholderSequenceType;
100 static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k) {
101 Index start = k + 1 + h.m_shift;
102 return Block<const VectorsType, 1, Dynamic>(h.m_vectors, k, start, 1, h.rows() - start).transpose();
103 }
104};
105
106template <typename OtherScalarType, typename MatrixType>
107struct matrix_type_times_scalar_type {
108 typedef typename ScalarBinaryOpTraits<OtherScalarType, typename MatrixType::Scalar>::ReturnType ResultScalar;
109 typedef Matrix<ResultScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime, 0,
110 MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime>
111 Type;
112};
113
114} // end namespace internal
115
116template <typename VectorsType, typename CoeffsType, int Side>
117class HouseholderSequence : public EigenBase<HouseholderSequence<VectorsType, CoeffsType, Side> > {
120
121 public:
122 enum {
123 RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
124 ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
125 MaxRowsAtCompileTime = internal::traits<HouseholderSequence>::MaxRowsAtCompileTime,
126 MaxColsAtCompileTime = internal::traits<HouseholderSequence>::MaxColsAtCompileTime
127 };
128 typedef typename internal::traits<HouseholderSequence>::Scalar Scalar;
129
130 typedef HouseholderSequence<
131 std::conditional_t<NumTraits<Scalar>::IsComplex,
132 internal::remove_all_t<typename VectorsType::ConjugateReturnType>, VectorsType>,
133 std::conditional_t<NumTraits<Scalar>::IsComplex, internal::remove_all_t<typename CoeffsType::ConjugateReturnType>,
134 CoeffsType>,
135 Side>
137
138 typedef HouseholderSequence<
139 VectorsType,
140 std::conditional_t<NumTraits<Scalar>::IsComplex, internal::remove_all_t<typename CoeffsType::ConjugateReturnType>,
141 CoeffsType>,
142 Side>
144
145 typedef HouseholderSequence<
146 std::conditional_t<NumTraits<Scalar>::IsComplex,
147 internal::remove_all_t<typename VectorsType::ConjugateReturnType>, VectorsType>,
148 CoeffsType, Side>
150
151 typedef HouseholderSequence<std::add_const_t<VectorsType>, std::add_const_t<CoeffsType>, Side>
153
171 EIGEN_DEVICE_FUNC HouseholderSequence(const VectorsType& v, const CoeffsType& h)
172 : m_vectors(v), m_coeffs(h), m_reverse(false), m_length(v.diagonalSize()), m_shift(0) {}
173
175 EIGEN_DEVICE_FUNC HouseholderSequence(const HouseholderSequence& other)
176 : m_vectors(other.m_vectors),
177 m_coeffs(other.m_coeffs),
178 m_reverse(other.m_reverse),
179 m_length(other.m_length),
180 m_shift(other.m_shift) {}
181
186 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT {
187 return Side == OnTheLeft ? m_vectors.rows() : m_vectors.cols();
188 }
189
194 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return rows(); }
195
210 EIGEN_DEVICE_FUNC const EssentialVectorType essentialVector(Index k) const {
211 eigen_assert(k >= 0 && k < m_length);
212 return internal::hseq_side_dependent_impl<VectorsType, CoeffsType, Side>::essentialVector(*this, k);
213 }
214
217 return TransposeReturnType(m_vectors.conjugate(), m_coeffs)
218 .setReverseFlag(!m_reverse)
219 .setLength(m_length)
220 .setShift(m_shift);
221 }
222
225 return ConjugateReturnType(m_vectors.conjugate(), m_coeffs.conjugate())
226 .setReverseFlag(m_reverse)
227 .setLength(m_length)
228 .setShift(m_shift);
229 }
230
234 template <bool Cond>
235 EIGEN_DEVICE_FUNC inline std::conditional_t<Cond, ConjugateReturnType, ConstHouseholderSequence> conjugateIf() const {
236 typedef std::conditional_t<Cond, ConjugateReturnType, ConstHouseholderSequence> ReturnType;
237 return ReturnType(m_vectors.template conjugateIf<Cond>(), m_coeffs.template conjugateIf<Cond>());
238 }
239
242 return AdjointReturnType(m_vectors, m_coeffs.conjugate())
243 .setReverseFlag(!m_reverse)
244 .setLength(m_length)
245 .setShift(m_shift);
246 }
247
249 AdjointReturnType inverse() const { return adjoint(); }
250
252 template <typename DestType>
253 inline EIGEN_DEVICE_FUNC void evalTo(DestType& dst) const {
255 rows());
256 evalTo(dst, workspace);
257 }
258
260 template <typename Dest, typename Workspace>
261 EIGEN_DEVICE_FUNC void evalTo(Dest& dst, Workspace& workspace) const {
262 workspace.resize(rows());
263 Index vecs = m_length;
264 if (internal::is_same_dense(dst, m_vectors)) {
265 // in-place
266 dst.diagonal().setOnes();
267 dst.template triangularView<StrictlyUpper>().setZero();
268 for (Index k = vecs - 1; k >= 0; --k) {
269 Index cornerSize = rows() - k - m_shift;
270 if (m_reverse)
271 dst.bottomRightCorner(cornerSize, cornerSize)
272 .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
273 else
274 dst.bottomRightCorner(cornerSize, cornerSize)
275 .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
276
277 // clear the off diagonal vector
278 dst.col(k).tail(rows() - k - 1).setZero();
279 }
280 // clear the remaining columns if needed
281 for (Index k = 0; k < cols() - vecs; ++k) dst.col(k).tail(rows() - k - 1).setZero();
282 } else if (m_length > BlockSize) {
283 dst.setIdentity(rows(), rows());
284 if (m_reverse)
285 applyThisOnTheLeft(dst, workspace, true);
286 else
287 applyThisOnTheLeft(dst, workspace, true);
288 } else {
289 dst.setIdentity(rows(), rows());
290 for (Index k = vecs - 1; k >= 0; --k) {
291 Index cornerSize = rows() - k - m_shift;
292 if (m_reverse)
293 dst.bottomRightCorner(cornerSize, cornerSize)
294 .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
295 else
296 dst.bottomRightCorner(cornerSize, cornerSize)
297 .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
298 }
299 }
300 }
301
303 template <typename Dest>
304 inline void applyThisOnTheRight(Dest& dst) const {
305 Matrix<Scalar, 1, Dest::RowsAtCompileTime, RowMajor, 1, Dest::MaxRowsAtCompileTime> workspace(dst.rows());
306 applyThisOnTheRight(dst, workspace);
307 }
308
310 template <typename Dest, typename Workspace>
311 inline void applyThisOnTheRight(Dest& dst, Workspace& workspace) const {
312 workspace.resize(dst.rows());
313 for (Index k = 0; k < m_length; ++k) {
314 Index actual_k = m_reverse ? m_length - k - 1 : k;
315 dst.rightCols(rows() - m_shift - actual_k)
316 .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
317 }
318 }
319
321 template <typename Dest>
322 inline void applyThisOnTheLeft(Dest& dst, bool inputIsIdentity = false) const {
323 Matrix<Scalar, 1, Dest::ColsAtCompileTime, RowMajor, 1, Dest::MaxColsAtCompileTime> workspace;
324 applyThisOnTheLeft(dst, workspace, inputIsIdentity);
325 }
326
328 template <typename Dest, typename Workspace>
329 inline void applyThisOnTheLeft(Dest& dst, Workspace& workspace, bool inputIsIdentity = false) const {
330 if (inputIsIdentity && m_reverse) inputIsIdentity = false;
331 // if the entries are large enough, then apply the reflectors by block
332 if (m_length >= BlockSize && dst.cols() > 1) {
333 // Make sure we have at least 2 useful blocks, otherwise it is point-less:
334 Index blockSize = m_length < Index(2 * BlockSize) ? (m_length + 1) / 2 : Index(BlockSize);
335 for (Index i = 0; i < m_length; i += blockSize) {
336 Index end = m_reverse ? (std::min)(m_length, i + blockSize) : m_length - i;
337 Index k = m_reverse ? i : (std::max)(Index(0), end - blockSize);
338 Index bs = end - k;
339 Index start = k + m_shift;
340
341 typedef Block<internal::remove_all_t<VectorsType>, Dynamic, Dynamic> SubVectorsType;
342 SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side == OnTheRight ? k : start,
343 Side == OnTheRight ? start : k, Side == OnTheRight ? bs : m_vectors.rows() - start,
344 Side == OnTheRight ? m_vectors.cols() - start : bs);
345 std::conditional_t<Side == OnTheRight, Transpose<SubVectorsType>, SubVectorsType&> sub_vecs(sub_vecs1);
346
347 Index dstRows = rows() - m_shift - k;
348
349 if (inputIsIdentity) {
350 Block<Dest, Dynamic, Dynamic> sub_dst = dst.bottomRightCorner(dstRows, dstRows);
351 apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse);
352 } else {
353 auto sub_dst = dst.bottomRows(dstRows);
354 apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse);
355 }
356 }
357 } else {
358 workspace.resize(dst.cols());
359 for (Index k = 0; k < m_length; ++k) {
360 Index actual_k = m_reverse ? k : m_length - k - 1;
361 Index dstRows = rows() - m_shift - actual_k;
362
363 if (inputIsIdentity) {
364 Block<Dest, Dynamic, Dynamic> sub_dst = dst.bottomRightCorner(dstRows, dstRows);
365 sub_dst.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
366 } else {
367 auto sub_dst = dst.bottomRows(dstRows);
368 sub_dst.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
369 }
370 }
371 }
372 }
373
381 template <typename OtherDerived>
383 const MatrixBase<OtherDerived>& other) const {
385 other.template cast<typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::ResultScalar>());
386 applyThisOnTheLeft(res, internal::is_identity<OtherDerived>::value && res.rows() == res.cols());
387 return res;
388 }
389
390 template <typename VectorsType_, typename CoeffsType_, int Side_>
391 friend struct internal::hseq_side_dependent_impl;
392
403 m_length = length;
404 return *this;
405 }
406
419 m_shift = shift;
420 return *this;
421 }
422
423 EIGEN_DEVICE_FUNC Index length() const {
424 return m_length;
425 }
427 EIGEN_DEVICE_FUNC Index shift() const {
428 return m_shift;
429 }
431 /* Necessary for .adjoint() and .conjugate() */
432 template <typename VectorsType2, typename CoeffsType2, int Side2>
433 friend class HouseholderSequence;
434
435 protected:
446 HouseholderSequence& setReverseFlag(bool reverse) {
447 m_reverse = reverse;
448 return *this;
449 }
450
451 bool reverseFlag() const { return m_reverse; }
453 typename VectorsType::Nested m_vectors;
454 typename CoeffsType::Nested m_coeffs;
455 bool m_reverse;
456 Index m_length;
457 Index m_shift;
458 enum { BlockSize = 48 };
459};
460
469template <typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
473 other.template cast<typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,
474 OtherDerived>::ResultScalar>());
475 h.applyThisOnTheRight(res);
476 return res;
477}
478
483template <typename VectorsType, typename CoeffsType>
487
494template <typename VectorsType, typename CoeffsType>
499
500} // end namespace Eigen
501
502#endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
Expression of a fixed-size or dynamic-size block.
Definition Block.h:110
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition HouseholderSequence.h:117
AdjointReturnType inverse() const
Inverse of the Householder sequence (equals the adjoint).
Definition HouseholderSequence.h:249
HouseholderSequence & setLength(Index length)
Sets the length of the Householder sequence.
Definition HouseholderSequence.h:402
std::conditional_t< Cond, ConjugateReturnType, ConstHouseholderSequence > conjugateIf() const
Definition HouseholderSequence.h:235
Index shift() const
Returns the shift of the Householder sequence.
Definition HouseholderSequence.h:427
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Number of columns of transformation viewed as a matrix.
Definition HouseholderSequence.h:194
HouseholderSequence & setShift(Index shift)
Sets the shift of the Householder sequence.
Definition HouseholderSequence.h:418
HouseholderSequence(const HouseholderSequence &other)
Copy constructor.
Definition HouseholderSequence.h:175
internal::matrix_type_times_scalar_type< Scalar, OtherDerived >::Type operator*(const MatrixBase< OtherDerived > &other) const
Computes the product of a Householder sequence with a matrix.
Definition HouseholderSequence.h:382
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Number of rows of transformation viewed as a matrix.
Definition HouseholderSequence.h:186
Index length() const
Returns the length of the Householder sequence.
Definition HouseholderSequence.h:423
ConjugateReturnType conjugate() const
Complex conjugate of the Householder sequence.
Definition HouseholderSequence.h:224
const EssentialVectorType essentialVector(Index k) const
Essential part of a Householder vector.
Definition HouseholderSequence.h:210
TransposeReturnType transpose() const
Transpose of the Householder sequence.
Definition HouseholderSequence.h:216
AdjointReturnType adjoint() const
Adjoint (conjugate transpose) of the Householder sequence.
Definition HouseholderSequence.h:241
HouseholderSequence(const VectorsType &v, const CoeffsType &h)
Constructor.
Definition HouseholderSequence.h:171
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition HouseholderSequence.h:484
HouseholderSequence< VectorsType, CoeffsType, OnTheRight > rightHouseholderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition HouseholderSequence.h:495
@ OnTheLeft
Definition Constants.h:331
@ OnTheRight
Definition Constants.h:333
Namespace containing all symbols from the Eigen library.
Definition Core:137
const int Dynamic
Definition Constants.h:25
Definition EigenBase.h:33