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())
 
   83     if (
svd.m_computeFullU) m_workspace.resize(
svd.rows());
 
   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();
 
  104 template<
typename MatrixType>
 
  111     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
 
  112     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
 
  113     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
 
  114     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
 
  115     Options = MatrixType::Options
 
  119     Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime
 
  124     if (
svd.cols() != m_qr.rows() || 
svd.rows() != m_qr.cols())
 
  129     m_adjoint.resize(
svd.cols(), 
svd.rows());
 
  130     if (
svd.m_computeFullV) m_workspace.resize(
svd.cols());
 
  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();
 
  140       if(
svd.m_computeFullV) m_qr.matrixQ().evalTo(
svd.m_matrixV, m_workspace);
 
  141       if(
svd.computeU()) 
svd.m_matrixU = m_qr.colsPermutation();
 
  155 template<
typename MatrixType>
 
  161     if (
svd.rows() != m_qr.rows() || 
svd.cols() != m_qr.cols())
 
  166     if (
svd.m_computeFullU) m_workspace.resize(
svd.rows());
 
  167     else if (
svd.m_computeThinU) m_workspace.resize(
svd.cols());
 
  175       svd.m_workMatrix = m_qr.matrixQR().block(0,0,
matrix.cols(),
matrix.cols()).template triangularView<Upper>();
 
  176       if(
svd.m_computeFullU) m_qr.householderQ().evalTo(
svd.m_matrixU, m_workspace);
 
  177       else if(
svd.m_computeThinU)
 
  180         m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixU, m_workspace);
 
  182       if(
svd.computeV()) 
svd.m_matrixV = m_qr.colsPermutation();
 
  194 template<
typename MatrixType>
 
  201     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
 
  202     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
 
  203     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
 
  204     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
 
  205     Options = MatrixType::Options
 
  209     Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime
 
  214     if (
svd.cols() != m_qr.rows() || 
svd.rows() != m_qr.cols())
 
  219     if (
svd.m_computeFullV) m_workspace.resize(
svd.cols());
 
  220     else if (
svd.m_computeThinV) m_workspace.resize(
svd.rows());
 
  221     m_adjoint.resize(
svd.cols(), 
svd.rows());
 
  228       m_adjoint = 
matrix.adjoint();
 
  229       m_qr.compute(m_adjoint);
 
  231       svd.m_workMatrix = m_qr.matrixQR().block(0,0,
matrix.rows(),
matrix.rows()).template triangularView<Upper>().adjoint();
 
  232       if(
svd.m_computeFullV) m_qr.householderQ().evalTo(
svd.m_matrixV, m_workspace);
 
  233       else if(
svd.m_computeThinV)
 
  236         m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixV, m_workspace);
 
  238       if(
svd.computeU()) 
svd.m_matrixU = m_qr.colsPermutation();
 
  253 template<
typename MatrixType>
 
  259     if (
svd.rows() != m_qr.rows() || 
svd.cols() != m_qr.cols())
 
  264     if (
svd.m_computeFullU) m_workspace.resize(
svd.rows());
 
  265     else if (
svd.m_computeThinU) m_workspace.resize(
svd.cols());
 
  273       svd.m_workMatrix = m_qr.matrixQR().block(0,0,
matrix.cols(),
matrix.cols()).template triangularView<Upper>();
 
  274       if(
svd.m_computeFullU) m_qr.householderQ().evalTo(
svd.m_matrixU, m_workspace);
 
  275       else if(
svd.m_computeThinU)
 
  278         m_qr.householderQ().applyThisOnTheLeft(
svd.m_matrixU, m_workspace);
 
  291 template<
typename MatrixType>
 
  298     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
 
  299     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
 
  300     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
 
  301     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
 
  302     Options = MatrixType::Options
 
  306     Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime
 
  311     if (
svd.cols() != m_qr.rows() || 
svd.rows() != m_qr.cols())
 
  316     if (
svd.m_computeFullV) m_workspace.resize(
svd.cols());
 
  317     else if (
svd.m_computeThinV) m_workspace.resize(
svd.rows());
 
  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();
 
  329       if(
svd.m_computeFullV) m_qr.householderQ().evalTo(
svd.m_matrixV, m_workspace);
 
  330       else if(
svd.m_computeThinV)
 
  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);
 
  403       if(
svd.computeU()) 
svd.m_matrixU.applyOnTheRight(
p,
q,
rot.adjoint());
 
  407         work_matrix.col(
q) *= 
z;
 
  408         if(
svd.computeV()) 
svd.m_matrixV.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))));
 
  426 template<
typename _MatrixType, 
int QRPreconditioner> 
 
  488 template<
typename _MatrixType, 
int QRPreconditioner> 
class JacobiSVD 
  489  : 
public SVDBase<JacobiSVD<_MatrixType,QRPreconditioner> >
 
  604     template<
typename __MatrixType, 
int _QRPreconditioner, 
bool _IsComplex>
 
  606     template<
typename __MatrixType, 
int _QRPreconditioner, 
int _Case, 
bool _DoAnything>
 
  614 template<
typename MatrixType, 
int QRPreconditioner>
 
  622       computationOptions == m_computationOptions)
 
  630   m_isInitialized = 
false;
 
  631   m_isAllocated = 
true;
 
  632   m_computationOptions = computationOptions;
 
  633   m_computeFullU = (computationOptions & 
ComputeFullU) != 0;
 
  634   m_computeThinU = (computationOptions & 
ComputeThinU) != 0;
 
  635   m_computeFullV = (computationOptions & 
ComputeFullV) != 0;
 
  636   m_computeThinV = (computationOptions & 
ComputeThinV) != 0;
 
  637   eigen_assert(!(m_computeFullU && m_computeThinU) && 
"JacobiSVD: you can't ask for both full and thin U");
 
  638   eigen_assert(!(m_computeFullV && m_computeThinV) && 
"JacobiSVD: you can't ask for both full and thin V");
 
  640               "JacobiSVD: thin U and V are only available when your matrix has a dynamic number of columns.");
 
  644               "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. " 
  645               "Use the ColPivHouseholderQR preconditioner instead.");
 
  647   m_diagSize = (
std::min)(m_rows, m_cols);
 
  648   m_singularValues.resize(m_diagSize);
 
  650     m_matrixU.resize(m_rows, m_computeFullU ? m_rows
 
  651                             : m_computeThinU ? m_diagSize
 
  654     m_matrixV.resize(m_cols, m_computeFullV ? m_cols
 
  655                             : m_computeThinV ? m_diagSize
 
  657   m_workMatrix.resize(m_diagSize, m_diagSize);
 
  659   if(m_cols>m_rows)   m_qr_precond_morecols.allocate(*
this);
 
  660   if(m_rows>m_cols)   m_qr_precond_morerows.allocate(*
this);
 
  661   if(m_rows!=m_cols)  m_scaledMatrix.resize(
rows,
cols);
 
  664 template<
typename MatrixType, 
int QRPreconditioner>
 
  669   allocate(
matrix.rows(), 
matrix.cols(), computationOptions);
 
  681     m_isInitialized = 
true;
 
  692     m_qr_precond_morecols.run(*
this, m_scaledMatrix);
 
  693     m_qr_precond_morerows.run(*
this, m_scaledMatrix);
 
  697     m_workMatrix = 
matrix.block(0,0,m_diagSize,m_diagSize) / 
scale;
 
  698     if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
 
  699     if(m_computeThinU) m_matrixU.setIdentity(m_rows,m_diagSize);
 
  700     if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
 
  701     if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
 
  705   RealScalar maxDiagEntry = m_workMatrix.cwiseAbs().diagonal().maxCoeff();
 
  707   bool finished = 
false;
 
  714     for(
Index p = 1; 
p < m_diagSize; ++
p)
 
  722         if(
abs(m_workMatrix.coeff(
p,
q))>threshold || 
abs(m_workMatrix.coeff(
q,
p)) > threshold)
 
  733             m_workMatrix.applyOnTheLeft(
p,
q,j_left);
 
  734             if(computeU()) m_matrixU.applyOnTheRight(
p,
q,j_left.
transpose());
 
  736             m_workMatrix.applyOnTheRight(
p,
q,j_right);
 
  737             if(computeV()) m_matrixV.applyOnTheRight(
p,
q,j_right);
 
  740             maxDiagEntry = numext::maxi<RealScalar>(maxDiagEntry,numext::maxi<RealScalar>(
abs(m_workMatrix.coeff(
p,
p)), 
abs(m_workMatrix.coeff(
q,
q))));
 
  749   for(
Index i = 0; 
i < m_diagSize; ++
i)
 
  757       m_singularValues.coeffRef(
i) = 
abs(
a);
 
  758       if(computeU()) m_matrixU.col(
i) *= m_workMatrix.coeff(
i,
i)/
a;
 
  764       m_singularValues.coeffRef(
i) = 
abs(
a);
 
  765       if(computeU() && (
a<
RealScalar(0))) m_matrixU.col(
i) = -m_matrixU.col(
i);
 
  769   m_singularValues *= 
scale;
 
  773   m_nonzeroSingularValues = m_diagSize;
 
  774   for(
Index i = 0; 
i < m_diagSize; 
i++)
 
  777     RealScalar maxRemainingSingularValue = m_singularValues.tail(m_diagSize-
i).maxCoeff(&
pos);
 
  778     if(maxRemainingSingularValue == 
RealScalar(0))
 
  780       m_nonzeroSingularValues = 
i;
 
  786       std::swap(m_singularValues.coeffRef(
i), m_singularValues.coeffRef(
pos));
 
  787       if(computeU()) m_matrixU.col(
pos).swap(m_matrixU.col(
i));
 
  788       if(computeV()) m_matrixV.col(
pos).swap(m_matrixV.col(
i));
 
  792   m_isInitialized = 
true;
 
  803 template<
typename Derived>
 
  812 #endif // EIGEN_JACOBISVD_H