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-2010 Benoit Jacob <[email protected]> 00005 // Copyright (C) 2014 Gael Guennebaud <[email protected]> 00006 // 00007 // Copyright (C) 2013 Gauthier Brun <[email protected]> 00008 // Copyright (C) 2013 Nicolas Carre <[email protected]> 00009 // Copyright (C) 2013 Jean Ceccato <[email protected]> 00010 // Copyright (C) 2013 Pierre Zoppitelli <[email protected]> 00011 // 00012 // This Source Code Form is subject to the terms of the Mozilla 00013 // Public License v. 2.0. If a copy of the MPL was not distributed 00014 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00015 00016 #ifndef EIGEN_SVDBASE_H 00017 #define EIGEN_SVDBASE_H 00018 00019 namespace Eigen { 00047 template<typename Derived> 00048 class SVDBase 00049 { 00050 00051 public: 00052 typedef typename internal::traits<Derived>::MatrixType MatrixType; 00053 typedef typename MatrixType::Scalar Scalar; 00054 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; 00055 typedef typename MatrixType::StorageIndex StorageIndex; 00056 typedef Eigen::Index Index; 00057 enum { 00058 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 00059 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 00060 DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime), 00061 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 00062 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, 00063 MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime), 00064 MatrixOptions = MatrixType::Options 00065 }; 00066 00067 typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixUType; 00068 typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime> MatrixVType; 00069 typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType; 00070 00071 Derived& derived() { return *static_cast<Derived*>(this); } 00072 const Derived& derived() const { return *static_cast<const Derived*>(this); } 00073 00083 const MatrixUType& matrixU() const 00084 { 00085 eigen_assert(m_isInitialized && "SVD is not initialized."); 00086 eigen_assert(computeU() && "This SVD decomposition didn't compute U. Did you ask for it?"); 00087 return m_matrixU; 00088 } 00089 00099 const MatrixVType& matrixV() const 00100 { 00101 eigen_assert(m_isInitialized && "SVD is not initialized."); 00102 eigen_assert(computeV() && "This SVD decomposition didn't compute V. Did you ask for it?"); 00103 return m_matrixV; 00104 } 00105 00111 const SingularValuesType& singularValues() const 00112 { 00113 eigen_assert(m_isInitialized && "SVD is not initialized."); 00114 return m_singularValues; 00115 } 00116 00118 Index nonzeroSingularValues() const 00119 { 00120 eigen_assert(m_isInitialized && "SVD is not initialized."); 00121 return m_nonzeroSingularValues; 00122 } 00123 00130 inline Index rank() const 00131 { 00132 using std::abs; 00133 using std::max; 00134 eigen_assert(m_isInitialized && "JacobiSVD is not initialized."); 00135 if(m_singularValues.size()==0) return 0; 00136 RealScalar premultiplied_threshold = (max)(m_singularValues.coeff(0) * threshold(), (std::numeric_limits<RealScalar>::min)()); 00137 Index i = m_nonzeroSingularValues-1; 00138 while(i>=0 && m_singularValues.coeff(i) < premultiplied_threshold) --i; 00139 return i+1; 00140 } 00141 00156 Derived& setThreshold(const RealScalar& threshold) 00157 { 00158 m_usePrescribedThreshold = true; 00159 m_prescribedThreshold = threshold; 00160 return derived(); 00161 } 00162 00171 Derived& setThreshold(Default_t) 00172 { 00173 m_usePrescribedThreshold = false; 00174 return derived(); 00175 } 00176 00181 RealScalar threshold() const 00182 { 00183 eigen_assert(m_isInitialized || m_usePrescribedThreshold); 00184 return m_usePrescribedThreshold ? m_prescribedThreshold 00185 : (std::max<Index>)(1,m_diagSize)*NumTraits<Scalar>::epsilon(); 00186 } 00187 00189 inline bool computeU() const { return m_computeFullU || m_computeThinU; } 00191 inline bool computeV() const { return m_computeFullV || m_computeThinV; } 00192 00193 inline Index rows() const { return m_rows; } 00194 inline Index cols() const { return m_cols; } 00195 00205 template<typename Rhs> 00206 inline const Solve<Derived, Rhs> 00207 solve(const MatrixBase<Rhs>& b) const 00208 { 00209 eigen_assert(m_isInitialized && "SVD is not initialized."); 00210 eigen_assert(computeU() && computeV() && "SVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice)."); 00211 return Solve<Derived, Rhs>(derived(), b.derived()); 00212 } 00213 00214 #ifndef EIGEN_PARSED_BY_DOXYGEN 00215 template<typename RhsType, typename DstType> 00216 EIGEN_DEVICE_FUNC 00217 void _solve_impl(const RhsType &rhs, DstType &dst) const; 00218 #endif 00219 00220 protected: 00221 00222 static void check_template_parameters() 00223 { 00224 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 00225 } 00226 00227 // return true if already allocated 00228 bool allocate(Index rows, Index cols, unsigned int computationOptions) ; 00229 00230 MatrixUType m_matrixU; 00231 MatrixVType m_matrixV; 00232 SingularValuesType m_singularValues; 00233 bool m_isInitialized, m_isAllocated, m_usePrescribedThreshold; 00234 bool m_computeFullU, m_computeThinU; 00235 bool m_computeFullV, m_computeThinV; 00236 unsigned int m_computationOptions; 00237 Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize; 00238 RealScalar m_prescribedThreshold; 00239 00244 SVDBase() 00245 : m_isInitialized(false), 00246 m_isAllocated(false), 00247 m_usePrescribedThreshold(false), 00248 m_computationOptions(0), 00249 m_rows(-1), m_cols(-1), m_diagSize(0) 00250 { 00251 check_template_parameters(); 00252 } 00253 00254 00255 }; 00256 00257 #ifndef EIGEN_PARSED_BY_DOXYGEN 00258 template<typename Derived> 00259 template<typename RhsType, typename DstType> 00260 void SVDBase<Derived>::_solve_impl(const RhsType &rhs, DstType &dst) const 00261 { 00262 eigen_assert(rhs.rows() == rows()); 00263 00264 // A = U S V^* 00265 // So A^{-1} = V S^{-1} U^* 00266 00267 Matrix<Scalar, Dynamic, RhsType::ColsAtCompileTime, 0, MatrixType::MaxRowsAtCompileTime, RhsType::MaxColsAtCompileTime> tmp; 00268 Index l_rank = rank(); 00269 tmp.noalias() = m_matrixU.leftCols(l_rank).adjoint() * rhs; 00270 tmp = m_singularValues.head(l_rank).asDiagonal().inverse() * tmp; 00271 dst = m_matrixV.leftCols(l_rank) * tmp; 00272 } 00273 #endif 00274 00275 template<typename MatrixType> 00276 bool SVDBase<MatrixType>::allocate(Index rows, Index cols, unsigned int computationOptions) 00277 { 00278 eigen_assert(rows >= 0 && cols >= 0); 00279 00280 if (m_isAllocated && 00281 rows == m_rows && 00282 cols == m_cols && 00283 computationOptions == m_computationOptions) 00284 { 00285 return true; 00286 } 00287 00288 m_rows = rows; 00289 m_cols = cols; 00290 m_isInitialized = false; 00291 m_isAllocated = true; 00292 m_computationOptions = computationOptions; 00293 m_computeFullU = (computationOptions & ComputeFullU) != 0; 00294 m_computeThinU = (computationOptions & ComputeThinU) != 0; 00295 m_computeFullV = (computationOptions & ComputeFullV) != 0; 00296 m_computeThinV = (computationOptions & ComputeThinV) != 0; 00297 eigen_assert(!(m_computeFullU && m_computeThinU) && "SVDBase: you can't ask for both full and thin U"); 00298 eigen_assert(!(m_computeFullV && m_computeThinV) && "SVDBase: you can't ask for both full and thin V"); 00299 eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) && 00300 "SVDBase: thin U and V are only available when your matrix has a dynamic number of columns."); 00301 00302 m_diagSize = (std::min)(m_rows, m_cols); 00303 m_singularValues.resize(m_diagSize); 00304 if(RowsAtCompileTime==Dynamic) 00305 m_matrixU.resize(m_rows, m_computeFullU ? m_rows : m_computeThinU ? m_diagSize : 0); 00306 if(ColsAtCompileTime==Dynamic) 00307 m_matrixV.resize(m_cols, m_computeFullV ? m_cols : m_computeThinV ? m_diagSize : 0); 00308 00309 return false; 00310 } 00311 00312 }// end namespace 00313 00314 #endif // EIGEN_SVDBASE_H