MOAB
4.9.3pre
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008-2010 Gael Guennebaud <[email protected]> 00005 // Copyright (C) 2009 Benoit Jacob <[email protected]> 00006 // Copyright (C) 2010 Vincent Lejeune 00007 // 00008 // This Source Code Form is subject to the terms of the Mozilla 00009 // Public License v. 2.0. If a copy of the MPL was not distributed 00010 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00011 00012 #ifndef EIGEN_QR_H 00013 #define EIGEN_QR_H 00014 00015 namespace Eigen { 00016 00042 template<typename _MatrixType> class HouseholderQR 00043 { 00044 public: 00045 00046 typedef _MatrixType MatrixType; 00047 enum { 00048 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 00049 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 00050 Options = MatrixType::Options, 00051 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 00052 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 00053 }; 00054 typedef typename MatrixType::Scalar Scalar; 00055 typedef typename MatrixType::RealScalar RealScalar; 00056 // FIXME should be int 00057 typedef typename MatrixType::StorageIndex StorageIndex; 00058 typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType; 00059 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType; 00060 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType; 00061 typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType; 00062 00069 HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {} 00070 00077 HouseholderQR(Index rows, Index cols) 00078 : m_qr(rows, cols), 00079 m_hCoeffs((std::min)(rows,cols)), 00080 m_temp(cols), 00081 m_isInitialized(false) {} 00082 00095 template<typename InputType> 00096 explicit HouseholderQR(const EigenBase<InputType>& matrix) 00097 : m_qr(matrix.rows(), matrix.cols()), 00098 m_hCoeffs((std::min)(matrix.rows(),matrix.cols())), 00099 m_temp(matrix.cols()), 00100 m_isInitialized(false) 00101 { 00102 compute(matrix.derived()); 00103 } 00104 00122 template<typename Rhs> 00123 inline const Solve<HouseholderQR, Rhs> 00124 solve(const MatrixBase<Rhs>& b) const 00125 { 00126 eigen_assert(m_isInitialized && "HouseholderQR is not initialized."); 00127 return Solve<HouseholderQR, Rhs>(*this, b.derived()); 00128 } 00129 00138 HouseholderSequenceType householderQ() const 00139 { 00140 eigen_assert(m_isInitialized && "HouseholderQR is not initialized."); 00141 return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate()); 00142 } 00143 00147 const MatrixType& matrixQR() const 00148 { 00149 eigen_assert(m_isInitialized && "HouseholderQR is not initialized."); 00150 return m_qr; 00151 } 00152 00153 template<typename InputType> 00154 HouseholderQR& compute(const EigenBase<InputType>& matrix); 00155 00169 typename MatrixType::RealScalar absDeterminant() const; 00170 00183 typename MatrixType::RealScalar logAbsDeterminant() const; 00184 00185 inline Index rows() const { return m_qr.rows(); } 00186 inline Index cols() const { return m_qr.cols(); } 00187 00192 const HCoeffsType& hCoeffs() const { return m_hCoeffs; } 00193 00194 #ifndef EIGEN_PARSED_BY_DOXYGEN 00195 template<typename RhsType, typename DstType> 00196 EIGEN_DEVICE_FUNC 00197 void _solve_impl(const RhsType &rhs, DstType &dst) const; 00198 #endif 00199 00200 protected: 00201 00202 static void check_template_parameters() 00203 { 00204 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 00205 } 00206 00207 MatrixType m_qr; 00208 HCoeffsType m_hCoeffs; 00209 RowVectorType m_temp; 00210 bool m_isInitialized; 00211 }; 00212 00213 template<typename MatrixType> 00214 typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const 00215 { 00216 using std::abs; 00217 eigen_assert(m_isInitialized && "HouseholderQR is not initialized."); 00218 eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!"); 00219 return abs(m_qr.diagonal().prod()); 00220 } 00221 00222 template<typename MatrixType> 00223 typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const 00224 { 00225 eigen_assert(m_isInitialized && "HouseholderQR is not initialized."); 00226 eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!"); 00227 return m_qr.diagonal().cwiseAbs().array().log().sum(); 00228 } 00229 00230 namespace internal { 00231 00233 template<typename MatrixQR, typename HCoeffs> 00234 void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0) 00235 { 00236 typedef typename MatrixQR::Scalar Scalar; 00237 typedef typename MatrixQR::RealScalar RealScalar; 00238 Index rows = mat.rows(); 00239 Index cols = mat.cols(); 00240 Index size = (std::min)(rows,cols); 00241 00242 eigen_assert(hCoeffs.size() == size); 00243 00244 typedef Matrix<Scalar,MatrixQR::ColsAtCompileTime,1> TempType; 00245 TempType tempVector; 00246 if(tempData==0) 00247 { 00248 tempVector.resize(cols); 00249 tempData = tempVector.data(); 00250 } 00251 00252 for(Index k = 0; k < size; ++k) 00253 { 00254 Index remainingRows = rows - k; 00255 Index remainingCols = cols - k - 1; 00256 00257 RealScalar beta; 00258 mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta); 00259 mat.coeffRef(k,k) = beta; 00260 00261 // apply H to remaining part of m_qr from the left 00262 mat.bottomRightCorner(remainingRows, remainingCols) 00263 .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), hCoeffs.coeffRef(k), tempData+k+1); 00264 } 00265 } 00266 00268 template<typename MatrixQR, typename HCoeffs, 00269 typename MatrixQRScalar = typename MatrixQR::Scalar, 00270 bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)> 00271 struct householder_qr_inplace_blocked 00272 { 00273 // This is specialized for MKL-supported Scalar types in HouseholderQR_MKL.h 00274 static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index maxBlockSize=32, 00275 typename MatrixQR::Scalar* tempData = 0) 00276 { 00277 typedef typename MatrixQR::Scalar Scalar; 00278 typedef Block<MatrixQR,Dynamic,Dynamic> BlockType; 00279 00280 Index rows = mat.rows(); 00281 Index cols = mat.cols(); 00282 Index size = (std::min)(rows, cols); 00283 00284 typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType; 00285 TempType tempVector; 00286 if(tempData==0) 00287 { 00288 tempVector.resize(cols); 00289 tempData = tempVector.data(); 00290 } 00291 00292 Index blockSize = (std::min)(maxBlockSize,size); 00293 00294 Index k = 0; 00295 for (k = 0; k < size; k += blockSize) 00296 { 00297 Index bs = (std::min)(size-k,blockSize); // actual size of the block 00298 Index tcols = cols - k - bs; // trailing columns 00299 Index brows = rows-k; // rows of the block 00300 00301 // partition the matrix: 00302 // A00 | A01 | A02 00303 // mat = A10 | A11 | A12 00304 // A20 | A21 | A22 00305 // and performs the qr dec of [A11^T A12^T]^T 00306 // and update [A21^T A22^T]^T using level 3 operations. 00307 // Finally, the algorithm continue on A22 00308 00309 BlockType A11_21 = mat.block(k,k,brows,bs); 00310 Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs); 00311 00312 householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData); 00313 00314 if(tcols) 00315 { 00316 BlockType A21_22 = mat.block(k,k+bs,brows,tcols); 00317 apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment, false); // false == backward 00318 } 00319 } 00320 } 00321 }; 00322 00323 } // end namespace internal 00324 00325 #ifndef EIGEN_PARSED_BY_DOXYGEN 00326 template<typename _MatrixType> 00327 template<typename RhsType, typename DstType> 00328 void HouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const 00329 { 00330 const Index rank = (std::min)(rows(), cols()); 00331 eigen_assert(rhs.rows() == rows()); 00332 00333 typename RhsType::PlainObject c(rhs); 00334 00335 // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T 00336 c.applyOnTheLeft(householderSequence( 00337 m_qr.leftCols(rank), 00338 m_hCoeffs.head(rank)).transpose() 00339 ); 00340 00341 m_qr.topLeftCorner(rank, rank) 00342 .template triangularView<Upper>() 00343 .solveInPlace(c.topRows(rank)); 00344 00345 dst.topRows(rank) = c.topRows(rank); 00346 dst.bottomRows(cols()-rank).setZero(); 00347 } 00348 #endif 00349 00356 template<typename MatrixType> 00357 template<typename InputType> 00358 HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const EigenBase<InputType>& matrix) 00359 { 00360 check_template_parameters(); 00361 00362 Index rows = matrix.rows(); 00363 Index cols = matrix.cols(); 00364 Index size = (std::min)(rows,cols); 00365 00366 m_qr = matrix.derived(); 00367 m_hCoeffs.resize(size); 00368 00369 m_temp.resize(cols); 00370 00371 internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, 48, m_temp.data()); 00372 00373 m_isInitialized = true; 00374 return *this; 00375 } 00376 00377 #ifndef __CUDACC__ 00378 00382 template<typename Derived> 00383 const HouseholderQR<typename MatrixBase<Derived>::PlainObject> 00384 MatrixBase<Derived>::householderQr() const 00385 { 00386 return HouseholderQR<PlainObject>(eval()); 00387 } 00388 #endif // __CUDACC__ 00389 00390 } // end namespace Eigen 00391 00392 #endif // EIGEN_QR_H