488template<
typename _MatrixType,
int QRPreconditioner>
class JacobiSVD
489 :
public SVDBase<JacobiSVD<_MatrixType,QRPreconditioner> >
494 typedef _MatrixType MatrixType;
495 typedef typename MatrixType::Scalar Scalar;
496 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
498 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
499 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
500 DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
501 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
502 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
503 MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
504 MatrixOptions = MatrixType::Options
513 typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
514 MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
534 allocate(rows, cols, computationOptions);
547 explicit JacobiSVD(
const MatrixType& matrix,
unsigned int computationOptions = 0)
549 compute(matrix, computationOptions);
572 return compute(matrix, m_computationOptions);
582 void allocate(
Index rows,
Index cols,
unsigned int computationOptions);
585 using Base::m_matrixU;
586 using Base::m_matrixV;
587 using Base::m_singularValues;
589 using Base::m_isInitialized;
590 using Base::m_isAllocated;
591 using Base::m_usePrescribedThreshold;
592 using Base::m_computeFullU;
593 using Base::m_computeThinU;
594 using Base::m_computeFullV;
595 using Base::m_computeThinV;
596 using Base::m_computationOptions;
597 using Base::m_nonzeroSingularValues;
600 using Base::m_diagSize;
601 using Base::m_prescribedThreshold;
602 WorkMatrixType m_workMatrix;
604 template<
typename __MatrixType,
int _QRPreconditioner,
bool _IsComplex>
606 template<
typename __MatrixType,
int _QRPreconditioner,
int _Case,
bool _DoAnything>
669 allocate(matrix.rows(), matrix.cols(), computationOptions);
676 const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
679 RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
680 if (!(numext::isfinite)(scale)) {
681 m_isInitialized =
true;
685 if(scale==RealScalar(0)) scale = RealScalar(1);
691 m_scaledMatrix = matrix / scale;
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)
716 for(
Index q = 0; q < p; ++q)
721 RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
722 if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
730 internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
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)
756 RealScalar a = abs(m_workMatrix.coeff(i,i));
757 m_singularValues.coeffRef(i) = abs(a);
758 if(computeU()) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/a;
763 RealScalar a = numext::real(m_workMatrix.coeff(i,i));
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;