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