xref: /aosp_15_r20/external/eigen/Eigen/src/Householder/HouseholderSequence.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2009 Gael Guennebaud <[email protected]>
5*bf2c3715SXin Li // Copyright (C) 2010 Benoit Jacob <[email protected]>
6*bf2c3715SXin Li //
7*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
8*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
9*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10*bf2c3715SXin Li 
11*bf2c3715SXin Li #ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
12*bf2c3715SXin Li #define EIGEN_HOUSEHOLDER_SEQUENCE_H
13*bf2c3715SXin Li 
14*bf2c3715SXin Li namespace Eigen {
15*bf2c3715SXin Li 
16*bf2c3715SXin Li /** \ingroup Householder_Module
17*bf2c3715SXin Li   * \householder_module
18*bf2c3715SXin Li   * \class HouseholderSequence
19*bf2c3715SXin Li   * \brief Sequence of Householder reflections acting on subspaces with decreasing size
20*bf2c3715SXin Li   * \tparam VectorsType type of matrix containing the Householder vectors
21*bf2c3715SXin Li   * \tparam CoeffsType  type of vector containing the Householder coefficients
22*bf2c3715SXin Li   * \tparam Side        either OnTheLeft (the default) or OnTheRight
23*bf2c3715SXin Li   *
24*bf2c3715SXin Li   * This class represents a product sequence of Householder reflections where the first Householder reflection
25*bf2c3715SXin Li   * acts on the whole space, the second Householder reflection leaves the one-dimensional subspace spanned by
26*bf2c3715SXin Li   * the first unit vector invariant, the third Householder reflection leaves the two-dimensional subspace
27*bf2c3715SXin Li   * spanned by the first two unit vectors invariant, and so on up to the last reflection which leaves all but
28*bf2c3715SXin Li   * one dimensions invariant and acts only on the last dimension. Such sequences of Householder reflections
29*bf2c3715SXin Li   * are used in several algorithms to zero out certain parts of a matrix. Indeed, the methods
30*bf2c3715SXin Li   * HessenbergDecomposition::matrixQ(), Tridiagonalization::matrixQ(), HouseholderQR::householderQ(),
31*bf2c3715SXin Li   * and ColPivHouseholderQR::householderQ() all return a %HouseholderSequence.
32*bf2c3715SXin Li   *
33*bf2c3715SXin Li   * More precisely, the class %HouseholderSequence represents an \f$ n \times n \f$ matrix \f$ H \f$ of the
34*bf2c3715SXin Li   * form \f$ H = \prod_{i=0}^{n-1} H_i \f$ where the i-th Householder reflection is \f$ H_i = I - h_i v_i
35*bf2c3715SXin Li   * v_i^* \f$. The i-th Householder coefficient \f$ h_i \f$ is a scalar and the i-th Householder vector \f$
36*bf2c3715SXin Li   * v_i \f$ is a vector of the form
37*bf2c3715SXin Li   * \f[
38*bf2c3715SXin Li   * v_i = [\underbrace{0, \ldots, 0}_{i-1\mbox{ zeros}}, 1, \underbrace{*, \ldots,*}_{n-i\mbox{ arbitrary entries}} ].
39*bf2c3715SXin Li   * \f]
40*bf2c3715SXin Li   * The last \f$ n-i \f$ entries of \f$ v_i \f$ are called the essential part of the Householder vector.
41*bf2c3715SXin Li   *
42*bf2c3715SXin Li   * Typical usages are listed below, where H is a HouseholderSequence:
43*bf2c3715SXin Li   * \code
44*bf2c3715SXin Li   * A.applyOnTheRight(H);             // A = A * H
45*bf2c3715SXin Li   * A.applyOnTheLeft(H);              // A = H * A
46*bf2c3715SXin Li   * A.applyOnTheRight(H.adjoint());   // A = A * H^*
47*bf2c3715SXin Li   * A.applyOnTheLeft(H.adjoint());    // A = H^* * A
48*bf2c3715SXin Li   * MatrixXd Q = H;                   // conversion to a dense matrix
49*bf2c3715SXin Li   * \endcode
50*bf2c3715SXin Li   * In addition to the adjoint, you can also apply the inverse (=adjoint), the transpose, and the conjugate operators.
51*bf2c3715SXin Li   *
52*bf2c3715SXin Li   * See the documentation for HouseholderSequence(const VectorsType&, const CoeffsType&) for an example.
53*bf2c3715SXin Li   *
54*bf2c3715SXin Li   * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
55*bf2c3715SXin Li   */
56*bf2c3715SXin Li 
57*bf2c3715SXin Li namespace internal {
58*bf2c3715SXin Li 
59*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType, int Side>
60*bf2c3715SXin Li struct traits<HouseholderSequence<VectorsType,CoeffsType,Side> >
61*bf2c3715SXin Li {
62*bf2c3715SXin Li   typedef typename VectorsType::Scalar Scalar;
63*bf2c3715SXin Li   typedef typename VectorsType::StorageIndex StorageIndex;
64*bf2c3715SXin Li   typedef typename VectorsType::StorageKind StorageKind;
65*bf2c3715SXin Li   enum {
66*bf2c3715SXin Li     RowsAtCompileTime = Side==OnTheLeft ? traits<VectorsType>::RowsAtCompileTime
67*bf2c3715SXin Li                                         : traits<VectorsType>::ColsAtCompileTime,
68*bf2c3715SXin Li     ColsAtCompileTime = RowsAtCompileTime,
69*bf2c3715SXin Li     MaxRowsAtCompileTime = Side==OnTheLeft ? traits<VectorsType>::MaxRowsAtCompileTime
70*bf2c3715SXin Li                                            : traits<VectorsType>::MaxColsAtCompileTime,
71*bf2c3715SXin Li     MaxColsAtCompileTime = MaxRowsAtCompileTime,
72*bf2c3715SXin Li     Flags = 0
73*bf2c3715SXin Li   };
74*bf2c3715SXin Li };
75*bf2c3715SXin Li 
76*bf2c3715SXin Li struct HouseholderSequenceShape {};
77*bf2c3715SXin Li 
78*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType, int Side>
79*bf2c3715SXin Li struct evaluator_traits<HouseholderSequence<VectorsType,CoeffsType,Side> >
80*bf2c3715SXin Li   : public evaluator_traits_base<HouseholderSequence<VectorsType,CoeffsType,Side> >
81*bf2c3715SXin Li {
82*bf2c3715SXin Li   typedef HouseholderSequenceShape Shape;
83*bf2c3715SXin Li };
84*bf2c3715SXin Li 
85*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType, int Side>
86*bf2c3715SXin Li struct hseq_side_dependent_impl
87*bf2c3715SXin Li {
88*bf2c3715SXin Li   typedef Block<const VectorsType, Dynamic, 1> EssentialVectorType;
89*bf2c3715SXin Li   typedef HouseholderSequence<VectorsType, CoeffsType, OnTheLeft> HouseholderSequenceType;
90*bf2c3715SXin Li   static EIGEN_DEVICE_FUNC inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k)
91*bf2c3715SXin Li   {
92*bf2c3715SXin Li     Index start = k+1+h.m_shift;
93*bf2c3715SXin Li     return Block<const VectorsType,Dynamic,1>(h.m_vectors, start, k, h.rows()-start, 1);
94*bf2c3715SXin Li   }
95*bf2c3715SXin Li };
96*bf2c3715SXin Li 
97*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType>
98*bf2c3715SXin Li struct hseq_side_dependent_impl<VectorsType, CoeffsType, OnTheRight>
99*bf2c3715SXin Li {
100*bf2c3715SXin Li   typedef Transpose<Block<const VectorsType, 1, Dynamic> > EssentialVectorType;
101*bf2c3715SXin Li   typedef HouseholderSequence<VectorsType, CoeffsType, OnTheRight> HouseholderSequenceType;
102*bf2c3715SXin Li   static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k)
103*bf2c3715SXin Li   {
104*bf2c3715SXin Li     Index start = k+1+h.m_shift;
105*bf2c3715SXin Li     return Block<const VectorsType,1,Dynamic>(h.m_vectors, k, start, 1, h.rows()-start).transpose();
106*bf2c3715SXin Li   }
107*bf2c3715SXin Li };
108*bf2c3715SXin Li 
109*bf2c3715SXin Li template<typename OtherScalarType, typename MatrixType> struct matrix_type_times_scalar_type
110*bf2c3715SXin Li {
111*bf2c3715SXin Li   typedef typename ScalarBinaryOpTraits<OtherScalarType, typename MatrixType::Scalar>::ReturnType
112*bf2c3715SXin Li     ResultScalar;
113*bf2c3715SXin Li   typedef Matrix<ResultScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
114*bf2c3715SXin Li                  0, MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime> Type;
115*bf2c3715SXin Li };
116*bf2c3715SXin Li 
117*bf2c3715SXin Li } // end namespace internal
118*bf2c3715SXin Li 
119*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType, int Side> class HouseholderSequence
120*bf2c3715SXin Li   : public EigenBase<HouseholderSequence<VectorsType,CoeffsType,Side> >
121*bf2c3715SXin Li {
122*bf2c3715SXin Li     typedef typename internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::EssentialVectorType EssentialVectorType;
123*bf2c3715SXin Li 
124*bf2c3715SXin Li   public:
125*bf2c3715SXin Li     enum {
126*bf2c3715SXin Li       RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
127*bf2c3715SXin Li       ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
128*bf2c3715SXin Li       MaxRowsAtCompileTime = internal::traits<HouseholderSequence>::MaxRowsAtCompileTime,
129*bf2c3715SXin Li       MaxColsAtCompileTime = internal::traits<HouseholderSequence>::MaxColsAtCompileTime
130*bf2c3715SXin Li     };
131*bf2c3715SXin Li     typedef typename internal::traits<HouseholderSequence>::Scalar Scalar;
132*bf2c3715SXin Li 
133*bf2c3715SXin Li     typedef HouseholderSequence<
134*bf2c3715SXin Li       typename internal::conditional<NumTraits<Scalar>::IsComplex,
135*bf2c3715SXin Li         typename internal::remove_all<typename VectorsType::ConjugateReturnType>::type,
136*bf2c3715SXin Li         VectorsType>::type,
137*bf2c3715SXin Li       typename internal::conditional<NumTraits<Scalar>::IsComplex,
138*bf2c3715SXin Li         typename internal::remove_all<typename CoeffsType::ConjugateReturnType>::type,
139*bf2c3715SXin Li         CoeffsType>::type,
140*bf2c3715SXin Li       Side
141*bf2c3715SXin Li     > ConjugateReturnType;
142*bf2c3715SXin Li 
143*bf2c3715SXin Li     typedef HouseholderSequence<
144*bf2c3715SXin Li       VectorsType,
145*bf2c3715SXin Li       typename internal::conditional<NumTraits<Scalar>::IsComplex,
146*bf2c3715SXin Li         typename internal::remove_all<typename CoeffsType::ConjugateReturnType>::type,
147*bf2c3715SXin Li         CoeffsType>::type,
148*bf2c3715SXin Li       Side
149*bf2c3715SXin Li     > AdjointReturnType;
150*bf2c3715SXin Li 
151*bf2c3715SXin Li     typedef HouseholderSequence<
152*bf2c3715SXin Li       typename internal::conditional<NumTraits<Scalar>::IsComplex,
153*bf2c3715SXin Li         typename internal::remove_all<typename VectorsType::ConjugateReturnType>::type,
154*bf2c3715SXin Li         VectorsType>::type,
155*bf2c3715SXin Li       CoeffsType,
156*bf2c3715SXin Li       Side
157*bf2c3715SXin Li     > TransposeReturnType;
158*bf2c3715SXin Li 
159*bf2c3715SXin Li     typedef HouseholderSequence<
160*bf2c3715SXin Li       typename internal::add_const<VectorsType>::type,
161*bf2c3715SXin Li       typename internal::add_const<CoeffsType>::type,
162*bf2c3715SXin Li       Side
163*bf2c3715SXin Li     > ConstHouseholderSequence;
164*bf2c3715SXin Li 
165*bf2c3715SXin Li     /** \brief Constructor.
166*bf2c3715SXin Li       * \param[in]  v      %Matrix containing the essential parts of the Householder vectors
167*bf2c3715SXin Li       * \param[in]  h      Vector containing the Householder coefficients
168*bf2c3715SXin Li       *
169*bf2c3715SXin Li       * Constructs the Householder sequence with coefficients given by \p h and vectors given by \p v. The
170*bf2c3715SXin Li       * i-th Householder coefficient \f$ h_i \f$ is given by \p h(i) and the essential part of the i-th
171*bf2c3715SXin Li       * Householder vector \f$ v_i \f$ is given by \p v(k,i) with \p k > \p i (the subdiagonal part of the
172*bf2c3715SXin Li       * i-th column). If \p v has fewer columns than rows, then the Householder sequence contains as many
173*bf2c3715SXin Li       * Householder reflections as there are columns.
174*bf2c3715SXin Li       *
175*bf2c3715SXin Li       * \note The %HouseholderSequence object stores \p v and \p h by reference.
176*bf2c3715SXin Li       *
177*bf2c3715SXin Li       * Example: \include HouseholderSequence_HouseholderSequence.cpp
178*bf2c3715SXin Li       * Output: \verbinclude HouseholderSequence_HouseholderSequence.out
179*bf2c3715SXin Li       *
180*bf2c3715SXin Li       * \sa setLength(), setShift()
181*bf2c3715SXin Li       */
182*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
183*bf2c3715SXin Li     HouseholderSequence(const VectorsType& v, const CoeffsType& h)
184*bf2c3715SXin Li       : m_vectors(v), m_coeffs(h), m_reverse(false), m_length(v.diagonalSize()),
185*bf2c3715SXin Li         m_shift(0)
186*bf2c3715SXin Li     {
187*bf2c3715SXin Li     }
188*bf2c3715SXin Li 
189*bf2c3715SXin Li     /** \brief Copy constructor. */
190*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
191*bf2c3715SXin Li     HouseholderSequence(const HouseholderSequence& other)
192*bf2c3715SXin Li       : m_vectors(other.m_vectors),
193*bf2c3715SXin Li         m_coeffs(other.m_coeffs),
194*bf2c3715SXin Li         m_reverse(other.m_reverse),
195*bf2c3715SXin Li         m_length(other.m_length),
196*bf2c3715SXin Li         m_shift(other.m_shift)
197*bf2c3715SXin Li     {
198*bf2c3715SXin Li     }
199*bf2c3715SXin Li 
200*bf2c3715SXin Li     /** \brief Number of rows of transformation viewed as a matrix.
201*bf2c3715SXin Li       * \returns Number of rows
202*bf2c3715SXin Li       * \details This equals the dimension of the space that the transformation acts on.
203*bf2c3715SXin Li       */
204*bf2c3715SXin Li     EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
205*bf2c3715SXin Li     Index rows() const EIGEN_NOEXCEPT { return Side==OnTheLeft ? m_vectors.rows() : m_vectors.cols(); }
206*bf2c3715SXin Li 
207*bf2c3715SXin Li     /** \brief Number of columns of transformation viewed as a matrix.
208*bf2c3715SXin Li       * \returns Number of columns
209*bf2c3715SXin Li       * \details This equals the dimension of the space that the transformation acts on.
210*bf2c3715SXin Li       */
211*bf2c3715SXin Li     EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
212*bf2c3715SXin Li     Index cols() const EIGEN_NOEXCEPT { return rows(); }
213*bf2c3715SXin Li 
214*bf2c3715SXin Li     /** \brief Essential part of a Householder vector.
215*bf2c3715SXin Li       * \param[in]  k  Index of Householder reflection
216*bf2c3715SXin Li       * \returns    Vector containing non-trivial entries of k-th Householder vector
217*bf2c3715SXin Li       *
218*bf2c3715SXin Li       * This function returns the essential part of the Householder vector \f$ v_i \f$. This is a vector of
219*bf2c3715SXin Li       * length \f$ n-i \f$ containing the last \f$ n-i \f$ entries of the vector
220*bf2c3715SXin Li       * \f[
221*bf2c3715SXin Li       * v_i = [\underbrace{0, \ldots, 0}_{i-1\mbox{ zeros}}, 1, \underbrace{*, \ldots,*}_{n-i\mbox{ arbitrary entries}} ].
222*bf2c3715SXin Li       * \f]
223*bf2c3715SXin Li       * The index \f$ i \f$ equals \p k + shift(), corresponding to the k-th column of the matrix \p v
224*bf2c3715SXin Li       * passed to the constructor.
225*bf2c3715SXin Li       *
226*bf2c3715SXin Li       * \sa setShift(), shift()
227*bf2c3715SXin Li       */
228*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
229*bf2c3715SXin Li     const EssentialVectorType essentialVector(Index k) const
230*bf2c3715SXin Li     {
231*bf2c3715SXin Li       eigen_assert(k >= 0 && k < m_length);
232*bf2c3715SXin Li       return internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::essentialVector(*this, k);
233*bf2c3715SXin Li     }
234*bf2c3715SXin Li 
235*bf2c3715SXin Li     /** \brief %Transpose of the Householder sequence. */
236*bf2c3715SXin Li     TransposeReturnType transpose() const
237*bf2c3715SXin Li     {
238*bf2c3715SXin Li       return TransposeReturnType(m_vectors.conjugate(), m_coeffs)
239*bf2c3715SXin Li               .setReverseFlag(!m_reverse)
240*bf2c3715SXin Li               .setLength(m_length)
241*bf2c3715SXin Li               .setShift(m_shift);
242*bf2c3715SXin Li     }
243*bf2c3715SXin Li 
244*bf2c3715SXin Li     /** \brief Complex conjugate of the Householder sequence. */
245*bf2c3715SXin Li     ConjugateReturnType conjugate() const
246*bf2c3715SXin Li     {
247*bf2c3715SXin Li       return ConjugateReturnType(m_vectors.conjugate(), m_coeffs.conjugate())
248*bf2c3715SXin Li              .setReverseFlag(m_reverse)
249*bf2c3715SXin Li              .setLength(m_length)
250*bf2c3715SXin Li              .setShift(m_shift);
251*bf2c3715SXin Li     }
252*bf2c3715SXin Li 
253*bf2c3715SXin Li     /** \returns an expression of the complex conjugate of \c *this if Cond==true,
254*bf2c3715SXin Li      *           returns \c *this otherwise.
255*bf2c3715SXin Li      */
256*bf2c3715SXin Li     template<bool Cond>
257*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
258*bf2c3715SXin Li     inline typename internal::conditional<Cond,ConjugateReturnType,ConstHouseholderSequence>::type
259*bf2c3715SXin Li     conjugateIf() const
260*bf2c3715SXin Li     {
261*bf2c3715SXin Li       typedef typename internal::conditional<Cond,ConjugateReturnType,ConstHouseholderSequence>::type ReturnType;
262*bf2c3715SXin Li       return ReturnType(m_vectors.template conjugateIf<Cond>(), m_coeffs.template conjugateIf<Cond>());
263*bf2c3715SXin Li     }
264*bf2c3715SXin Li 
265*bf2c3715SXin Li     /** \brief Adjoint (conjugate transpose) of the Householder sequence. */
266*bf2c3715SXin Li     AdjointReturnType adjoint() const
267*bf2c3715SXin Li     {
268*bf2c3715SXin Li       return AdjointReturnType(m_vectors, m_coeffs.conjugate())
269*bf2c3715SXin Li               .setReverseFlag(!m_reverse)
270*bf2c3715SXin Li               .setLength(m_length)
271*bf2c3715SXin Li               .setShift(m_shift);
272*bf2c3715SXin Li     }
273*bf2c3715SXin Li 
274*bf2c3715SXin Li     /** \brief Inverse of the Householder sequence (equals the adjoint). */
275*bf2c3715SXin Li     AdjointReturnType inverse() const { return adjoint(); }
276*bf2c3715SXin Li 
277*bf2c3715SXin Li     /** \internal */
278*bf2c3715SXin Li     template<typename DestType>
279*bf2c3715SXin Li     inline EIGEN_DEVICE_FUNC
280*bf2c3715SXin Li     void evalTo(DestType& dst) const
281*bf2c3715SXin Li     {
282*bf2c3715SXin Li       Matrix<Scalar, DestType::RowsAtCompileTime, 1,
283*bf2c3715SXin Li              AutoAlign|ColMajor, DestType::MaxRowsAtCompileTime, 1> workspace(rows());
284*bf2c3715SXin Li       evalTo(dst, workspace);
285*bf2c3715SXin Li     }
286*bf2c3715SXin Li 
287*bf2c3715SXin Li     /** \internal */
288*bf2c3715SXin Li     template<typename Dest, typename Workspace>
289*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
290*bf2c3715SXin Li     void evalTo(Dest& dst, Workspace& workspace) const
291*bf2c3715SXin Li     {
292*bf2c3715SXin Li       workspace.resize(rows());
293*bf2c3715SXin Li       Index vecs = m_length;
294*bf2c3715SXin Li       if(internal::is_same_dense(dst,m_vectors))
295*bf2c3715SXin Li       {
296*bf2c3715SXin Li         // in-place
297*bf2c3715SXin Li         dst.diagonal().setOnes();
298*bf2c3715SXin Li         dst.template triangularView<StrictlyUpper>().setZero();
299*bf2c3715SXin Li         for(Index k = vecs-1; k >= 0; --k)
300*bf2c3715SXin Li         {
301*bf2c3715SXin Li           Index cornerSize = rows() - k - m_shift;
302*bf2c3715SXin Li           if(m_reverse)
303*bf2c3715SXin Li             dst.bottomRightCorner(cornerSize, cornerSize)
304*bf2c3715SXin Li                .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
305*bf2c3715SXin Li           else
306*bf2c3715SXin Li             dst.bottomRightCorner(cornerSize, cornerSize)
307*bf2c3715SXin Li                .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
308*bf2c3715SXin Li 
309*bf2c3715SXin Li           // clear the off diagonal vector
310*bf2c3715SXin Li           dst.col(k).tail(rows()-k-1).setZero();
311*bf2c3715SXin Li         }
312*bf2c3715SXin Li         // clear the remaining columns if needed
313*bf2c3715SXin Li         for(Index k = 0; k<cols()-vecs ; ++k)
314*bf2c3715SXin Li           dst.col(k).tail(rows()-k-1).setZero();
315*bf2c3715SXin Li       }
316*bf2c3715SXin Li       else if(m_length>BlockSize)
317*bf2c3715SXin Li       {
318*bf2c3715SXin Li         dst.setIdentity(rows(), rows());
319*bf2c3715SXin Li         if(m_reverse)
320*bf2c3715SXin Li           applyThisOnTheLeft(dst,workspace,true);
321*bf2c3715SXin Li         else
322*bf2c3715SXin Li           applyThisOnTheLeft(dst,workspace,true);
323*bf2c3715SXin Li       }
324*bf2c3715SXin Li       else
325*bf2c3715SXin Li       {
326*bf2c3715SXin Li         dst.setIdentity(rows(), rows());
327*bf2c3715SXin Li         for(Index k = vecs-1; k >= 0; --k)
328*bf2c3715SXin Li         {
329*bf2c3715SXin Li           Index cornerSize = rows() - k - m_shift;
330*bf2c3715SXin Li           if(m_reverse)
331*bf2c3715SXin Li             dst.bottomRightCorner(cornerSize, cornerSize)
332*bf2c3715SXin Li                .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
333*bf2c3715SXin Li           else
334*bf2c3715SXin Li             dst.bottomRightCorner(cornerSize, cornerSize)
335*bf2c3715SXin Li                .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
336*bf2c3715SXin Li         }
337*bf2c3715SXin Li       }
338*bf2c3715SXin Li     }
339*bf2c3715SXin Li 
340*bf2c3715SXin Li     /** \internal */
341*bf2c3715SXin Li     template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
342*bf2c3715SXin Li     {
343*bf2c3715SXin Li       Matrix<Scalar,1,Dest::RowsAtCompileTime,RowMajor,1,Dest::MaxRowsAtCompileTime> workspace(dst.rows());
344*bf2c3715SXin Li       applyThisOnTheRight(dst, workspace);
345*bf2c3715SXin Li     }
346*bf2c3715SXin Li 
347*bf2c3715SXin Li     /** \internal */
348*bf2c3715SXin Li     template<typename Dest, typename Workspace>
349*bf2c3715SXin Li     inline void applyThisOnTheRight(Dest& dst, Workspace& workspace) const
350*bf2c3715SXin Li     {
351*bf2c3715SXin Li       workspace.resize(dst.rows());
352*bf2c3715SXin Li       for(Index k = 0; k < m_length; ++k)
353*bf2c3715SXin Li       {
354*bf2c3715SXin Li         Index actual_k = m_reverse ? m_length-k-1 : k;
355*bf2c3715SXin Li         dst.rightCols(rows()-m_shift-actual_k)
356*bf2c3715SXin Li            .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
357*bf2c3715SXin Li       }
358*bf2c3715SXin Li     }
359*bf2c3715SXin Li 
360*bf2c3715SXin Li     /** \internal */
361*bf2c3715SXin Li     template<typename Dest> inline void applyThisOnTheLeft(Dest& dst, bool inputIsIdentity = false) const
362*bf2c3715SXin Li     {
363*bf2c3715SXin Li       Matrix<Scalar,1,Dest::ColsAtCompileTime,RowMajor,1,Dest::MaxColsAtCompileTime> workspace;
364*bf2c3715SXin Li       applyThisOnTheLeft(dst, workspace, inputIsIdentity);
365*bf2c3715SXin Li     }
366*bf2c3715SXin Li 
367*bf2c3715SXin Li     /** \internal */
368*bf2c3715SXin Li     template<typename Dest, typename Workspace>
369*bf2c3715SXin Li     inline void applyThisOnTheLeft(Dest& dst, Workspace& workspace, bool inputIsIdentity = false) const
370*bf2c3715SXin Li     {
371*bf2c3715SXin Li       if(inputIsIdentity && m_reverse)
372*bf2c3715SXin Li         inputIsIdentity = false;
373*bf2c3715SXin Li       // if the entries are large enough, then apply the reflectors by block
374*bf2c3715SXin Li       if(m_length>=BlockSize && dst.cols()>1)
375*bf2c3715SXin Li       {
376*bf2c3715SXin Li         // Make sure we have at least 2 useful blocks, otherwise it is point-less:
377*bf2c3715SXin Li         Index blockSize = m_length<Index(2*BlockSize) ? (m_length+1)/2 : Index(BlockSize);
378*bf2c3715SXin Li         for(Index i = 0; i < m_length; i+=blockSize)
379*bf2c3715SXin Li         {
380*bf2c3715SXin Li           Index end = m_reverse ? (std::min)(m_length,i+blockSize) : m_length-i;
381*bf2c3715SXin Li           Index k = m_reverse ? i : (std::max)(Index(0),end-blockSize);
382*bf2c3715SXin Li           Index bs = end-k;
383*bf2c3715SXin Li           Index start = k + m_shift;
384*bf2c3715SXin Li 
385*bf2c3715SXin Li           typedef Block<typename internal::remove_all<VectorsType>::type,Dynamic,Dynamic> SubVectorsType;
386*bf2c3715SXin Li           SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side==OnTheRight ? k : start,
387*bf2c3715SXin Li                                                                    Side==OnTheRight ? start : k,
388*bf2c3715SXin Li                                                                    Side==OnTheRight ? bs : m_vectors.rows()-start,
389*bf2c3715SXin Li                                                                    Side==OnTheRight ? m_vectors.cols()-start : bs);
390*bf2c3715SXin Li           typename internal::conditional<Side==OnTheRight, Transpose<SubVectorsType>, SubVectorsType&>::type sub_vecs(sub_vecs1);
391*bf2c3715SXin Li 
392*bf2c3715SXin Li           Index dstStart = dst.rows()-rows()+m_shift+k;
393*bf2c3715SXin Li           Index dstRows  = rows()-m_shift-k;
394*bf2c3715SXin Li           Block<Dest,Dynamic,Dynamic> sub_dst(dst,
395*bf2c3715SXin Li                                               dstStart,
396*bf2c3715SXin Li                                               inputIsIdentity ? dstStart : 0,
397*bf2c3715SXin Li                                               dstRows,
398*bf2c3715SXin Li                                               inputIsIdentity ? dstRows : dst.cols());
399*bf2c3715SXin Li           apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse);
400*bf2c3715SXin Li         }
401*bf2c3715SXin Li       }
402*bf2c3715SXin Li       else
403*bf2c3715SXin Li       {
404*bf2c3715SXin Li         workspace.resize(dst.cols());
405*bf2c3715SXin Li         for(Index k = 0; k < m_length; ++k)
406*bf2c3715SXin Li         {
407*bf2c3715SXin Li           Index actual_k = m_reverse ? k : m_length-k-1;
408*bf2c3715SXin Li           Index dstStart = rows()-m_shift-actual_k;
409*bf2c3715SXin Li           dst.bottomRightCorner(dstStart, inputIsIdentity ? dstStart : dst.cols())
410*bf2c3715SXin Li             .applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
411*bf2c3715SXin Li         }
412*bf2c3715SXin Li       }
413*bf2c3715SXin Li     }
414*bf2c3715SXin Li 
415*bf2c3715SXin Li     /** \brief Computes the product of a Householder sequence with a matrix.
416*bf2c3715SXin Li       * \param[in]  other  %Matrix being multiplied.
417*bf2c3715SXin Li       * \returns    Expression object representing the product.
418*bf2c3715SXin Li       *
419*bf2c3715SXin Li       * This function computes \f$ HM \f$ where \f$ H \f$ is the Householder sequence represented by \p *this
420*bf2c3715SXin Li       * and \f$ M \f$ is the matrix \p other.
421*bf2c3715SXin Li       */
422*bf2c3715SXin Li     template<typename OtherDerived>
423*bf2c3715SXin Li     typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other) const
424*bf2c3715SXin Li     {
425*bf2c3715SXin Li       typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type
426*bf2c3715SXin Li         res(other.template cast<typename internal::matrix_type_times_scalar_type<Scalar,OtherDerived>::ResultScalar>());
427*bf2c3715SXin Li       applyThisOnTheLeft(res, internal::is_identity<OtherDerived>::value && res.rows()==res.cols());
428*bf2c3715SXin Li       return res;
429*bf2c3715SXin Li     }
430*bf2c3715SXin Li 
431*bf2c3715SXin Li     template<typename _VectorsType, typename _CoeffsType, int _Side> friend struct internal::hseq_side_dependent_impl;
432*bf2c3715SXin Li 
433*bf2c3715SXin Li     /** \brief Sets the length of the Householder sequence.
434*bf2c3715SXin Li       * \param [in]  length  New value for the length.
435*bf2c3715SXin Li       *
436*bf2c3715SXin Li       * By default, the length \f$ n \f$ of the Householder sequence \f$ H = H_0 H_1 \ldots H_{n-1} \f$ is set
437*bf2c3715SXin Li       * to the number of columns of the matrix \p v passed to the constructor, or the number of rows if that
438*bf2c3715SXin Li       * is smaller. After this function is called, the length equals \p length.
439*bf2c3715SXin Li       *
440*bf2c3715SXin Li       * \sa length()
441*bf2c3715SXin Li       */
442*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
443*bf2c3715SXin Li     HouseholderSequence& setLength(Index length)
444*bf2c3715SXin Li     {
445*bf2c3715SXin Li       m_length = length;
446*bf2c3715SXin Li       return *this;
447*bf2c3715SXin Li     }
448*bf2c3715SXin Li 
449*bf2c3715SXin Li     /** \brief Sets the shift of the Householder sequence.
450*bf2c3715SXin Li       * \param [in]  shift  New value for the shift.
451*bf2c3715SXin Li       *
452*bf2c3715SXin Li       * By default, a %HouseholderSequence object represents \f$ H = H_0 H_1 \ldots H_{n-1} \f$ and the i-th
453*bf2c3715SXin Li       * column of the matrix \p v passed to the constructor corresponds to the i-th Householder
454*bf2c3715SXin Li       * reflection. After this function is called, the object represents \f$ H = H_{\mathrm{shift}}
455*bf2c3715SXin Li       * H_{\mathrm{shift}+1} \ldots H_{n-1} \f$ and the i-th column of \p v corresponds to the (shift+i)-th
456*bf2c3715SXin Li       * Householder reflection.
457*bf2c3715SXin Li       *
458*bf2c3715SXin Li       * \sa shift()
459*bf2c3715SXin Li       */
460*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
461*bf2c3715SXin Li     HouseholderSequence& setShift(Index shift)
462*bf2c3715SXin Li     {
463*bf2c3715SXin Li       m_shift = shift;
464*bf2c3715SXin Li       return *this;
465*bf2c3715SXin Li     }
466*bf2c3715SXin Li 
467*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
468*bf2c3715SXin Li     Index length() const { return m_length; }  /**< \brief Returns the length of the Householder sequence. */
469*bf2c3715SXin Li 
470*bf2c3715SXin Li     EIGEN_DEVICE_FUNC
471*bf2c3715SXin Li     Index shift() const { return m_shift; }    /**< \brief Returns the shift of the Householder sequence. */
472*bf2c3715SXin Li 
473*bf2c3715SXin Li     /* Necessary for .adjoint() and .conjugate() */
474*bf2c3715SXin Li     template <typename VectorsType2, typename CoeffsType2, int Side2> friend class HouseholderSequence;
475*bf2c3715SXin Li 
476*bf2c3715SXin Li   protected:
477*bf2c3715SXin Li 
478*bf2c3715SXin Li     /** \internal
479*bf2c3715SXin Li       * \brief Sets the reverse flag.
480*bf2c3715SXin Li       * \param [in]  reverse  New value of the reverse flag.
481*bf2c3715SXin Li       *
482*bf2c3715SXin Li       * By default, the reverse flag is not set. If the reverse flag is set, then this object represents
483*bf2c3715SXin Li       * \f$ H^r = H_{n-1} \ldots H_1 H_0 \f$ instead of \f$ H = H_0 H_1 \ldots H_{n-1} \f$.
484*bf2c3715SXin Li       * \note For real valued HouseholderSequence this is equivalent to transposing \f$ H \f$.
485*bf2c3715SXin Li       *
486*bf2c3715SXin Li       * \sa reverseFlag(), transpose(), adjoint()
487*bf2c3715SXin Li       */
488*bf2c3715SXin Li     HouseholderSequence& setReverseFlag(bool reverse)
489*bf2c3715SXin Li     {
490*bf2c3715SXin Li       m_reverse = reverse;
491*bf2c3715SXin Li       return *this;
492*bf2c3715SXin Li     }
493*bf2c3715SXin Li 
494*bf2c3715SXin Li     bool reverseFlag() const { return m_reverse; }     /**< \internal \brief Returns the reverse flag. */
495*bf2c3715SXin Li 
496*bf2c3715SXin Li     typename VectorsType::Nested m_vectors;
497*bf2c3715SXin Li     typename CoeffsType::Nested m_coeffs;
498*bf2c3715SXin Li     bool m_reverse;
499*bf2c3715SXin Li     Index m_length;
500*bf2c3715SXin Li     Index m_shift;
501*bf2c3715SXin Li     enum { BlockSize = 48 };
502*bf2c3715SXin Li };
503*bf2c3715SXin Li 
504*bf2c3715SXin Li /** \brief Computes the product of a matrix with a Householder sequence.
505*bf2c3715SXin Li   * \param[in]  other  %Matrix being multiplied.
506*bf2c3715SXin Li   * \param[in]  h      %HouseholderSequence being multiplied.
507*bf2c3715SXin Li   * \returns    Expression object representing the product.
508*bf2c3715SXin Li   *
509*bf2c3715SXin Li   * This function computes \f$ MH \f$ where \f$ M \f$ is the matrix \p other and \f$ H \f$ is the
510*bf2c3715SXin Li   * Householder sequence represented by \p h.
511*bf2c3715SXin Li   */
512*bf2c3715SXin Li template<typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
513*bf2c3715SXin Li typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other, const HouseholderSequence<VectorsType,CoeffsType,Side>& h)
514*bf2c3715SXin Li {
515*bf2c3715SXin Li   typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type
516*bf2c3715SXin Li     res(other.template cast<typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::ResultScalar>());
517*bf2c3715SXin Li   h.applyThisOnTheRight(res);
518*bf2c3715SXin Li   return res;
519*bf2c3715SXin Li }
520*bf2c3715SXin Li 
521*bf2c3715SXin Li /** \ingroup Householder_Module \householder_module
522*bf2c3715SXin Li   * \brief Convenience function for constructing a Householder sequence.
523*bf2c3715SXin Li   * \returns A HouseholderSequence constructed from the specified arguments.
524*bf2c3715SXin Li   */
525*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType>
526*bf2c3715SXin Li HouseholderSequence<VectorsType,CoeffsType> householderSequence(const VectorsType& v, const CoeffsType& h)
527*bf2c3715SXin Li {
528*bf2c3715SXin Li   return HouseholderSequence<VectorsType,CoeffsType,OnTheLeft>(v, h);
529*bf2c3715SXin Li }
530*bf2c3715SXin Li 
531*bf2c3715SXin Li /** \ingroup Householder_Module \householder_module
532*bf2c3715SXin Li   * \brief Convenience function for constructing a Householder sequence.
533*bf2c3715SXin Li   * \returns A HouseholderSequence constructed from the specified arguments.
534*bf2c3715SXin Li   * \details This function differs from householderSequence() in that the template argument \p OnTheSide of
535*bf2c3715SXin Li   * the constructed HouseholderSequence is set to OnTheRight, instead of the default OnTheLeft.
536*bf2c3715SXin Li   */
537*bf2c3715SXin Li template<typename VectorsType, typename CoeffsType>
538*bf2c3715SXin Li HouseholderSequence<VectorsType,CoeffsType,OnTheRight> rightHouseholderSequence(const VectorsType& v, const CoeffsType& h)
539*bf2c3715SXin Li {
540*bf2c3715SXin Li   return HouseholderSequence<VectorsType,CoeffsType,OnTheRight>(v, h);
541*bf2c3715SXin Li }
542*bf2c3715SXin Li 
543*bf2c3715SXin Li } // end namespace Eigen
544*bf2c3715SXin Li 
545*bf2c3715SXin Li #endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
546