11 #ifndef EIGEN_JACOBISVD_H
12 #define EIGEN_JACOBISVD_H
22 template <typename MatrixType, int Options, bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
23 struct svd_precondition_2x2_block_to_be_real {};
34 template<
typename MatrixType,
int QRPreconditioner,
int Case>
35 struct qr_preconditioner_should_do_anything
37 enum {
a = MatrixType::RowsAtCompileTime !=
Dynamic &&
38 MatrixType::ColsAtCompileTime !=
Dynamic &&
39 MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
40 b = MatrixType::RowsAtCompileTime !=
Dynamic &&
41 MatrixType::ColsAtCompileTime !=
Dynamic &&
42 MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
49 template <
typename MatrixType,
int Options,
int QRPreconditioner,
int Case,
50 bool DoAnything = qr_preconditioner_should_do_anything<MatrixType, QRPreconditioner, Case>::ret>
51 struct qr_preconditioner_impl {};
53 template <
typename MatrixType,
int Options,
int QRPreconditioner,
int Case>
54 class qr_preconditioner_impl<
MatrixType, Options, QRPreconditioner, Case, false> {
56 void allocate(
const JacobiSVD<MatrixType, Options>&) {}
57 bool run(JacobiSVD<MatrixType, Options>&,
const MatrixType&) {
return false; }
62 template <
typename MatrixType,
int Options>
67 typedef JacobiSVD<MatrixType, Options> SVDType;
69 enum { WorkspaceSize = MatrixType::RowsAtCompileTime, MaxWorkspaceSize = MatrixType::MaxRowsAtCompileTime };
71 typedef Matrix<Scalar, 1, WorkspaceSize, RowMajor, 1, MaxWorkspaceSize> WorkspaceType;
73 void allocate(
const SVDType&
svd) {
74 if (
svd.rows() != m_qr.rows() ||
svd.cols() != m_qr.cols())
79 if (
svd.m_computeFullU) m_workspace.resize(
svd.rows());
83 if(matrix.rows() > matrix.cols())
86 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
87 if(
svd.m_computeFullU) m_qr.matrixQ().evalTo(
svd.m_matrixU, m_workspace);
88 if(
svd.computeV())
svd.m_matrixV = m_qr.colsPermutation();
95 typedef FullPivHouseholderQR<MatrixType> QRType;
97 WorkspaceType m_workspace;
100 template <
typename MatrixType,
int Options>
105 typedef JacobiSVD<MatrixType, Options> SVDType;
108 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
109 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
110 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
111 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
112 MatrixOptions = MatrixType::Options
115 typedef typename internal::make_proper_matrix_type<Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions,
116 MaxColsAtCompileTime, MaxRowsAtCompileTime>::type
117 TransposeTypeWithSameStorageOrder;
119 void allocate(
const SVDType&
svd) {
120 if (
svd.cols() != m_qr.rows() ||
svd.rows() != m_qr.cols())
125 m_adjoint.resize(
svd.cols(),
svd.rows());
126 if (
svd.m_computeFullV) m_workspace.resize(
svd.cols());
130 if(matrix.cols() > matrix.rows())
132 m_adjoint = matrix.adjoint();
133 m_qr.compute(m_adjoint);
134 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
135 if(
svd.m_computeFullV) m_qr.matrixQ().evalTo(
svd.m_matrixV, m_workspace);
136 if(
svd.computeU())
svd.m_matrixU = m_qr.colsPermutation();
143 typedef FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
145 TransposeTypeWithSameStorageOrder m_adjoint;
146 typename plain_row_type<MatrixType>::type m_workspace;
151 template <
typename MatrixType,
int Options>
156 typedef JacobiSVD<MatrixType, Options> SVDType;
159 WorkspaceSize = internal::traits<SVDType>::MatrixUColsAtCompileTime,
160 MaxWorkspaceSize = internal::traits<SVDType>::MatrixUMaxColsAtCompileTime
163 typedef Matrix<Scalar, 1, WorkspaceSize, RowMajor, 1, MaxWorkspaceSize> WorkspaceType;
165 void allocate(
const SVDType&
svd) {
166 if (
svd.rows() != m_qr.rows() ||
svd.cols() != m_qr.cols())
171 if (
svd.m_computeFullU) m_workspace.resize(
svd.rows());
172 else if (
svd.m_computeThinU) m_workspace.resize(
svd.cols());
176 if(matrix.rows() > matrix.cols())
178 m_qr.compute(matrix);
179 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
180 if(
svd.m_computeFullU) m_qr.householderQ().evalTo(
svd.m_matrixU, m_workspace);
181 else if(
svd.m_computeThinU)
183 svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
184 m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixU, m_workspace);
186 if(
svd.computeV())
svd.m_matrixV = m_qr.colsPermutation();
193 typedef ColPivHouseholderQR<MatrixType> QRType;
195 WorkspaceType m_workspace;
198 template <
typename MatrixType,
int Options>
203 typedef JacobiSVD<MatrixType, Options> SVDType;
206 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
207 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
208 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
209 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
210 MatrixOptions = MatrixType::Options,
211 WorkspaceSize = internal::traits<SVDType>::MatrixVColsAtCompileTime,
212 MaxWorkspaceSize = internal::traits<SVDType>::MatrixVMaxColsAtCompileTime
215 typedef Matrix<Scalar, WorkspaceSize, 1, ColMajor, MaxWorkspaceSize, 1> WorkspaceType;
217 typedef typename internal::make_proper_matrix_type<Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions,
218 MaxColsAtCompileTime, MaxRowsAtCompileTime>::type
219 TransposeTypeWithSameStorageOrder;
221 void allocate(
const SVDType&
svd) {
222 if (
svd.cols() != m_qr.rows() ||
svd.rows() != m_qr.cols())
227 if (
svd.m_computeFullV) m_workspace.resize(
svd.cols());
228 else if (
svd.m_computeThinV) m_workspace.resize(
svd.rows());
229 m_adjoint.resize(
svd.cols(),
svd.rows());
233 if(matrix.cols() > matrix.rows())
235 m_adjoint = matrix.adjoint();
236 m_qr.compute(m_adjoint);
238 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
239 if(
svd.m_computeFullV) m_qr.householderQ().evalTo(
svd.m_matrixV, m_workspace);
240 else if(
svd.m_computeThinV)
242 svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
243 m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixV, m_workspace);
245 if(
svd.computeU())
svd.m_matrixU = m_qr.colsPermutation();
252 typedef ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
254 TransposeTypeWithSameStorageOrder m_adjoint;
255 WorkspaceType m_workspace;
260 template <
typename MatrixType,
int Options>
264 typedef JacobiSVD<MatrixType, Options> SVDType;
267 WorkspaceSize = internal::traits<SVDType>::MatrixUColsAtCompileTime,
268 MaxWorkspaceSize = internal::traits<SVDType>::MatrixUMaxColsAtCompileTime
271 typedef Matrix<Scalar, 1, WorkspaceSize, RowMajor, 1, MaxWorkspaceSize> WorkspaceType;
273 void allocate(
const SVDType&
svd) {
274 if (
svd.rows() != m_qr.rows() ||
svd.cols() != m_qr.cols())
279 if (
svd.m_computeFullU) m_workspace.resize(
svd.rows());
280 else if (
svd.m_computeThinU) m_workspace.resize(
svd.cols());
284 if(matrix.rows() > matrix.cols())
286 m_qr.compute(matrix);
287 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
288 if(
svd.m_computeFullU) m_qr.householderQ().evalTo(
svd.m_matrixU, m_workspace);
289 else if(
svd.m_computeThinU)
291 svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
292 m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixU, m_workspace);
294 if(
svd.computeV())
svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
301 typedef HouseholderQR<MatrixType> QRType;
303 WorkspaceType m_workspace;
306 template <
typename MatrixType,
int Options>
310 typedef JacobiSVD<MatrixType, Options> SVDType;
313 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
314 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
315 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
316 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
317 MatrixOptions = MatrixType::Options,
318 WorkspaceSize = internal::traits<SVDType>::MatrixVColsAtCompileTime,
319 MaxWorkspaceSize = internal::traits<SVDType>::MatrixVMaxColsAtCompileTime
322 typedef Matrix<Scalar, WorkspaceSize, 1, ColMajor, MaxWorkspaceSize, 1> WorkspaceType;
324 typedef typename internal::make_proper_matrix_type<Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions,
325 MaxColsAtCompileTime, MaxRowsAtCompileTime>::type
326 TransposeTypeWithSameStorageOrder;
328 void allocate(
const SVDType&
svd) {
329 if (
svd.cols() != m_qr.rows() ||
svd.rows() != m_qr.cols())
334 if (
svd.m_computeFullV) m_workspace.resize(
svd.cols());
335 else if (
svd.m_computeThinV) m_workspace.resize(
svd.rows());
336 m_adjoint.resize(
svd.cols(),
svd.rows());
340 if(matrix.cols() > matrix.rows())
342 m_adjoint = matrix.adjoint();
343 m_qr.compute(m_adjoint);
345 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
346 if(
svd.m_computeFullV) m_qr.householderQ().evalTo(
svd.m_matrixV, m_workspace);
347 else if(
svd.m_computeThinV)
349 svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
350 m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixV, m_workspace);
352 if(
svd.computeU())
svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
359 typedef HouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
361 TransposeTypeWithSameStorageOrder m_adjoint;
362 WorkspaceType m_workspace;
370 template <
typename MatrixType,
int Options>
371 struct svd_precondition_2x2_block_to_be_real<
MatrixType, Options, false> {
372 typedef JacobiSVD<MatrixType, Options> SVD;
374 static bool run(
typename SVD::WorkMatrixType&, SVD&,
Index,
Index, RealScalar&) {
return true; }
377 template <
typename MatrixType,
int Options>
378 struct svd_precondition_2x2_block_to_be_real<
MatrixType, Options, true> {
379 typedef JacobiSVD<MatrixType, Options> SVD;
382 static bool run(
typename SVD::WorkMatrixType& work_matrix, SVD&
svd,
Index p,
Index q, RealScalar& maxDiagEntry)
387 JacobiRotation<Scalar> rot;
391 const RealScalar precision = NumTraits<Scalar>::epsilon();
396 work_matrix.coeffRef(
p,
p) = work_matrix.coeffRef(q,
p) = Scalar(0);
401 z =
abs(work_matrix.coeff(
p,q)) / work_matrix.coeff(
p,q);
402 work_matrix.row(
p) *= z;
403 if(
svd.computeU())
svd.m_matrixU.col(
p) *=
conj(z);
407 z =
abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
408 work_matrix.row(q) *= z;
409 if(
svd.computeU())
svd.m_matrixU.col(q) *=
conj(z);
415 rot.c() =
conj(work_matrix.coeff(
p,
p)) /
n;
416 rot.s() = work_matrix.coeff(q,
p) /
n;
417 work_matrix.applyOnTheLeft(
p,q,rot);
418 if(
svd.computeU())
svd.m_matrixU.applyOnTheRight(
p,q,rot.adjoint());
421 z =
abs(work_matrix.coeff(
p,q)) / work_matrix.coeff(
p,q);
422 work_matrix.col(q) *= z;
423 if(
svd.computeV())
svd.m_matrixV.col(q) *= z;
427 z =
abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
428 work_matrix.row(q) *= z;
429 if(
svd.computeU())
svd.m_matrixU.col(q) *=
conj(z);
434 maxDiagEntry = numext::maxi<RealScalar>(maxDiagEntry,numext::maxi<RealScalar>(
abs(work_matrix.coeff(
p,
p)),
abs(work_matrix.coeff(q,q))));
436 RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
437 return abs(work_matrix.coeff(
p,q))>threshold ||
abs(work_matrix.coeff(q,
p)) > threshold;
441 template <
typename MatrixType_,
int Options>
442 struct traits<JacobiSVD<MatrixType_, Options> > : svd_traits<MatrixType_, Options> {
513 template <
typename MatrixType_,
int Options_>
573 internal::check_svd_options_assertions<MatrixType, Options>(computationOptions,
rows,
cols);
598 internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
620 internal::check_svd_options_assertions<MatrixType, Options>(
m_computationOptions, matrix.rows(), matrix.cols());
657 "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
658 "Use the ColPivHouseholderQR preconditioner instead.")
660 template <typename MatrixType__,
int Options__,
bool IsComplex_>
661 friend struct
internal::svd_precondition_2x2_block_to_be_real;
662 template <typename MatrixType__,
int Options__,
int QRPreconditioner_,
int Case_,
bool DoAnything_>
663 friend struct
internal::qr_preconditioner_impl;
679 "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
680 "Use the ColPivHouseholderQR preconditioner instead.");
688 template <
typename MatrixType,
int Options>
690 unsigned int computationOptions) {
693 allocate(matrix.rows(), matrix.cols(), computationOptions);
703 RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
732 bool finished =
false;
741 for(
Index q = 0; q <
p; ++q)
752 if (internal::svd_precondition_2x2_block_to_be_real<MatrixType, Options>::run(
m_workMatrix, *
this,
p, q,
828 template <
typename Derived>
829 template <
int Options>
834 template <
typename Derived>
835 template <
int Options>
837 unsigned int computationOptions)
const {
const AbsReturnType abs() const
const SqrtReturnType sqrt() const
const ImagReturnType imag() const
RealReturnType real() const
cout<< "Here is the matrix m:"<< endl<< m<< endl;JacobiSVD< MatrixXf, ComputeThinU|ComputeThinV > svd(m)
Matrix< float, 1, Dynamic > MatrixType
NumTraits< Scalar >::Real RealScalar
internal::traits< Derived >::Scalar Scalar
void swap(const DenseBase< OtherDerived > &other)
Rotation given by a cosine-sine pair.
JacobiRotation transpose() const
Two-sided Jacobi SVD decomposition of a rectangular matrix.
EIGEN_DEPRECATED JacobiSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix, as specified by the computationOptions parameter...
Base::RealScalar RealScalar
Base::SingularValuesType SingularValuesType
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
void allocate(Index rows, Index cols, unsigned int computationOptions)
Base::MatrixVType MatrixVType
SVDBase< JacobiSVD > Base
JacobiSVD()
Default Constructor.
EIGEN_DEPRECATED JacobiSVD(Index rows, Index cols, unsigned int computationOptions)
Default Constructor with memory preallocation.
@ MaxDiagSizeAtCompileTime
EIGEN_STATIC_ASSERT(!(ShouldComputeThinU &&int(QRPreconditioner)==int(FullPivHouseholderQRPreconditioner)) &&!(ShouldComputeThinU &&int(QRPreconditioner)==int(FullPivHouseholderQRPreconditioner)), "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. " "Use the ColPivHouseholderQR preconditioner instead.") template< typename MatrixType__
JacobiSVD(const MatrixType &matrix, unsigned int computationOptions)
Constructor performing the decomposition of given matrix using specified options for computing unitar...
JacobiSVD & compute_impl(const MatrixType &matrix, unsigned int computationOptions)
Base::MatrixUType MatrixUType
JacobiSVD(Index rows, Index cols)
Default Constructor with memory preallocation.
internal::qr_preconditioner_impl< MatrixType, Options, QRPreconditioner, internal::PreconditionIfMoreColsThanRows > m_qr_precond_morecols
JacobiSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix. Computes Thin/Full unitaries U/V if specified us...
JacobiSVD(const MatrixType &matrix)
Constructor performing the decomposition of given matrix, using the custom options specified with the...
internal::qr_preconditioner_impl< MatrixType, Options, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols > m_qr_precond_morerows
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
MatrixType m_scaledMatrix
Matrix< Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime, MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime > WorkMatrixType
WorkMatrixType m_workMatrix
void applyOnTheRight(const EigenBase< OtherDerived > &other)
JacobiSVD< PlainObject, Options > jacobiSvd() const
The matrix class, also used for vectors and row-vectors.
constexpr const Scalar & coeff(Index rowId, Index colId) const
constexpr void resize(Index rows, Index cols)
Base class of SVD algorithms.
internal::make_proper_matrix_type< Scalar, RowsAtCompileTime, MatrixUColsAtCompileTime, MatrixOptions, MaxRowsAtCompileTime, MatrixUMaxColsAtCompileTime >::type MatrixUType
bool m_usePrescribedThreshold
static constexpr bool ShouldComputeThinV
NumTraits< typename MatrixType::Scalar >::Real RealScalar
unsigned int m_computationOptions
internal::plain_diag_type< MatrixType, RealScalar >::type SingularValuesType
internal::make_proper_matrix_type< Scalar, ColsAtCompileTime, MatrixVColsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MatrixVMaxColsAtCompileTime >::type MatrixVType
RealScalar threshold() const
MatrixType::Scalar Scalar
Index m_nonzeroSingularValues
SingularValuesType m_singularValues
RealScalar m_prescribedThreshold
static constexpr bool ShouldComputeThinU
bool allocate(Index rows, Index cols, unsigned int computationOptions)
@ MaxDiagSizeAtCompileTime
internal::traits< Derived >::MatrixType MatrixType
@ HouseholderQRPreconditioner
@ ColPivHouseholderQRPreconditioner
@ FullPivHouseholderQRPreconditioner
bfloat16() min(const bfloat16 &a, const bfloat16 &b)
constexpr int get_qr_preconditioner(int options)
void real_2x2_jacobi_svd(const MatrixType &matrix, Index p, Index q, JacobiRotation< RealScalar > *j_left, JacobiRotation< RealScalar > *j_right)
constexpr int get_computation_options(int options)
T * construct_at(T *p, Args &&... args)
@ PreconditionIfMoreColsThanRows
@ PreconditionIfMoreRowsThanCols
void swap(scoped_array< T > &a, scoped_array< T > &b)
EIGEN_ALWAYS_INLINE bool() isfinite(const Eigen::bfloat16 &h)
bool is_exactly_zero(const X &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
Eigen::Index Index
The interface type of indices.
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.