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);
404template<
typename MatrixType,
typename RealScalar,
typename Index>
405void real_2x2_jacobi_svd(
const MatrixType& matrix, Index p, Index q,
406 JacobiRotation<RealScalar> *j_left,
407 JacobiRotation<RealScalar> *j_right)
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();
437template<
typename _MatrixType,
int QRPreconditioner>
440 typedef _MatrixType MatrixType;
498template<
typename _MatrixType,
int QRPreconditioner>
class JacobiSVD
499 :
public SVDBase<JacobiSVD<_MatrixType,QRPreconditioner> >
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
523 typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
524 MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
582 return compute(matrix, m_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>
615 template<
typename __MatrixType,
int _QRPreconditioner,
int _Case,
bool _DoAnything>
620 MatrixType m_scaledMatrix;
623template<
typename MatrixType,
int QRPreconditioner>
624void 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_rows!=m_cols) m_scaledMatrix.resize(rows,cols);
672template<
typename MatrixType,
int QRPreconditioner>
673JacobiSVD<MatrixType, QRPreconditioner>&
689 RealScalar scale = matrix.cwiseAbs().maxCoeff();
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)
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)
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)
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++)
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;
793template<
typename Derived>