12#ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
13#define EIGEN_HOUSEHOLDER_SEQUENCE_H
16#include "./InternalHeaderCheck.h"
63template <
typename VectorsType,
typename CoeffsType,
int S
ide>
64struct traits<HouseholderSequence<VectorsType, CoeffsType, Side> > {
65 using Scalar =
typename VectorsType::Scalar;
66 using StorageIndex =
typename VectorsType::StorageIndex;
67 using StorageKind =
typename VectorsType::StorageKind;
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,
79struct HouseholderSequenceShape {};
81template <
typename VectorsType,
typename CoeffsType,
int S
ide>
82struct evaluator_traits<HouseholderSequence<VectorsType, CoeffsType, Side> >
83 :
public evaluator_traits_base<HouseholderSequence<VectorsType, CoeffsType, Side> > {
84 using Shape = HouseholderSequenceShape;
87template <
typename VectorsType,
typename CoeffsType,
int S
ide>
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);
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();
107template <
typename OtherScalarType,
typename MatrixType>
108struct matrix_type_times_scalar_type {
109 using ResultScalar =
typename ScalarBinaryOpTraits<OtherScalarType, typename MatrixType::Scalar>::ReturnType;
111 Matrix<ResultScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
112 (MatrixType::MaxRowsAtCompileTime == 1 && MatrixType::MaxColsAtCompileTime != 1) ?
RowMajor :
ColMajor,
113 MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime>;
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>;
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();
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>();
139template <
typename VectorsType,
typename CoeffsType,
int S
ide>
140class HouseholderSequence :
public EigenBase<HouseholderSequence<VectorsType, CoeffsType, Side> > {
141 using EssentialVectorType =
142 typename internal::hseq_side_dependent_impl<VectorsType, CoeffsType, Side>::EssentialVectorType;
146 RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
147 ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
148 MaxRowsAtCompileTime = internal::traits<HouseholderSequence>::MaxRowsAtCompileTime,
149 MaxColsAtCompileTime = internal::traits<HouseholderSequence>::MaxColsAtCompileTime
151 using Scalar =
typename internal::traits<HouseholderSequence>::Scalar;
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>,
160 using AdjointReturnType = HouseholderSequence<
162 std::conditional_t<NumTraits<Scalar>::IsComplex, internal::remove_all_t<typename CoeffsType::ConjugateReturnType>,
166 using TransposeReturnType = HouseholderSequence<
167 std::conditional_t<NumTraits<Scalar>::IsComplex,
168 internal::remove_all_t<typename VectorsType::ConjugateReturnType>, VectorsType>,
171 using ConstHouseholderSequence =
172 HouseholderSequence<std::add_const_t<VectorsType>, std::add_const_t<CoeffsType>, Side>;
192 : m_vectors(v), m_coeffs(h), m_reverse(false), m_length(v.diagonalSize()), m_shift(0) {}
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) {}
206 EIGEN_DEVICE_FUNC
constexpr Index rows() const noexcept {
207 return Side ==
OnTheLeft ? m_vectors.rows() : m_vectors.cols();
231 eigen_assert(k >= 0 && k < m_length);
232 return internal::hseq_side_dependent_impl<VectorsType, CoeffsType, Side>::essentialVector(*
this, k);
237 return TransposeReturnType(m_vectors.conjugate(), m_coeffs)
238 .setReverseFlag(!m_reverse)
245 return ConjugateReturnType(m_vectors.conjugate(), m_coeffs.conjugate())
246 .setReverseFlag(m_reverse)
258 EIGEN_DEVICE_FUNC
inline std::conditional_t<Cond, ConjugateReturnType, ConstHouseholderSequence>
conjugateIf()
const {
259 using ReturnType = std::conditional_t<Cond, ConjugateReturnType, ConstHouseholderSequence>;
265 return AdjointReturnType(m_vectors, m_coeffs.conjugate())
266 .setReverseFlag(!m_reverse)
275 template <
typename DestType>
276 inline EIGEN_DEVICE_FUNC
void evalTo(DestType& dst)
const {
279 evalTo(dst, workspace);
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)) {
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;
294 dst.bottomRightCorner(cornerSize, cornerSize)
295 .applyHouseholderOnTheRight(
essentialVector(k), m_coeffs.coeff(k), workspace.data());
297 dst.bottomRightCorner(cornerSize, cornerSize)
298 .applyHouseholderOnTheLeft(
essentialVector(k), m_coeffs.coeff(k), workspace.data());
301 dst.col(k).tail(
rows() - k - 1).setZero();
304 for (
Index k = 0; k <
cols() - vecs; ++k) dst.col(k).tail(
rows() - k - 1).setZero();
305 }
else if (m_length > BlockSize) {
307 applyThisOnTheLeft(dst, workspace,
true);
310 for (
Index k = vecs - 1; k >= 0; --k) {
313 dst.bottomRightCorner(cornerSize, cornerSize)
314 .applyHouseholderOnTheRight(
essentialVector(k), m_coeffs.coeff(k), workspace.data());
316 dst.bottomRightCorner(cornerSize, cornerSize)
317 .applyHouseholderOnTheLeft(
essentialVector(k), m_coeffs.coeff(k), workspace.data());
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);
330 template <
typename Dest,
typename Workspace>
331 inline void applyThisOnTheRight(Dest& dst, Workspace& workspace)
const {
335 if (m_length >= BlockSize &&
rows() - m_shift >= 4 * BlockSize) {
336 applyBlockOnTheRight(dst);
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());
350 template <
typename Dest>
351 EIGEN_DONT_INLINE
void applyBlockOnTheRight(Dest& dst)
const {
353 Index blockSize = m_length <
Index(2 * BlockSize) ? (m_length + 1) / 2 :
Index(BlockSize);
354 for (
Index i = 0; i < m_length; i += blockSize) {
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;
360 Index start = k + m_shift;
362 using SubVectorsType = Block<internal::remove_all_t<VectorsType>, Dynamic, Dynamic>;
363 SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side ==
OnTheRight ? k : start,
365 Side ==
OnTheRight ? m_vectors.cols() - start : bs);
366 std::conditional_t<Side == OnTheRight, Transpose<SubVectorsType>, SubVectorsType&> sub_vecs(sub_vecs1);
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);
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);
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;
387 if (m_length >= BlockSize && dst.cols() > 1) {
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);
394 Index start = k + m_shift;
396 using SubVectorsType = Block<internal::remove_all_t<VectorsType>, Dynamic, Dynamic>;
397 SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side ==
OnTheRight ? k : start,
399 Side ==
OnTheRight ? m_vectors.cols() - start : bs);
400 std::conditional_t<Side == OnTheRight, Transpose<SubVectorsType>, SubVectorsType&> sub_vecs(sub_vecs1);
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);
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);
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;
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());
422 auto sub_dst = dst.bottomRows(dstRows);
423 sub_dst.applyHouseholderOnTheLeft(
essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
436 template <
typename OtherDerived>
437 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type
operator*(
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());
450 template <
typename OtherDerived>
451 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type
operator*(
453 return applyToUpperTriangularOnTheLeft<
454 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type>(other,
true);
462 template <
typename OtherDerived>
463 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type
operator*(
465 constexpr bool kUpperTriangular =
467 return applyToUpperTriangularOnTheLeft<
468 typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type>(other, kUpperTriangular);
476 template <
typename OtherDerived>
477 typename internal::permutation_type_as_matrix_type<Scalar, OtherDerived>::Type
operator*(
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);
484 res.noalias() = res * other.
derived();
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();
500 template <
typename VectorsType_,
typename CoeffsType_,
int S
ide_>
501 friend struct internal::hseq_side_dependent_impl;
507 template <
typename ResultType,
typename OtherDerived>
509 eigen_assert(
cols() == other.
rows());
511 internal::assign_householder_operand(res, other);
512 applyThisOnTheLeft(res, upperTriangular && res.rows() == res.cols());
556 template <
typename VectorsType2,
typename CoeffsType2,
int S
ide2>
575 bool reverseFlag()
const {
return m_reverse; }
577 typename VectorsType::Nested m_vectors;
578 typename CoeffsType::Nested m_coeffs;
582 enum { BlockSize = 48 };
593template <
typename OtherDerived,
typename VectorsType,
typename CoeffsType,
int S
ide>
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);
607template <
typename OtherDerived,
typename VectorsType,
typename CoeffsType,
int S
ide>
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);
616 res = other.derived() * res;
625template <
typename OtherDerived,
typename VectorsType,
typename CoeffsType,
int S
ide>
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;
630 internal::assign_householder_operand(res, other);
631 h.applyThisOnTheRight(res);
640template <
typename OtherDerived,
typename VectorsType,
typename CoeffsType,
int S
ide>
641typename internal::permutation_type_as_matrix_type<typename VectorsType::Scalar, OtherDerived>::Type operator*(
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);
649 res.noalias() = other.derived() * res;
654template <
typename OtherDerived,
typename VectorsType,
typename CoeffsType,
int S
ide>
655typename internal::permutation_type_as_matrix_type<typename VectorsType::Scalar, Inverse<OtherDerived>>::Type operator*(
656 const InverseImpl<OtherDerived, PermutationStorage>& other,
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;
672template <
typename VectorsType,
typename CoeffsType>
684template <
typename VectorsType,
typename CoeffsType>
686 const CoeffsType& 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
Index shift() const
Definition HouseholderSequence.h:551
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
Index length() const
Definition HouseholderSequence.h:547
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