11 #ifndef EIGEN_JACOBISVD_H
12 #define EIGEN_JACOBISVD_H
19 template<
typename MatrixType,
int QRPreconditioner,
20 bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
21 struct svd_precondition_2x2_block_to_be_real {};
30 enum { PreconditionIfMoreColsThanRows, PreconditionIfMoreRowsThanCols };
32 template<
typename MatrixType,
int QRPreconditioner,
int Case>
33 struct qr_preconditioner_should_do_anything
35 enum { a = MatrixType::RowsAtCompileTime != Dynamic &&
36 MatrixType::ColsAtCompileTime != Dynamic &&
37 MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
38 b = MatrixType::RowsAtCompileTime != Dynamic &&
39 MatrixType::ColsAtCompileTime != Dynamic &&
40 MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
42 (Case == PreconditionIfMoreColsThanRows &&
bool(a)) ||
43 (Case == PreconditionIfMoreRowsThanCols &&
bool(b)) )
47 template<
typename MatrixType,
int QRPreconditioner,
int Case,
48 bool DoAnything = qr_preconditioner_should_do_anything<MatrixType, QRPreconditioner, Case>::ret
49 >
struct qr_preconditioner_impl {};
51 template<
typename MatrixType,
int QRPreconditioner,
int Case>
52 class qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
55 void allocate(
const JacobiSVD<MatrixType, QRPreconditioner>&) {}
56 bool run(JacobiSVD<MatrixType, QRPreconditioner>&,
const MatrixType&)
64 template<
typename MatrixType>
68 typedef typename MatrixType::Scalar Scalar;
71 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
72 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
74 typedef Matrix<Scalar, 1, RowsAtCompileTime, RowMajor, 1, MaxRowsAtCompileTime> WorkspaceType;
76 void allocate(
const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
78 if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
81 ::new (&m_qr) QRType(svd.rows(), svd.cols());
83 if (svd.m_computeFullU) m_workspace.resize(svd.rows());
88 if(matrix.rows() > matrix.cols())
91 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).
template triangularView<Upper>();
92 if(svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace);
93 if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
99 typedef FullPivHouseholderQR<MatrixType> QRType;
101 WorkspaceType m_workspace;
104 template<
typename MatrixType>
108 typedef typename MatrixType::Scalar Scalar;
111 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
112 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
113 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
114 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
115 Options = MatrixType::Options
117 typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
118 TransposeTypeWithSameStorageOrder;
120 void allocate(
const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
122 if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
125 ::new (&m_qr) QRType(svd.cols(), svd.rows());
127 m_adjoint.resize(svd.cols(), svd.rows());
128 if (svd.m_computeFullV) m_workspace.resize(svd.cols());
133 if(matrix.cols() > matrix.rows())
135 m_adjoint = matrix.adjoint();
136 m_qr.compute(m_adjoint);
137 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).
template triangularView<Upper>().adjoint();
138 if(svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace);
139 if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
145 typedef FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
147 TransposeTypeWithSameStorageOrder m_adjoint;
148 typename internal::plain_row_type<MatrixType>::type m_workspace;
153 template<
typename MatrixType>
157 void allocate(
const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
159 if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
162 ::new (&m_qr) QRType(svd.rows(), svd.cols());
164 if (svd.m_computeFullU) m_workspace.resize(svd.rows());
165 else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
170 if(matrix.rows() > matrix.cols())
172 m_qr.compute(matrix);
173 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).
template triangularView<Upper>();
174 if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
175 else if(svd.m_computeThinU)
177 svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
178 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
180 if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
187 typedef ColPivHouseholderQR<MatrixType> QRType;
189 typename internal::plain_col_type<MatrixType>::type m_workspace;
192 template<
typename MatrixType>
196 typedef typename MatrixType::Scalar Scalar;
199 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
200 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
201 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
202 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
203 Options = MatrixType::Options
206 typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
207 TransposeTypeWithSameStorageOrder;
209 void allocate(
const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
211 if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
214 ::new (&m_qr) QRType(svd.cols(), svd.rows());
216 if (svd.m_computeFullV) m_workspace.resize(svd.cols());
217 else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
218 m_adjoint.resize(svd.cols(), svd.rows());
223 if(matrix.cols() > matrix.rows())
225 m_adjoint = matrix.adjoint();
226 m_qr.compute(m_adjoint);
228 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).
template triangularView<Upper>().adjoint();
229 if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
230 else if(svd.m_computeThinV)
232 svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
233 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
235 if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
242 typedef ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
244 TransposeTypeWithSameStorageOrder m_adjoint;
245 typename internal::plain_row_type<MatrixType>::type m_workspace;
250 template<
typename MatrixType>
254 void allocate(
const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
256 if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
259 ::new (&m_qr) QRType(svd.rows(), svd.cols());
261 if (svd.m_computeFullU) m_workspace.resize(svd.rows());
262 else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
267 if(matrix.rows() > matrix.cols())
269 m_qr.compute(matrix);
270 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).
template triangularView<Upper>();
271 if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
272 else if(svd.m_computeThinU)
274 svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
275 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
277 if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
283 typedef HouseholderQR<MatrixType> QRType;
285 typename internal::plain_col_type<MatrixType>::type m_workspace;
288 template<
typename MatrixType>
292 typedef typename MatrixType::Scalar Scalar;
295 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
296 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
297 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
298 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
299 Options = MatrixType::Options
302 typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
303 TransposeTypeWithSameStorageOrder;
305 void allocate(
const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
307 if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
310 ::new (&m_qr) QRType(svd.cols(), svd.rows());
312 if (svd.m_computeFullV) m_workspace.resize(svd.cols());
313 else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
314 m_adjoint.resize(svd.cols(), svd.rows());
319 if(matrix.cols() > matrix.rows())
321 m_adjoint = matrix.adjoint();
322 m_qr.compute(m_adjoint);
324 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).
template triangularView<Upper>().adjoint();
325 if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
326 else if(svd.m_computeThinV)
328 svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
329 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
331 if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
338 typedef HouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
340 TransposeTypeWithSameStorageOrder m_adjoint;
341 typename internal::plain_row_type<MatrixType>::type m_workspace;
349 template<
typename MatrixType,
int QRPreconditioner>
350 struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false>
352 typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
353 static void run(
typename SVD::WorkMatrixType&, SVD&, Index, Index) {}
356 template<
typename MatrixType,
int QRPreconditioner>
357 struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
359 typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
360 typedef typename MatrixType::Scalar Scalar;
361 typedef typename MatrixType::RealScalar RealScalar;
362 static void run(
typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
366 JacobiRotation<Scalar> rot;
367 RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
371 z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
372 work_matrix.row(p) *= z;
373 if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
374 if(work_matrix.coeff(q,q)!=Scalar(0))
376 z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
377 work_matrix.row(q) *= z;
378 if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
384 rot.c() = conj(work_matrix.coeff(p,p)) / n;
385 rot.s() = work_matrix.coeff(q,p) / n;
386 work_matrix.applyOnTheLeft(p,q,rot);
387 if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
388 if(work_matrix.coeff(p,q) != Scalar(0))
390 z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
391 work_matrix.col(q) *= z;
392 if(svd.computeV()) svd.m_matrixV.col(q) *= z;
394 if(work_matrix.coeff(q,q) != Scalar(0))
396 z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
397 work_matrix.row(q) *= z;
398 if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
404 template<
typename MatrixType,
typename RealScalar,
typename Index>
405 void real_2x2_jacobi_svd(
const MatrixType& matrix, Index p, Index q,
406 JacobiRotation<RealScalar> *j_left,
407 JacobiRotation<RealScalar> *j_right)
411 Matrix<RealScalar,2,2> m;
412 m << numext::real(matrix.coeff(p,p)), numext::real(matrix.coeff(p,q)),
413 numext::real(matrix.coeff(q,p)), numext::real(matrix.coeff(q,q));
414 JacobiRotation<RealScalar> rot1;
415 RealScalar t = m.coeff(0,0) + m.coeff(1,1);
416 RealScalar d = m.coeff(1,0) - m.coeff(0,1);
418 if(d == RealScalar(0))
420 rot1.s() = RealScalar(0);
421 rot1.c() = RealScalar(1);
427 RealScalar u = t / d;
428 RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u));
429 rot1.s() = RealScalar(1) / tmp;
432 m.applyOnTheLeft(0,1,rot1);
433 j_right->makeJacobi(m,0,1);
434 *j_left = rot1 * j_right->transpose();
437 template<
typename _MatrixType,
int QRPreconditioner>
438 struct traits<JacobiSVD<_MatrixType,QRPreconditioner> >
440 typedef _MatrixType MatrixType;
498 template<
typename _MatrixType,
int QRPreconditioner>
class JacobiSVD
499 :
public SVDBase<JacobiSVD<_MatrixType,QRPreconditioner> >
501 typedef SVDBase<JacobiSVD> Base;
504 typedef _MatrixType MatrixType;
505 typedef typename MatrixType::Scalar Scalar;
506 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
508 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
509 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
510 DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
511 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
512 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
513 MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
514 MatrixOptions = MatrixType::Options
517 typedef typename Base::MatrixUType MatrixUType;
518 typedef typename Base::MatrixVType MatrixVType;
519 typedef typename Base::SingularValuesType SingularValuesType;
521 typedef typename internal::plain_row_type<MatrixType>::type RowType;
522 typedef typename internal::plain_col_type<MatrixType>::type ColType;
523 typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
524 MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
544 allocate(rows, cols, computationOptions);
557 explicit JacobiSVD(
const MatrixType& matrix,
unsigned int computationOptions = 0)
559 compute(matrix, computationOptions);
572 JacobiSVD& compute(
const MatrixType& matrix,
unsigned int computationOptions);
582 return compute(matrix, m_computationOptions);
585 using Base::computeU;
586 using Base::computeV;
592 void allocate(Index rows, Index cols,
unsigned int computationOptions);
595 using Base::m_matrixU;
596 using Base::m_matrixV;
597 using Base::m_singularValues;
598 using Base::m_isInitialized;
599 using Base::m_isAllocated;
600 using Base::m_usePrescribedThreshold;
601 using Base::m_computeFullU;
602 using Base::m_computeThinU;
603 using Base::m_computeFullV;
604 using Base::m_computeThinV;
605 using Base::m_computationOptions;
606 using Base::m_nonzeroSingularValues;
609 using Base::m_diagSize;
610 using Base::m_prescribedThreshold;
611 WorkMatrixType m_workMatrix;
613 template<
typename __MatrixType,
int _QRPreconditioner,
bool _IsComplex>
614 friend struct internal::svd_precondition_2x2_block_to_be_real;
615 template<
typename __MatrixType,
int _QRPreconditioner,
int _Case,
bool _DoAnything>
616 friend struct internal::qr_preconditioner_impl;
618 internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows> m_qr_precond_morecols;
619 internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols> m_qr_precond_morerows;
620 MatrixType m_scaledMatrix;
623 template<
typename MatrixType,
int QRPreconditioner>
624 void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols,
unsigned int computationOptions)
626 eigen_assert(rows >= 0 && cols >= 0);
631 computationOptions == m_computationOptions)
638 m_isInitialized =
false;
639 m_isAllocated =
true;
640 m_computationOptions = computationOptions;
641 m_computeFullU = (computationOptions &
ComputeFullU) != 0;
642 m_computeThinU = (computationOptions &
ComputeThinU) != 0;
643 m_computeFullV = (computationOptions &
ComputeFullV) != 0;
644 m_computeThinV = (computationOptions &
ComputeThinV) != 0;
645 eigen_assert(!(m_computeFullU && m_computeThinU) &&
"JacobiSVD: you can't ask for both full and thin U");
646 eigen_assert(!(m_computeFullV && m_computeThinV) &&
"JacobiSVD: you can't ask for both full and thin V");
647 eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) &&
648 "JacobiSVD: thin U and V are only available when your matrix has a dynamic number of columns.");
651 eigen_assert(!(m_computeThinU || m_computeThinV) &&
652 "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
653 "Use the ColPivHouseholderQR preconditioner instead.");
655 m_diagSize = (std::min)(m_rows, m_cols);
656 m_singularValues.resize(m_diagSize);
657 if(RowsAtCompileTime==Dynamic)
658 m_matrixU.resize(m_rows, m_computeFullU ? m_rows
659 : m_computeThinU ? m_diagSize
661 if(ColsAtCompileTime==Dynamic)
662 m_matrixV.resize(m_cols, m_computeFullV ? m_cols
663 : m_computeThinV ? m_diagSize
665 m_workMatrix.resize(m_diagSize, m_diagSize);
667 if(m_cols>m_rows) m_qr_precond_morecols.allocate(*
this);
668 if(m_rows>m_cols) m_qr_precond_morerows.allocate(*
this);
669 if(m_cols!=m_cols) m_scaledMatrix.resize(rows,cols);
672 template<
typename MatrixType,
int QRPreconditioner>
673 JacobiSVD<MatrixType, QRPreconditioner>&
677 allocate(matrix.rows(), matrix.cols(), computationOptions);
686 const RealScalar considerAsZero = RealScalar(2) * std::numeric_limits<RealScalar>::denorm_min();
689 RealScalar scale = matrix.cwiseAbs().maxCoeff();
690 if(scale==RealScalar(0)) scale = RealScalar(1);
696 m_scaledMatrix = matrix / scale;
697 m_qr_precond_morecols.run(*
this, m_scaledMatrix);
698 m_qr_precond_morerows.run(*
this, m_scaledMatrix);
702 m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize) / scale;
703 if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
704 if(m_computeThinU) m_matrixU.setIdentity(m_rows,m_diagSize);
705 if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
706 if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
711 bool finished =
false;
718 for(
Index p = 1; p < m_diagSize; ++p)
720 for(
Index q = 0; q < p; ++q)
725 RealScalar threshold = numext::maxi<RealScalar>(considerAsZero,
726 precision * numext::maxi<RealScalar>(abs(m_workMatrix.coeff(p,p)),
727 abs(m_workMatrix.coeff(q,q))));
729 if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
734 internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *
this, p, q);
736 internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
739 m_workMatrix.applyOnTheLeft(p,q,j_left);
740 if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.
transpose());
742 m_workMatrix.applyOnTheRight(p,q,j_right);
743 if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
751 for(
Index i = 0; i < m_diagSize; ++i)
753 RealScalar a = abs(m_workMatrix.coeff(i,i));
754 m_singularValues.coeffRef(i) = a;
755 if(computeU() && (a!=RealScalar(0))) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/a;
758 m_singularValues *= scale;
762 m_nonzeroSingularValues = m_diagSize;
763 for(
Index i = 0; i < m_diagSize; i++)
766 RealScalar maxRemainingSingularValue = m_singularValues.tail(m_diagSize-i).maxCoeff(&pos);
767 if(maxRemainingSingularValue == RealScalar(0))
769 m_nonzeroSingularValues = i;
775 std::swap(m_singularValues.coeffRef(i), m_singularValues.coeffRef(pos));
776 if(computeU()) m_matrixU.col(pos).swap(m_matrixU.col(i));
777 if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
781 m_isInitialized =
true;
793 template<
typename Derived>
803 #endif // EIGEN_JACOBISVD_H
Definition: Constants.h:375
Definition: Constants.h:407
Definition: Constants.h:381
Eigen::Index Index
Definition: SVDBase.h:56
Rotation given by a cosine-sine pair.
Definition: ForwardDeclarations.h:259
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:107
Definition: Constants.h:409
JacobiRotation transpose() const
Definition: Jacobi.h:59
Definition: Constants.h:411
JacobiSVD()
Default Constructor.
Definition: JacobiSVD.h:532
Definition: Constants.h:413
Definition: Eigen_Colamd.h:54
JacobiSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix using current options.
Definition: JacobiSVD.h:580
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition: ForwardDeclarations.h:254
JacobiSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix using custom options.
Definition: JacobiSVD.h:674
Definition: Constants.h:379
Definition: Constants.h:377
JacobiSVD(Index rows, Index cols, unsigned int computationOptions=0)
Default Constructor with memory preallocation.
Definition: JacobiSVD.h:542
JacobiSVD(const MatrixType &matrix, unsigned int computationOptions=0)
Constructor performing the decomposition of given matrix.
Definition: JacobiSVD.h:557
JacobiSVD< PlainObject > jacobiSvd(unsigned int computationOptions=0) const
Definition: JacobiSVD.h:795