Eigen  5.0.1
 
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 <gael.guennebaud@inria.fr>
5// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
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// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
13#define EIGEN_HOUSEHOLDER_SEQUENCE_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
60
61namespace internal {
62
63template <typename VectorsType, typename CoeffsType, int Side>
64struct traits<HouseholderSequence<VectorsType, CoeffsType, Side> > {
65 using Scalar = typename VectorsType::Scalar;
66 using StorageIndex = typename VectorsType::StorageIndex;
67 using StorageKind = typename VectorsType::StorageKind;
68 enum {
69 RowsAtCompileTime =
70 Side == OnTheLeft ? traits<VectorsType>::RowsAtCompileTime : traits<VectorsType>::ColsAtCompileTime,
71 ColsAtCompileTime = RowsAtCompileTime,
72 MaxRowsAtCompileTime =
73 Side == OnTheLeft ? traits<VectorsType>::MaxRowsAtCompileTime : traits<VectorsType>::MaxColsAtCompileTime,
74 MaxColsAtCompileTime = MaxRowsAtCompileTime,
75 Flags = 0
76 };
77};
78
79struct HouseholderSequenceShape {};
80
81template <typename VectorsType, typename CoeffsType, int Side>
82struct evaluator_traits<HouseholderSequence<VectorsType, CoeffsType, Side> >
83 : public evaluator_traits_base<HouseholderSequence<VectorsType, CoeffsType, Side> > {
84 using Shape = HouseholderSequenceShape;
85};
86
87template <typename VectorsType, typename CoeffsType, int Side>
88struct hseq_side_dependent_impl {
89 using EssentialVectorType = Block<const VectorsType, Dynamic, 1>;
90 using HouseholderSequenceType = HouseholderSequence<VectorsType, CoeffsType, OnTheLeft>;
91 static EIGEN_DEVICE_FUNC inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k) {
92 Index start = k + 1 + h.m_shift;
93 return Block<const VectorsType, Dynamic, 1>(h.m_vectors, start, k, h.rows() - start, 1);
94 }
95};
96
97template <typename VectorsType, typename CoeffsType>
98struct hseq_side_dependent_impl<VectorsType, CoeffsType, OnTheRight> {
99 using EssentialVectorType = Transpose<Block<const VectorsType, 1, Dynamic>>;
100 using HouseholderSequenceType = HouseholderSequence<VectorsType, CoeffsType, OnTheRight>;
101 static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k) {
102 Index start = k + 1 + h.m_shift;
103 return Block<const VectorsType, 1, Dynamic>(h.m_vectors, k, start, 1, h.rows() - start).transpose();
104 }
105};
106
107template <typename OtherScalarType, typename MatrixType>
108struct matrix_type_times_scalar_type {
109 using ResultScalar = typename ScalarBinaryOpTraits<OtherScalarType, typename MatrixType::Scalar>::ReturnType;
110 using Type =
111 Matrix<ResultScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
112 (MatrixType::MaxRowsAtCompileTime == 1 && MatrixType::MaxColsAtCompileTime != 1) ? RowMajor : ColMajor,
113 MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime>;
114};
115
116// A permutation has no scalar type; its product with a Householder sequence takes the sequence's.
117template <typename Scalar, typename PermutationType>
118struct permutation_type_as_matrix_type {
119 using Type = Matrix<Scalar, PermutationType::RowsAtCompileTime, PermutationType::ColsAtCompileTime, 0,
120 PermutationType::MaxRowsAtCompileTime, PermutationType::MaxColsAtCompileTime>;
121};
122
123// A diagonal or triangular operand is assigned to the result directly when the scalar types agree. The triangular
124// assignment kernel does not convert scalars, so a promoted result evaluates the operand and casts it, as the dense
125// product casts its operand.
126template <typename ResultType, typename OtherDerived>
127std::enable_if_t<std::is_same<typename ResultType::Scalar, typename OtherDerived::Scalar>::value>
128assign_householder_operand(ResultType& res, const EigenBase<OtherDerived>& other) {
129 res = other.derived();
130}
131template <typename ResultType, typename OtherDerived>
132std::enable_if_t<!std::is_same<typename ResultType::Scalar, typename OtherDerived::Scalar>::value>
133assign_householder_operand(ResultType& res, const EigenBase<OtherDerived>& other) {
134 res = other.derived().toDenseMatrix().template cast<typename ResultType::Scalar>();
135}
136
137} // end namespace internal
138
139template <typename VectorsType, typename CoeffsType, int Side>
140class HouseholderSequence : public EigenBase<HouseholderSequence<VectorsType, CoeffsType, Side> > {
141 using EssentialVectorType =
142 typename internal::hseq_side_dependent_impl<VectorsType, CoeffsType, Side>::EssentialVectorType;
143
144 public:
145 enum {
146 RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
147 ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
148 MaxRowsAtCompileTime = internal::traits<HouseholderSequence>::MaxRowsAtCompileTime,
149 MaxColsAtCompileTime = internal::traits<HouseholderSequence>::MaxColsAtCompileTime
150 };
151 using Scalar = typename internal::traits<HouseholderSequence>::Scalar;
152
153 using ConjugateReturnType = HouseholderSequence<
154 std::conditional_t<NumTraits<Scalar>::IsComplex,
155 internal::remove_all_t<typename VectorsType::ConjugateReturnType>, VectorsType>,
156 std::conditional_t<NumTraits<Scalar>::IsComplex, internal::remove_all_t<typename CoeffsType::ConjugateReturnType>,
157 CoeffsType>,
158 Side>;
159
160 using AdjointReturnType = HouseholderSequence<
161 VectorsType,
162 std::conditional_t<NumTraits<Scalar>::IsComplex, internal::remove_all_t<typename CoeffsType::ConjugateReturnType>,
163 CoeffsType>,
164 Side>;
165
166 using TransposeReturnType = HouseholderSequence<
167 std::conditional_t<NumTraits<Scalar>::IsComplex,
168 internal::remove_all_t<typename VectorsType::ConjugateReturnType>, VectorsType>,
169 CoeffsType, Side>;
170
171 using ConstHouseholderSequence =
172 HouseholderSequence<std::add_const_t<VectorsType>, std::add_const_t<CoeffsType>, Side>;
173
191 EIGEN_DEVICE_FUNC HouseholderSequence(const VectorsType& v, const CoeffsType& h)
192 : m_vectors(v), m_coeffs(h), m_reverse(false), m_length(v.diagonalSize()), m_shift(0) {}
193
195 EIGEN_DEVICE_FUNC HouseholderSequence(const HouseholderSequence& other)
196 : m_vectors(other.m_vectors),
197 m_coeffs(other.m_coeffs),
198 m_reverse(other.m_reverse),
199 m_length(other.m_length),
200 m_shift(other.m_shift) {}
201
206 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept {
207 return Side == OnTheLeft ? m_vectors.rows() : m_vectors.cols();
208 }
209
214 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return rows(); }
215
230 EIGEN_DEVICE_FUNC const EssentialVectorType essentialVector(Index k) const {
231 eigen_assert(k >= 0 && k < m_length);
232 return internal::hseq_side_dependent_impl<VectorsType, CoeffsType, Side>::essentialVector(*this, k);
233 }
234
236 TransposeReturnType transpose() const {
237 return TransposeReturnType(m_vectors.conjugate(), m_coeffs)
238 .setReverseFlag(!m_reverse)
239 .setLength(m_length)
240 .setShift(m_shift);
241 }
242
244 ConjugateReturnType conjugate() const {
245 return ConjugateReturnType(m_vectors.conjugate(), m_coeffs.conjugate())
246 .setReverseFlag(m_reverse)
247 .setLength(m_length)
248 .setShift(m_shift);
249 }
250
257 template <bool Cond>
258 EIGEN_DEVICE_FUNC inline std::conditional_t<Cond, ConjugateReturnType, ConstHouseholderSequence> conjugateIf() const {
259 using ReturnType = std::conditional_t<Cond, ConjugateReturnType, ConstHouseholderSequence>;
260 return ReturnType(m_vectors.template conjugateIf<Cond>(), m_coeffs.template conjugateIf<Cond>());
261 }
262
264 AdjointReturnType adjoint() const {
265 return AdjointReturnType(m_vectors, m_coeffs.conjugate())
266 .setReverseFlag(!m_reverse)
267 .setLength(m_length)
268 .setShift(m_shift);
269 }
270
272 AdjointReturnType inverse() const { return adjoint(); }
273
275 template <typename DestType>
276 inline EIGEN_DEVICE_FUNC void evalTo(DestType& dst) const {
278 rows());
279 evalTo(dst, workspace);
280 }
281
283 template <typename Dest, typename Workspace>
284 EIGEN_DEVICE_FUNC void evalTo(Dest& dst, Workspace& workspace) const {
285 workspace.resize(rows());
286 Index vecs = m_length;
287 if (internal::is_same_dense(dst, m_vectors)) {
288 // in-place
289 dst.diagonal().setOnes();
290 dst.template triangularView<StrictlyUpper>().setZero();
291 for (Index k = vecs - 1; k >= 0; --k) {
292 Index cornerSize = rows() - k - m_shift;
293 if (m_reverse)
294 dst.bottomRightCorner(cornerSize, cornerSize)
295 .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
296 else
297 dst.bottomRightCorner(cornerSize, cornerSize)
298 .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
299
300 // clear the off diagonal vector
301 dst.col(k).tail(rows() - k - 1).setZero();
302 }
303 // clear the remaining columns if needed
304 for (Index k = 0; k < cols() - vecs; ++k) dst.col(k).tail(rows() - k - 1).setZero();
305 } else if (m_length > BlockSize) {
306 dst.setIdentity(rows(), rows());
307 applyThisOnTheLeft(dst, workspace, true);
308 } else {
309 dst.setIdentity(rows(), rows());
310 for (Index k = vecs - 1; k >= 0; --k) {
311 Index cornerSize = rows() - k - m_shift;
312 if (m_reverse)
313 dst.bottomRightCorner(cornerSize, cornerSize)
314 .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
315 else
316 dst.bottomRightCorner(cornerSize, cornerSize)
317 .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
318 }
319 }
320 }
321
323 template <typename Dest>
324 inline void applyThisOnTheRight(Dest& dst) const {
325 Matrix<Scalar, 1, Dest::RowsAtCompileTime, RowMajor, 1, Dest::MaxRowsAtCompileTime> workspace(dst.rows());
326 applyThisOnTheRight(dst, workspace);
327 }
328
330 template <typename Dest, typename Workspace>
331 inline void applyThisOnTheRight(Dest& dst, Workspace& workspace) const {
332 // Use the block path when the reflectors are long enough for GEMM to outperform GEMV.
333 // The threshold on rows() (the reflector length) is higher than for the left-side path because
334 // the right-side block application has more overhead from the tmp = mat * V product layout.
335 if (m_length >= BlockSize && rows() - m_shift >= 4 * BlockSize) {
336 applyBlockOnTheRight(dst);
337 } else {
338 workspace.resize(dst.rows());
339 for (Index k = 0; k < m_length; ++k) {
340 Index actual_k = m_reverse ? m_length - k - 1 : k;
341 dst.rightCols(rows() - m_shift - actual_k)
342 .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
343 }
344 }
345 }
346
347 private:
350 template <typename Dest>
351 EIGEN_DONT_INLINE void applyBlockOnTheRight(Dest& dst) const {
352 // Make sure we have at least 2 useful blocks, otherwise it is point-less:
353 Index blockSize = m_length < Index(2 * BlockSize) ? (m_length + 1) / 2 : Index(BlockSize);
354 for (Index i = 0; i < m_length; i += blockSize) {
355 // Right-side application processes blocks in opposite order to left-side:
356 // forward (m_reverse=false): first block first; reversed: last block first.
357 Index end = m_reverse ? m_length - i : (std::min)(m_length, i + blockSize);
358 Index k = m_reverse ? (std::max)(Index(0), end - blockSize) : i;
359 Index bs = end - k;
360 Index start = k + m_shift;
361
362 using SubVectorsType = Block<internal::remove_all_t<VectorsType>, Dynamic, Dynamic>;
363 SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side == OnTheRight ? k : start,
364 Side == OnTheRight ? start : k, Side == OnTheRight ? bs : m_vectors.rows() - start,
365 Side == OnTheRight ? m_vectors.cols() - start : bs);
366 std::conditional_t<Side == OnTheRight, Transpose<SubVectorsType>, SubVectorsType&> sub_vecs(sub_vecs1);
367
368 Index dstCols = rows() - m_shift - k;
369 auto sub_dst = dst.rightCols(dstCols);
370 internal::apply_block_householder_on_the_right(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse);
371 }
372 }
373
374 public:
376 template <typename Dest>
377 inline void applyThisOnTheLeft(Dest& dst, bool inputIsIdentity = false) const {
378 Matrix<Scalar, 1, Dest::ColsAtCompileTime, RowMajor, 1, Dest::MaxColsAtCompileTime> workspace;
379 applyThisOnTheLeft(dst, workspace, inputIsIdentity);
380 }
381
383 template <typename Dest, typename Workspace>
384 inline void applyThisOnTheLeft(Dest& dst, Workspace& workspace, bool inputIsIdentity = false) const {
385 if (inputIsIdentity && m_reverse) inputIsIdentity = false;
386 // if the entries are large enough, then apply the reflectors by block
387 if (m_length >= BlockSize && dst.cols() > 1) {
388 // Make sure we have at least 2 useful blocks, otherwise it is point-less:
389 Index blockSize = m_length < Index(2 * BlockSize) ? (m_length + 1) / 2 : Index(BlockSize);
390 for (Index i = 0; i < m_length; i += blockSize) {
391 Index end = m_reverse ? (std::min)(m_length, i + blockSize) : m_length - i;
392 Index k = m_reverse ? i : (std::max)(Index(0), end - blockSize);
393 Index bs = end - k;
394 Index start = k + m_shift;
395
396 using SubVectorsType = Block<internal::remove_all_t<VectorsType>, Dynamic, Dynamic>;
397 SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side == OnTheRight ? k : start,
398 Side == OnTheRight ? start : k, Side == OnTheRight ? bs : m_vectors.rows() - start,
399 Side == OnTheRight ? m_vectors.cols() - start : bs);
400 std::conditional_t<Side == OnTheRight, Transpose<SubVectorsType>, SubVectorsType&> sub_vecs(sub_vecs1);
401
402 Index dstRows = rows() - m_shift - k;
403
404 if (inputIsIdentity) {
405 Block<Dest, Dynamic, Dynamic> sub_dst = dst.bottomRightCorner(dstRows, dstRows);
406 apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse);
407 } else {
408 auto sub_dst = dst.bottomRows(dstRows);
409 apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse);
410 }
411 }
412 } else {
413 workspace.resize(dst.cols());
414 for (Index k = 0; k < m_length; ++k) {
415 Index actual_k = m_reverse ? k : m_length - k - 1;
416 Index dstRows = rows() - m_shift - actual_k;
417
418 if (inputIsIdentity) {
419 Block<Dest, Dynamic, Dynamic> sub_dst = dst.bottomRightCorner(dstRows, dstRows);
420 sub_dst.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
421 } else {
422 auto sub_dst = dst.bottomRows(dstRows);
423 sub_dst.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
424 }
425 }
426 }
427 }
428
436 template <typename OtherDerived>
437 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type operator*(
438 const MatrixBase<OtherDerived>& other) const {
439 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type res(
440 other.template cast<typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::ResultScalar>());
441 applyThisOnTheLeft(res, internal::is_identity<OtherDerived>::value && res.rows() == res.cols());
442 return res;
443 }
444
450 template <typename OtherDerived>
451 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type operator*(
452 const DiagonalBase<OtherDerived>& other) const {
453 return applyToUpperTriangularOnTheLeft<
454 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type>(other, true);
455 }
456
462 template <typename OtherDerived>
463 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type operator*(
464 const TriangularBase<OtherDerived>& other) const {
465 constexpr bool kUpperTriangular =
466 (int(OtherDerived::Mode) & (int(Upper) | int(Lower) | int(SelfAdjoint))) == int(Upper);
467 return applyToUpperTriangularOnTheLeft<
468 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type>(other, kUpperTriangular);
469 }
470
476 template <typename OtherDerived>
477 typename internal::permutation_type_as_matrix_type<Scalar, OtherDerived>::Type operator*(
478 const PermutationBase<OtherDerived>& other) const {
479 using ResultType = typename internal::permutation_type_as_matrix_type<Scalar, OtherDerived>::Type;
480 eigen_assert(cols() == other.rows());
481 ResultType res = ResultType::Identity(rows(), rows());
482 applyThisOnTheLeft(res, true);
483 // The permutation product runs in place when its operand is the destination.
484 res.noalias() = res * other.derived();
485 return res;
486 }
487
489 template <typename OtherDerived>
490 typename internal::permutation_type_as_matrix_type<Scalar, Inverse<OtherDerived>>::Type operator*(
491 const InverseImpl<OtherDerived, PermutationStorage>& other) const {
492 using ResultType = typename internal::permutation_type_as_matrix_type<Scalar, Inverse<OtherDerived>>::Type;
493 eigen_assert(cols() == other.rows());
494 ResultType res = ResultType::Identity(rows(), rows());
495 applyThisOnTheLeft(res, true);
496 res.noalias() = res * other.derived();
497 return res;
498 }
499
500 template <typename VectorsType_, typename CoeffsType_, int Side_>
501 friend struct internal::hseq_side_dependent_impl;
502
503 private:
504 // The identity path of applyThisOnTheLeft() skips the columns left of the rows each reflection acts on, which is
505 // valid for any square input that vanishes below the diagonal: a diagonal or upper triangular matrix as much as
506 // the identity. Other inputs take the full path.
507 template <typename ResultType, typename OtherDerived>
508 ResultType applyToUpperTriangularOnTheLeft(const EigenBase<OtherDerived>& other, bool upperTriangular) const {
509 eigen_assert(cols() == other.rows());
510 ResultType res;
511 internal::assign_householder_operand(res, other);
512 applyThisOnTheLeft(res, upperTriangular && res.rows() == res.cols());
513 return res;
514 }
515
516 public:
526 EIGEN_DEVICE_FUNC HouseholderSequence& setLength(Index length) {
527 m_length = length;
528 return *this;
529 }
530
542 EIGEN_DEVICE_FUNC HouseholderSequence& setShift(Index shift) {
543 m_shift = shift;
544 return *this;
545 }
546
547 EIGEN_DEVICE_FUNC Index length() const {
548 return m_length;
549 }
550
551 EIGEN_DEVICE_FUNC Index shift() const {
552 return m_shift;
553 }
554
555 /* Necessary for .adjoint() and .conjugate() */
556 template <typename VectorsType2, typename CoeffsType2, int Side2>
557 friend class HouseholderSequence;
558
559 protected:
570 HouseholderSequence& setReverseFlag(bool reverse) {
571 m_reverse = reverse;
572 return *this;
573 }
574
575 bool reverseFlag() const { return m_reverse; }
576
577 typename VectorsType::Nested m_vectors;
578 typename CoeffsType::Nested m_coeffs;
579 bool m_reverse;
580 Index m_length;
581 Index m_shift;
582 enum { BlockSize = 48 };
583};
584
593template <typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
594typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type operator*(
596 typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type res(
597 other.template cast<typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,
598 OtherDerived>::ResultScalar>());
599 h.applyThisOnTheRight(res);
600 return res;
601}
602
607template <typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
608typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type operator*(
610 using ResultType = typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type;
611 eigen_assert(other.cols() == h.rows());
612 ResultType res = ResultType::Identity(h.rows(), h.rows());
613 h.applyThisOnTheLeft(res, true);
614 // The lazy diagonal product multiplies from the left, D(i,i) * H(i,j), as a noncommutative scalar requires, and
615 // reads each coefficient only to overwrite it, so it runs in place.
616 res = other.derived() * res;
617 return res;
618}
619
625template <typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
626typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type operator*(
628 using ResultType = typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type;
629 ResultType res;
630 internal::assign_householder_operand(res, other);
631 h.applyThisOnTheRight(res);
632 return res;
633}
634
640template <typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
641typename internal::permutation_type_as_matrix_type<typename VectorsType::Scalar, OtherDerived>::Type operator*(
643 using ResultType =
644 typename internal::permutation_type_as_matrix_type<typename VectorsType::Scalar, OtherDerived>::Type;
645 eigen_assert(other.cols() == h.rows());
646 ResultType res = ResultType::Identity(h.rows(), h.rows());
647 h.applyThisOnTheLeft(res, true);
648 // The permutation product runs in place when its operand is the destination.
649 res.noalias() = other.derived() * res;
650 return res;
651}
652
654template <typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
655typename internal::permutation_type_as_matrix_type<typename VectorsType::Scalar, Inverse<OtherDerived>>::Type operator*(
656 const InverseImpl<OtherDerived, PermutationStorage>& other,
658 using ResultType =
659 typename internal::permutation_type_as_matrix_type<typename VectorsType::Scalar, Inverse<OtherDerived>>::Type;
660 eigen_assert(other.cols() == h.rows());
661 ResultType res = ResultType::Identity(h.rows(), h.rows());
662 h.applyThisOnTheLeft(res, true);
663 res.noalias() = other.derived() * res;
664 return res;
665}
666
672template <typename VectorsType, typename CoeffsType>
676
684template <typename VectorsType, typename CoeffsType>
689
690} // end namespace Eigen
691
692#endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
Base class for diagonal matrices and expressions.
Definition DiagonalMatrix.h:34
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition HouseholderSequence.h:140
AdjointReturnType inverse() const
Inverse of the Householder sequence (equals the adjoint).
Definition HouseholderSequence.h:272
HouseholderSequence & setLength(Index length)
Sets the length of the Householder sequence.
Definition HouseholderSequence.h:526
std::conditional_t< Cond, ConjugateReturnType, ConstHouseholderSequence > conjugateIf() const
Definition HouseholderSequence.h:258
internal::permutation_type_as_matrix_type< Scalar, OtherDerived >::Type operator*(const PermutationBase< OtherDerived > &other) const
Computes the product of a Householder sequence with a permutation matrix.
Definition HouseholderSequence.h:477
internal::permutation_type_as_matrix_type< Scalar, Inverse< OtherDerived > >::Type operator*(const InverseImpl< OtherDerived, PermutationStorage > &other) const
Computes the product of a Householder sequence with the inverse of a permutation matrix.
Definition HouseholderSequence.h:490
constexpr Index cols() const noexcept
Number of columns of transformation viewed as a matrix.
Definition HouseholderSequence.h:214
constexpr Index rows() const noexcept
Number of rows of transformation viewed as a matrix.
Definition HouseholderSequence.h:206
HouseholderSequence & setShift(Index shift)
Sets the shift of the Householder sequence.
Definition HouseholderSequence.h:542
HouseholderSequence(const HouseholderSequence &other)
Copy constructor.
Definition HouseholderSequence.h:195
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:437
internal::matrix_type_times_scalar_type< Scalar, OtherDerived >::Type operator*(const DiagonalBase< OtherDerived > &other) const
Computes the product of a Householder sequence with a diagonal matrix.
Definition HouseholderSequence.h:451
ConjugateReturnType conjugate() const
Complex conjugate of the Householder sequence.
Definition HouseholderSequence.h:244
const EssentialVectorType essentialVector(Index k) const
Essential part of a Householder vector.
Definition HouseholderSequence.h:230
TransposeReturnType transpose() const
Transpose of the Householder sequence.
Definition HouseholderSequence.h:236
AdjointReturnType adjoint() const
Adjoint (conjugate transpose) of the Householder sequence.
Definition HouseholderSequence.h:264
HouseholderSequence(const VectorsType &v, const CoeffsType &h)
Constructor.
Definition HouseholderSequence.h:191
internal::matrix_type_times_scalar_type< Scalar, OtherDerived >::Type operator*(const TriangularBase< OtherDerived > &other) const
Computes the product of a Householder sequence with a triangular or self-adjoint view.
Definition HouseholderSequence.h:463
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Base class for permutations.
Definition PermutationMatrix.h:92
Index rows() const
Definition PermutationMatrix.h:133
Base class for triangular part in a matrix.
Definition TriangularMatrix.h:68
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition HouseholderSequence.h:673
HouseholderSequence< VectorsType, CoeffsType, OnTheRight > rightHouseholderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition HouseholderSequence.h:685
@ SelfAdjoint
Definition Constants.h:228
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
@ OnTheLeft
Definition Constants.h:332
@ OnTheRight
Definition Constants.h:334
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
constexpr Index rows() const noexcept
Definition EigenBase.h:60
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44