$darkmode
Eigen  5.0.1-dev
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 
11 #ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
12 #define EIGEN_HOUSEHOLDER_SEQUENCE_H
13 
14 // IWYU pragma: private
15 #include "./InternalHeaderCheck.h"
16 
17 namespace Eigen {
18 
60 namespace internal {
61 
62 template <typename VectorsType, typename CoeffsType, int Side>
63 struct 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 
78 struct HouseholderSequenceShape {};
79 
80 template <typename VectorsType, typename CoeffsType, int Side>
81 struct evaluator_traits<HouseholderSequence<VectorsType, CoeffsType, Side> >
82  : public evaluator_traits_base<HouseholderSequence<VectorsType, CoeffsType, Side> > {
83  typedef HouseholderSequenceShape Shape;
84 };
85 
86 template <typename VectorsType, typename CoeffsType, int Side>
87 struct 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 
96 template <typename VectorsType, typename CoeffsType>
97 struct 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 
106 template <typename OtherScalarType, typename MatrixType>
107 struct 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 
116 template <typename VectorsType, typename CoeffsType, int Side>
117 class HouseholderSequence : public EigenBase<HouseholderSequence<VectorsType, CoeffsType, Side> > {
118  typedef typename internal::hseq_side_dependent_impl<VectorsType, CoeffsType, Side>::EssentialVectorType
119  EssentialVectorType;
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>
136  ConjugateReturnType;
137 
138  typedef HouseholderSequence<
139  VectorsType,
140  std::conditional_t<NumTraits<Scalar>::IsComplex, internal::remove_all_t<typename CoeffsType::ConjugateReturnType>,
141  CoeffsType>,
142  Side>
143  AdjointReturnType;
144 
145  typedef HouseholderSequence<
146  std::conditional_t<NumTraits<Scalar>::IsComplex,
147  internal::remove_all_t<typename VectorsType::ConjugateReturnType>, VectorsType>,
148  CoeffsType, Side>
149  TransposeReturnType;
150 
151  typedef HouseholderSequence<std::add_const_t<VectorsType>, std::add_const_t<CoeffsType>, Side>
152  ConstHouseholderSequence;
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 constexpr Index rows() const noexcept {
187  return Side == OnTheLeft ? m_vectors.rows() : m_vectors.cols();
188  }
189 
194  EIGEN_DEVICE_FUNC constexpr Index cols() const 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 
418  EIGEN_DEVICE_FUNC HouseholderSequence& setShift(Index shift) {
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 
469 template <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 
484 template <typename VectorsType, typename CoeffsType>
485 HouseholderSequence<VectorsType, CoeffsType> householderSequence(const VectorsType& v, const CoeffsType& h) {
487 }
488 
496 template <typename VectorsType, typename CoeffsType>
498  const CoeffsType& h) {
500 }
501 
502 } // end namespace Eigen
503 
504 #endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
static constexpr lastp1_t end
Definition: IndexedViewHelper.h:79
const Product< MatrixDerived, PermutationDerived, DefaultProduct > operator*(const MatrixBase< MatrixDerived > &matrix, const PermutationBase< PermutationDerived > &permutation)
Definition: PermutationMatrix.h:474
Definition: Constants.h:333
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition: HouseholderSequence.h:485
HouseholderSequence & setLength(Index length)
Sets the length of the Householder sequence.
Definition: HouseholderSequence.h:402
HouseholderSequence(const HouseholderSequence &other)
Copy constructor.
Definition: HouseholderSequence.h:175
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
HouseholderSequence(const VectorsType &v, const CoeffsType &h)
Constructor.
Definition: HouseholderSequence.h:171
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:43
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition: ForwardDeclarations.h:445
AdjointReturnType inverse() const
Inverse of the Householder sequence (equals the adjoint).
Definition: HouseholderSequence.h:249
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
Definition: Constants.h:331
Index length() const
Returns the length of the Householder sequence.
Definition: HouseholderSequence.h:423
AdjointReturnType adjoint() const
Adjoint (conjugate transpose) of the Householder sequence.
Definition: HouseholderSequence.h:241
HouseholderSequence & setShift(Index shift)
Sets the shift of the Householder sequence.
Definition: HouseholderSequence.h:418
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
const EssentialVectorType essentialVector(Index k) const
Essential part of a Householder vector.
Definition: HouseholderSequence.h:210
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:109
constexpr Index rows() const noexcept
Number of rows of transformation viewed as a matrix.
Definition: HouseholderSequence.h:186
std::conditional_t< Cond, ConjugateReturnType, ConstHouseholderSequence > conjugateIf() const
Definition: HouseholderSequence.h:235
constexpr Index cols() const noexcept
Number of columns of transformation viewed as a matrix.
Definition: HouseholderSequence.h:194
HouseholderSequence< VectorsType, CoeffsType, OnTheRight > rightHouseholderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition: HouseholderSequence.h:497
const int Dynamic
Definition: Constants.h:25
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:186
Index shift() const
Returns the shift of the Householder sequence.
Definition: HouseholderSequence.h:427
TransposeReturnType transpose() const
Transpose of the Householder sequence.
Definition: HouseholderSequence.h:216
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:52
ConjugateReturnType conjugate() const
Complex conjugate of the Householder sequence.
Definition: HouseholderSequence.h:224