MOAB
4.9.3pre
|
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