Warning, file /include/eigen3/Eigen/src/SVD/SVDBase.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef EIGEN_SVDBASE_H
0017 #define EIGEN_SVDBASE_H
0018
0019 namespace Eigen {
0020
0021 namespace internal {
0022 template<typename Derived> struct traits<SVDBase<Derived> >
0023 : traits<Derived>
0024 {
0025 typedef MatrixXpr XprKind;
0026 typedef SolverStorage StorageKind;
0027 typedef int StorageIndex;
0028 enum { Flags = 0 };
0029 };
0030 }
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 template<typename Derived> class SVDBase
0063 : public SolverBase<SVDBase<Derived> >
0064 {
0065 public:
0066
0067 template<typename Derived_>
0068 friend struct internal::solve_assertion;
0069
0070 typedef typename internal::traits<Derived>::MatrixType MatrixType;
0071 typedef typename MatrixType::Scalar Scalar;
0072 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
0073 typedef typename Eigen::internal::traits<SVDBase>::StorageIndex StorageIndex;
0074 typedef Eigen::Index Index;
0075 enum {
0076 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
0077 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0078 DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
0079 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
0080 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
0081 MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
0082 MatrixOptions = MatrixType::Options
0083 };
0084
0085 typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixUType;
0086 typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime> MatrixVType;
0087 typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType;
0088
0089 Derived& derived() { return *static_cast<Derived*>(this); }
0090 const Derived& derived() const { return *static_cast<const Derived*>(this); }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 const MatrixUType& matrixU() const
0102 {
0103 _check_compute_assertions();
0104 eigen_assert(computeU() && "This SVD decomposition didn't compute U. Did you ask for it?");
0105 return m_matrixU;
0106 }
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 const MatrixVType& matrixV() const
0118 {
0119 _check_compute_assertions();
0120 eigen_assert(computeV() && "This SVD decomposition didn't compute V. Did you ask for it?");
0121 return m_matrixV;
0122 }
0123
0124
0125
0126
0127
0128
0129 const SingularValuesType& singularValues() const
0130 {
0131 _check_compute_assertions();
0132 return m_singularValues;
0133 }
0134
0135
0136 Index nonzeroSingularValues() const
0137 {
0138 _check_compute_assertions();
0139 return m_nonzeroSingularValues;
0140 }
0141
0142
0143
0144
0145
0146
0147
0148 inline Index rank() const
0149 {
0150 using std::abs;
0151 _check_compute_assertions();
0152 if(m_singularValues.size()==0) return 0;
0153 RealScalar premultiplied_threshold = numext::maxi<RealScalar>(m_singularValues.coeff(0) * threshold(), (std::numeric_limits<RealScalar>::min)());
0154 Index i = m_nonzeroSingularValues-1;
0155 while(i>=0 && m_singularValues.coeff(i) < premultiplied_threshold) --i;
0156 return i+1;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 Derived& setThreshold(const RealScalar& threshold)
0174 {
0175 m_usePrescribedThreshold = true;
0176 m_prescribedThreshold = threshold;
0177 return derived();
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 Derived& setThreshold(Default_t)
0189 {
0190 m_usePrescribedThreshold = false;
0191 return derived();
0192 }
0193
0194
0195
0196
0197
0198 RealScalar threshold() const
0199 {
0200 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
0201
0202 Index diagSize = (std::max<Index>)(1,m_diagSize);
0203 return m_usePrescribedThreshold ? m_prescribedThreshold
0204 : RealScalar(diagSize)*NumTraits<Scalar>::epsilon();
0205 }
0206
0207
0208 inline bool computeU() const { return m_computeFullU || m_computeThinU; }
0209
0210 inline bool computeV() const { return m_computeFullV || m_computeThinV; }
0211
0212 inline Index rows() const { return m_rows; }
0213 inline Index cols() const { return m_cols; }
0214
0215 #ifdef EIGEN_PARSED_BY_DOXYGEN
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 template<typename Rhs>
0226 inline const Solve<Derived, Rhs>
0227 solve(const MatrixBase<Rhs>& b) const;
0228 #endif
0229
0230
0231
0232
0233
0234
0235 EIGEN_DEVICE_FUNC
0236 ComputationInfo info() const
0237 {
0238 eigen_assert(m_isInitialized && "SVD is not initialized.");
0239 return m_info;
0240 }
0241
0242 #ifndef EIGEN_PARSED_BY_DOXYGEN
0243 template<typename RhsType, typename DstType>
0244 void _solve_impl(const RhsType &rhs, DstType &dst) const;
0245
0246 template<bool Conjugate, typename RhsType, typename DstType>
0247 void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
0248 #endif
0249
0250 protected:
0251
0252 static void check_template_parameters()
0253 {
0254 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
0255 }
0256
0257 void _check_compute_assertions() const {
0258 eigen_assert(m_isInitialized && "SVD is not initialized.");
0259 }
0260
0261 template<bool Transpose_, typename Rhs>
0262 void _check_solve_assertion(const Rhs& b) const {
0263 EIGEN_ONLY_USED_FOR_DEBUG(b);
0264 _check_compute_assertions();
0265 eigen_assert(computeU() && computeV() && "SVDBase::solve(): Both unitaries U and V are required to be computed (thin unitaries suffice).");
0266 eigen_assert((Transpose_?cols():rows())==b.rows() && "SVDBase::solve(): invalid number of rows of the right hand side matrix b");
0267 }
0268
0269
0270 bool allocate(Index rows, Index cols, unsigned int computationOptions) ;
0271
0272 MatrixUType m_matrixU;
0273 MatrixVType m_matrixV;
0274 SingularValuesType m_singularValues;
0275 ComputationInfo m_info;
0276 bool m_isInitialized, m_isAllocated, m_usePrescribedThreshold;
0277 bool m_computeFullU, m_computeThinU;
0278 bool m_computeFullV, m_computeThinV;
0279 unsigned int m_computationOptions;
0280 Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize;
0281 RealScalar m_prescribedThreshold;
0282
0283
0284
0285
0286
0287 SVDBase()
0288 : m_info(Success),
0289 m_isInitialized(false),
0290 m_isAllocated(false),
0291 m_usePrescribedThreshold(false),
0292 m_computeFullU(false),
0293 m_computeThinU(false),
0294 m_computeFullV(false),
0295 m_computeThinV(false),
0296 m_computationOptions(0),
0297 m_rows(-1), m_cols(-1), m_diagSize(0)
0298 {
0299 check_template_parameters();
0300 }
0301
0302
0303 };
0304
0305 #ifndef EIGEN_PARSED_BY_DOXYGEN
0306 template<typename Derived>
0307 template<typename RhsType, typename DstType>
0308 void SVDBase<Derived>::_solve_impl(const RhsType &rhs, DstType &dst) const
0309 {
0310
0311
0312
0313 Matrix<typename RhsType::Scalar, Dynamic, RhsType::ColsAtCompileTime, 0, MatrixType::MaxRowsAtCompileTime, RhsType::MaxColsAtCompileTime> tmp;
0314 Index l_rank = rank();
0315 tmp.noalias() = m_matrixU.leftCols(l_rank).adjoint() * rhs;
0316 tmp = m_singularValues.head(l_rank).asDiagonal().inverse() * tmp;
0317 dst = m_matrixV.leftCols(l_rank) * tmp;
0318 }
0319
0320 template<typename Derived>
0321 template<bool Conjugate, typename RhsType, typename DstType>
0322 void SVDBase<Derived>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
0323 {
0324
0325
0326
0327 Matrix<typename RhsType::Scalar, Dynamic, RhsType::ColsAtCompileTime, 0, MatrixType::MaxRowsAtCompileTime, RhsType::MaxColsAtCompileTime> tmp;
0328 Index l_rank = rank();
0329
0330 tmp.noalias() = m_matrixV.leftCols(l_rank).transpose().template conjugateIf<Conjugate>() * rhs;
0331 tmp = m_singularValues.head(l_rank).asDiagonal().inverse() * tmp;
0332 dst = m_matrixU.template conjugateIf<!Conjugate>().leftCols(l_rank) * tmp;
0333 }
0334 #endif
0335
0336 template<typename MatrixType>
0337 bool SVDBase<MatrixType>::allocate(Index rows, Index cols, unsigned int computationOptions)
0338 {
0339 eigen_assert(rows >= 0 && cols >= 0);
0340
0341 if (m_isAllocated &&
0342 rows == m_rows &&
0343 cols == m_cols &&
0344 computationOptions == m_computationOptions)
0345 {
0346 return true;
0347 }
0348
0349 m_rows = rows;
0350 m_cols = cols;
0351 m_info = Success;
0352 m_isInitialized = false;
0353 m_isAllocated = true;
0354 m_computationOptions = computationOptions;
0355 m_computeFullU = (computationOptions & ComputeFullU) != 0;
0356 m_computeThinU = (computationOptions & ComputeThinU) != 0;
0357 m_computeFullV = (computationOptions & ComputeFullV) != 0;
0358 m_computeThinV = (computationOptions & ComputeThinV) != 0;
0359 eigen_assert(!(m_computeFullU && m_computeThinU) && "SVDBase: you can't ask for both full and thin U");
0360 eigen_assert(!(m_computeFullV && m_computeThinV) && "SVDBase: you can't ask for both full and thin V");
0361 eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) &&
0362 "SVDBase: thin U and V are only available when your matrix has a dynamic number of columns.");
0363
0364 m_diagSize = (std::min)(m_rows, m_cols);
0365 m_singularValues.resize(m_diagSize);
0366 if(RowsAtCompileTime==Dynamic)
0367 m_matrixU.resize(m_rows, m_computeFullU ? m_rows : m_computeThinU ? m_diagSize : 0);
0368 if(ColsAtCompileTime==Dynamic)
0369 m_matrixV.resize(m_cols, m_computeFullV ? m_cols : m_computeThinV ? m_diagSize : 0);
0370
0371 return false;
0372 }
0373
0374 }
0375
0376 #endif