BDCSVD.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // We used the "A Divide-And-Conquer Algorithm for the Bidiagonal SVD"
5 // research report written by Ming Gu and Stanley C.Eisenstat
6 // The code variable names correspond to the names they used in their
7 // report
8 //
9 // Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
10 // Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
11 // Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
12 // Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.fr>
13 // Copyright (C) 2013 Jitse Niesen <jitse@maths.leeds.ac.uk>
14 // Copyright (C) 2014-2017 Gael Guennebaud <gael.guennebaud@inria.fr>
15 //
16 // Source Code Form is subject to the terms of the Mozilla
17 // Public License v. 2.0. If a copy of the MPL was not distributed
18 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
19 
20 #ifndef EIGEN_BDCSVD_H
21 #define EIGEN_BDCSVD_H
22 // #define EIGEN_BDCSVD_DEBUG_VERBOSE
23 // #define EIGEN_BDCSVD_SANITY_CHECKS
24 
25 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
26 #undef eigen_internal_assert
27 #define eigen_internal_assert(X) assert(X);
28 #endif
29 
30 // IWYU pragma: private
31 #include "./InternalHeaderCheck.h"
32 
33 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
34 #include <iostream>
35 #endif
36 
37 namespace Eigen {
38 
39 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
40 IOFormat bdcsvdfmt(8, 0, ", ", "\n", " [", "]");
41 #endif
42 
43 template <typename MatrixType_, int Options>
44 class BDCSVD;
45 
46 namespace internal {
47 
48 template <typename MatrixType_, int Options>
49 struct traits<BDCSVD<MatrixType_, Options> > : svd_traits<MatrixType_, Options> {
50  typedef MatrixType_ MatrixType;
51 };
52 
53 } // end namespace internal
54 
84 template <typename MatrixType_, int Options_>
85 class BDCSVD : public SVDBase<BDCSVD<MatrixType_, Options_> > {
87 
88  public:
89  using Base::cols;
90  using Base::computeU;
91  using Base::computeV;
92  using Base::diagSize;
93  using Base::rows;
94 
95  typedef MatrixType_ MatrixType;
96  typedef typename Base::Scalar Scalar;
97  typedef typename Base::RealScalar RealScalar;
99  typedef typename Base::Index Index;
100  enum {
101  Options = Options_,
111  };
112 
113  typedef typename Base::MatrixUType MatrixUType;
114  typedef typename Base::MatrixVType MatrixVType;
116 
124 
130  BDCSVD() : m_algoswap(16), m_isTranspose(false), m_compU(false), m_compV(false), m_numIters(0) {}
131 
140  }
141 
156  EIGEN_DEPRECATED BDCSVD(Index rows, Index cols, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
157  internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, rows, cols);
158  allocate(rows, cols, computationOptions);
159  }
160 
168  }
169 
182  EIGEN_DEPRECATED BDCSVD(const MatrixType& matrix, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
183  internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
184  compute_impl(matrix, computationOptions);
185  }
186 
187  ~BDCSVD() {}
188 
195 
205  EIGEN_DEPRECATED BDCSVD& compute(const MatrixType& matrix, unsigned int computationOptions) {
206  internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
207  return compute_impl(matrix, computationOptions);
208  }
209 
210  void setSwitchSize(int s) {
211  eigen_assert(s >= 3 && "BDCSVD the size of the algo switch has to be at least 3.");
212  m_algoswap = s;
213  }
214 
215  private:
216  BDCSVD& compute_impl(const MatrixType& matrix, unsigned int computationOptions);
217  void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift);
218  void computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V);
219  void computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, VectorType& singVals,
220  ArrayRef shifts, ArrayRef mus);
221  void perturbCol0(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals,
222  const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat);
223  void computeSingVecs(const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals,
224  const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V);
225  void deflation43(Index firstCol, Index shift, Index i, Index size);
226  void deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size);
227  void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift);
228  template <typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
229  void copyUV(const HouseholderU& householderU, const HouseholderV& householderV, const NaiveU& naiveU,
230  const NaiveV& naivev);
232  static RealScalar secularEq(RealScalar x, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm,
233  const ArrayRef& diagShifted, RealScalar shift);
234  template <typename SVDType>
235  void computeBaseCase(SVDType& svd, Index n, Index firstCol, Index firstRowW, Index firstColW, Index shift);
236 
237  protected:
238  void allocate(Index rows, Index cols, unsigned int computationOptions);
251 
253  using Base::m_computeThinU;
254  using Base::m_computeThinV;
255  using Base::m_info;
256  using Base::m_isInitialized;
257  using Base::m_matrixU;
258  using Base::m_matrixV;
261 
262  public:
264 }; // end class BDCSVD
265 
266 // Method to allocate and initialize matrix and attributes
267 template <typename MatrixType, int Options>
268 void BDCSVD<MatrixType, Options>::allocate(Index rows, Index cols, unsigned int computationOptions) {
269  if (Base::allocate(rows, cols, computationOptions)) return;
270 
271  if (cols < m_algoswap)
272  smallSvd.allocate(rows, cols, Options == 0 ? computationOptions : internal::get_computation_options(Options));
273 
274  m_computed = MatrixXr::Zero(diagSize() + 1, diagSize());
275  m_compU = computeV();
276  m_compV = computeU();
277  m_isTranspose = (cols > rows);
278  if (m_isTranspose) std::swap(m_compU, m_compV);
279 
280  // kMinAspectRatio is the crossover point that determines if we perform R-Bidiagonalization
281  // or bidiagonalize the input matrix directly.
282  // It is based off of LAPACK's dgesdd routine, which uses 11.0/6.0
283  // we use a larger scalar to prevent a regression for relatively square matrices.
284  constexpr Index kMinAspectRatio = 4;
285  constexpr bool disableQrDecomp = static_cast<int>(QRDecomposition) == static_cast<int>(DisableQRDecomposition);
286  m_useQrDecomp = !disableQrDecomp && ((rows / kMinAspectRatio > cols) || (cols / kMinAspectRatio > rows));
287  if (m_useQrDecomp) {
289  reducedTriangle = MatrixX(diagSize(), diagSize());
290  }
291 
292  copyWorkspace = MatrixX(m_isTranspose ? cols : rows, m_isTranspose ? rows : cols);
293  bid = internal::UpperBidiagonalization<MatrixX>(m_useQrDecomp ? diagSize() : copyWorkspace.rows(),
294  m_useQrDecomp ? diagSize() : copyWorkspace.cols());
295 
296  if (m_compU)
297  m_naiveU = MatrixXr::Zero(diagSize() + 1, diagSize() + 1);
298  else
299  m_naiveU = MatrixXr::Zero(2, diagSize() + 1);
300 
301  if (m_compV) m_naiveV = MatrixXr::Zero(diagSize(), diagSize());
302 
303  m_workspace.resize((diagSize() + 1) * (diagSize() + 1) * 3);
304  m_workspaceI.resize(3 * diagSize());
305 } // end allocate
306 
307 template <typename MatrixType, int Options>
309  unsigned int computationOptions) {
310 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
311  std::cout << "\n\n\n================================================================================================="
312  "=====================\n\n\n";
313 #endif
314  using std::abs;
315 
316  allocate(matrix.rows(), matrix.cols(), computationOptions);
317 
318  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
319 
320  //**** step -1 - If the problem is too small, directly falls back to JacobiSVD and return
321  if (matrix.cols() < m_algoswap) {
322  smallSvd.compute(matrix);
323  m_isInitialized = true;
324  m_info = smallSvd.info();
325  if (m_info == Success || m_info == NoConvergence) {
326  if (computeU()) m_matrixU = smallSvd.matrixU();
327  if (computeV()) m_matrixV = smallSvd.matrixV();
328  m_singularValues = smallSvd.singularValues();
329  m_nonzeroSingularValues = smallSvd.nonzeroSingularValues();
330  }
331  return *this;
332  }
333 
334  //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows
335  RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
336  if (!(numext::isfinite)(scale)) {
337  m_isInitialized = true;
338  m_info = InvalidInput;
339  return *this;
340  }
341 
342  if (numext::is_exactly_zero(scale)) scale = Literal(1);
343 
344  if (m_isTranspose)
345  copyWorkspace = matrix.adjoint() / scale;
346  else
347  copyWorkspace = matrix / scale;
348 
349  //**** step 1 - Bidiagonalization.
350  // If the problem is sufficiently rectangular, we perform R-Bidiagonalization: compute A = Q(R/0)
351  // and then bidiagonalize R. Otherwise, if the problem is relatively square, we
352  // bidiagonalize the input matrix directly.
353  if (m_useQrDecomp) {
354  qrDecomp.compute(copyWorkspace);
355  reducedTriangle = qrDecomp.matrixQR().topRows(diagSize());
356  reducedTriangle.template triangularView<StrictlyLower>().setZero();
357  bid.compute(reducedTriangle);
358  } else {
359  bid.compute(copyWorkspace);
360  }
361 
362  //**** step 2 - Divide & Conquer
363  m_naiveU.setZero();
364  m_naiveV.setZero();
365  // FIXME this line involves a temporary matrix
366  m_computed.topRows(diagSize()) = bid.bidiagonal().toDenseMatrix().transpose();
367  m_computed.template bottomRows<1>().setZero();
368  divide(0, diagSize() - 1, 0, 0, 0);
369  if (m_info != Success && m_info != NoConvergence) {
370  m_isInitialized = true;
371  return *this;
372  }
373 
374  //**** step 3 - Copy singular values and vectors
375  for (int i = 0; i < diagSize(); i++) {
376  RealScalar a = abs(m_computed.coeff(i, i));
377  m_singularValues.coeffRef(i) = a * scale;
378  if (a < considerZero) {
379  m_nonzeroSingularValues = i;
380  m_singularValues.tail(diagSize() - i - 1).setZero();
381  break;
382  } else if (i == diagSize() - 1) {
383  m_nonzeroSingularValues = i + 1;
384  break;
385  }
386  }
387 
388  //**** step 4 - Finalize unitaries U and V
389  if (m_isTranspose)
390  copyUV(bid.householderV(), bid.householderU(), m_naiveV, m_naiveU);
391  else
392  copyUV(bid.householderU(), bid.householderV(), m_naiveU, m_naiveV);
393 
394  if (m_useQrDecomp) {
395  if (m_isTranspose && computeV())
396  m_matrixV.applyOnTheLeft(qrDecomp.householderQ());
397  else if (!m_isTranspose && computeU())
398  m_matrixU.applyOnTheLeft(qrDecomp.householderQ());
399  }
400 
401  m_isInitialized = true;
402  return *this;
403 } // end compute
404 
405 template <typename MatrixType, int Options>
406 template <typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
407 void BDCSVD<MatrixType, Options>::copyUV(const HouseholderU& householderU, const HouseholderV& householderV,
408  const NaiveU& naiveU, const NaiveV& naiveV) {
409  // Note exchange of U and V: m_matrixU is set from m_naiveV and vice versa
410  if (computeU()) {
411  Index Ucols = m_computeThinU ? diagSize() : rows();
412  m_matrixU = MatrixX::Identity(rows(), Ucols);
413  m_matrixU.topLeftCorner(diagSize(), diagSize()) =
414  naiveV.template cast<Scalar>().topLeftCorner(diagSize(), diagSize());
415  // FIXME the following conditionals involve temporary buffers
416  if (m_useQrDecomp)
417  m_matrixU.topLeftCorner(householderU.cols(), diagSize()).applyOnTheLeft(householderU);
418  else
419  m_matrixU.applyOnTheLeft(householderU);
420  }
421  if (computeV()) {
422  Index Vcols = m_computeThinV ? diagSize() : cols();
423  m_matrixV = MatrixX::Identity(cols(), Vcols);
424  m_matrixV.topLeftCorner(diagSize(), diagSize()) =
425  naiveU.template cast<Scalar>().topLeftCorner(diagSize(), diagSize());
426  // FIXME the following conditionals involve temporary buffers
427  if (m_useQrDecomp)
428  m_matrixV.topLeftCorner(householderV.cols(), diagSize()).applyOnTheLeft(householderV);
429  else
430  m_matrixV.applyOnTheLeft(householderV);
431  }
432 }
433 
442 template <typename MatrixType, int Options>
444  Index n = A.rows();
445  if (n > 100) {
446  // If the matrices are large enough, let's exploit the sparse structure of A by
447  // splitting it in half (wrt n1), and packing the non-zero columns.
448  Index n2 = n - n1;
449  Map<MatrixXr> A1(m_workspace.data(), n1, n);
450  Map<MatrixXr> A2(m_workspace.data() + n1 * n, n2, n);
451  Map<MatrixXr> B1(m_workspace.data() + n * n, n, n);
452  Map<MatrixXr> B2(m_workspace.data() + 2 * n * n, n, n);
453  Index k1 = 0, k2 = 0;
454  for (Index j = 0; j < n; ++j) {
455  if ((A.col(j).head(n1).array() != Literal(0)).any()) {
456  A1.col(k1) = A.col(j).head(n1);
457  B1.row(k1) = B.row(j);
458  ++k1;
459  }
460  if ((A.col(j).tail(n2).array() != Literal(0)).any()) {
461  A2.col(k2) = A.col(j).tail(n2);
462  B2.row(k2) = B.row(j);
463  ++k2;
464  }
465  }
466 
467  A.topRows(n1).noalias() = A1.leftCols(k1) * B1.topRows(k1);
468  A.bottomRows(n2).noalias() = A2.leftCols(k2) * B2.topRows(k2);
469  } else {
470  Map<MatrixXr, Aligned> tmp(m_workspace.data(), n, n);
471  tmp.noalias() = A * B;
472  A = tmp;
473  }
474 }
475 
476 template <typename MatrixType, int Options>
477 template <typename SVDType>
479  Index firstColW, Index shift) {
480  svd.compute(m_computed.block(firstCol, firstCol, n + 1, n));
481  m_info = svd.info();
482  if (m_info != Success && m_info != NoConvergence) return;
483  if (m_compU)
484  m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() = svd.matrixU();
485  else {
486  m_naiveU.row(0).segment(firstCol, n + 1).real() = svd.matrixU().row(0);
487  m_naiveU.row(1).segment(firstCol, n + 1).real() = svd.matrixU().row(n);
488  }
489  if (m_compV) m_naiveV.block(firstRowW, firstColW, n, n).real() = svd.matrixV();
490  m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
491  m_computed.diagonal().segment(firstCol + shift, n) = svd.singularValues().head(n);
492 }
493 
494 // The divide algorithm is done "in place", we are always working on subsets of the same matrix. The divide methods
495 // takes as argument the place of the submatrix we are currently working on.
496 
497 //@param firstCol : The Index of the first column of the submatrix of m_computed and for m_naiveU;
498 //@param lastCol : The Index of the last column of the submatrix of m_computed and for m_naiveU;
499 // lastCol + 1 - firstCol is the size of the submatrix.
500 //@param firstRowW : The Index of the first row of the matrix W that we are to change. (see the reference paper section
501 // 1 for more information on W)
502 //@param firstColW : Same as firstRowW with the column.
503 //@param shift : Each time one takes the left submatrix, one must add 1 to the shift. Why? Because! We actually want the
504 // last column of the U submatrix
505 // to become the first column (*coeff) and to shift all the other columns to the right. There are more details on the
506 // reference paper.
507 template <typename MatrixType, int Options>
508 void BDCSVD<MatrixType, Options>::divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift) {
509  // requires rows = cols + 1;
510  using std::abs;
511  using std::pow;
512  using std::sqrt;
513  const Index n = lastCol - firstCol + 1;
514  const Index k = n / 2;
515  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
516  RealScalar alphaK;
517  RealScalar betaK;
518  RealScalar r0;
519  RealScalar lambda, phi, c0, s0;
520  VectorType l, f;
521  // We use the other algorithm which is more efficient for small
522  // matrices.
523  if (n < m_algoswap) {
524  // FIXME this block involves temporaries
525  if (m_compV) {
527  computeBaseCase(baseSvd, n, firstCol, firstRowW, firstColW, shift);
528  } else {
530  computeBaseCase(baseSvd, n, firstCol, firstRowW, firstColW, shift);
531  }
532  return;
533  }
534  // We use the divide and conquer algorithm
535  alphaK = m_computed(firstCol + k, firstCol + k);
536  betaK = m_computed(firstCol + k + 1, firstCol + k);
537  // The divide must be done in that order in order to have good results. Divide change the data inside the submatrices
538  // and the divide of the right submatrice reads one column of the left submatrice. That's why we need to treat the
539  // right submatrix before the left one.
540  divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
541  if (m_info != Success && m_info != NoConvergence) return;
542  divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
543  if (m_info != Success && m_info != NoConvergence) return;
544 
545  if (m_compU) {
546  lambda = m_naiveU(firstCol + k, firstCol + k);
547  phi = m_naiveU(firstCol + k + 1, lastCol + 1);
548  } else {
549  lambda = m_naiveU(1, firstCol + k);
550  phi = m_naiveU(0, lastCol + 1);
551  }
552  r0 = sqrt((abs(alphaK * lambda) * abs(alphaK * lambda)) + abs(betaK * phi) * abs(betaK * phi));
553  if (m_compU) {
554  l = m_naiveU.row(firstCol + k).segment(firstCol, k);
555  f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1, n - k - 1);
556  } else {
557  l = m_naiveU.row(1).segment(firstCol, k);
558  f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
559  }
560  if (m_compV) m_naiveV(firstRowW + k, firstColW) = Literal(1);
561  if (r0 < considerZero) {
562  c0 = Literal(1);
563  s0 = Literal(0);
564  } else {
565  c0 = alphaK * lambda / r0;
566  s0 = betaK * phi / r0;
567  }
568 
569 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
570  eigen_internal_assert(m_naiveU.allFinite());
571  eigen_internal_assert(m_naiveV.allFinite());
572  eigen_internal_assert(m_computed.allFinite());
573 #endif
574 
575  if (m_compU) {
576  MatrixXr q1(m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
577  // we shiftW Q1 to the right
578  for (Index i = firstCol + k - 1; i >= firstCol; i--)
579  m_naiveU.col(i + 1).segment(firstCol, k + 1) = m_naiveU.col(i).segment(firstCol, k + 1);
580  // we shift q1 at the left with a factor c0
581  m_naiveU.col(firstCol).segment(firstCol, k + 1) = (q1 * c0);
582  // last column = q1 * - s0
583  m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (q1 * (-s0));
584  // first column = q2 * s0
585  m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) =
586  m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) * s0;
587  // q2 *= c0
588  m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *= c0;
589  } else {
590  RealScalar q1 = m_naiveU(0, firstCol + k);
591  // we shift Q1 to the right
592  for (Index i = firstCol + k - 1; i >= firstCol; i--) m_naiveU(0, i + 1) = m_naiveU(0, i);
593  // we shift q1 at the left with a factor c0
594  m_naiveU(0, firstCol) = (q1 * c0);
595  // last column = q1 * - s0
596  m_naiveU(0, lastCol + 1) = (q1 * (-s0));
597  // first column = q2 * s0
598  m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) * s0;
599  // q2 *= c0
600  m_naiveU(1, lastCol + 1) *= c0;
601  m_naiveU.row(1).segment(firstCol + 1, k).setZero();
602  m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1).setZero();
603  }
604 
605 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
606  eigen_internal_assert(m_naiveU.allFinite());
607  eigen_internal_assert(m_naiveV.allFinite());
608  eigen_internal_assert(m_computed.allFinite());
609 #endif
610 
611  m_computed(firstCol + shift, firstCol + shift) = r0;
612  m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) = alphaK * l.transpose().real();
613  m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1, n - k - 1) = betaK * f.transpose().real();
614 
615 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
616  ArrayXr tmp1 = (m_computed.block(firstCol + shift, firstCol + shift, n, n)).jacobiSvd().singularValues();
617 #endif
618  // Second part: try to deflate singular values in combined matrix
619  deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
620 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
621  ArrayXr tmp2 = (m_computed.block(firstCol + shift, firstCol + shift, n, n)).jacobiSvd().singularValues();
622  std::cout << "\n\nj1 = " << tmp1.transpose().format(bdcsvdfmt) << "\n";
623  std::cout << "j2 = " << tmp2.transpose().format(bdcsvdfmt) << "\n\n";
624  std::cout << "err: " << ((tmp1 - tmp2).abs() > 1e-12 * tmp2.abs()).transpose() << "\n";
625  static int count = 0;
626  std::cout << "# " << ++count << "\n\n";
627  eigen_internal_assert((tmp1 - tmp2).matrix().norm() < 1e-14 * tmp2.matrix().norm());
628 // eigen_internal_assert(count<681);
629 // eigen_internal_assert(((tmp1-tmp2).abs()<1e-13*tmp2.abs()).all());
630 #endif
631 
632  // Third part: compute SVD of combined matrix
633  MatrixXr UofSVD, VofSVD;
634  VectorType singVals;
635  computeSVDofM(firstCol + shift, n, UofSVD, singVals, VofSVD);
636 
637 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
638  eigen_internal_assert(UofSVD.allFinite());
639  eigen_internal_assert(VofSVD.allFinite());
640 #endif
641 
642  if (m_compU)
643  structured_update(m_naiveU.block(firstCol, firstCol, n + 1, n + 1), UofSVD, (n + 2) / 2);
644  else {
645  Map<Matrix<RealScalar, 2, Dynamic>, Aligned> tmp(m_workspace.data(), 2, n + 1);
646  tmp.noalias() = m_naiveU.middleCols(firstCol, n + 1) * UofSVD;
647  m_naiveU.middleCols(firstCol, n + 1) = tmp;
648  }
649 
650  if (m_compV) structured_update(m_naiveV.block(firstRowW, firstColW, n, n), VofSVD, (n + 1) / 2);
651 
652 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
653  eigen_internal_assert(m_naiveU.allFinite());
654  eigen_internal_assert(m_naiveV.allFinite());
655  eigen_internal_assert(m_computed.allFinite());
656 #endif
657 
658  m_computed.block(firstCol + shift, firstCol + shift, n, n).setZero();
659  m_computed.block(firstCol + shift, firstCol + shift, n, n).diagonal() = singVals;
660 } // end divide
661 
662 // Compute SVD of m_computed.block(firstCol, firstCol, n + 1, n); this block only has non-zeros in
663 // the first column and on the diagonal and has undergone deflation, so diagonal is in increasing
664 // order except for possibly the (0,0) entry. The computed SVD is stored U, singVals and V, except
665 // that if m_compV is false, then V is not computed. Singular values are sorted in decreasing order.
666 //
667 // TODO Opportunities for optimization: better root finding algo, better stopping criterion, better
668 // handling of round-off errors, be consistent in ordering
669 // For instance, to solve the secular equation using FMM, see
670 // http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf
671 template <typename MatrixType, int Options>
673  MatrixXr& V) {
674  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
675  using std::abs;
676  ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n);
677  m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal();
678  ArrayRef diag = m_workspace.head(n);
679  diag(0) = Literal(0);
680 
681  // Allocate space for singular values and vectors
682  singVals.resize(n);
683  U.resize(n + 1, n + 1);
684  if (m_compV) V.resize(n, n);
685 
686 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
687  if (col0.hasNaN() || diag.hasNaN()) std::cout << "\n\nHAS NAN\n\n";
688 #endif
689 
690  // Many singular values might have been deflated, the zero ones have been moved to the end,
691  // but others are interleaved and we must ignore them at this stage.
692  // To this end, let's compute a permutation skipping them:
693  Index actual_n = n;
694  while (actual_n > 1 && numext::is_exactly_zero(diag(actual_n - 1))) {
695  --actual_n;
697  }
698  Index m = 0; // size of the deflated problem
699  for (Index k = 0; k < actual_n; ++k)
700  if (abs(col0(k)) > considerZero) m_workspaceI(m++) = k;
701  Map<ArrayXi> perm(m_workspaceI.data(), m);
702 
703  Map<ArrayXr> shifts(m_workspace.data() + 1 * n, n);
704  Map<ArrayXr> mus(m_workspace.data() + 2 * n, n);
705  Map<ArrayXr> zhat(m_workspace.data() + 3 * n, n);
706 
707 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
708  std::cout << "computeSVDofM using:\n";
709  std::cout << " z: " << col0.transpose() << "\n";
710  std::cout << " d: " << diag.transpose() << "\n";
711 #endif
712 
713  // Compute singVals, shifts, and mus
714  computeSingVals(col0, diag, perm, singVals, shifts, mus);
715 
716 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
717  std::cout << " j: "
718  << (m_computed.block(firstCol, firstCol, n, n)).jacobiSvd().singularValues().transpose().reverse()
719  << "\n\n";
720  std::cout << " sing-val: " << singVals.transpose() << "\n";
721  std::cout << " mu: " << mus.transpose() << "\n";
722  std::cout << " shift: " << shifts.transpose() << "\n";
723 
724  {
725  std::cout << "\n\n mus: " << mus.head(actual_n).transpose() << "\n\n";
726  std::cout << " check1 (expect0) : "
727  << ((singVals.array() - (shifts + mus)) / singVals.array()).head(actual_n).transpose() << "\n\n";
728  eigen_internal_assert((((singVals.array() - (shifts + mus)) / singVals.array()).head(actual_n) >= 0).all());
729  std::cout << " check2 (>0) : " << ((singVals.array() - diag) / singVals.array()).head(actual_n).transpose()
730  << "\n\n";
731  eigen_internal_assert((((singVals.array() - diag) / singVals.array()).head(actual_n) >= 0).all());
732  }
733 #endif
734 
735 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
736  eigen_internal_assert(singVals.allFinite());
737  eigen_internal_assert(mus.allFinite());
738  eigen_internal_assert(shifts.allFinite());
739 #endif
740 
741  // Compute zhat
742  perturbCol0(col0, diag, perm, singVals, shifts, mus, zhat);
743 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
744  std::cout << " zhat: " << zhat.transpose() << "\n";
745 #endif
746 
747 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
748  eigen_internal_assert(zhat.allFinite());
749 #endif
750 
751  computeSingVecs(zhat, diag, perm, singVals, shifts, mus, U, V);
752 
753 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
754  std::cout << "U^T U: " << (U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(), U.cols()))).norm() << "\n";
755  std::cout << "V^T V: " << (V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(), V.cols()))).norm() << "\n";
756 #endif
757 
758 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
759  eigen_internal_assert(m_naiveU.allFinite());
760  eigen_internal_assert(m_naiveV.allFinite());
761  eigen_internal_assert(m_computed.allFinite());
762  eigen_internal_assert(U.allFinite());
763  eigen_internal_assert(V.allFinite());
764 // eigen_internal_assert((U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() <
765 // 100*NumTraits<RealScalar>::epsilon() * n); eigen_internal_assert((V.transpose() * V -
766 // MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() < 100*NumTraits<RealScalar>::epsilon() * n);
767 #endif
768 
769  // Because of deflation, the singular values might not be completely sorted.
770  // Fortunately, reordering them is a O(n) problem
771  for (Index i = 0; i < actual_n - 1; ++i) {
772  if (singVals(i) > singVals(i + 1)) {
773  using std::swap;
774  swap(singVals(i), singVals(i + 1));
775  U.col(i).swap(U.col(i + 1));
776  if (m_compV) V.col(i).swap(V.col(i + 1));
777  }
778  }
779 
780 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
781  {
782  bool singular_values_sorted =
783  (((singVals.segment(1, actual_n - 1) - singVals.head(actual_n - 1))).array() >= 0).all();
784  if (!singular_values_sorted)
785  std::cout << "Singular values are not sorted: " << singVals.segment(1, actual_n).transpose() << "\n";
786  eigen_internal_assert(singular_values_sorted);
787  }
788 #endif
789 
790  // Reverse order so that singular values in increased order
791  // Because of deflation, the zeros singular-values are already at the end
792  singVals.head(actual_n).reverseInPlace();
793  U.leftCols(actual_n).rowwise().reverseInPlace();
794  if (m_compV) V.leftCols(actual_n).rowwise().reverseInPlace();
795 
796 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
797  JacobiSVD<MatrixXr> jsvd(m_computed.block(firstCol, firstCol, n, n));
798  std::cout << " * j: " << jsvd.singularValues().transpose() << "\n\n";
799  std::cout << " * sing-val: " << singVals.transpose() << "\n";
800 // std::cout << " * err: " << ((jsvd.singularValues()-singVals)>1e-13*singVals.norm()).transpose() << "\n";
801 #endif
802 }
803 
804 template <typename MatrixType, int Options>
806  RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const ArrayRef& diagShifted,
807  RealScalar shift) {
808  Index m = perm.size();
809  RealScalar res = Literal(1);
810  for (Index i = 0; i < m; ++i) {
811  Index j = perm(i);
812  // The following expression could be rewritten to involve only a single division,
813  // but this would make the expression more sensitive to overflow.
814  res += (col0(j) / (diagShifted(j) - mu)) * (col0(j) / (diag(j) + shift + mu));
815  }
816  return res;
817 }
818 
819 template <typename MatrixType, int Options>
821  VectorType& singVals, ArrayRef shifts, ArrayRef mus) {
822  using std::abs;
823  using std::sqrt;
824  using std::swap;
825 
826  Index n = col0.size();
827  Index actual_n = n;
828  // Note that here actual_n is computed based on col0(i)==0 instead of diag(i)==0 as above
829  // because 1) we have diag(i)==0 => col0(i)==0 and 2) if col0(i)==0, then diag(i) is already a singular value.
830  while (actual_n > 1 && numext::is_exactly_zero(col0(actual_n - 1))) --actual_n;
831 
832  for (Index k = 0; k < n; ++k) {
833  if (numext::is_exactly_zero(col0(k)) || actual_n == 1) {
834  // if col0(k) == 0, then entry is deflated, so singular value is on diagonal
835  // if actual_n==1, then the deflated problem is already diagonalized
836  singVals(k) = k == 0 ? col0(0) : diag(k);
837  mus(k) = Literal(0);
838  shifts(k) = k == 0 ? col0(0) : diag(k);
839  continue;
840  }
841 
842  // otherwise, use secular equation to find singular value
843  RealScalar left = diag(k);
844  RealScalar right; // was: = (k != actual_n-1) ? diag(k+1) : (diag(actual_n-1) + col0.matrix().norm());
845  if (k == actual_n - 1)
846  right = (diag(actual_n - 1) + col0.matrix().norm());
847  else {
848  // Skip deflated singular values,
849  // recall that at this stage we assume that z[j]!=0 and all entries for which z[j]==0 have been put aside.
850  // This should be equivalent to using perm[]
851  Index l = k + 1;
852  while (numext::is_exactly_zero(col0(l))) {
853  ++l;
855  }
856  right = diag(l);
857  }
858 
859  // first decide whether it's closer to the left end or the right end
860  RealScalar mid = left + (right - left) / Literal(2);
861  RealScalar fMid = secularEq(mid, col0, diag, perm, diag, Literal(0));
862 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
863  std::cout << "right-left = " << right - left << "\n";
864  // std::cout << "fMid = " << fMid << " " << secularEq(mid-left, col0, diag, perm, ArrayXr(diag-left), left)
865  // << " " << secularEq(mid-right, col0, diag, perm, ArrayXr(diag-right), right) <<
866  // "\n";
867  std::cout << " = " << secularEq(left + RealScalar(0.000001) * (right - left), col0, diag, perm, diag, 0) << " "
868  << secularEq(left + RealScalar(0.1) * (right - left), col0, diag, perm, diag, 0) << " "
869  << secularEq(left + RealScalar(0.2) * (right - left), col0, diag, perm, diag, 0) << " "
870  << secularEq(left + RealScalar(0.3) * (right - left), col0, diag, perm, diag, 0) << " "
871  << secularEq(left + RealScalar(0.4) * (right - left), col0, diag, perm, diag, 0) << " "
872  << secularEq(left + RealScalar(0.49) * (right - left), col0, diag, perm, diag, 0) << " "
873  << secularEq(left + RealScalar(0.5) * (right - left), col0, diag, perm, diag, 0) << " "
874  << secularEq(left + RealScalar(0.51) * (right - left), col0, diag, perm, diag, 0) << " "
875  << secularEq(left + RealScalar(0.6) * (right - left), col0, diag, perm, diag, 0) << " "
876  << secularEq(left + RealScalar(0.7) * (right - left), col0, diag, perm, diag, 0) << " "
877  << secularEq(left + RealScalar(0.8) * (right - left), col0, diag, perm, diag, 0) << " "
878  << secularEq(left + RealScalar(0.9) * (right - left), col0, diag, perm, diag, 0) << " "
879  << secularEq(left + RealScalar(0.999999) * (right - left), col0, diag, perm, diag, 0) << "\n";
880 #endif
881  RealScalar shift = (k == actual_n - 1 || fMid > Literal(0)) ? left : right;
882 
883  // measure everything relative to shift
884  Map<ArrayXr> diagShifted(m_workspace.data() + 4 * n, n);
885  diagShifted = diag - shift;
886 
887  if (k != actual_n - 1) {
888  // check that after the shift, f(mid) is still negative:
889  RealScalar midShifted = (right - left) / RealScalar(2);
890  // we can test exact equality here, because shift comes from `... ? left : right`
891  if (numext::equal_strict(shift, right)) midShifted = -midShifted;
892  RealScalar fMidShifted = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
893  if (fMidShifted > 0) {
894  // fMid was erroneous, fix it:
895  shift = fMidShifted > Literal(0) ? left : right;
896  diagShifted = diag - shift;
897  }
898  }
899 
900  // initial guess
901  RealScalar muPrev, muCur;
902  // we can test exact equality here, because shift comes from `... ? left : right`
903  if (numext::equal_strict(shift, left)) {
904  muPrev = (right - left) * RealScalar(0.1);
905  if (k == actual_n - 1)
906  muCur = right - left;
907  else
908  muCur = (right - left) * RealScalar(0.5);
909  } else {
910  muPrev = -(right - left) * RealScalar(0.1);
911  muCur = -(right - left) * RealScalar(0.5);
912  }
913 
914  RealScalar fPrev = secularEq(muPrev, col0, diag, perm, diagShifted, shift);
915  RealScalar fCur = secularEq(muCur, col0, diag, perm, diagShifted, shift);
916  if (abs(fPrev) < abs(fCur)) {
917  swap(fPrev, fCur);
918  swap(muPrev, muCur);
919  }
920 
921  // rational interpolation: fit a function of the form a / mu + b through the two previous
922  // iterates and use its zero to compute the next iterate
923  bool useBisection = fPrev * fCur > Literal(0);
924  while (!numext::is_exactly_zero(fCur) &&
925  abs(muCur - muPrev) >
926  Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) &&
927  abs(fCur - fPrev) > NumTraits<RealScalar>::epsilon() && !useBisection) {
928  ++m_numIters;
929 
930  // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples.
931  RealScalar a = (fCur - fPrev) / (Literal(1) / muCur - Literal(1) / muPrev);
932  RealScalar b = fCur - a / muCur;
933  // And find mu such that f(mu)==0:
934  RealScalar muZero = -a / b;
935  RealScalar fZero = secularEq(muZero, col0, diag, perm, diagShifted, shift);
936 
937 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
939 #endif
940 
941  muPrev = muCur;
942  fPrev = fCur;
943  muCur = muZero;
944  fCur = fZero;
945 
946  // we can test exact equality here, because shift comes from `... ? left : right`
947  if (numext::equal_strict(shift, left) && (muCur < Literal(0) || muCur > right - left)) useBisection = true;
948  if (numext::equal_strict(shift, right) && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true;
949  if (abs(fCur) > abs(fPrev)) useBisection = true;
950  }
951 
952  // fall back on bisection method if rational interpolation did not work
953  if (useBisection) {
954 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
955  std::cout << "useBisection for k = " << k << ", actual_n = " << actual_n << "\n";
956 #endif
957  RealScalar leftShifted, rightShifted;
958  // we can test exact equality here, because shift comes from `... ? left : right`
959  if (numext::equal_strict(shift, left)) {
960  // to avoid overflow, we must have mu > max(real_min, |z(k)|/sqrt(real_max)),
961  // the factor 2 is to be more conservative
962  leftShifted =
963  numext::maxi<RealScalar>((std::numeric_limits<RealScalar>::min)(),
965 
966  // check that we did it right:
968  (numext::isfinite)((col0(k) / leftShifted) * (col0(k) / (diag(k) + shift + leftShifted))));
969  // I don't understand why the case k==0 would be special there:
970  // if (k == 0) rightShifted = right - left; else
971  rightShifted = (k == actual_n - 1)
972  ? right
973  : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe
974  } else {
975  leftShifted = -(right - left) * RealScalar(0.51);
976  if (k + 1 < n)
977  rightShifted = -numext::maxi<RealScalar>((std::numeric_limits<RealScalar>::min)(),
978  abs(col0(k + 1)) / sqrt((std::numeric_limits<RealScalar>::max)()));
979  else
980  rightShifted = -(std::numeric_limits<RealScalar>::min)();
981  }
982 
983  RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift);
984  eigen_internal_assert(fLeft < Literal(0));
985 
986 #if defined EIGEN_BDCSVD_DEBUG_VERBOSE || defined EIGEN_BDCSVD_SANITY_CHECKS || defined EIGEN_INTERNAL_DEBUGGING
987  RealScalar fRight = secularEq(rightShifted, col0, diag, perm, diagShifted, shift);
988 #endif
989 
990 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
991  if (!(numext::isfinite)(fLeft))
992  std::cout << "f(" << leftShifted << ") =" << fLeft << " ; " << left << " " << shift << " " << right << "\n";
994 
995  if (!(numext::isfinite)(fRight))
996  std::cout << "f(" << rightShifted << ") =" << fRight << " ; " << left << " " << shift << " " << right << "\n";
997  // eigen_internal_assert((numext::isfinite)(fRight));
998 #endif
999 
1000 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1001  if (!(fLeft * fRight < 0)) {
1002  std::cout << "f(leftShifted) using leftShifted=" << leftShifted
1003  << " ; diagShifted(1:10):" << diagShifted.head(10).transpose() << "\n ; "
1004  << "left==shift=" << bool(left == shift) << " ; left-shift = " << (left - shift) << "\n";
1005  std::cout << "k=" << k << ", " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; "
1006  << "[" << left << " .. " << right << "] -> [" << leftShifted << " " << rightShifted
1007  << "], shift=" << shift << " , f(right)=" << secularEq(0, col0, diag, perm, diagShifted, shift)
1008  << " == " << secularEq(right, col0, diag, perm, diag, 0) << " == " << fRight << "\n";
1009  }
1010 #endif
1011  eigen_internal_assert(fLeft * fRight < Literal(0));
1012 
1013  if (fLeft < Literal(0)) {
1014  while (rightShifted - leftShifted > Literal(2) * NumTraits<RealScalar>::epsilon() *
1015  numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted))) {
1016  RealScalar midShifted = (leftShifted + rightShifted) / Literal(2);
1017  fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
1019 
1020  if (fLeft * fMid < Literal(0)) {
1021  rightShifted = midShifted;
1022  } else {
1023  leftShifted = midShifted;
1024  fLeft = fMid;
1025  }
1026  }
1027  muCur = (leftShifted + rightShifted) / Literal(2);
1028  } else {
1029  // We have a problem as shifting on the left or right give either a positive or negative value
1030  // at the middle of [left,right]...
1031  // Instead of abbording or entering an infinite loop,
1032  // let's just use the middle as the estimated zero-crossing:
1033  muCur = (right - left) * RealScalar(0.5);
1034  // we can test exact equality here, because shift comes from `... ? left : right`
1035  if (numext::equal_strict(shift, right)) muCur = -muCur;
1036  }
1037  }
1038 
1039  singVals[k] = shift + muCur;
1040  shifts[k] = shift;
1041  mus[k] = muCur;
1042 
1043 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1044  if (k + 1 < n)
1045  std::cout << "found " << singVals[k] << " == " << shift << " + " << muCur << " from " << diag(k) << " .. "
1046  << diag(k + 1) << "\n";
1047 #endif
1048 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1049  eigen_internal_assert(k == 0 || singVals[k] >= singVals[k - 1]);
1050  eigen_internal_assert(singVals[k] >= diag(k));
1051 #endif
1052 
1053  // perturb singular value slightly if it equals diagonal entry to avoid division by zero later
1054  // (deflation is supposed to avoid this from happening)
1055  // - this does no seem to be necessary anymore -
1056  // if (singVals[k] == left) singVals[k] *= 1 + NumTraits<RealScalar>::epsilon();
1057  // if (singVals[k] == right) singVals[k] *= 1 - NumTraits<RealScalar>::epsilon();
1058  }
1059 }
1060 
1061 // zhat is perturbation of col0 for which singular vectors can be computed stably (see Section 3.1)
1062 template <typename MatrixType, int Options>
1064  const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus,
1065  ArrayRef zhat) {
1066  using std::sqrt;
1067  Index n = col0.size();
1068  Index m = perm.size();
1069  if (m == 0) {
1070  zhat.setZero();
1071  return;
1072  }
1073  Index lastIdx = perm(m - 1);
1074  // The offset permits to skip deflated entries while computing zhat
1075  for (Index k = 0; k < n; ++k) {
1076  if (numext::is_exactly_zero(col0(k))) // deflated
1077  zhat(k) = Literal(0);
1078  else {
1079  // see equation (3.6)
1080  RealScalar dk = diag(k);
1081  RealScalar prod = (singVals(lastIdx) + dk) * (mus(lastIdx) + (shifts(lastIdx) - dk));
1082 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1083  if (prod < 0) {
1084  std::cout << "k = " << k << " ; z(k)=" << col0(k) << ", diag(k)=" << dk << "\n";
1085  std::cout << "prod = "
1086  << "(" << singVals(lastIdx) << " + " << dk << ") * (" << mus(lastIdx) << " + (" << shifts(lastIdx)
1087  << " - " << dk << "))"
1088  << "\n";
1089  std::cout << " = " << singVals(lastIdx) + dk << " * " << mus(lastIdx) + (shifts(lastIdx) - dk) << "\n";
1090  }
1092 #endif
1093 
1094  for (Index l = 0; l < m; ++l) {
1095  Index i = perm(l);
1096  if (i != k) {
1097 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1098  if (i >= k && (l == 0 || l - 1 >= m)) {
1099  std::cout << "Error in perturbCol0\n";
1100  std::cout << " " << k << "/" << n << " " << l << "/" << m << " " << i << "/" << n << " ; " << col0(k)
1101  << " " << diag(k) << " "
1102  << "\n";
1103  std::cout << " " << diag(i) << "\n";
1104  Index j = (i < k /*|| l==0*/) ? i : perm(l - 1);
1105  std::cout << " "
1106  << "j=" << j << "\n";
1107  }
1108 #endif
1109  Index j = i < k ? i : l > 0 ? perm(l - 1) : i;
1110 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1111  if (!(dk != Literal(0) || diag(i) != Literal(0))) {
1112  std::cout << "k=" << k << ", i=" << i << ", l=" << l << ", perm.size()=" << perm.size() << "\n";
1113  }
1114  eigen_internal_assert(dk != Literal(0) || diag(i) != Literal(0));
1115 #endif
1116  prod *= ((singVals(j) + dk) / ((diag(i) + dk))) * ((mus(j) + (shifts(j) - dk)) / ((diag(i) - dk)));
1117 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1119 #endif
1120 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1121  if (i != k &&
1122  numext::abs(((singVals(j) + dk) * (mus(j) + (shifts(j) - dk))) / ((diag(i) + dk) * (diag(i) - dk)) - 1) >
1123  0.9)
1124  std::cout << " "
1125  << ((singVals(j) + dk) * (mus(j) + (shifts(j) - dk))) / ((diag(i) + dk) * (diag(i) - dk))
1126  << " == (" << (singVals(j) + dk) << " * " << (mus(j) + (shifts(j) - dk)) << ") / ("
1127  << (diag(i) + dk) << " * " << (diag(i) - dk) << ")\n";
1128 #endif
1129  }
1130  }
1131 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1132  std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(lastIdx) + dk) << " * "
1133  << mus(lastIdx) + shifts(lastIdx) << " - " << dk << "\n";
1134 #endif
1135  RealScalar tmp = sqrt(prod);
1136 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1138 #endif
1139  zhat(k) = col0(k) > Literal(0) ? RealScalar(tmp) : RealScalar(-tmp);
1140  }
1141  }
1142 }
1143 
1144 // compute singular vectors
1145 template <typename MatrixType, int Options>
1147  const VectorType& singVals, const ArrayRef& shifts,
1148  const ArrayRef& mus, MatrixXr& U, MatrixXr& V) {
1149  Index n = zhat.size();
1150  Index m = perm.size();
1151 
1152  for (Index k = 0; k < n; ++k) {
1153  if (numext::is_exactly_zero(zhat(k))) {
1154  U.col(k) = VectorType::Unit(n + 1, k);
1155  if (m_compV) V.col(k) = VectorType::Unit(n, k);
1156  } else {
1157  U.col(k).setZero();
1158  for (Index l = 0; l < m; ++l) {
1159  Index i = perm(l);
1160  U(i, k) = zhat(i) / (((diag(i) - shifts(k)) - mus(k))) / ((diag(i) + singVals[k]));
1161  }
1162  U(n, k) = Literal(0);
1163  U.col(k).normalize();
1164 
1165  if (m_compV) {
1166  V.col(k).setZero();
1167  for (Index l = 1; l < m; ++l) {
1168  Index i = perm(l);
1169  V(i, k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k))) / ((diag(i) + singVals[k]));
1170  }
1171  V(0, k) = Literal(-1);
1172  V.col(k).normalize();
1173  }
1174  }
1175  }
1176  U.col(n) = VectorType::Unit(n + 1, n);
1177 }
1178 
1179 // page 12_13
1180 // i >= 1, di almost null and zi non null.
1181 // We use a rotation to zero out zi applied to the left of M, and set di = 0.
1182 template <typename MatrixType, int Options>
1184  using std::abs;
1185  using std::pow;
1186  using std::sqrt;
1187  Index start = firstCol + shift;
1188  RealScalar c = m_computed(start, start);
1189  RealScalar s = m_computed(start + i, start);
1190  RealScalar r = numext::hypot(c, s);
1191  if (numext::is_exactly_zero(r)) {
1192  m_computed(start + i, start + i) = Literal(0);
1193  return;
1194  }
1195  m_computed(start, start) = r;
1196  m_computed(start + i, start) = Literal(0);
1197  m_computed(start + i, start + i) = Literal(0);
1198 
1199  JacobiRotation<RealScalar> J(c / r, -s / r);
1200  if (m_compU)
1201  m_naiveU.middleRows(firstCol, size + 1).applyOnTheRight(firstCol, firstCol + i, J);
1202  else
1203  m_naiveU.applyOnTheRight(firstCol, firstCol + i, J);
1204 } // end deflation 43
1205 
1206 // page 13
1207 // i,j >= 1, i > j, and |di - dj| < epsilon * norm2(M)
1208 // We apply two rotations to have zi = 0, and dj = di.
1209 template <typename MatrixType, int Options>
1210 void BDCSVD<MatrixType, Options>::deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW,
1211  Index i, Index j, Index size) {
1212  using std::abs;
1213  using std::conj;
1214  using std::pow;
1215  using std::sqrt;
1216 
1217  RealScalar s = m_computed(firstColm + i, firstColm);
1218  RealScalar c = m_computed(firstColm + j, firstColm);
1219  RealScalar r = numext::hypot(c, s);
1220 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1221  std::cout << "deflation 4.4: " << i << "," << j << " -> " << c << " " << s << " " << r << " ; "
1222  << m_computed(firstColm + i - 1, firstColm) << " " << m_computed(firstColm + i, firstColm) << " "
1223  << m_computed(firstColm + i + 1, firstColm) << " " << m_computed(firstColm + i + 2, firstColm) << "\n";
1224  std::cout << m_computed(firstColm + i - 1, firstColm + i - 1) << " " << m_computed(firstColm + i, firstColm + i)
1225  << " " << m_computed(firstColm + i + 1, firstColm + i + 1) << " "
1226  << m_computed(firstColm + i + 2, firstColm + i + 2) << "\n";
1227 #endif
1228  if (numext::is_exactly_zero(r)) {
1229  m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
1230  return;
1231  }
1232  c /= r;
1233  s /= r;
1234  m_computed(firstColm + j, firstColm) = r;
1235  m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
1236  m_computed(firstColm + i, firstColm) = Literal(0);
1237 
1239  if (m_compU)
1240  m_naiveU.middleRows(firstColu, size + 1).applyOnTheRight(firstColu + j, firstColu + i, J);
1241  else
1242  m_naiveU.applyOnTheRight(firstColu + j, firstColu + i, J);
1243  if (m_compV) m_naiveV.middleRows(firstRowW, size).applyOnTheRight(firstColW + j, firstColW + i, J);
1244 } // end deflation 44
1245 
1246 // acts on block from (firstCol+shift, firstCol+shift) to (lastCol+shift, lastCol+shift) [inclusive]
1247 template <typename MatrixType, int Options>
1248 void BDCSVD<MatrixType, Options>::deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW,
1249  Index shift) {
1250  using std::abs;
1251  using std::sqrt;
1252  const Index length = lastCol + 1 - firstCol;
1253 
1254  Block<MatrixXr, Dynamic, 1> col0(m_computed, firstCol + shift, firstCol + shift, length, 1);
1255  Diagonal<MatrixXr> fulldiag(m_computed);
1256  VectorBlock<Diagonal<MatrixXr>, Dynamic> diag(fulldiag, firstCol + shift, length);
1257 
1258  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
1259  RealScalar maxDiag = diag.tail((std::max)(Index(1), length - 1)).cwiseAbs().maxCoeff();
1260  RealScalar epsilon_strict = numext::maxi<RealScalar>(considerZero, NumTraits<RealScalar>::epsilon() * maxDiag);
1261  RealScalar epsilon_coarse =
1262  Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
1263 
1264 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1265  eigen_internal_assert(m_naiveU.allFinite());
1266  eigen_internal_assert(m_naiveV.allFinite());
1267  eigen_internal_assert(m_computed.allFinite());
1268 #endif
1269 
1270 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1271  std::cout << "\ndeflate:" << diag.head(k + 1).transpose() << " | "
1272  << diag.segment(k + 1, length - k - 1).transpose() << "\n";
1273 #endif
1274 
1275  // condition 4.1
1276  if (diag(0) < epsilon_coarse) {
1277 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1278  std::cout << "deflation 4.1, because " << diag(0) << " < " << epsilon_coarse << "\n";
1279 #endif
1280  diag(0) = epsilon_coarse;
1281  }
1282 
1283  // condition 4.2
1284  for (Index i = 1; i < length; ++i)
1285  if (abs(col0(i)) < epsilon_strict) {
1286 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1287  std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict
1288  << " (diag(" << i << ")=" << diag(i) << ")\n";
1289 #endif
1290  col0(i) = Literal(0);
1291  }
1292 
1293  // condition 4.3
1294  for (Index i = 1; i < length; i++)
1295  if (diag(i) < epsilon_coarse) {
1296 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1297  std::cout << "deflation 4.3, cancel z(" << i << ")=" << col0(i) << " because diag(" << i << ")=" << diag(i)
1298  << " < " << epsilon_coarse << "\n";
1299 #endif
1300  deflation43(firstCol, shift, i, length);
1301  }
1302 
1303 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1304  eigen_internal_assert(m_naiveU.allFinite());
1305  eigen_internal_assert(m_naiveV.allFinite());
1306  eigen_internal_assert(m_computed.allFinite());
1307 #endif
1308 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1309  std::cout << "to be sorted: " << diag.transpose() << "\n\n";
1310  std::cout << " : " << col0.transpose() << "\n\n";
1311 #endif
1312  {
1313  // Check for total deflation:
1314  // If we have a total deflation, then we have to consider col0(0)==diag(0) as a singular value during sorting.
1315  const bool total_deflation = (col0.tail(length - 1).array().abs() < considerZero).all();
1316 
1317  // Sort the diagonal entries, since diag(1:k-1) and diag(k:length) are already sorted, let's do a sorted merge.
1318  // First, compute the respective permutation.
1319  Index* permutation = m_workspaceI.data();
1320  {
1321  permutation[0] = 0;
1322  Index p = 1;
1323 
1324  // Move deflated diagonal entries at the end.
1325  for (Index i = 1; i < length; ++i)
1326  if (diag(i) < considerZero) permutation[p++] = i;
1327 
1328  Index i = 1, j = k + 1;
1329  for (; p < length; ++p) {
1330  if (i > k)
1331  permutation[p] = j++;
1332  else if (j >= length)
1333  permutation[p] = i++;
1334  else if (diag(i) < diag(j))
1335  permutation[p] = j++;
1336  else
1337  permutation[p] = i++;
1338  }
1339  }
1340 
1341  // If we have a total deflation, then we have to insert diag(0) at the right place
1342  if (total_deflation) {
1343  for (Index i = 1; i < length; ++i) {
1344  Index pi = permutation[i];
1345  if (diag(pi) < considerZero || diag(0) < diag(pi))
1346  permutation[i - 1] = permutation[i];
1347  else {
1348  permutation[i - 1] = 0;
1349  break;
1350  }
1351  }
1352  }
1353 
1354  // Current index of each col, and current column of each index
1355  Index* realInd = m_workspaceI.data() + length;
1356  Index* realCol = m_workspaceI.data() + 2 * length;
1357 
1358  for (int pos = 0; pos < length; pos++) {
1359  realCol[pos] = pos;
1360  realInd[pos] = pos;
1361  }
1362 
1363  for (Index i = total_deflation ? 0 : 1; i < length; i++) {
1364  const Index pi = permutation[length - (total_deflation ? i + 1 : i)];
1365  const Index J = realCol[pi];
1366 
1367  using std::swap;
1368  // swap diagonal and first column entries:
1369  swap(diag(i), diag(J));
1370  if (i != 0 && J != 0) swap(col0(i), col0(J));
1371 
1372  // change columns
1373  if (m_compU)
1374  m_naiveU.col(firstCol + i)
1375  .segment(firstCol, length + 1)
1376  .swap(m_naiveU.col(firstCol + J).segment(firstCol, length + 1));
1377  else
1378  m_naiveU.col(firstCol + i).segment(0, 2).swap(m_naiveU.col(firstCol + J).segment(0, 2));
1379  if (m_compV)
1380  m_naiveV.col(firstColW + i)
1381  .segment(firstRowW, length)
1382  .swap(m_naiveV.col(firstColW + J).segment(firstRowW, length));
1383 
1384  // update real pos
1385  const Index realI = realInd[i];
1386  realCol[realI] = J;
1387  realCol[pi] = i;
1388  realInd[J] = realI;
1389  realInd[i] = pi;
1390  }
1391  }
1392 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1393  std::cout << "sorted: " << diag.transpose().format(bdcsvdfmt) << "\n";
1394  std::cout << " : " << col0.transpose() << "\n\n";
1395 #endif
1396 
1397  // condition 4.4
1398  {
1399  Index i = length - 1;
1400  // Find last non-deflated entry.
1401  while (i > 0 && (diag(i) < considerZero || abs(col0(i)) < considerZero)) --i;
1402 
1403  for (; i > 1; --i)
1404  if ((diag(i) - diag(i - 1)) < epsilon_strict) {
1405 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1406  std::cout << "deflation 4.4 with i = " << i << " because " << diag(i) << " - " << diag(i - 1)
1407  << " == " << (diag(i) - diag(i - 1)) << " < " << epsilon_strict << "\n";
1408 #endif
1409  eigen_internal_assert(abs(diag(i) - diag(i - 1)) < epsilon_coarse &&
1410  " diagonal entries are not properly sorted");
1411  deflation44(firstCol, firstCol + shift, firstRowW, firstColW, i, i - 1, length);
1412  }
1413  }
1414 
1415 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1416  for (Index j = 2; j < length; ++j) eigen_internal_assert(diag(j - 1) <= diag(j) || abs(diag(j)) < considerZero);
1417 #endif
1418 
1419 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1420  eigen_internal_assert(m_naiveU.allFinite());
1421  eigen_internal_assert(m_naiveV.allFinite());
1422  eigen_internal_assert(m_computed.allFinite());
1423 #endif
1424 } // end deflation
1425 
1432 template <typename Derived>
1433 template <int Options>
1435  return BDCSVD<PlainObject, Options>(*this);
1436 }
1437 
1444 template <typename Derived>
1445 template <int Options>
1447  unsigned int computationOptions) const {
1448  return BDCSVD<PlainObject, Options>(*this, computationOptions);
1449 }
1450 
1451 } // end namespace Eigen
1452 
1453 #endif
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar conj(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:133
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
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
Definition: ComplexEigenSolver_compute.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
MatrixXcd V
Definition: EigenSolver_EigenSolver_MatrixType.cpp:15
cout<< "Here is the matrix m:"<< endl<< m<< endl;JacobiSVD< MatrixXf, ComputeThinU|ComputeThinV > svd(m)
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
#define EIGEN_DEPRECATED
Definition: Macros.h:931
#define eigen_internal_assert(x)
Definition: Macros.h:916
#define eigen_assert(x)
Definition: Macros.h:910
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
Definition: PartialRedux_count.cpp:3
float * p
Definition: Tutorial_Map_using.cpp:9
int rows
Definition: Tutorial_commainit_02.cpp:1
int cols
Definition: Tutorial_commainit_02.cpp:1
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
Scalar * b
Definition: benchVecAdd.cpp:17
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:48
class Bidiagonal Divide and Conquer SVD
Definition: BDCSVD.h:85
Index m_nRec
Definition: BDCSVD.h:241
void allocate(Index rows, Index cols, unsigned int computationOptions)
Definition: BDCSVD.h:268
void structured_update(Block< MatrixXr, Dynamic, Dynamic > A, const MatrixXr &B, Index n1)
Definition: BDCSVD.h:443
void copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naivev)
Definition: BDCSVD.h:407
bool m_isTranspose
Definition: BDCSVD.h:245
Ref< ArrayXi > IndicesRef
Definition: BDCSVD.h:123
Base::MatrixUType MatrixUType
Definition: BDCSVD.h:113
BDCSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix. Computes Thin/Full unitaries U/V if specified us...
Definition: BDCSVD.h:194
ArrayXi m_workspaceI
Definition: BDCSVD.h:243
Base::SingularValuesType SingularValuesType
Definition: BDCSVD.h:115
EIGEN_DEPRECATED BDCSVD(const MatrixType &matrix, unsigned int computationOptions)
Constructor performing the decomposition of given matrix using specified options for computing unitar...
Definition: BDCSVD.h:182
BDCSVD & compute_impl(const MatrixType &matrix, unsigned int computationOptions)
Definition: BDCSVD.h:308
Base::RealScalar RealScalar
Definition: BDCSVD.h:97
void computeBaseCase(SVDType &svd, Index n, Index firstCol, Index firstRowW, Index firstColW, Index shift)
Definition: BDCSVD.h:478
NumTraits< RealScalar >::Literal Literal
Definition: BDCSVD.h:98
bool m_useQrDecomp
Definition: BDCSVD.h:245
Base::Index Index
Definition: BDCSVD.h:99
Array< Index, 1, Dynamic > ArrayXi
Definition: BDCSVD.h:121
void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift)
Definition: BDCSVD.h:508
void computeSVDofM(Index firstCol, Index n, MatrixXr &U, VectorType &singVals, MatrixXr &V)
Definition: BDCSVD.h:672
@ QRDecomposition
Definition: BDCSVD.h:102
@ DiagSizeAtCompileTime
Definition: BDCSVD.h:106
@ ComputationOptions
Definition: BDCSVD.h:103
@ MaxColsAtCompileTime
Definition: BDCSVD.h:108
@ RowsAtCompileTime
Definition: BDCSVD.h:104
@ ColsAtCompileTime
Definition: BDCSVD.h:105
@ MaxDiagSizeAtCompileTime
Definition: BDCSVD.h:109
@ MatrixOptions
Definition: BDCSVD.h:110
@ MaxRowsAtCompileTime
Definition: BDCSVD.h:107
@ Options
Definition: BDCSVD.h:101
static RealScalar secularEq(RealScalar x, const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, const ArrayRef &diagShifted, RealScalar shift)
Definition: BDCSVD.h:805
MatrixType_ MatrixType
Definition: BDCSVD.h:95
Array< RealScalar, Dynamic, 1 > ArrayXr
Definition: BDCSVD.h:120
void computeSingVecs(const ArrayRef &zhat, const ArrayRef &diag, const IndicesRef &perm, const VectorType &singVals, const ArrayRef &shifts, const ArrayRef &mus, MatrixXr &U, MatrixXr &V)
Definition: BDCSVD.h:1146
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition: EigenBase.h:61
Matrix< RealScalar, Dynamic, Dynamic, ColMajor > MatrixXr
Definition: BDCSVD.h:118
BDCSVD(const MatrixType &matrix)
Constructor performing the decomposition of given matrix, using the custom options specified with the...
Definition: BDCSVD.h:166
void setSwitchSize(int s)
Definition: BDCSVD.h:210
SVDBase< BDCSVD > Base
Definition: BDCSVD.h:86
void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift)
Definition: BDCSVD.h:1248
MatrixX copyWorkspace
Definition: BDCSVD.h:249
JacobiSVD< MatrixType, ComputationOptions > smallSvd
Definition: BDCSVD.h:246
void perturbCol0(const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, const VectorType &singVals, const ArrayRef &shifts, const ArrayRef &mus, ArrayRef zhat)
Definition: BDCSVD.h:1063
MatrixXr m_computed
Definition: BDCSVD.h:240
Matrix< RealScalar, Dynamic, 1 > VectorType
Definition: BDCSVD.h:119
EIGEN_DEPRECATED BDCSVD(Index rows, Index cols, unsigned int computationOptions)
Default Constructor with memory preallocation.
Definition: BDCSVD.h:156
void deflation43(Index firstCol, Index shift, Index i, Index size)
Definition: BDCSVD.h:1183
MatrixXr m_naiveV
Definition: BDCSVD.h:239
int m_numIters
Definition: BDCSVD.h:263
~BDCSVD()
Definition: BDCSVD.h:187
bool m_compU
Definition: BDCSVD.h:245
int m_algoswap
Definition: BDCSVD.h:244
BDCSVD()
Default Constructor.
Definition: BDCSVD.h:130
Matrix< Scalar, Dynamic, Dynamic, ColMajor > MatrixX
Definition: BDCSVD.h:117
MatrixXr m_naiveU
Definition: BDCSVD.h:239
Base::MatrixVType MatrixVType
Definition: BDCSVD.h:114
HouseholderQR< MatrixX > qrDecomp
Definition: BDCSVD.h:247
Base::Scalar Scalar
Definition: BDCSVD.h:96
void computeSingVals(const ArrayRef &col0, const ArrayRef &diag, const IndicesRef &perm, VectorType &singVals, ArrayRef shifts, ArrayRef mus)
Definition: BDCSVD.h:820
bool m_compV
Definition: BDCSVD.h:245
ArrayXr m_workspace
Definition: BDCSVD.h:242
MatrixX reducedTriangle
Definition: BDCSVD.h:250
EIGEN_DEPRECATED BDCSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix, as specified by the computationOptions parameter...
Definition: BDCSVD.h:205
void deflation44(Index firstColu, Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size)
Definition: BDCSVD.h:1210
Ref< ArrayXr > ArrayRef
Definition: BDCSVD.h:122
internal::UpperBidiagonalization< MatrixX > bid
Definition: BDCSVD.h:248
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: EigenBase.h:59
BDCSVD(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition: BDCSVD.h:138
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:110
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition: Diagonal.h:68
Householder QR decomposition of a matrix.
Definition: HouseholderQR.h:59
Rotation given by a cosine-sine pair.
Definition: Jacobi.h:38
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:96
BDCSVD< PlainObject, Options > bdcSvd() const
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: PlainObjectBase.h:191
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:264
Base class of SVD algorithms.
Definition: SVDBase.h:119
Index cols() const
Definition: SVDBase.h:278
internal::make_proper_matrix_type< Scalar, RowsAtCompileTime, MatrixUColsAtCompileTime, MatrixOptions, MaxRowsAtCompileTime, MatrixUMaxColsAtCompileTime >::type MatrixUType
Definition: SVDBase.h:153
ComputationInfo m_info
Definition: SVDBase.h:334
bool m_computeThinU
Definition: SVDBase.h:336
const SingularValuesType & singularValues() const
Definition: SVDBase.h:200
NumTraits< typename MatrixType::Scalar >::Real RealScalar
Definition: SVDBase.h:126
bool computeV() const
Definition: SVDBase.h:275
bool m_isInitialized
Definition: SVDBase.h:335
unsigned int m_computationOptions
Definition: SVDBase.h:338
MatrixVType m_matrixV
Definition: SVDBase.h:332
bool computeU() const
Definition: SVDBase.h:273
internal::plain_diag_type< MatrixType, RealScalar >::type SingularValuesType
Definition: SVDBase.h:158
internal::make_proper_matrix_type< Scalar, ColsAtCompileTime, MatrixVColsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MatrixVMaxColsAtCompileTime >::type MatrixVType
Definition: SVDBase.h:156
@ MatrixOptions
Definition: SVDBase.h:141
@ ColsAtCompileTime
Definition: SVDBase.h:136
@ DiagSizeAtCompileTime
Definition: SVDBase.h:137
@ MaxRowsAtCompileTime
Definition: SVDBase.h:138
@ MaxDiagSizeAtCompileTime
Definition: SVDBase.h:140
@ MaxColsAtCompileTime
Definition: SVDBase.h:139
@ RowsAtCompileTime
Definition: SVDBase.h:135
MatrixType::Scalar Scalar
Definition: SVDBase.h:125
Index m_nonzeroSingularValues
Definition: SVDBase.h:339
Index rows() const
Definition: SVDBase.h:277
SingularValuesType m_singularValues
Definition: SVDBase.h:333
bool m_computeThinV
Definition: SVDBase.h:337
Index diagSize() const
Definition: SVDBase.h:279
internal::traits< BDCSVD< MatrixType_, Options_ > >::MatrixType MatrixType
Definition: SVDBase.h:124
MatrixUType m_matrixU
Definition: SVDBase.h:331
Expression of a fixed-size or dynamic-size sub-vector.
Definition: VectorBlock.h:58
Definition: UpperBidiagonalization.h:24
Definition: matrices.h:74
Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor >, 0, Eigen::OuterStride<> > matrix(T *data, int rows, int cols, int stride)
Definition: common.h:85
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: cxx11_tensor_map.cpp:237
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23
static constexpr Eigen::internal::all_t all
Definition: IndexedViewHelper.h:86
@ Aligned
Definition: Constants.h:242
@ DisableQRDecomposition
Definition: Constants.h:429
@ InvalidInput
Definition: Constants.h:447
@ Success
Definition: Constants.h:440
@ NoConvergence
Definition: Constants.h:444
RealScalar s
Definition: level1_cplx_impl.h:130
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117
const Scalar * a
Definition: level2_cplx_impl.h:32
int * m
Definition: level2_cplx_impl.h:294
actual_n
Definition: level2_impl.h:445
const char const char const char * diag
Definition: level2_impl.h:86
char char char int int * k
Definition: level2_impl.h:374
Eigen::Matrix< Scalar, Dynamic, Dynamic, ColMajor > tmp
Definition: level3_impl.h:365
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
@ QRPreconditionerBits
Definition: SVDBase.h:27
@ ComputationOptionsBits
Definition: SVDBase.h:29
constexpr int get_computation_options(int options)
Definition: SVDBase.h:34
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const X &x, const Y &y)
Definition: Meta.h:571
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool() isfinite(const Eigen::bfloat16 &h)
Definition: BFloat16.h:752
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::enable_if_t< NumTraits< T >::IsSigned||NumTraits< T >::IsComplex, typename NumTraits< T >::Real > abs(const T &x)
Definition: MathFunctions.h:1355
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_zero(const X &x)
Definition: Meta.h:592
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
const int Dynamic
Definition: Constants.h:25
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::enable_if_t< std::is_base_of< DenseBase< std::decay_t< DerivedA > >, std::decay_t< DerivedA > >::value &&std::is_base_of< DenseBase< std::decay_t< DerivedB > >, std::decay_t< DerivedB > >::value, void > swap(DerivedA &&a, DerivedB &&b)
Definition: DenseBase.h:655
const Product< Lhs, Rhs > prod(const Lhs &lhs, const Rhs &rhs)
Definition: evaluators.cpp:7
std::complex< double > mu
Definition: time_harmonic_fourier_decomposed_linear_elasticity/cylinder/cylinder.cc:52
double U
Swimming speed.
Definition: two_d_variable_diff_adapt.cc:53
r
Definition: UniformPSDSelfTest.py:20
void transpose()
Definition: skew_symmetric_matrix3.cpp:135
int c
Definition: calibrate.py:100
const Mdouble pi
Definition: ExtendedMath.h:23
Definition: Eigen_Colamd.h:49
void start(const unsigned &i)
(Re-)start i-th timer
Definition: oomph_utilities.cc:243
double Zero
Definition: pseudosolid_node_update_elements.cc:35
double epsilon
Definition: osc_ring_sarah_asymptotics.h:43
list x
Definition: plotDoE.py:28
list mus
Definition: plotDoE.py:17
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:43
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
Definition: EigenBase.h:64
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
Definition: SVDBase.h:68
Definition: ForwardDeclarations.h:21
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2