20 #ifndef EIGEN_BDCSVD_H
21 #define EIGEN_BDCSVD_H
25 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
26 #undef eigen_internal_assert
27 #define eigen_internal_assert(X) assert(X);
32 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
38 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
39 IOFormat bdcsvdfmt(8, 0,
", ",
"\n",
" [",
"]");
42 template <
typename MatrixType_,
int Options>
47 template <
typename MatrixType_,
int Options>
48 struct traits<BDCSVD<MatrixType_, Options> > : svd_traits<MatrixType_, Options> {
52 template <
typename MatrixType,
int Options>
53 struct allocate_small_svd {
54 static void run(JacobiSVD<MatrixType, Options>& smallSvd,
Index rows,
Index cols,
unsigned int computationOptions) {
55 (void)computationOptions;
56 smallSvd = JacobiSVD<MatrixType, Options>(
rows,
cols);
63 template <
typename MatrixType>
65 static void run(JacobiSVD<MatrixType>& smallSvd,
Index rows,
Index cols,
unsigned int computationOptions) {
66 smallSvd = JacobiSVD<MatrixType>(
rows,
cols, computationOptions);
103 template <
typename MatrixType_,
int Options_>
177 internal::check_svd_options_assertions<MatrixType, Options>(computationOptions,
rows,
cols);
204 internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
228 internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
234 eigen_assert(s>=3 &&
"BDCSVD the size of the algo switch has to be at least 3.");
248 template<
typename HouseholderU,
typename HouseholderV,
typename NaiveU,
typename NaiveV>
249 void copyUV(
const HouseholderU &householderU,
const HouseholderV &householderV,
const NaiveU &naiveU,
const NaiveV &naivev);
252 template <
typename SVDType>
266 internal::UpperBidiagonalization<MatrixX>
bid;
286 template <
typename MatrixType,
int Options>
288 if (Base::allocate(
rows,
cols, computationOptions))
291 if (
cols < m_algoswap)
292 internal::allocate_small_svd<MatrixType, ComputationOptions>::run(smallSvd,
rows,
cols, computationOptions);
294 m_computed = MatrixXr::Zero(m_diagSize + 1, m_diagSize );
295 m_compU = computeV();
296 m_compV = computeU();
305 constexpr
Index kMinAspectRatio = 4;
306 constexpr
bool disableQrDecomp =
static_cast<int>(QRDecomposition) ==
static_cast<int>(
DisableQRDecomposition);
307 m_useQrDecomp = !disableQrDecomp && ((
rows / kMinAspectRatio >
cols) || (
cols / kMinAspectRatio >
rows));
310 reducedTriangle =
MatrixX(m_diagSize, m_diagSize);
314 bid = internal::UpperBidiagonalization<MatrixX>(m_useQrDecomp ? m_diagSize : copyWorkspace.rows(),
315 m_useQrDecomp ? m_diagSize : copyWorkspace.cols());
317 if (m_compU) m_naiveU = MatrixXr::Zero(m_diagSize + 1, m_diagSize + 1 );
318 else m_naiveU = MatrixXr::Zero(2, m_diagSize + 1 );
320 if (m_compV) m_naiveV = MatrixXr::Zero(m_diagSize, m_diagSize);
322 m_workspace.resize((m_diagSize+1)*(m_diagSize+1)*3);
323 m_workspaceI.resize(3*m_diagSize);
326 template <
typename MatrixType,
int Options>
328 unsigned int computationOptions) {
329 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
330 std::cout <<
"\n\n\n======================================================================================================================\n\n\n";
334 allocate(matrix.rows(), matrix.cols(), computationOptions);
339 if(matrix.cols() < m_algoswap)
341 smallSvd.compute(matrix);
342 m_isInitialized =
true;
343 m_info = smallSvd.info();
345 if (computeU()) m_matrixU = smallSvd.matrixU();
346 if (computeV()) m_matrixV = smallSvd.matrixV();
347 m_singularValues = smallSvd.singularValues();
348 m_nonzeroSingularValues = smallSvd.nonzeroSingularValues();
354 RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
356 m_isInitialized =
true;
363 if (m_isTranspose) copyWorkspace = matrix.adjoint() / scale;
364 else copyWorkspace = matrix / scale;
371 qrDecomp.compute(copyWorkspace);
372 reducedTriangle = qrDecomp.matrixQR().topRows(m_diagSize);
373 reducedTriangle.template triangularView<StrictlyLower>().setZero();
374 bid.compute(reducedTriangle);
376 bid.compute(copyWorkspace);
383 m_computed.topRows(m_diagSize) = bid.bidiagonal().toDenseMatrix().transpose();
384 m_computed.template bottomRows<1>().setZero();
385 divide(0, m_diagSize - 1, 0, 0, 0);
387 m_isInitialized =
true;
392 for (
int i=0;
i<m_diagSize;
i++)
395 m_singularValues.coeffRef(
i) =
a * scale;
398 m_nonzeroSingularValues =
i;
399 m_singularValues.tail(m_diagSize -
i - 1).setZero();
402 else if (
i == m_diagSize - 1)
404 m_nonzeroSingularValues =
i + 1;
410 if(m_isTranspose) copyUV(bid.householderV(), bid.householderU(), m_naiveV, m_naiveU);
411 else copyUV(bid.householderU(), bid.householderV(), m_naiveU, m_naiveV);
414 if (m_isTranspose && computeV()) m_matrixV.applyOnTheLeft(qrDecomp.householderQ());
415 else if (!m_isTranspose && computeU()) m_matrixU.applyOnTheLeft(qrDecomp.householderQ());
418 m_isInitialized =
true;
422 template <
typename MatrixType,
int Options>
423 template <
typename HouseholderU,
typename HouseholderV,
typename NaiveU,
typename NaiveV>
425 const NaiveU& naiveU,
const NaiveV& naiveV) {
429 Index Ucols = m_computeThinU ? m_diagSize :
rows();
431 m_matrixU.topLeftCorner(m_diagSize, m_diagSize) = naiveV.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
433 if (m_useQrDecomp) m_matrixU.topLeftCorner(householderU.cols(), m_diagSize).applyOnTheLeft(householderU);
434 else m_matrixU.applyOnTheLeft(householderU);
438 Index Vcols = m_computeThinV ? m_diagSize :
cols();
440 m_matrixV.topLeftCorner(m_diagSize, m_diagSize) = naiveU.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
442 if (m_useQrDecomp) m_matrixV.topLeftCorner(householderV.cols(), m_diagSize).applyOnTheLeft(householderV);
443 else m_matrixV.applyOnTheLeft(householderV);
455 template <
typename MatrixType,
int Options>
472 A1.col(k1) =
A.col(
j).head(n1);
473 B1.row(k1) =
B.row(
j);
478 A2.col(k2) =
A.col(
j).tail(n2);
479 B2.row(k2) =
B.row(
j);
484 A.topRows(n1).
noalias() = A1.leftCols(k1) * B1.topRows(k1);
485 A.bottomRows(n2).
noalias() = A2.leftCols(k2) * B2.topRows(k2);
495 template <
typename MatrixType,
int Options>
496 template <
typename SVDType>
499 svd.compute(m_computed.block(firstCol, firstCol,
n + 1,
n));
503 m_naiveU.block(firstCol, firstCol,
n + 1,
n + 1).real() =
svd.matrixU();
505 m_naiveU.row(0).segment(firstCol,
n + 1).real() =
svd.matrixU().row(0);
506 m_naiveU.row(1).segment(firstCol,
n + 1).real() =
svd.matrixU().row(
n);
508 if (m_compV) m_naiveV.block(firstRowW, firstColW,
n,
n).real() =
svd.matrixV();
509 m_computed.block(firstCol + shift, firstCol + shift,
n + 1,
n).setZero();
510 m_computed.diagonal().segment(firstCol + shift,
n) =
svd.singularValues().head(
n);
523 template <
typename MatrixType,
int Options>
530 const Index n = lastCol - firstCol + 1;
545 computeBaseCase(baseSvd,
n, firstCol, firstRowW, firstColW, shift);
548 computeBaseCase(baseSvd,
n, firstCol, firstRowW, firstColW, shift);
553 alphaK = m_computed(firstCol + k, firstCol + k);
554 betaK = m_computed(firstCol + k + 1, firstCol + k);
558 divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
560 divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
565 lambda = m_naiveU(firstCol + k, firstCol + k);
566 phi = m_naiveU(firstCol + k + 1, lastCol + 1);
570 lambda = m_naiveU(1, firstCol + k);
571 phi = m_naiveU(0, lastCol + 1);
576 l = m_naiveU.row(firstCol + k).segment(firstCol, k);
577 f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1,
n - k - 1);
581 l = m_naiveU.row(1).segment(firstCol, k);
582 f = m_naiveU.row(0).segment(firstCol + k + 1,
n - k - 1);
584 if (m_compV) m_naiveV(firstRowW+k, firstColW) =
Literal(1);
592 c0 = alphaK *
lambda / r0;
593 s0 = betaK * phi / r0;
596 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
604 MatrixXr q1 (m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
606 for (
Index i = firstCol + k - 1;
i >= firstCol;
i--)
607 m_naiveU.col(
i + 1).segment(firstCol, k + 1) = m_naiveU.col(
i).segment(firstCol, k + 1);
609 m_naiveU.col(firstCol).segment( firstCol, k + 1) = (q1 * c0);
611 m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (q1 * ( - s0));
613 m_naiveU.col(firstCol).segment(firstCol + k + 1,
n - k) = m_naiveU.col(lastCol + 1).segment(firstCol + k + 1,
n - k) * s0;
615 m_naiveU.col(lastCol + 1).segment(firstCol + k + 1,
n - k) *= c0;
621 for (
Index i = firstCol + k - 1;
i >= firstCol;
i--)
622 m_naiveU(0,
i + 1) = m_naiveU(0,
i);
624 m_naiveU(0, firstCol) = (q1 * c0);
626 m_naiveU(0, lastCol + 1) = (q1 * ( - s0));
628 m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) *s0;
630 m_naiveU(1, lastCol + 1) *= c0;
631 m_naiveU.row(1).segment(firstCol + 1, k).setZero();
632 m_naiveU.row(0).segment(firstCol + k + 1,
n - k - 1).setZero();
635 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
641 m_computed(firstCol + shift, firstCol + shift) = r0;
642 m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) = alphaK * l.transpose().real();
643 m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1,
n - k - 1) = betaK * f.transpose().real();
645 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
646 ArrayXr tmp1 = (m_computed.block(firstCol+shift, firstCol+shift,
n,
n)).jacobiSvd().singularValues();
649 deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
650 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
651 ArrayXr tmp2 = (m_computed.block(firstCol+shift, firstCol+shift,
n,
n)).jacobiSvd().singularValues();
652 std::cout <<
"\n\nj1 = " << tmp1.transpose().format(bdcsvdfmt) <<
"\n";
653 std::cout <<
"j2 = " << tmp2.transpose().format(bdcsvdfmt) <<
"\n\n";
654 std::cout <<
"err: " << ((tmp1-tmp2).
abs()>1
e-12*tmp2.abs()).transpose() <<
"\n";
655 static int count = 0;
656 std::cout <<
"# " << ++count <<
"\n\n";
665 computeSVDofM(firstCol + shift,
n, UofSVD, singVals, VofSVD);
667 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
673 structured_update(m_naiveU.block(firstCol, firstCol,
n + 1,
n + 1), UofSVD, (
n+2)/2);
677 tmp.noalias() = m_naiveU.middleCols(firstCol,
n+1) * UofSVD;
678 m_naiveU.middleCols(firstCol,
n + 1) = tmp;
681 if (m_compV) structured_update(m_naiveV.block(firstRowW, firstColW,
n,
n), VofSVD, (
n+1)/2);
683 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
689 m_computed.block(firstCol + shift, firstCol + shift,
n,
n).setZero();
690 m_computed.block(firstCol + shift, firstCol + shift,
n,
n).diagonal() = singVals;
701 template <
typename MatrixType,
int Options>
706 ArrayRef col0 = m_computed.col(firstCol).segment(firstCol,
n);
707 m_workspace.head(
n) = m_computed.block(firstCol, firstCol,
n,
n).diagonal();
716 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
717 if (col0.hasNaN() || diag.hasNaN())
718 std::cout <<
"\n\nHAS NAN\n\n";
730 for(
Index k=0;k<actual_n;++k)
731 if(
abs(col0(k))>considerZero)
732 m_workspaceI(
m++) = k;
739 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
740 std::cout <<
"computeSVDofM using:\n";
741 std::cout <<
" z: " << col0.transpose() <<
"\n";
742 std::cout <<
" d: " << diag.transpose() <<
"\n";
746 computeSingVals(col0, diag, perm, singVals, shifts, mus);
748 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
749 std::cout <<
" j: " << (m_computed.block(firstCol, firstCol,
n,
n)).jacobiSvd().singularValues().transpose().reverse() <<
"\n\n";
750 std::cout <<
" sing-val: " << singVals.transpose() <<
"\n";
751 std::cout <<
" mu: " << mus.transpose() <<
"\n";
752 std::cout <<
" shift: " << shifts.transpose() <<
"\n";
755 std::cout <<
"\n\n mus: " << mus.head(actual_n).transpose() <<
"\n\n";
756 std::cout <<
" check1 (expect0) : " << ((singVals.array()-(shifts+mus)) / singVals.array()).
head(actual_n).transpose() <<
"\n\n";
757 eigen_internal_assert((((singVals.array()-(shifts+mus)) / singVals.array()).head(actual_n) >= 0).all());
758 std::cout <<
" check2 (>0) : " << ((singVals.array()-diag) / singVals.array()).
head(actual_n).transpose() <<
"\n\n";
763 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
770 perturbCol0(col0, diag, perm, singVals, shifts, mus, zhat);
771 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
772 std::cout <<
" zhat: " << zhat.transpose() <<
"\n";
775 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
779 computeSingVecs(zhat, diag, perm, singVals, shifts, mus, U,
V);
781 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
782 std::cout <<
"U^T U: " << (U.transpose() * U -
MatrixXr(MatrixXr::Identity(U.
cols(),U.
cols()))).norm() <<
"\n";
786 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
800 if(singVals(
i)>singVals(
i+1))
803 swap(singVals(
i),singVals(
i+1));
804 U.col(
i).swap(U.col(
i+1));
805 if(m_compV)
V.col(
i).
swap(
V.col(
i+1));
809 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
811 bool singular_values_sorted = (((singVals.segment(1,actual_n-1)-singVals.head(actual_n-1))).array() >= 0).
all();
812 if(!singular_values_sorted)
813 std::cout <<
"Singular values are not sorted: " << singVals.segment(1,actual_n).transpose() <<
"\n";
820 singVals.head(actual_n).reverseInPlace();
821 U.leftCols(actual_n).rowwise().reverseInPlace();
824 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
826 std::cout <<
" * j: " << jsvd.
singularValues().transpose() <<
"\n\n";
827 std::cout <<
" * sing-val: " << singVals.transpose() <<
"\n";
832 template <
typename MatrixType,
int Options>
843 res += (col0(
j) / (diagShifted(
j) - mu)) * (col0(
j) / (diag(
j) + shift + mu));
848 template <
typename MatrixType,
int Options>
861 for (
Index k = 0; k <
n; ++k)
867 singVals(k) = k==0 ? col0(0) : diag(k);
869 shifts(k) = k==0 ? col0(0) : diag(k);
877 right = (diag(actual_n-1) + col0.matrix().norm());
891 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
892 std::cout <<
"right-left = " << right-left <<
"\n";
895 std::cout <<
" = " << secularEq(left+
RealScalar(0.000001)*(right-left), col0, diag, perm, diag, 0)
896 <<
" " << secularEq(left+
RealScalar(0.1) *(right-left), col0, diag, perm, diag, 0)
897 <<
" " << secularEq(left+
RealScalar(0.2) *(right-left), col0, diag, perm, diag, 0)
898 <<
" " << secularEq(left+
RealScalar(0.3) *(right-left), col0, diag, perm, diag, 0)
899 <<
" " << secularEq(left+
RealScalar(0.4) *(right-left), col0, diag, perm, diag, 0)
900 <<
" " << secularEq(left+
RealScalar(0.49) *(right-left), col0, diag, perm, diag, 0)
901 <<
" " << secularEq(left+
RealScalar(0.5) *(right-left), col0, diag, perm, diag, 0)
902 <<
" " << secularEq(left+
RealScalar(0.51) *(right-left), col0, diag, perm, diag, 0)
903 <<
" " << secularEq(left+
RealScalar(0.6) *(right-left), col0, diag, perm, diag, 0)
904 <<
" " << secularEq(left+
RealScalar(0.7) *(right-left), col0, diag, perm, diag, 0)
905 <<
" " << secularEq(left+
RealScalar(0.8) *(right-left), col0, diag, perm, diag, 0)
906 <<
" " << secularEq(left+
RealScalar(0.9) *(right-left), col0, diag, perm, diag, 0)
907 <<
" " << secularEq(left+
RealScalar(0.999999)*(right-left), col0, diag, perm, diag, 0) <<
"\n";
913 diagShifted = diag - shift;
921 midShifted = -midShifted;
922 RealScalar fMidShifted = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
926 shift = fMidShifted >
Literal(0) ? left : right;
927 diagShifted = diag - shift;
937 if (k == actual_n-1) muCur = right - left;
938 else muCur = (right - left) *
RealScalar(0.5);
946 RealScalar fPrev = secularEq(muPrev, col0, diag, perm, diagShifted, shift);
947 RealScalar fCur = secularEq(muCur, col0, diag, perm, diagShifted, shift);
948 if (
abs(fPrev) <
abs(fCur))
956 bool useBisection = fPrev*fCur>
Literal(0);
966 RealScalar fZero = secularEq(muZero, col0, diag, perm, diagShifted, shift);
968 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
980 if (
abs(fCur)>
abs(fPrev)) useBisection =
true;
986 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
987 std::cout <<
"useBisection for k = " << k <<
", actual_n = " << actual_n <<
"\n";
1001 rightShifted = (k==actual_n-1) ? right : ((right - left) *
RealScalar(0.51));
1005 leftShifted = -(right - left) *
RealScalar(0.51);
1012 RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift);
1015 #if defined EIGEN_BDCSVD_DEBUG_VERBOSE || defined EIGEN_BDCSVD_SANITY_CHECKS || defined EIGEN_INTERNAL_DEBUGGING
1016 RealScalar fRight = secularEq(rightShifted, col0, diag, perm, diagShifted, shift);
1019 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1021 std::cout <<
"f(" << leftShifted <<
") =" << fLeft <<
" ; " << left <<
" " << shift <<
" " << right <<
"\n";
1025 std::cout <<
"f(" << rightShifted <<
") =" << fRight <<
" ; " << left <<
" " << shift <<
" " << right <<
"\n";
1029 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1030 if(!(fLeft * fRight<0))
1032 std::cout <<
"f(leftShifted) using leftShifted=" << leftShifted <<
" ; diagShifted(1:10):" << diagShifted.head(10).transpose() <<
"\n ; "
1033 <<
"left==shift=" <<
bool(left==shift) <<
" ; left-shift = " << (left-shift) <<
"\n";
1034 std::cout <<
"k=" << k <<
", " << fLeft <<
" * " << fRight <<
" == " << fLeft * fRight <<
" ; "
1035 <<
"[" << left <<
" .. " << right <<
"] -> [" << leftShifted <<
" " << rightShifted <<
"], shift=" << shift
1036 <<
" , f(right)=" << secularEq(0, col0, diag, perm, diagShifted, shift)
1037 <<
" == " << secularEq(right, col0, diag, perm, diag, 0) <<
" == " << fRight <<
"\n";
1047 fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
1050 if (fLeft * fMid <
Literal(0))
1052 rightShifted = midShifted;
1056 leftShifted = midShifted;
1060 muCur = (leftShifted + rightShifted) /
Literal(2);
1075 singVals[k] = shift + muCur;
1079 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1081 std::cout <<
"found " << singVals[k] <<
" == " << shift <<
" + " << muCur <<
" from " << diag(k) <<
" .. " << diag(k+1) <<
"\n";
1083 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1097 template <
typename MatrixType,
int Options>
1109 Index lastIdx = perm(
m-1);
1111 for (
Index k = 0; k <
n; ++k)
1119 RealScalar prod = (singVals(lastIdx) + dk) * (mus(lastIdx) + (shifts(lastIdx) - dk));
1120 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1122 std::cout <<
"k = " << k <<
" ; z(k)=" << col0(k) <<
", diag(k)=" << dk <<
"\n";
1123 std::cout <<
"prod = " <<
"(" << singVals(lastIdx) <<
" + " << dk <<
") * (" << mus(lastIdx) <<
" + (" << shifts(lastIdx) <<
" - " << dk <<
"))" <<
"\n";
1124 std::cout <<
" = " << singVals(lastIdx) + dk <<
" * " << mus(lastIdx) + (shifts(lastIdx) - dk) <<
"\n";
1129 for(
Index l = 0; l<
m; ++l)
1134 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1135 if(
i>=k && (l==0 || l-1>=
m))
1137 std::cout <<
"Error in perturbCol0\n";
1138 std::cout <<
" " << k <<
"/" <<
n <<
" " << l <<
"/" <<
m <<
" " <<
i <<
"/" <<
n <<
" ; " << col0(k) <<
" " << diag(k) <<
" " <<
"\n";
1139 std::cout <<
" " <<diag(
i) <<
"\n";
1141 std::cout <<
" " <<
"j=" <<
j <<
"\n";
1146 if (
i >= k && l == 0) {
1151 Index j = i<k ? i : l > 0 ? perm(l-1) :
i;
1152 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1155 std::cout <<
"k=" << k <<
", i=" <<
i <<
", l=" << l <<
", perm.size()=" << perm.size() <<
"\n";
1159 prod *= ((singVals(
j)+dk) / ((diag(
i)+dk))) * ((mus(
j)+(shifts(
j)-dk)) / ((diag(
i)-dk)));
1160 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1163 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1164 if(
i!=k &&
numext::abs(((singVals(
j)+dk)*(mus(
j)+(shifts(
j)-dk)))/((diag(
i)+dk)*(diag(
i)-dk)) - 1) > 0.9 )
1165 std::cout <<
" " << ((singVals(
j)+dk)*(mus(
j)+(shifts(
j)-dk)))/((diag(
i)+dk)*(diag(
i)-dk)) <<
" == (" << (singVals(
j)+dk) <<
" * " << (mus(
j)+(shifts(
j)-dk))
1166 <<
") / (" << (diag(
i)+dk) <<
" * " << (diag(
i)-dk) <<
")\n";
1170 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1171 std::cout <<
"zhat(" << k <<
") = sqrt( " << prod <<
") ; " << (singVals(lastIdx) + dk) <<
" * " << mus(lastIdx) + shifts(lastIdx) <<
" - " << dk <<
"\n";
1174 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1183 template <
typename MatrixType,
int Options>
1190 for (
Index k = 0; k <
n; ++k)
1194 U.col(k) = VectorType::Unit(
n+1, k);
1195 if (m_compV)
V.col(k) = VectorType::Unit(
n, k);
1203 U(
i,k) = zhat(
i)/(((diag(
i) - shifts(k)) - mus(k)) )/( (diag(
i) + singVals[k]));
1206 U.col(k).normalize();
1214 V(
i,k) = diag(
i) * zhat(
i) / (((diag(
i) - shifts(k)) - mus(k)) )/( (diag(
i) + singVals[k]));
1221 U.col(
n) = VectorType::Unit(
n+1,
n);
1227 template <
typename MatrixType,
int Options>
1233 Index start = firstCol + shift;
1239 m_computed(start+
i, start+
i) =
Literal(0);
1242 m_computed(start,start) = r;
1243 m_computed(start+
i, start) =
Literal(0);
1244 m_computed(start+
i, start+
i) =
Literal(0);
1247 if (m_compU) m_naiveU.middleRows(firstCol,
size+1).applyOnTheRight(firstCol, firstCol+
i,
J);
1248 else m_naiveU.applyOnTheRight(firstCol, firstCol+
i,
J);
1255 template <
typename MatrixType,
int Options>
1264 RealScalar s = m_computed(firstColm+
j, firstColm);
1266 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1267 std::cout <<
"deflation 4.4: " <<
i <<
"," <<
j <<
" -> " <<
c <<
" " << s <<
" " << r <<
" ; "
1268 << m_computed(firstColm +
i-1, firstColm) <<
" "
1269 << m_computed(firstColm +
i, firstColm) <<
" "
1270 << m_computed(firstColm +
i+1, firstColm) <<
" "
1271 << m_computed(firstColm +
i+2, firstColm) <<
"\n";
1272 std::cout << m_computed(firstColm +
i-1, firstColm +
i-1) <<
" "
1273 << m_computed(firstColm +
i, firstColm+
i) <<
" "
1274 << m_computed(firstColm +
i+1, firstColm+
i+1) <<
" "
1275 << m_computed(firstColm +
i+2, firstColm+
i+2) <<
"\n";
1279 m_computed(firstColm +
i, firstColm +
i) = m_computed(firstColm +
j, firstColm +
j);
1284 m_computed(firstColm +
i, firstColm) = r;
1285 m_computed(firstColm +
j, firstColm +
j) = m_computed(firstColm +
i, firstColm +
i);
1286 m_computed(firstColm +
j, firstColm) =
Literal(0);
1289 if (m_compU) m_naiveU.middleRows(firstColu,
size+1).applyOnTheRight(firstColu +
i, firstColu +
j,
J);
1290 else m_naiveU.applyOnTheRight(firstColu+
i, firstColu+
j,
J);
1291 if (m_compV) m_naiveV.middleRows(firstRowW,
size).applyOnTheRight(firstColW +
i, firstColW +
j,
J);
1295 template <
typename MatrixType,
int Options>
1300 const Index length = lastCol + 1 - firstCol;
1311 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1317 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1318 std::cout <<
"\ndeflate:" << diag.head(k+1).transpose() <<
" | " << diag.segment(k+1,length-k-1).transpose() <<
"\n";
1322 if (diag(0) < epsilon_coarse)
1324 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1325 std::cout <<
"deflation 4.1, because " << diag(0) <<
" < " << epsilon_coarse <<
"\n";
1327 diag(0) = epsilon_coarse;
1332 if (
abs(col0(
i)) < epsilon_strict)
1334 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1335 std::cout <<
"deflation 4.2, set z(" <<
i <<
") to zero because " <<
abs(col0(
i)) <<
" < " << epsilon_strict <<
" (diag(" <<
i <<
")=" << diag(
i) <<
")\n";
1342 if (diag(
i) < epsilon_coarse)
1344 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1345 std::cout <<
"deflation 4.3, cancel z(" <<
i <<
")=" << col0(
i) <<
" because diag(" <<
i <<
")=" << diag(
i) <<
" < " << epsilon_coarse <<
"\n";
1347 deflation43(firstCol, shift,
i, length);
1350 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1355 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1356 std::cout <<
"to be sorted: " << diag.transpose() <<
"\n\n";
1357 std::cout <<
" : " << col0.transpose() <<
"\n\n";
1362 const bool total_deflation = (col0.tail(length-1).array().abs()<considerZero).
all();
1366 Index *permutation = m_workspaceI.data();
1373 if(
abs(diag(
i))<considerZero)
1374 permutation[
p++] =
i;
1377 for( ;
p < length; ++
p)
1379 if (
i > k) permutation[
p] =
j++;
1380 else if (
j >= length) permutation[
p] =
i++;
1381 else if (diag(
i) < diag(
j)) permutation[
p] =
j++;
1382 else permutation[
p] =
i++;
1391 Index pi = permutation[
i];
1392 if(
abs(diag(pi))<considerZero || diag(0)<diag(pi))
1393 permutation[
i-1] = permutation[
i];
1396 permutation[
i-1] = 0;
1403 Index *realInd = m_workspaceI.data()+length;
1404 Index *realCol = m_workspaceI.data()+2*length;
1406 for(
int pos = 0; pos< length; pos++)
1412 for(
Index i = total_deflation?0:1;
i < length;
i++)
1414 const Index pi = permutation[length - (total_deflation ?
i+1 :
i)];
1415 const Index J = realCol[pi];
1420 if(
i!=0 &&
J!=0)
swap(col0(
i), col0(
J));
1423 if (m_compU) m_naiveU.col(firstCol+
i).segment(firstCol, length + 1).swap(m_naiveU.col(firstCol+
J).segment(firstCol, length + 1));
1424 else m_naiveU.col(firstCol+
i).segment(0, 2) .swap(m_naiveU.col(firstCol+
J).segment(0, 2));
1425 if (m_compV) m_naiveV.col(firstColW +
i).segment(firstRowW, length).swap(m_naiveV.col(firstColW +
J).segment(firstRowW, length));
1428 const Index realI = realInd[
i];
1435 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1436 std::cout <<
"sorted: " << diag.transpose().format(bdcsvdfmt) <<
"\n";
1437 std::cout <<
" : " << col0.transpose() <<
"\n\n";
1443 while(
i>0 && (
abs(diag(
i))<considerZero ||
abs(col0(
i))<considerZero)) --
i;
1447 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1448 std::cout <<
"deflation 4.4 with i = " <<
i <<
" because " << diag(
i) <<
" - " << diag(
i-1) <<
" == " << (diag(
i) - diag(
i-1)) <<
" < " <<
NumTraits<RealScalar>::epsilon()*maxDiag <<
"\n";
1451 deflation44(firstCol, firstCol + shift, firstRowW, firstColW,
i-1,
i, length);
1455 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1460 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1473 template <
typename Derived>
1474 template <
int Options>
1485 template <
typename Derived>
1486 template <
int Options>
1488 unsigned int computationOptions)
const {
const AbsReturnType abs() const
const SqrtReturnType sqrt() const
FixedSegmentReturnType<... >::Type head(NType n)
cout<< "The eigenvalues of A are:"<< endl<< ces.eigenvalues()<< endl;cout<< "The matrix of eigenvectors, V, is:"<< endl<< ces.eigenvectors()<< endl<< endl;complex< float > lambda
Array< double, 1, 3 > e(1./3., 0.5, 2.)
cout<< "Here is the matrix m:"<< endl<< m<< endl;JacobiSVD< MatrixXf, ComputeThinU|ComputeThinV > svd(m)
JacobiRotation< float > J
#define eigen_internal_assert(x)
#define EIGEN_DISABLE_DEPRECATED_WARNING
#define EIGEN_DIAGNOSTICS(tokens)
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
Matrix< float, 1, Dynamic > MatrixType
class Bidiagonal Divide and Conquer SVD
void allocate(Index rows, Index cols, unsigned int computationOptions)
void structured_update(Block< MatrixXr, Dynamic, Dynamic > A, const MatrixXr &B, Index n1)
void copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naivev)
Ref< ArrayXi > IndicesRef
Base::MatrixUType MatrixUType
BDCSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix. Computes Thin/Full unitaries U/V if specified us...
Base::SingularValuesType SingularValuesType
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
EIGEN_DEPRECATED BDCSVD(const MatrixType &matrix, unsigned int computationOptions)
Constructor performing the decomposition of given matrix using specified options for computing unitar...
BDCSVD & compute_impl(const MatrixType &matrix, unsigned int computationOptions)
Base::RealScalar RealScalar
void computeBaseCase(SVDType &svd, Index n, Index firstCol, Index firstRowW, Index firstColW, Index shift)
NumTraits< RealScalar >::Literal Literal
void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift)
void computeSVDofM(Index firstCol, Index n, MatrixXr &U, VectorType &singVals, MatrixXr &V)
static RealScalar secularEq(RealScalar x, const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, const ArrayRef &diagShifted, RealScalar shift)
Array< RealScalar, Dynamic, 1 > ArrayXr
void computeSingVecs(const ArrayRef &zhat, const ArrayRef &diag, const IndicesRef &perm, const VectorType &singVals, const ArrayRef &shifts, const ArrayRef &mus, MatrixXr &U, MatrixXr &V)
Matrix< RealScalar, Dynamic, Dynamic, ColMajor > MatrixXr
BDCSVD(const MatrixType &matrix)
Constructor performing the decomposition of given matrix, using the custom options specified with the...
void setSwitchSize(int s)
void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift)
@ MaxDiagSizeAtCompileTime
JacobiSVD< MatrixType, ComputationOptions > smallSvd
void perturbCol0(const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, const VectorType &singVals, const ArrayRef &shifts, const ArrayRef &mus, ArrayRef zhat)
Matrix< RealScalar, Dynamic, 1 > VectorType
EIGEN_DEPRECATED BDCSVD(Index rows, Index cols, unsigned int computationOptions)
Default Constructor with memory preallocation.
void deflation43(Index firstCol, Index shift, Index i, Index size)
BDCSVD()
Default Constructor.
Matrix< Scalar, Dynamic, Dynamic, ColMajor > MatrixX
Base::MatrixVType MatrixVType
HouseholderQR< MatrixX > qrDecomp
void computeSingVals(const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, VectorType &singVals, ArrayRef shifts, ArrayRef mus)
Array< Index, 1, Dynamic > ArrayXi
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
EIGEN_DEPRECATED BDCSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix, as specified by the computationOptions parameter...
void deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size)
internal::UpperBidiagonalization< MatrixX > bid
BDCSVD(Index rows, Index cols)
Default Constructor with memory preallocation.
Expression of a fixed-size or dynamic-size block.
TransposeReturnType transpose()
ConstRowwiseReturnType rowwise() const
void swap(const DenseBase< OtherDerived > &other)
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Householder QR decomposition of a matrix.
Rotation given by a cosine-sine pair.
A matrix or vector expression mapping an existing array of data.
NoAlias< Derived, Eigen::MatrixBase > noalias()
ArrayWrapper< Derived > array()
BDCSVD< PlainObject, Options > bdcSvd() const
static const IdentityReturnType Identity()
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Derived & setZero(Index size)
constexpr void resize(Index rows, Index cols)
A matrix or vector expression mapping an existing expression.
Base class of SVD algorithms.
internal::make_proper_matrix_type< Scalar, RowsAtCompileTime, MatrixUColsAtCompileTime, MatrixOptions, MaxRowsAtCompileTime, MatrixUMaxColsAtCompileTime >::type MatrixUType
const SingularValuesType & singularValues() const
NumTraits< typename MatrixType::Scalar >::Real RealScalar
unsigned int m_computationOptions
internal::plain_diag_type< MatrixType, RealScalar >::type SingularValuesType
internal::make_proper_matrix_type< Scalar, ColsAtCompileTime, MatrixVColsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MatrixVMaxColsAtCompileTime >::type MatrixVType
MatrixType::Scalar Scalar
Index m_nonzeroSingularValues
SingularValuesType m_singularValues
@ MaxDiagSizeAtCompileTime
internal::traits< BDCSVD< MatrixType_, Options_ > >::MatrixType MatrixType
Expression of a fixed-size or dynamic-size sub-vector.
static const Eigen::internal::all_t all
Matrix< Type, Dynamic, Dynamic > MatrixX
[c++11] Dynamic×Dynamic matrix of type Type.
bfloat16() max(const bfloat16 &a, const bfloat16 &b)
bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
bfloat16() min(const bfloat16 &a, const bfloat16 &b)
constexpr int get_computation_options(int options)
void swap(scoped_array< T > &a, scoped_array< T > &b)
bool equal_strict(const X &x, const Y &y)
EIGEN_ALWAYS_INLINE bool() isfinite(const Eigen::bfloat16 &h)
bool is_exactly_zero(const X &x)
EIGEN_ALWAYS_INLINE std::enable_if_t< NumTraits< T >::IsSigned||NumTraits< T >::IsComplex, typename NumTraits< T >::Real > abs(const T &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
Eigen::Index Index
The interface type of indices.
EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.