MOAB  4.9.3pre
HouseholderSequence.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2009 Gael Guennebaud <[email protected]>
00005 // Copyright (C) 2010 Benoit Jacob <[email protected]>
00006 //
00007 // This Source Code Form is subject to the terms of the Mozilla
00008 // Public License v. 2.0. If a copy of the MPL was not distributed
00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00010 
00011 #ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
00012 #define EIGEN_HOUSEHOLDER_SEQUENCE_H
00013 
00014 namespace Eigen { 
00015 
00057 namespace internal {
00058 
00059 template<typename VectorsType, typename CoeffsType, int Side>
00060 struct traits<HouseholderSequence<VectorsType,CoeffsType,Side> >
00061 {
00062   typedef typename VectorsType::Scalar Scalar;
00063   typedef typename VectorsType::StorageIndex StorageIndex;
00064   typedef typename VectorsType::StorageKind StorageKind;
00065   enum {
00066     RowsAtCompileTime = Side==OnTheLeft ? traits<VectorsType>::RowsAtCompileTime
00067                                         : traits<VectorsType>::ColsAtCompileTime,
00068     ColsAtCompileTime = RowsAtCompileTime,
00069     MaxRowsAtCompileTime = Side==OnTheLeft ? traits<VectorsType>::MaxRowsAtCompileTime
00070                                            : traits<VectorsType>::MaxColsAtCompileTime,
00071     MaxColsAtCompileTime = MaxRowsAtCompileTime,
00072     Flags = 0
00073   };
00074 };
00075 
00076 struct HouseholderSequenceShape {};
00077 
00078 template<typename VectorsType, typename CoeffsType, int Side>
00079 struct evaluator_traits<HouseholderSequence<VectorsType,CoeffsType,Side> >
00080   : public evaluator_traits_base<HouseholderSequence<VectorsType,CoeffsType,Side> >
00081 {
00082   typedef HouseholderSequenceShape Shape;
00083 };
00084 
00085 template<typename VectorsType, typename CoeffsType, int Side>
00086 struct hseq_side_dependent_impl
00087 {
00088   typedef Block<const VectorsType, Dynamic, 1> EssentialVectorType;
00089   typedef HouseholderSequence<VectorsType, CoeffsType, OnTheLeft> HouseholderSequenceType;
00090   static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k)
00091   {
00092     Index start = k+1+h.m_shift;
00093     return Block<const VectorsType,Dynamic,1>(h.m_vectors, start, k, h.rows()-start, 1);
00094   }
00095 };
00096 
00097 template<typename VectorsType, typename CoeffsType>
00098 struct hseq_side_dependent_impl<VectorsType, CoeffsType, OnTheRight>
00099 {
00100   typedef Transpose<Block<const VectorsType, 1, Dynamic> > EssentialVectorType;
00101   typedef HouseholderSequence<VectorsType, CoeffsType, OnTheRight> HouseholderSequenceType;
00102   static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k)
00103   {
00104     Index start = k+1+h.m_shift;
00105     return Block<const VectorsType,1,Dynamic>(h.m_vectors, k, start, 1, h.rows()-start).transpose();
00106   }
00107 };
00108 
00109 template<typename OtherScalarType, typename MatrixType> struct matrix_type_times_scalar_type
00110 {
00111   typedef typename scalar_product_traits<OtherScalarType, typename MatrixType::Scalar>::ReturnType
00112     ResultScalar;
00113   typedef Matrix<ResultScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
00114                  0, MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime> Type;
00115 };
00116 
00117 } // end namespace internal
00118 
00119 template<typename VectorsType, typename CoeffsType, int Side> class HouseholderSequence
00120   : public EigenBase<HouseholderSequence<VectorsType,CoeffsType,Side> >
00121 {
00122     typedef typename internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::EssentialVectorType EssentialVectorType;
00123   
00124   public:
00125     enum {
00126       RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
00127       ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
00128       MaxRowsAtCompileTime = internal::traits<HouseholderSequence>::MaxRowsAtCompileTime,
00129       MaxColsAtCompileTime = internal::traits<HouseholderSequence>::MaxColsAtCompileTime
00130     };
00131     typedef typename internal::traits<HouseholderSequence>::Scalar Scalar;
00132 
00133     typedef HouseholderSequence<
00134       typename internal::conditional<NumTraits<Scalar>::IsComplex,
00135         typename internal::remove_all<typename VectorsType::ConjugateReturnType>::type,
00136         VectorsType>::type,
00137       typename internal::conditional<NumTraits<Scalar>::IsComplex,
00138         typename internal::remove_all<typename CoeffsType::ConjugateReturnType>::type,
00139         CoeffsType>::type,
00140       Side
00141     > ConjugateReturnType;
00142 
00160     HouseholderSequence(const VectorsType& v, const CoeffsType& h)
00161       : m_vectors(v), m_coeffs(h), m_trans(false), m_length(v.diagonalSize()),
00162         m_shift(0)
00163     {
00164     }
00165 
00167     HouseholderSequence(const HouseholderSequence& other)
00168       : m_vectors(other.m_vectors),
00169         m_coeffs(other.m_coeffs),
00170         m_trans(other.m_trans),
00171         m_length(other.m_length),
00172         m_shift(other.m_shift)
00173     {
00174     }
00175 
00180     Index rows() const { return Side==OnTheLeft ? m_vectors.rows() : m_vectors.cols(); }
00181 
00186     Index cols() const { return rows(); }
00187 
00202     const EssentialVectorType essentialVector(Index k) const
00203     {
00204       eigen_assert(k >= 0 && k < m_length);
00205       return internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::essentialVector(*this, k);
00206     }
00207 
00209     HouseholderSequence transpose() const
00210     {
00211       return HouseholderSequence(*this).setTrans(!m_trans);
00212     }
00213 
00215     ConjugateReturnType conjugate() const
00216     {
00217       return ConjugateReturnType(m_vectors.conjugate(), m_coeffs.conjugate())
00218              .setTrans(m_trans)
00219              .setLength(m_length)
00220              .setShift(m_shift);
00221     }
00222 
00224     ConjugateReturnType adjoint() const
00225     {
00226       return conjugate().setTrans(!m_trans);
00227     }
00228 
00230     ConjugateReturnType inverse() const { return adjoint(); }
00231 
00233     template<typename DestType> inline void evalTo(DestType& dst) const
00234     {
00235       Matrix<Scalar, DestType::RowsAtCompileTime, 1,
00236              AutoAlign|ColMajor, DestType::MaxRowsAtCompileTime, 1> workspace(rows());
00237       evalTo(dst, workspace);
00238     }
00239 
00241     template<typename Dest, typename Workspace>
00242     void evalTo(Dest& dst, Workspace& workspace) const
00243     {
00244       workspace.resize(rows());
00245       Index vecs = m_length;
00246       if(    internal::is_same<typename internal::remove_all<VectorsType>::type,Dest>::value
00247           && internal::extract_data(dst) == internal::extract_data(m_vectors))
00248       {
00249         // in-place
00250         dst.diagonal().setOnes();
00251         dst.template triangularView<StrictlyUpper>().setZero();
00252         for(Index k = vecs-1; k >= 0; --k)
00253         {
00254           Index cornerSize = rows() - k - m_shift;
00255           if(m_trans)
00256             dst.bottomRightCorner(cornerSize, cornerSize)
00257                .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data());
00258           else
00259             dst.bottomRightCorner(cornerSize, cornerSize)
00260                .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data());
00261 
00262           // clear the off diagonal vector
00263           dst.col(k).tail(rows()-k-1).setZero();
00264         }
00265         // clear the remaining columns if needed
00266         for(Index k = 0; k<cols()-vecs ; ++k)
00267           dst.col(k).tail(rows()-k-1).setZero();
00268       }
00269       else
00270       {
00271         dst.setIdentity(rows(), rows());
00272         for(Index k = vecs-1; k >= 0; --k)
00273         {
00274           Index cornerSize = rows() - k - m_shift;
00275           if(m_trans)
00276             dst.bottomRightCorner(cornerSize, cornerSize)
00277                .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &workspace.coeffRef(0));
00278           else
00279             dst.bottomRightCorner(cornerSize, cornerSize)
00280                .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &workspace.coeffRef(0));
00281         }
00282       }
00283     }
00284 
00286     template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
00287     {
00288       Matrix<Scalar,1,Dest::RowsAtCompileTime,RowMajor,1,Dest::MaxRowsAtCompileTime> workspace(dst.rows());
00289       applyThisOnTheRight(dst, workspace);
00290     }
00291 
00293     template<typename Dest, typename Workspace>
00294     inline void applyThisOnTheRight(Dest& dst, Workspace& workspace) const
00295     {
00296       workspace.resize(dst.rows());
00297       for(Index k = 0; k < m_length; ++k)
00298       {
00299         Index actual_k = m_trans ? m_length-k-1 : k;
00300         dst.rightCols(rows()-m_shift-actual_k)
00301            .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
00302       }
00303     }
00304 
00306     template<typename Dest> inline void applyThisOnTheLeft(Dest& dst) const
00307     {
00308       Matrix<Scalar,1,Dest::ColsAtCompileTime,RowMajor,1,Dest::MaxColsAtCompileTime> workspace(dst.cols());
00309       applyThisOnTheLeft(dst, workspace);
00310     }
00311 
00313     template<typename Dest, typename Workspace>
00314     inline void applyThisOnTheLeft(Dest& dst, Workspace& workspace) const
00315     {
00316       const Index BlockSize = 48;
00317       // if the entries are large enough, then apply the reflectors by block
00318       if(m_length>=BlockSize && dst.cols()>1)
00319       {
00320         for(Index i = 0; i < m_length; i+=BlockSize)
00321         {
00322           Index end = m_trans ? (std::min)(m_length,i+BlockSize) : m_length-i;
00323           Index k = m_trans ? i : (std::max)(Index(0),end-BlockSize);
00324           Index bs = end-k;
00325           Index start = k + m_shift;
00326           
00327           typedef Block<typename internal::remove_all<VectorsType>::type,Dynamic,Dynamic> SubVectorsType;
00328           SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side==OnTheRight ? k : start,
00329                                                                    Side==OnTheRight ? start : k,
00330                                                                    Side==OnTheRight ? bs : m_vectors.rows()-start,
00331                                                                    Side==OnTheRight ? m_vectors.cols()-start : bs);
00332           typename internal::conditional<Side==OnTheRight, Transpose<SubVectorsType>, SubVectorsType&>::type sub_vecs(sub_vecs1);
00333           Block<Dest,Dynamic,Dynamic> sub_dst(dst,dst.rows()-rows()+m_shift+k,0, rows()-m_shift-k,dst.cols());
00334           apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_trans);
00335         }
00336       }
00337       else
00338       {
00339         workspace.resize(dst.cols());
00340         for(Index k = 0; k < m_length; ++k)
00341         {
00342           Index actual_k = m_trans ? k : m_length-k-1;
00343           dst.bottomRows(rows()-m_shift-actual_k)
00344             .applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data());
00345         }
00346       }
00347     }
00348 
00356     template<typename OtherDerived>
00357     typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other) const
00358     {
00359       typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type
00360         res(other.template cast<typename internal::matrix_type_times_scalar_type<Scalar,OtherDerived>::ResultScalar>());
00361       applyThisOnTheLeft(res);
00362       return res;
00363     }
00364 
00365     template<typename _VectorsType, typename _CoeffsType, int _Side> friend struct internal::hseq_side_dependent_impl;
00366 
00376     HouseholderSequence& setLength(Index length)
00377     {
00378       m_length = length;
00379       return *this;
00380     }
00381 
00393     HouseholderSequence& setShift(Index shift)
00394     {
00395       m_shift = shift;
00396       return *this;
00397     }
00398 
00399     Index length() const { return m_length; }  
00400     Index shift() const { return m_shift; }    
00402     /* Necessary for .adjoint() and .conjugate() */
00403     template <typename VectorsType2, typename CoeffsType2, int Side2> friend class HouseholderSequence;
00404 
00405   protected:
00406 
00415     HouseholderSequence& setTrans(bool trans)
00416     {
00417       m_trans = trans;
00418       return *this;
00419     }
00420 
00421     bool trans() const { return m_trans; }     
00423     typename VectorsType::Nested m_vectors;
00424     typename CoeffsType::Nested m_coeffs;
00425     bool m_trans;
00426     Index m_length;
00427     Index m_shift;
00428 };
00429 
00438 template<typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
00439 typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other, const HouseholderSequence<VectorsType,CoeffsType,Side>& h)
00440 {
00441   typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type
00442     res(other.template cast<typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::ResultScalar>());
00443   h.applyThisOnTheRight(res);
00444   return res;
00445 }
00446 
00451 template<typename VectorsType, typename CoeffsType>
00452 HouseholderSequence<VectorsType,CoeffsType> householderSequence(const VectorsType& v, const CoeffsType& h)
00453 {
00454   return HouseholderSequence<VectorsType,CoeffsType,OnTheLeft>(v, h);
00455 }
00456 
00463 template<typename VectorsType, typename CoeffsType>
00464 HouseholderSequence<VectorsType,CoeffsType,OnTheRight> rightHouseholderSequence(const VectorsType& v, const CoeffsType& h)
00465 {
00466   return HouseholderSequence<VectorsType,CoeffsType,OnTheRight>(v, h);
00467 }
00468 
00469 } // end namespace Eigen
00470 
00471 #endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines