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 Gael Guennebaud <[email protected]> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_LLT_H 00011 #define EIGEN_LLT_H 00012 00013 namespace Eigen { 00014 00015 namespace internal{ 00016 template<typename MatrixType, int UpLo> struct LLT_Traits; 00017 } 00018 00046 /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH) 00047 * Note that during the decomposition, only the upper triangular part of A is considered. Therefore, 00048 * the strict lower part does not have to store correct values. 00049 */ 00050 template<typename _MatrixType, int _UpLo> class LLT 00051 { 00052 public: 00053 typedef _MatrixType MatrixType; 00054 enum { 00055 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 00056 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 00057 Options = MatrixType::Options, 00058 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 00059 }; 00060 typedef typename MatrixType::Scalar Scalar; 00061 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; 00062 typedef Eigen::Index Index; 00063 typedef typename MatrixType::StorageIndex StorageIndex; 00064 00065 enum { 00066 PacketSize = internal::packet_traits<Scalar>::size, 00067 AlignmentMask = int(PacketSize)-1, 00068 UpLo = _UpLo 00069 }; 00070 00071 typedef internal::LLT_Traits<MatrixType,UpLo> Traits; 00072 00079 LLT() : m_matrix(), m_isInitialized(false) {} 00080 00087 explicit LLT(Index size) : m_matrix(size, size), 00088 m_isInitialized(false) {} 00089 00090 template<typename InputType> 00091 explicit LLT(const EigenBase<InputType>& matrix) 00092 : m_matrix(matrix.rows(), matrix.cols()), 00093 m_isInitialized(false) 00094 { 00095 compute(matrix.derived()); 00096 } 00097 00099 inline typename Traits::MatrixU matrixU() const 00100 { 00101 eigen_assert(m_isInitialized && "LLT is not initialized."); 00102 return Traits::getU(m_matrix); 00103 } 00104 00106 inline typename Traits::MatrixL matrixL() const 00107 { 00108 eigen_assert(m_isInitialized && "LLT is not initialized."); 00109 return Traits::getL(m_matrix); 00110 } 00111 00122 template<typename Rhs> 00123 inline const Solve<LLT, Rhs> 00124 solve(const MatrixBase<Rhs>& b) const 00125 { 00126 eigen_assert(m_isInitialized && "LLT is not initialized."); 00127 eigen_assert(m_matrix.rows()==b.rows() 00128 && "LLT::solve(): invalid number of rows of the right hand side matrix b"); 00129 return Solve<LLT, Rhs>(*this, b.derived()); 00130 } 00131 00132 template<typename Derived> 00133 void solveInPlace(MatrixBase<Derived> &bAndX) const; 00134 00135 template<typename InputType> 00136 LLT& compute(const EigenBase<InputType>& matrix); 00137 00142 inline const MatrixType& matrixLLT() const 00143 { 00144 eigen_assert(m_isInitialized && "LLT is not initialized."); 00145 return m_matrix; 00146 } 00147 00148 MatrixType reconstructedMatrix() const; 00149 00150 00156 ComputationInfo info() const 00157 { 00158 eigen_assert(m_isInitialized && "LLT is not initialized."); 00159 return m_info; 00160 } 00161 00162 inline Index rows() const { return m_matrix.rows(); } 00163 inline Index cols() const { return m_matrix.cols(); } 00164 00165 template<typename VectorType> 00166 LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1); 00167 00168 #ifndef EIGEN_PARSED_BY_DOXYGEN 00169 template<typename RhsType, typename DstType> 00170 EIGEN_DEVICE_FUNC 00171 void _solve_impl(const RhsType &rhs, DstType &dst) const; 00172 #endif 00173 00174 protected: 00175 00176 static void check_template_parameters() 00177 { 00178 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 00179 } 00180 00185 MatrixType m_matrix; 00186 bool m_isInitialized; 00187 ComputationInfo m_info; 00188 }; 00189 00190 namespace internal { 00191 00192 template<typename Scalar, int UpLo> struct llt_inplace; 00193 00194 template<typename MatrixType, typename VectorType> 00195 static Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) 00196 { 00197 using std::sqrt; 00198 typedef typename MatrixType::Scalar Scalar; 00199 typedef typename MatrixType::RealScalar RealScalar; 00200 typedef typename MatrixType::ColXpr ColXpr; 00201 typedef typename internal::remove_all<ColXpr>::type ColXprCleaned; 00202 typedef typename ColXprCleaned::SegmentReturnType ColXprSegment; 00203 typedef Matrix<Scalar,Dynamic,1> TempVectorType; 00204 typedef typename TempVectorType::SegmentReturnType TempVecSegment; 00205 00206 Index n = mat.cols(); 00207 eigen_assert(mat.rows()==n && vec.size()==n); 00208 00209 TempVectorType temp; 00210 00211 if(sigma>0) 00212 { 00213 // This version is based on Givens rotations. 00214 // It is faster than the other one below, but only works for updates, 00215 // i.e., for sigma > 0 00216 temp = sqrt(sigma) * vec; 00217 00218 for(Index i=0; i<n; ++i) 00219 { 00220 JacobiRotation<Scalar> g; 00221 g.makeGivens(mat(i,i), -temp(i), &mat(i,i)); 00222 00223 Index rs = n-i-1; 00224 if(rs>0) 00225 { 00226 ColXprSegment x(mat.col(i).tail(rs)); 00227 TempVecSegment y(temp.tail(rs)); 00228 apply_rotation_in_the_plane(x, y, g); 00229 } 00230 } 00231 } 00232 else 00233 { 00234 temp = vec; 00235 RealScalar beta = 1; 00236 for(Index j=0; j<n; ++j) 00237 { 00238 RealScalar Ljj = numext::real(mat.coeff(j,j)); 00239 RealScalar dj = numext::abs2(Ljj); 00240 Scalar wj = temp.coeff(j); 00241 RealScalar swj2 = sigma*numext::abs2(wj); 00242 RealScalar gamma = dj*beta + swj2; 00243 00244 RealScalar x = dj + swj2/beta; 00245 if (x<=RealScalar(0)) 00246 return j; 00247 RealScalar nLjj = sqrt(x); 00248 mat.coeffRef(j,j) = nLjj; 00249 beta += swj2/dj; 00250 00251 // Update the terms of L 00252 Index rs = n-j-1; 00253 if(rs) 00254 { 00255 temp.tail(rs) -= (wj/Ljj) * mat.col(j).tail(rs); 00256 if(gamma != 0) 00257 mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*numext::conj(wj)/gamma)*temp.tail(rs); 00258 } 00259 } 00260 } 00261 return -1; 00262 } 00263 00264 template<typename Scalar> struct llt_inplace<Scalar, Lower> 00265 { 00266 typedef typename NumTraits<Scalar>::Real RealScalar; 00267 template<typename MatrixType> 00268 static Index unblocked(MatrixType& mat) 00269 { 00270 using std::sqrt; 00271 00272 eigen_assert(mat.rows()==mat.cols()); 00273 const Index size = mat.rows(); 00274 for(Index k = 0; k < size; ++k) 00275 { 00276 Index rs = size-k-1; // remaining size 00277 00278 Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1); 00279 Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k); 00280 Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k); 00281 00282 RealScalar x = numext::real(mat.coeff(k,k)); 00283 if (k>0) x -= A10.squaredNorm(); 00284 if (x<=RealScalar(0)) 00285 return k; 00286 mat.coeffRef(k,k) = x = sqrt(x); 00287 if (k>0 && rs>0) A21.noalias() -= A20 * A10.adjoint(); 00288 if (rs>0) A21 /= x; 00289 } 00290 return -1; 00291 } 00292 00293 template<typename MatrixType> 00294 static Index blocked(MatrixType& m) 00295 { 00296 eigen_assert(m.rows()==m.cols()); 00297 Index size = m.rows(); 00298 if(size<32) 00299 return unblocked(m); 00300 00301 Index blockSize = size/8; 00302 blockSize = (blockSize/16)*16; 00303 blockSize = (std::min)((std::max)(blockSize,Index(8)), Index(128)); 00304 00305 for (Index k=0; k<size; k+=blockSize) 00306 { 00307 // partition the matrix: 00308 // A00 | - | - 00309 // lu = A10 | A11 | - 00310 // A20 | A21 | A22 00311 Index bs = (std::min)(blockSize, size-k); 00312 Index rs = size - k - bs; 00313 Block<MatrixType,Dynamic,Dynamic> A11(m,k, k, bs,bs); 00314 Block<MatrixType,Dynamic,Dynamic> A21(m,k+bs,k, rs,bs); 00315 Block<MatrixType,Dynamic,Dynamic> A22(m,k+bs,k+bs,rs,rs); 00316 00317 Index ret; 00318 if((ret=unblocked(A11))>=0) return k+ret; 00319 if(rs>0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21); 00320 if(rs>0) A22.template selfadjointView<Lower>().rankUpdate(A21,-1); // bottleneck 00321 } 00322 return -1; 00323 } 00324 00325 template<typename MatrixType, typename VectorType> 00326 static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) 00327 { 00328 return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); 00329 } 00330 }; 00331 00332 template<typename Scalar> struct llt_inplace<Scalar, Upper> 00333 { 00334 typedef typename NumTraits<Scalar>::Real RealScalar; 00335 00336 template<typename MatrixType> 00337 static EIGEN_STRONG_INLINE Index unblocked(MatrixType& mat) 00338 { 00339 Transpose<MatrixType> matt(mat); 00340 return llt_inplace<Scalar, Lower>::unblocked(matt); 00341 } 00342 template<typename MatrixType> 00343 static EIGEN_STRONG_INLINE Index blocked(MatrixType& mat) 00344 { 00345 Transpose<MatrixType> matt(mat); 00346 return llt_inplace<Scalar, Lower>::blocked(matt); 00347 } 00348 template<typename MatrixType, typename VectorType> 00349 static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) 00350 { 00351 Transpose<MatrixType> matt(mat); 00352 return llt_inplace<Scalar, Lower>::rankUpdate(matt, vec.conjugate(), sigma); 00353 } 00354 }; 00355 00356 template<typename MatrixType> struct LLT_Traits<MatrixType,Lower> 00357 { 00358 typedef const TriangularView<const MatrixType, Lower> MatrixL; 00359 typedef const TriangularView<const typename MatrixType::AdjointReturnType, Upper> MatrixU; 00360 static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); } 00361 static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); } 00362 static bool inplace_decomposition(MatrixType& m) 00363 { return llt_inplace<typename MatrixType::Scalar, Lower>::blocked(m)==-1; } 00364 }; 00365 00366 template<typename MatrixType> struct LLT_Traits<MatrixType,Upper> 00367 { 00368 typedef const TriangularView<const typename MatrixType::AdjointReturnType, Lower> MatrixL; 00369 typedef const TriangularView<const MatrixType, Upper> MatrixU; 00370 static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); } 00371 static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); } 00372 static bool inplace_decomposition(MatrixType& m) 00373 { return llt_inplace<typename MatrixType::Scalar, Upper>::blocked(m)==-1; } 00374 }; 00375 00376 } // end namespace internal 00377 00385 template<typename MatrixType, int _UpLo> 00386 template<typename InputType> 00387 LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>& a) 00388 { 00389 check_template_parameters(); 00390 00391 eigen_assert(a.rows()==a.cols()); 00392 const Index size = a.rows(); 00393 m_matrix.resize(size, size); 00394 m_matrix = a.derived(); 00395 00396 m_isInitialized = true; 00397 bool ok = Traits::inplace_decomposition(m_matrix); 00398 m_info = ok ? Success : NumericalIssue; 00399 00400 return *this; 00401 } 00402 00408 template<typename _MatrixType, int _UpLo> 00409 template<typename VectorType> 00410 LLT<_MatrixType,_UpLo> LLT<_MatrixType,_UpLo>::rankUpdate(const VectorType& v, const RealScalar& sigma) 00411 { 00412 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType); 00413 eigen_assert(v.size()==m_matrix.cols()); 00414 eigen_assert(m_isInitialized); 00415 if(internal::llt_inplace<typename MatrixType::Scalar, UpLo>::rankUpdate(m_matrix,v,sigma)>=0) 00416 m_info = NumericalIssue; 00417 else 00418 m_info = Success; 00419 00420 return *this; 00421 } 00422 00423 #ifndef EIGEN_PARSED_BY_DOXYGEN 00424 template<typename _MatrixType,int _UpLo> 00425 template<typename RhsType, typename DstType> 00426 void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const 00427 { 00428 dst = rhs; 00429 solveInPlace(dst); 00430 } 00431 #endif 00432 00443 template<typename MatrixType, int _UpLo> 00444 template<typename Derived> 00445 void LLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const 00446 { 00447 eigen_assert(m_isInitialized && "LLT is not initialized."); 00448 eigen_assert(m_matrix.rows()==bAndX.rows()); 00449 matrixL().solveInPlace(bAndX); 00450 matrixU().solveInPlace(bAndX); 00451 } 00452 00456 template<typename MatrixType, int _UpLo> 00457 MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const 00458 { 00459 eigen_assert(m_isInitialized && "LLT is not initialized."); 00460 return matrixL() * matrixL().adjoint().toDenseMatrix(); 00461 } 00462 00463 #ifndef __CUDACC__ 00464 00468 template<typename Derived> 00469 inline const LLT<typename MatrixBase<Derived>::PlainObject> 00470 MatrixBase<Derived>::llt() const 00471 { 00472 return LLT<PlainObject>(derived()); 00473 } 00474 00479 template<typename MatrixType, unsigned int UpLo> 00480 inline const LLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo> 00481 SelfAdjointView<MatrixType, UpLo>::llt() const 00482 { 00483 return LLT<PlainObject,UpLo>(m_matrix); 00484 } 00485 #endif // __CUDACC__ 00486 00487 } // end namespace Eigen 00488 00489 #endif // EIGEN_LLT_H