11 #ifndef EIGEN_JACOBISVD_H
12 #define EIGEN_JACOBISVD_H
19 template<
typename MatrixType,
int QRPreconditioner,
32 template<
typename MatrixType,
int QRPreconditioner,
int Case>
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,
47 template<
typename MatrixType,
int QRPreconditioner,
int Case,
51 template<
typename MatrixType,
int QRPreconditioner,
int Case>
64 template<
typename MatrixType>
71 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
72 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
78 if (svd.
rows() != m_qr.rows() || svd.
cols() != m_qr.cols())
104 template<
typename MatrixType>
111 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
112 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
113 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
114 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
115 TrOptions = RowsAtCompileTime==1 ? (MatrixType::Options & ~(
RowMajor))
116 : ColsAtCompileTime==1 ? (MatrixType::Options |
RowMajor)
117 : MatrixType::Options
124 if (svd.
cols() != m_qr.rows() || svd.
rows() != m_qr.cols())
129 m_adjoint.resize(svd.
cols(), svd.
rows());
137 m_adjoint =
matrix.adjoint();
138 m_qr.compute(m_adjoint);
139 svd.
m_workMatrix = m_qr.matrixQR().block(0,0,
matrix.rows(),
matrix.rows()).template triangularView<Upper>().adjoint();
155 template<
typename MatrixType>
161 if (svd.
rows() != m_qr.rows() || svd.
cols() != m_qr.cols())
180 m_qr.householderQ().applyThisOnTheLeft(svd.
m_matrixU, m_workspace);
194 template<
typename MatrixType>
201 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
202 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
203 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
204 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
205 TrOptions = RowsAtCompileTime==1 ? (MatrixType::Options & ~(
RowMajor))
206 : ColsAtCompileTime==1 ? (MatrixType::Options |
RowMajor)
207 : MatrixType::Options
215 if (svd.
cols() != m_qr.rows() || svd.
rows() != m_qr.cols())
222 m_adjoint.resize(svd.
cols(), svd.
rows());
229 m_adjoint =
matrix.adjoint();
230 m_qr.compute(m_adjoint);
232 svd.
m_workMatrix = m_qr.matrixQR().block(0,0,
matrix.rows(),
matrix.rows()).template triangularView<Upper>().adjoint();
237 m_qr.householderQ().applyThisOnTheLeft(svd.
m_matrixV, m_workspace);
254 template<
typename MatrixType>
260 if (svd.
rows() != m_qr.rows() || svd.
cols() != m_qr.cols())
279 m_qr.householderQ().applyThisOnTheLeft(svd.
m_matrixU, m_workspace);
292 template<
typename MatrixType>
299 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
300 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
301 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
302 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
303 Options = MatrixType::Options
311 if (svd.
cols() != m_qr.rows() || svd.
rows() != m_qr.cols())
318 m_adjoint.resize(svd.
cols(), svd.
rows());
325 m_adjoint =
matrix.adjoint();
326 m_qr.compute(m_adjoint);
328 svd.
m_workMatrix = m_qr.matrixQR().block(0,0,
matrix.rows(),
matrix.rows()).template triangularView<Upper>().adjoint();
333 m_qr.householderQ().applyThisOnTheLeft(svd.
m_matrixV, m_workspace);
353 template<
typename MatrixType,
int QRPreconditioner>
361 template<
typename MatrixType,
int QRPreconditioner>
387 work_matrix.row(p) *= z;
393 work_matrix.row(
q) *= z;
402 work_matrix.applyOnTheLeft(p,
q,
rot);
407 work_matrix.col(
q) *= z;
413 work_matrix.row(
q) *= z;
419 maxDiagEntry = numext::maxi<RealScalar>(maxDiagEntry,numext::maxi<RealScalar>(
abs(work_matrix.
coeff(p,p)),
abs(work_matrix.
coeff(
q,
q))));
421 RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
422 return abs(work_matrix.
coeff(p,
q))>threshold ||
abs(work_matrix.
coeff(
q,p)) > threshold;
426 template<
typename _MatrixType,
int QRPreconditioner>
487 template<
typename _MatrixType,
int QRPreconditioner>
class JacobiSVD
488 :
public SVDBase<JacobiSVD<_MatrixType,QRPreconditioner> >
533 allocate(rows, cols, computationOptions);
602 template<
typename __MatrixType,
int _QRPreconditioner,
bool _IsComplex>
604 template<
typename __MatrixType,
int _QRPreconditioner,
int _Case,
bool _DoAnything>
612 template<
typename MatrixType,
int QRPreconditioner>
620 computationOptions == m_computationOptions)
627 m_isInitialized =
false;
628 m_isAllocated =
true;
629 m_computationOptions = computationOptions;
630 m_computeFullU = (computationOptions &
ComputeFullU) != 0;
631 m_computeThinU = (computationOptions &
ComputeThinU) != 0;
632 m_computeFullV = (computationOptions &
ComputeFullV) != 0;
633 m_computeThinV = (computationOptions &
ComputeThinV) != 0;
634 eigen_assert(!(m_computeFullU && m_computeThinU) &&
"JacobiSVD: you can't ask for both full and thin U");
635 eigen_assert(!(m_computeFullV && m_computeThinV) &&
"JacobiSVD: you can't ask for both full and thin V");
637 "JacobiSVD: thin U and V are only available when your matrix has a dynamic number of columns.");
641 "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
642 "Use the ColPivHouseholderQR preconditioner instead.");
644 m_diagSize = (
std::min)(m_rows, m_cols);
645 m_singularValues.resize(m_diagSize);
647 m_matrixU.resize(m_rows, m_computeFullU ? m_rows
648 : m_computeThinU ? m_diagSize
651 m_matrixV.resize(m_cols, m_computeFullV ? m_cols
652 : m_computeThinV ? m_diagSize
654 m_workMatrix.resize(m_diagSize, m_diagSize);
656 if(m_cols>m_rows) m_qr_precond_morecols.allocate(*
this);
657 if(m_rows>m_cols) m_qr_precond_morerows.allocate(*
this);
658 if(m_rows!=m_cols) m_scaledMatrix.resize(rows,cols);
661 template<
typename MatrixType,
int QRPreconditioner>
666 allocate(
matrix.rows(),
matrix.cols(), computationOptions);
683 m_scaledMatrix =
matrix / scale;
684 m_qr_precond_morecols.run(*
this, m_scaledMatrix);
685 m_qr_precond_morerows.run(*
this, m_scaledMatrix);
689 m_workMatrix =
matrix.block(0,0,m_diagSize,m_diagSize) / scale;
690 if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
691 if(m_computeThinU) m_matrixU.setIdentity(m_rows,m_diagSize);
692 if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
693 if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
697 RealScalar maxDiagEntry = m_workMatrix.cwiseAbs().diagonal().maxCoeff();
699 bool finished =
false;
706 for(
Index p = 1; p < m_diagSize; ++p)
713 RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
714 if(
abs(m_workMatrix.coeff(p,
q))>threshold ||
abs(m_workMatrix.coeff(
q,p)) > threshold)
725 m_workMatrix.applyOnTheLeft(p,
q,j_left);
726 if(computeU()) m_matrixU.applyOnTheRight(p,
q,j_left.
transpose());
728 m_workMatrix.applyOnTheRight(p,
q,j_right);
729 if(computeV()) m_matrixV.applyOnTheRight(p,
q,j_right);
732 maxDiagEntry = numext::maxi<RealScalar>(maxDiagEntry,numext::maxi<RealScalar>(
abs(m_workMatrix.coeff(p,p)),
abs(m_workMatrix.coeff(
q,
q))));
741 for(
Index i = 0; i < m_diagSize; ++i)
749 m_singularValues.coeffRef(i) =
abs(
a);
750 if(computeU()) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/
a;
756 m_singularValues.coeffRef(i) =
abs(
a);
757 if(computeU() && (
a<
RealScalar(0))) m_matrixU.col(i) = -m_matrixU.col(i);
761 m_singularValues *= scale;
765 m_nonzeroSingularValues = m_diagSize;
766 for(
Index i = 0; i < m_diagSize; i++)
769 RealScalar maxRemainingSingularValue = m_singularValues.tail(m_diagSize-i).maxCoeff(&pos);
770 if(maxRemainingSingularValue ==
RealScalar(0))
772 m_nonzeroSingularValues = i;
778 std::swap(m_singularValues.coeffRef(i), m_singularValues.coeffRef(pos));
779 if(computeU()) m_matrixU.col(pos).swap(m_matrixU.col(i));
780 if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
784 m_isInitialized =
true;
795 template<
typename Derived>
804 #endif // EIGEN_JACOBISVD_H