20 #ifndef EIGEN_BDCSVD_H 21 #define EIGEN_BDCSVD_H 27 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 28 IOFormat bdcsvdfmt(8, 0,
", ",
"\n",
" [",
"]");
31 template<
typename _MatrixType>
class BDCSVD;
35 template<
typename _MatrixType>
66 template<
typename _MatrixType>
82 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
83 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
85 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
86 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
88 MatrixOptions = MatrixType::Options
119 : m_algoswap(16), m_numIters(0)
121 allocate(rows, cols, computationOptions);
135 : m_algoswap(16), m_numIters(0)
137 compute(matrix, computationOptions);
164 return compute(matrix, this->m_computationOptions);
169 eigen_assert(s>3 &&
"BDCSVD the size of the algo switch has to be greater than 3");
176 void computeSVDofM(
Index firstCol,
Index n, MatrixXr&
U, VectorType& singVals, MatrixXr&
V);
177 void computeSingVals(
const ArrayRef& col0,
const ArrayRef&
diag,
const IndicesRef&
perm, VectorType& singVals, ArrayRef shifts, ArrayRef mus);
178 void perturbCol0(
const ArrayRef& col0,
const ArrayRef& diag,
const IndicesRef& perm,
const VectorType& singVals,
const ArrayRef& shifts,
const ArrayRef& mus, ArrayRef zhat);
179 void computeSingVecs(
const ArrayRef& zhat,
const ArrayRef& diag,
const IndicesRef& perm,
const VectorType& singVals,
const ArrayRef& shifts,
const ArrayRef& mus, MatrixXr& U, MatrixXr& V);
183 template<
typename HouseholderU,
typename HouseholderV,
typename NaiveU,
typename NaiveV>
184 void copyUV(
const HouseholderU &householderU,
const HouseholderV &householderV,
const NaiveU &naiveU,
const NaiveV &naivev);
186 static RealScalar secularEq(RealScalar
x,
const ArrayRef& col0,
const ArrayRef& diag,
const IndicesRef &perm,
const ArrayRef& diagShifted, RealScalar shift);
197 using Base::m_singularValues;
198 using Base::m_diagSize;
199 using Base::m_computeFullU;
200 using Base::m_computeFullV;
201 using Base::m_computeThinU;
202 using Base::m_computeThinV;
203 using Base::m_matrixU;
204 using Base::m_matrixV;
205 using Base::m_isInitialized;
206 using Base::m_nonzeroSingularValues;
214 template<
typename MatrixType>
217 m_isTranspose = (cols >
rows);
219 if (Base::allocate(rows, cols, computationOptions))
222 m_computed = MatrixXr::Zero(m_diagSize + 1, m_diagSize );
223 m_compU = computeV();
224 m_compV = computeU();
228 if (m_compU) m_naiveU = MatrixXr::Zero(m_diagSize + 1, m_diagSize + 1 );
229 else m_naiveU = MatrixXr::Zero(2, m_diagSize + 1 );
231 if (m_compV) m_naiveV = MatrixXr::Zero(m_diagSize, m_diagSize);
233 m_workspace.resize((m_diagSize+1)*(m_diagSize+1)*3);
234 m_workspaceI.resize(3*m_diagSize);
237 template<
typename MatrixType>
240 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 241 std::cout <<
"\n\n\n======================================================================================================================\n\n\n";
243 allocate(matrix.rows(), matrix.cols(), computationOptions);
249 if(matrix.cols() < m_algoswap)
253 if(computeU()) m_matrixU = jsvd.
matrixU();
254 if(computeV()) m_matrixV = jsvd.
matrixV();
257 m_isInitialized =
true;
265 if (m_isTranspose) copy = matrix.adjoint()/
scale;
266 else copy = matrix/
scale;
276 m_computed.topRows(m_diagSize) = bid.
bidiagonal().toDenseMatrix().transpose();
277 m_computed.template bottomRows<1>().
setZero();
278 divide(0, m_diagSize - 1, 0, 0, 0);
281 for (
int i=0;
i<m_diagSize;
i++)
284 m_singularValues.coeffRef(
i) = a *
scale;
287 m_nonzeroSingularValues =
i;
288 m_singularValues.tail(m_diagSize -
i - 1).setZero();
291 else if (
i == m_diagSize - 1)
293 m_nonzeroSingularValues =
i + 1;
298 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 305 m_isInitialized =
true;
310 template<
typename MatrixType>
311 template<
typename HouseholderU,
typename HouseholderV,
typename NaiveU,
typename NaiveV>
312 void BDCSVD<MatrixType>::copyUV(
const HouseholderU &householderU,
const HouseholderV &householderV,
const NaiveU &naiveU,
const NaiveV &naiveV)
317 Index Ucols = m_computeThinU ? m_diagSize : householderU.cols();
318 m_matrixU = MatrixX::Identity(householderU.cols(), Ucols);
319 m_matrixU.topLeftCorner(m_diagSize, m_diagSize) = naiveV.template cast<Scalar>().
topLeftCorner(m_diagSize, m_diagSize);
320 householderU.applyThisOnTheLeft(m_matrixU);
324 Index Vcols = m_computeThinV ? m_diagSize : householderV.cols();
325 m_matrixV = MatrixX::Identity(householderV.cols(), Vcols);
326 m_matrixV.topLeftCorner(m_diagSize, m_diagSize) = naiveU.template cast<Scalar>().
topLeftCorner(m_diagSize, m_diagSize);
327 householderV.applyThisOnTheLeft(m_matrixV);
339 template<
typename MatrixType>
355 if( (A.col(
j).head(n1).array()!=
Literal(0)).any() )
357 A1.col(k1) = A.col(
j).head(n1);
358 B1.row(k1) = B.row(
j);
361 if( (A.col(
j).tail(n2).array()!=
Literal(0)).any() )
363 A2.col(k2) = A.col(
j).tail(n2);
364 B2.row(k2) = B.row(
j);
369 A.topRows(n1).noalias() = A1.leftCols(k1) * B1.topRows(k1);
370 A.bottomRows(n2).noalias() = A2.leftCols(k2) * B2.topRows(k2);
390 template<
typename MatrixType>
397 const Index n = lastCol - firstCol + 1;
412 m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() = b.
matrixU();
415 m_naiveU.row(0).segment(firstCol, n + 1).real() = b.
matrixU().row(0);
416 m_naiveU.row(1).segment(firstCol, n + 1).real() = b.
matrixU().row(n);
418 if (m_compV) m_naiveV.block(firstRowW, firstColW, n, n).real() = b.
matrixV();
419 m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
420 m_computed.diagonal().segment(firstCol + shift, n) = b.
singularValues().head(n);
424 alphaK = m_computed(firstCol + k, firstCol + k);
425 betaK = m_computed(firstCol + k + 1, firstCol + k);
429 divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
430 divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
434 lambda = m_naiveU(firstCol + k, firstCol + k);
435 phi = m_naiveU(firstCol + k + 1, lastCol + 1);
439 lambda = m_naiveU(1, firstCol + k);
440 phi = m_naiveU(0, lastCol + 1);
442 r0 =
sqrt((
abs(alphaK * lambda) *
abs(alphaK * lambda)) +
abs(betaK * phi) *
abs(betaK * phi));
445 l = m_naiveU.row(firstCol + k).segment(firstCol, k);
446 f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1, n - k - 1);
450 l = m_naiveU.row(1).segment(firstCol, k);
451 f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
453 if (m_compV) m_naiveV(firstRowW+k, firstColW) =
Literal(1);
461 c0 = alphaK * lambda / r0;
462 s0 = betaK * phi / r0;
465 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 466 assert(m_naiveU.allFinite());
467 assert(m_naiveV.allFinite());
468 assert(m_computed.allFinite());
473 MatrixXr q1 (m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
475 for (
Index i = firstCol + k - 1;
i >= firstCol;
i--)
476 m_naiveU.col(
i + 1).segment(firstCol, k + 1) = m_naiveU.col(
i).segment(firstCol, k + 1);
478 m_naiveU.col(firstCol).segment( firstCol, k + 1) = (
q1 * c0);
480 m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (
q1 * ( - s0));
482 m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) = m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) * s0;
484 m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *= c0;
490 for (
Index i = firstCol + k - 1;
i >= firstCol;
i--)
491 m_naiveU(0,
i + 1) = m_naiveU(0,
i);
493 m_naiveU(0, firstCol) = (q1 * c0);
495 m_naiveU(0, lastCol + 1) = (q1 * ( - s0));
497 m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) *s0;
499 m_naiveU(1, lastCol + 1) *= c0;
500 m_naiveU.row(1).segment(firstCol + 1, k).setZero();
501 m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1).setZero();
504 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 505 assert(m_naiveU.allFinite());
506 assert(m_naiveV.allFinite());
507 assert(m_computed.allFinite());
510 m_computed(firstCol + shift, firstCol + shift) = r0;
511 m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) = alphaK * l.transpose().real();
512 m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1, n - k - 1) = betaK * f.transpose().real();
514 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 515 ArrayXr tmp1 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
518 deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
519 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 520 ArrayXr tmp2 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
521 std::cout <<
"\n\nj1 = " << tmp1.transpose().format(bdcsvdfmt) <<
"\n";
522 std::cout <<
"j2 = " << tmp2.transpose().format(bdcsvdfmt) <<
"\n\n";
523 std::cout <<
"err: " << ((tmp1-tmp2).
abs()>1
e-12*tmp2.abs()).transpose() <<
"\n";
524 static int count = 0;
525 std::cout <<
"# " << ++count <<
"\n\n";
526 assert((tmp1-tmp2).
matrix().norm() < 1
e-14*tmp2.matrix().norm());
534 computeSVDofM(firstCol + shift, n, UofSVD, singVals, VofSVD);
536 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 537 assert(UofSVD.allFinite());
538 assert(VofSVD.allFinite());
542 structured_update(m_naiveU.block(firstCol, firstCol, n + 1, n + 1), UofSVD, (n+2)/2);
546 tmp.noalias() = m_naiveU.middleCols(firstCol, n+1) * UofSVD;
547 m_naiveU.middleCols(firstCol, n + 1) = tmp;
550 if (m_compV) structured_update(m_naiveV.block(firstRowW, firstColW, n, n), VofSVD, (n+1)/2);
552 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 553 assert(m_naiveU.allFinite());
554 assert(m_naiveV.allFinite());
555 assert(m_computed.allFinite());
558 m_computed.block(firstCol + shift, firstCol + shift, n, n).setZero();
559 m_computed.block(firstCol + shift, firstCol + shift, n, n).diagonal() = singVals;
570 template <
typename MatrixType>
575 ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n);
576 m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal();
583 if (m_compV) V.
resize(n, n);
585 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 586 if (col0.hasNaN() || diag.hasNaN())
587 std::cout <<
"\n\nHAS NAN\n\n";
594 while(actual_n>1 &&
diag(actual_n-1)==
Literal(0)) --actual_n;
596 for(
Index k=0;k<actual_n;++k)
597 if(
abs(col0(k))>considerZero)
598 m_workspaceI(m++) = k;
605 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 606 std::cout <<
"computeSVDofM using:\n";
607 std::cout <<
" z: " << col0.transpose() <<
"\n";
608 std::cout <<
" d: " << diag.transpose() <<
"\n";
612 computeSingVals(col0, diag,
perm, singVals, shifts, mus);
614 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 615 std::cout <<
" j: " << (m_computed.block(firstCol, firstCol, n, n)).jacobiSvd().singularValues().transpose().reverse() <<
"\n\n";
616 std::cout <<
" sing-val: " << singVals.transpose() <<
"\n";
617 std::cout <<
" mu: " << mus.transpose() <<
"\n";
618 std::cout <<
" shift: " << shifts.transpose() <<
"\n";
622 while(actual_n>1 &&
abs(col0(actual_n-1))<considerZero) --actual_n;
623 std::cout <<
"\n\n mus: " << mus.head(actual_n).transpose() <<
"\n\n";
624 std::cout <<
" check1 (expect0) : " << ((singVals.array()-(shifts+mus)) / singVals.array()).
head(actual_n).transpose() <<
"\n\n";
625 std::cout <<
" check2 (>0) : " << ((singVals.array()-
diag) / singVals.array()).
head(actual_n).transpose() <<
"\n\n";
626 std::cout <<
" check3 (>0) : " << ((diag.segment(1,actual_n-1)-singVals.head(actual_n-1).array()) / singVals.head(actual_n-1).array()).transpose() <<
"\n\n\n";
627 std::cout <<
" check4 (>0) : " << ((singVals.segment(1,actual_n-1)-singVals.head(actual_n-1))).transpose() <<
"\n\n\n";
631 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 632 assert(singVals.allFinite());
633 assert(mus.allFinite());
634 assert(shifts.allFinite());
638 perturbCol0(col0, diag,
perm, singVals, shifts, mus, zhat);
639 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 640 std::cout <<
" zhat: " << zhat.transpose() <<
"\n";
643 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 644 assert(zhat.allFinite());
647 computeSingVecs(zhat, diag,
perm, singVals, shifts, mus, U, V);
649 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 650 std::cout <<
"U^T U: " << (U.transpose() * U -
MatrixXr(MatrixXr::Identity(U.
cols(),U.
cols()))).norm() <<
"\n";
651 std::cout <<
"V^T V: " << (V.transpose() * V -
MatrixXr(MatrixXr::Identity(V.
cols(),V.
cols()))).norm() <<
"\n";
654 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 655 assert(U.allFinite());
656 assert(V.allFinite());
657 assert((U.transpose() * U -
MatrixXr(MatrixXr::Identity(U.
cols(),U.
cols()))).norm() < 1
e-14 *
n);
658 assert((V.transpose() * V -
MatrixXr(MatrixXr::Identity(V.
cols(),V.
cols()))).norm() < 1
e-14 *
n);
659 assert(m_naiveU.allFinite());
660 assert(m_naiveV.allFinite());
661 assert(m_computed.allFinite());
668 if(singVals(
i)>singVals(
i+1))
671 swap(singVals(
i),singVals(
i+1));
672 U.col(
i).
swap(U.col(
i+1));
673 if(m_compV) V.col(
i).
swap(V.col(
i+1));
679 singVals.head(actual_n).reverseInPlace();
680 U.leftCols(actual_n).rowwise().reverseInPlace();
681 if (m_compV) V.leftCols(actual_n).rowwise().reverseInPlace();
683 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 685 std::cout <<
" * j: " << jsvd.singularValues().transpose() <<
"\n\n";
686 std::cout <<
" * sing-val: " << singVals.transpose() <<
"\n";
691 template <
typename MatrixType>
701 res += (col0(j) / (diagShifted(j) -
mu)) * (col0(j) / (
diag(j) + shift +
mu));
707 template <
typename MatrixType>
719 while(actual_n>1 && col0(actual_n-1)==
Literal(0)) --actual_n;
721 for (
Index k = 0; k <
n; ++k)
723 if (col0(k) ==
Literal(0) || actual_n==1)
727 singVals(k) = k==0 ? col0(0) :
diag(k);
729 shifts(k) = k==0 ? col0(0) :
diag(k);
737 right = (
diag(actual_n-1) + col0.matrix().norm());
751 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 752 std::cout << right-left <<
"\n";
753 std::cout <<
"fMid = " << fMid <<
" " << secularEq(mid-left, col0, diag, perm, diag-left, left) <<
" " << secularEq(mid-right, col0, diag, perm, diag-right, right) <<
"\n";
754 std::cout <<
" = " << secularEq(0.1*(left+right), col0, diag, perm, diag, 0)
755 <<
" " << secularEq(0.2*(left+right), col0, diag, perm, diag, 0)
756 <<
" " << secularEq(0.3*(left+right), col0, diag, perm, diag, 0)
757 <<
" " << secularEq(0.4*(left+right), col0, diag, perm, diag, 0)
758 <<
" " << secularEq(0.49*(left+right), col0, diag, perm, diag, 0)
759 <<
" " << secularEq(0.5*(left+right), col0, diag, perm, diag, 0)
760 <<
" " << secularEq(0.51*(left+right), col0, diag, perm, diag, 0)
761 <<
" " << secularEq(0.6*(left+right), col0, diag, perm, diag, 0)
762 <<
" " << secularEq(0.7*(left+right), col0, diag, perm, diag, 0)
763 <<
" " << secularEq(0.8*(left+right), col0, diag, perm, diag, 0)
764 <<
" " << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) <<
"\n";
770 diagShifted = diag - shift;
777 if (k == actual_n-1) muCur = right -
left;
786 RealScalar fPrev = secularEq(muPrev, col0, diag, perm, diagShifted, shift);
787 RealScalar fCur = secularEq(muCur, col0, diag, perm, diagShifted, shift);
788 if (
abs(fPrev) <
abs(fCur))
796 bool useBisection = fPrev*fCur>
Literal(0);
802 RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev);
806 RealScalar fZero = secularEq(muZero, col0, diag, perm, diagShifted, shift);
814 if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection =
true;
815 if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection =
true;
816 if (
abs(fCur)>
abs(fPrev)) useBisection =
true;
822 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 823 std::cout <<
"useBisection for k = " << k <<
", actual_n = " << actual_n <<
"\n";
836 rightShifted = (k==actual_n-1) ? right : ((right - left) *
RealScalar(0.51));
847 RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift);
849 #if defined EIGEN_INTERNAL_DEBUGGING || defined EIGEN_BDCSVD_DEBUG_VERBOSE 850 RealScalar fRight = secularEq(rightShifted, col0, diag, perm, diagShifted, shift);
853 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 854 if(!(fLeft * fRight<0))
856 std::cout <<
"fLeft: " << leftShifted <<
" - " << diagShifted.head(10).transpose() <<
"\n ; " << bool(left==shift) <<
" " << (left-shift) <<
"\n";
857 std::cout << k <<
" : " << fLeft <<
" * " << fRight <<
" == " << fLeft * fRight <<
" ; " << left <<
" - " << right <<
" -> " << leftShifted <<
" " << rightShifted <<
" shift=" << shift <<
"\n";
864 RealScalar midShifted = (leftShifted + rightShifted) / Literal(2);
865 fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
866 if (fLeft * fMid < Literal(0))
868 rightShifted = midShifted;
872 leftShifted = midShifted;
877 muCur = (leftShifted + rightShifted) / Literal(2);
880 singVals[k] = shift + muCur;
894 template <
typename MatrixType>
909 for (
Index k = 0; k <
n; ++k)
917 RealScalar prod = (singVals(last) + dk) * (mus(last) + (shifts(last) - dk));
925 prod *= ((singVals(j)+dk) / ((
diag(i)+dk))) * ((mus(j)+(shifts(j)-dk)) / ((
diag(i)-dk)));
926 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 927 if(i!=k &&
std::abs(((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((
diag(i)+dk)*(
diag(i)-dk)) - 1) > 0.9 )
928 std::cout <<
" " << ((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((
diag(i)+dk)*(
diag(i)-dk)) <<
" == (" << (singVals(j)+dk) <<
" * " << (mus(j)+(shifts(j)-dk))
929 <<
") / (" << (
diag(i)+dk) <<
" * " << (
diag(i)-dk) <<
")\n";
933 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 934 std::cout <<
"zhat(" << k <<
") = sqrt( " << prod <<
") ; " << (singVals(last) + dk) <<
" * " << mus(last) + shifts(last) <<
" - " << dk <<
"\n";
937 zhat(k) = col0(k) >
Literal(0) ? tmp : -tmp;
943 template <
typename MatrixType>
951 for (
Index k = 0; k <
n; ++k)
955 U.col(k) = VectorType::Unit(n+1, k);
956 if (m_compV) V.col(k) = VectorType::Unit(n, k);
964 U(i,k) = zhat(i)/(((
diag(i) - shifts(k)) - mus(k)) )/( (
diag(i) + singVals[k]));
967 U.col(k).normalize();
975 V(i,k) =
diag(i) * zhat(i) / (((
diag(i) - shifts(k)) - mus(k)) )/( (
diag(i) + singVals[k]));
978 V.col(k).normalize();
982 U.col(n) = VectorType::Unit(n+1, n);
989 template <
typename MatrixType>
995 Index start = firstCol + shift;
1001 m_computed(start+i, start+i) =
Literal(0);
1004 m_computed(start,start) = r;
1005 m_computed(start+i, start) =
Literal(0);
1006 m_computed(start+i, start+i) =
Literal(0);
1009 if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J);
1010 else m_naiveU.applyOnTheRight(firstCol, firstCol+i, J);
1018 template <
typename MatrixType>
1025 RealScalar c = m_computed(firstColm+i, firstColm);
1026 RealScalar s = m_computed(firstColm+j, firstColm);
1028 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1029 std::cout <<
"deflation 4.4: " << i <<
"," << j <<
" -> " << c <<
" " << s <<
" " << r <<
" ; " 1030 << m_computed(firstColm + i-1, firstColm) <<
" " 1031 << m_computed(firstColm + i, firstColm) <<
" " 1032 << m_computed(firstColm + i+1, firstColm) <<
" " 1033 << m_computed(firstColm + i+2, firstColm) <<
"\n";
1034 std::cout << m_computed(firstColm + i-1, firstColm + i-1) <<
" " 1035 << m_computed(firstColm + i, firstColm+i) <<
" " 1036 << m_computed(firstColm + i+1, firstColm+i+1) <<
" " 1037 << m_computed(firstColm + i+2, firstColm+i+2) <<
"\n";
1041 m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
1046 m_computed(firstColm + i, firstColm) = r;
1047 m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
1048 m_computed(firstColm + j, firstColm) =
Literal(0);
1051 if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J);
1052 else m_naiveU.applyOnTheRight(firstColu+i, firstColu+j, J);
1053 if (m_compV) m_naiveV.middleRows(firstRowW, size).applyOnTheRight(firstColW + i, firstColW + j, J);
1058 template <
typename MatrixType>
1063 const Index length = lastCol + 1 - firstCol;
1074 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 1075 assert(m_naiveU.allFinite());
1076 assert(m_naiveV.allFinite());
1077 assert(m_computed.allFinite());
1080 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1081 std::cout <<
"\ndeflate:" << diag.head(k+1).transpose() <<
" | " << diag.segment(k+1,length-k-1).transpose() <<
"\n";
1085 if (
diag(0) < epsilon_coarse)
1087 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1088 std::cout <<
"deflation 4.1, because " <<
diag(0) <<
" < " << epsilon_coarse <<
"\n";
1090 diag(0) = epsilon_coarse;
1095 if (
abs(col0(
i)) < epsilon_strict)
1097 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1098 std::cout <<
"deflation 4.2, set z(" <<
i <<
") to zero because " <<
abs(col0(
i)) <<
" < " << epsilon_strict <<
" (diag(" <<
i <<
")=" <<
diag(
i) <<
")\n";
1105 if (
diag(
i) < epsilon_coarse)
1107 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1108 std::cout <<
"deflation 4.3, cancel z(" <<
i <<
")=" << col0(
i) <<
" because diag(" <<
i <<
")=" <<
diag(
i) <<
" < " << epsilon_coarse <<
"\n";
1110 deflation43(firstCol, shift,
i, length);
1113 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 1114 assert(m_naiveU.allFinite());
1115 assert(m_naiveV.allFinite());
1116 assert(m_computed.allFinite());
1118 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1119 std::cout <<
"to be sorted: " << diag.transpose() <<
"\n\n";
1124 bool total_deflation = (col0.tail(length-1).array()<considerZero).all();
1128 Index *permutation = m_workspaceI.data();
1136 permutation[p++] =
i;
1139 for( ; p < length; ++
p)
1141 if (i > k) permutation[
p] =
j++;
1142 else if (
j >= length) permutation[
p] = i++;
1144 else permutation[
p] = i++;
1153 Index pi = permutation[
i];
1155 permutation[
i-1] = permutation[
i];
1158 permutation[
i-1] = 0;
1165 Index *realInd = m_workspaceI.data()+length;
1166 Index *realCol = m_workspaceI.data()+2*length;
1174 for(
Index i = total_deflation?0:1;
i < length;
i++)
1176 const Index pi = permutation[length - (total_deflation ?
i+1 :
i)];
1177 const Index J = realCol[pi];
1182 if(
i!=0 && J!=0)
swap(col0(
i), col0(J));
1185 if (m_compU) m_naiveU.col(firstCol+
i).segment(firstCol, length + 1).swap(m_naiveU.col(firstCol+J).segment(firstCol, length + 1));
1186 else m_naiveU.col(firstCol+
i).segment(0, 2) .swap(m_naiveU.col(firstCol+J).segment(0, 2));
1187 if (m_compV) m_naiveV.col(firstColW +
i).segment(firstRowW, length).swap(m_naiveV.col(firstColW + J).segment(firstRowW, length));
1190 const Index realI = realInd[
i];
1197 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1198 std::cout <<
"sorted: " << diag.transpose().format(bdcsvdfmt) <<
"\n";
1199 std::cout <<
" : " << col0.transpose() <<
"\n\n";
1205 while(i>0 && (
abs(
diag(i))<considerZero ||
abs(col0(i))<considerZero)) --
i;
1209 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE 1213 deflation44(firstCol, firstCol + shift, firstRowW, firstColW, i-1, i, length);
1217 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 1222 #ifdef EIGEN_BDCSVD_SANITY_CHECKS 1223 assert(m_naiveU.allFinite());
1224 assert(m_naiveV.allFinite());
1225 assert(m_computed.allFinite());
1236 template<
typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const
BDCSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix using current options.
const BidiagonalType & bidiagonal() const
constexpr int last(int, int result)
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
void computeSVDofM(Index firstCol, Index n, MatrixXr &U, VectorType &singVals, MatrixXr &V)
EIGEN_DEVICE_FUNC void swap(DenseBase< OtherDerived > &other)
const HouseholderUSequenceType householderU() const
const HouseholderVSequenceType householderV()
EIGEN_DEVICE_FUNC bool() isfinite(const T &x)
Matrix< Scalar, Dynamic, Dynamic, ColMajor > MatrixX
Base::MatrixUType MatrixUType
Matrix< RealScalar, Dynamic, Dynamic, ColMajor > MatrixXr
Matrix diag(const std::vector< Matrix > &Hs)
const SingularValuesType & singularValues() const
void setSwitchSize(int s)
A matrix or vector expression mapping an existing array of data.
void deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size)
void copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naivev)
Array< RealScalar, Dynamic, 1 > ArrayXr
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Namespace containing all symbols from the Eigen library.
Rotation given by a cosine-sine pair.
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
void computeSingVals(const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, VectorType &singVals, ArrayRef shifts, ArrayRef mus)
#define EIGEN_SIZE_MIN_PREFER_FIXED(a, b)
BDCSVD< PlainObject > bdcSvd(unsigned int computationOptions=0) const
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
Base::MatrixVType MatrixVType
Expression of a fixed-size or dynamic-size sub-vector.
BDCSVD(Index rows, Index cols, unsigned int computationOptions=0)
Default Constructor with memory preallocation.
static const Line3 l(Rot3(), 1, 1)
Ref< ArrayXi > IndicesRef
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Base class of SVD algorithms.
void computeSingVecs(const ArrayRef &zhat, const ArrayRef &diag, const IndicesRef &perm, const VectorType &singVals, const ArrayRef &shifts, const ArrayRef &mus, MatrixXr &U, MatrixXr &V)
static RealScalar secularEq(RealScalar x, const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, const ArrayRef &diagShifted, RealScalar shift)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
void deflation43(Index firstCol, Index shift, Index i, Index size)
idx_t idx_t idx_t idx_t idx_t * perm
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Array< double, 1, 3 > e(1./3., 0.5, 2.)
BDCSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix using custom options.
const MatrixVType & matrixV() const
BDCSVD(const MatrixType &matrix, unsigned int computationOptions=0)
Constructor performing the decomposition of given matrix.
void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift)
const MatrixUType & matrixU() const
JacobiRotation< float > J
void perturbCol0(const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, const VectorType &singVals, const ArrayRef &shifts, const ArrayRef &mus, ArrayRef zhat)
NumTraits< Scalar >::Real RealScalar
MatrixType::Scalar Scalar
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Abs2ReturnType abs2() const
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
class Bidiagonal Divide and Conquer SVD
Index nonzeroSingularValues() const
NumTraits< RealScalar >::Literal Literal
A matrix or vector expression mapping an existing expression.
Array< Index, 1, Dynamic > ArrayXi
const mpreal hypot(const mpreal &x, const mpreal &y, mp_rnd_t rnd_mode=mpreal::get_default_rnd())
Expression of a fixed-size or dynamic-size block.
EIGEN_DEVICE_FUNC SegmentReturnType head(Index n)
This is the const version of head(Index).
void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift)
BDCSVD()
Default Constructor.
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Matrix< RealScalar, Dynamic, 1 > VectorType
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics scale
void allocate(Index rows, Index cols, unsigned int computationOptions)
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
int EIGEN_BLAS_FUNC() copy(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Base::SingularValuesType SingularValuesType
NumTraits< typename MatrixType::Scalar >::Real RealScalar
#define eigen_internal_assert(x)
Jet< T, N > pow(const Jet< T, N > &f, double g)
EIGEN_DONT_INLINE void compute(Solver &solver, const MatrixType &A)
Map< Matrix< T, Dynamic, Dynamic, ColMajor >, 0, OuterStride<> > matrix(T *data, int rows, int cols, int stride)
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
#define EIGEN_SIZE_MIN_PREFER_DYNAMIC(a, b)
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
ScalarWithExceptions conj(const ScalarWithExceptions &x)
void structured_update(Block< MatrixXr, Dynamic, Dynamic > A, const MatrixXr &B, Index n1)
void swap(scoped_array< T > &a, scoped_array< T > &b)
Eigen::Block< Derived > topLeftCorner(MatrixBase< Derived > &m, int rows, int cols)
const Product< Lhs, Rhs > prod(const Lhs &lhs, const Rhs &rhs)