JacobiSVD.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 // Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2013-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #ifndef EIGEN_JACOBISVD_H
12 #define EIGEN_JACOBISVD_H
13 
14 // IWYU pragma: private
15 #include "./InternalHeaderCheck.h"
16 
17 namespace Eigen {
18 
19 namespace internal {
20 
21 // forward declaration (needed by ICC)
22 // the empty body is required by MSVC
25 
26 /*** QR preconditioners (R-SVD)
27  ***
28  *** Their role is to reduce the problem of computing the SVD to the case of a square matrix.
29  *** This approach, known as R-SVD, is an optimization for rectangular-enough matrices, and is a requirement for
30  *** JacobiSVD which by itself is only able to work on square matrices.
31  ***/
32 
34 
35 template <typename MatrixType, int QRPreconditioner, int Case>
37  enum {
38  a = MatrixType::RowsAtCompileTime != Dynamic && MatrixType::ColsAtCompileTime != Dynamic &&
39  MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
40  b = MatrixType::RowsAtCompileTime != Dynamic && MatrixType::ColsAtCompileTime != Dynamic &&
41  MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
42  ret = !((QRPreconditioner == NoQRPreconditioner) || (Case == PreconditionIfMoreColsThanRows && bool(a)) ||
44  };
45 };
46 
47 template <typename MatrixType, int Options, int QRPreconditioner, int Case,
50 
51 template <typename MatrixType, int Options, int QRPreconditioner, int Case>
52 class qr_preconditioner_impl<MatrixType, Options, QRPreconditioner, Case, false> {
53  public:
55  template <typename Xpr>
56  bool run(JacobiSVD<MatrixType, Options>&, const Xpr&) {
57  return false;
58  }
59 };
60 
61 /*** preconditioner using FullPivHouseholderQR ***/
62 
63 template <typename MatrixType, int Options>
65  true> {
66  public:
67  typedef typename MatrixType::Scalar Scalar;
69 
70  enum { WorkspaceSize = MatrixType::RowsAtCompileTime, MaxWorkspaceSize = MatrixType::MaxRowsAtCompileTime };
71 
73 
74  void allocate(const SVDType& svd) {
75  if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) {
76  internal::destroy_at(&m_qr);
77  internal::construct_at(&m_qr, svd.rows(), svd.cols());
78  }
79  if (svd.m_computeFullU) m_workspace.resize(svd.rows());
80  }
81  template <typename Xpr>
82  bool run(SVDType& svd, const Xpr& matrix) {
83  if (matrix.rows() > matrix.cols()) {
84  m_qr.compute(matrix);
85  svd.m_workMatrix = m_qr.matrixQR().block(0, 0, matrix.cols(), matrix.cols()).template triangularView<Upper>();
86  if (svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace);
87  if (svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
88  return true;
89  }
90  return false;
91  }
92 
93  private:
97 };
98 
99 template <typename MatrixType, int Options>
101  true> {
102  public:
103  typedef typename MatrixType::Scalar Scalar;
105 
106  enum {
107  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
108  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
109  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
110  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
111  MatrixOptions = traits<MatrixType>::Options
112  };
113 
114  typedef typename internal::make_proper_matrix_type<Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions,
115  MaxColsAtCompileTime, MaxRowsAtCompileTime>::type
117 
118  void allocate(const SVDType& svd) {
119  if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) {
120  internal::destroy_at(&m_qr);
121  internal::construct_at(&m_qr, svd.cols(), svd.rows());
122  }
123  if (svd.m_computeFullV) m_workspace.resize(svd.cols());
124  }
125  template <typename Xpr>
126  bool run(SVDType& svd, const Xpr& matrix) {
127  if (matrix.cols() > matrix.rows()) {
128  m_qr.compute(matrix.adjoint());
129  svd.m_workMatrix =
130  m_qr.matrixQR().block(0, 0, matrix.rows(), matrix.rows()).template triangularView<Upper>().adjoint();
131  if (svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace);
132  if (svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
133  return true;
134  } else
135  return false;
136  }
137 
138  private:
142 };
143 
144 /*** preconditioner using ColPivHouseholderQR ***/
145 
146 template <typename MatrixType, int Options>
148  true> {
149  public:
150  typedef typename MatrixType::Scalar Scalar;
152 
153  enum {
156  };
157 
159 
160  void allocate(const SVDType& svd) {
161  if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) {
162  internal::destroy_at(&m_qr);
163  internal::construct_at(&m_qr, svd.rows(), svd.cols());
164  }
165  if (svd.m_computeFullU)
166  m_workspace.resize(svd.rows());
167  else if (svd.m_computeThinU)
168  m_workspace.resize(svd.cols());
169  }
170  template <typename Xpr>
171  bool run(SVDType& svd, const Xpr& matrix) {
172  if (matrix.rows() > matrix.cols()) {
173  m_qr.compute(matrix);
174  svd.m_workMatrix = m_qr.matrixQR().block(0, 0, matrix.cols(), matrix.cols()).template triangularView<Upper>();
175  if (svd.m_computeFullU)
176  m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
177  else if (svd.m_computeThinU) {
178  svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
179  m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
180  }
181  if (svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
182  return true;
183  }
184  return false;
185  }
186 
187  private:
191 };
192 
193 template <typename MatrixType, int Options>
195  true> {
196  public:
197  typedef typename MatrixType::Scalar Scalar;
199 
200  enum {
201  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
202  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
203  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
204  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
208  };
209 
211 
212  typedef typename internal::make_proper_matrix_type<Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions,
213  MaxColsAtCompileTime, MaxRowsAtCompileTime>::type
215 
216  void allocate(const SVDType& svd) {
217  if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) {
218  internal::destroy_at(&m_qr);
219  internal::construct_at(&m_qr, svd.cols(), svd.rows());
220  }
221  if (svd.m_computeFullV)
222  m_workspace.resize(svd.cols());
223  else if (svd.m_computeThinV)
224  m_workspace.resize(svd.rows());
225  }
226  template <typename Xpr>
227  bool run(SVDType& svd, const Xpr& matrix) {
228  if (matrix.cols() > matrix.rows()) {
229  m_qr.compute(matrix.adjoint());
230 
231  svd.m_workMatrix =
232  m_qr.matrixQR().block(0, 0, matrix.rows(), matrix.rows()).template triangularView<Upper>().adjoint();
233  if (svd.m_computeFullV)
234  m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
235  else if (svd.m_computeThinV) {
236  svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
237  m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
238  }
239  if (svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
240  return true;
241  } else
242  return false;
243  }
244 
245  private:
249 };
250 
251 /*** preconditioner using HouseholderQR ***/
252 
253 template <typename MatrixType, int Options>
255  public:
256  typedef typename MatrixType::Scalar Scalar;
258 
259  enum {
262  };
263 
265 
266  void allocate(const SVDType& svd) {
267  if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) {
268  internal::destroy_at(&m_qr);
269  internal::construct_at(&m_qr, svd.rows(), svd.cols());
270  }
271  if (svd.m_computeFullU)
272  m_workspace.resize(svd.rows());
273  else if (svd.m_computeThinU)
274  m_workspace.resize(svd.cols());
275  }
276  template <typename Xpr>
277  bool run(SVDType& svd, const Xpr& matrix) {
278  if (matrix.rows() > matrix.cols()) {
279  m_qr.compute(matrix);
280  svd.m_workMatrix = m_qr.matrixQR().block(0, 0, matrix.cols(), matrix.cols()).template triangularView<Upper>();
281  if (svd.m_computeFullU)
282  m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
283  else if (svd.m_computeThinU) {
284  svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
285  m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
286  }
287  if (svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
288  return true;
289  }
290  return false;
291  }
292 
293  private:
297 };
298 
299 template <typename MatrixType, int Options>
301  public:
302  typedef typename MatrixType::Scalar Scalar;
304 
305  enum {
306  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
307  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
308  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
309  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
313  };
314 
316 
317  typedef typename internal::make_proper_matrix_type<Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions,
318  MaxColsAtCompileTime, MaxRowsAtCompileTime>::type
320 
321  void allocate(const SVDType& svd) {
322  if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) {
323  internal::destroy_at(&m_qr);
324  internal::construct_at(&m_qr, svd.cols(), svd.rows());
325  }
326  if (svd.m_computeFullV)
327  m_workspace.resize(svd.cols());
328  else if (svd.m_computeThinV)
329  m_workspace.resize(svd.rows());
330  }
331 
332  template <typename Xpr>
333  bool run(SVDType& svd, const Xpr& matrix) {
334  if (matrix.cols() > matrix.rows()) {
335  m_qr.compute(matrix.adjoint());
336 
337  svd.m_workMatrix =
338  m_qr.matrixQR().block(0, 0, matrix.rows(), matrix.rows()).template triangularView<Upper>().adjoint();
339  if (svd.m_computeFullV)
340  m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
341  else if (svd.m_computeThinV) {
342  svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
343  m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
344  }
345  if (svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
346  return true;
347  } else
348  return false;
349  }
350 
351  private:
355 };
356 
357 /*** 2x2 SVD implementation
358  ***
359  *** JacobiSVD consists in performing a series of 2x2 SVD subproblems
360  ***/
361 
362 template <typename MatrixType, int Options>
366  static bool run(typename SVD::WorkMatrixType&, SVD&, Index, Index, RealScalar&) { return true; }
367 };
368 
369 template <typename MatrixType, int Options>
372  typedef typename MatrixType::Scalar Scalar;
374  static bool run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q, RealScalar& maxDiagEntry) {
375  using std::abs;
376  using std::sqrt;
377  Scalar z;
379  RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p, p)) + numext::abs2(work_matrix.coeff(q, p)));
380 
381  const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
382  const RealScalar precision = NumTraits<Scalar>::epsilon();
383 
384  if (numext::is_exactly_zero(n)) {
385  // make sure first column is zero
386  work_matrix.coeffRef(p, p) = work_matrix.coeffRef(q, p) = Scalar(0);
387 
388  if (abs(numext::imag(work_matrix.coeff(p, q))) > considerAsZero) {
389  // work_matrix.coeff(p,q) can be zero if work_matrix.coeff(q,p) is not zero but small enough to underflow when
390  // computing n
391  z = abs(work_matrix.coeff(p, q)) / work_matrix.coeff(p, q);
392  work_matrix.row(p) *= z;
393  if (svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
394  }
395  if (abs(numext::imag(work_matrix.coeff(q, q))) > considerAsZero) {
396  z = abs(work_matrix.coeff(q, q)) / work_matrix.coeff(q, q);
397  work_matrix.row(q) *= z;
398  if (svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
399  }
400  // otherwise the second row is already zero, so we have nothing to do.
401  } else {
402  rot.c() = conj(work_matrix.coeff(p, p)) / n;
403  rot.s() = work_matrix.coeff(q, p) / n;
404  work_matrix.applyOnTheLeft(p, q, rot);
405  if (svd.computeU()) svd.m_matrixU.applyOnTheRight(p, q, rot.adjoint());
406  if (abs(numext::imag(work_matrix.coeff(p, q))) > considerAsZero) {
407  z = abs(work_matrix.coeff(p, q)) / work_matrix.coeff(p, q);
408  work_matrix.col(q) *= z;
409  if (svd.computeV()) svd.m_matrixV.col(q) *= z;
410  }
411  if (abs(numext::imag(work_matrix.coeff(q, q))) > considerAsZero) {
412  z = abs(work_matrix.coeff(q, q)) / work_matrix.coeff(q, q);
413  work_matrix.row(q) *= z;
414  if (svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
415  }
416  }
417 
418  // update largest diagonal entry
419  maxDiagEntry = numext::maxi<RealScalar>(
420  maxDiagEntry, numext::maxi<RealScalar>(abs(work_matrix.coeff(p, p)), abs(work_matrix.coeff(q, q))));
421  // and check whether the 2x2 block is already diagonal
422  RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
423  return abs(work_matrix.coeff(p, q)) > threshold || abs(work_matrix.coeff(q, p)) > threshold;
424  }
425 };
426 
427 template <typename MatrixType_, int Options>
428 struct traits<JacobiSVD<MatrixType_, Options> > : svd_traits<MatrixType_, Options> {
429  typedef MatrixType_ MatrixType;
430 };
431 
432 } // end namespace internal
433 
499 template <typename MatrixType_, int Options_>
500 class JacobiSVD : public SVDBase<JacobiSVD<MatrixType_, Options_> > {
502 
503  public:
504  typedef MatrixType_ MatrixType;
505  typedef typename Base::Scalar Scalar;
506  typedef typename Base::RealScalar RealScalar;
507  enum : int {
508  Options = Options_,
517  };
518 
519  typedef typename Base::MatrixUType MatrixUType;
520  typedef typename Base::MatrixVType MatrixVType;
525 
532 
541 
556  EIGEN_DEPRECATED JacobiSVD(Index rows, Index cols, unsigned int computationOptions) {
557  internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, rows, cols);
558  allocate(rows, cols, computationOptions);
559  }
560 
567 
580  // EIGEN_DEPRECATED // TODO(cantonios): re-enable after fixing a few 3p libraries that error on deprecation warnings.
581  JacobiSVD(const MatrixType& matrix, unsigned int computationOptions) {
582  internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
583  compute_impl(matrix, computationOptions);
584  }
585 
592 
602  EIGEN_DEPRECATED JacobiSVD& compute(const MatrixType& matrix, unsigned int computationOptions) {
603  internal::check_svd_options_assertions<MatrixType, Options>(m_computationOptions, matrix.rows(), matrix.cols());
604  return compute_impl(matrix, computationOptions);
605  }
606 
607  using Base::cols;
608  using Base::computeU;
609  using Base::computeV;
610  using Base::diagSize;
611  using Base::rank;
612  using Base::rows;
613 
614  void allocate(Index rows_, Index cols_, unsigned int computationOptions) {
615  if (Base::allocate(rows_, cols_, computationOptions)) return;
618  "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
619  "Use the ColPivHouseholderQR preconditioner instead.");
620 
622  if (cols() > rows()) m_qr_precond_morecols.allocate(*this);
623  if (rows() > cols()) m_qr_precond_morerows.allocate(*this);
624  }
625 
626  private:
627  JacobiSVD& compute_impl(const MatrixType& matrix, unsigned int computationOptions);
628 
629  protected:
631  using Base::m_computeFullU;
632  using Base::m_computeFullV;
633  using Base::m_computeThinU;
634  using Base::m_computeThinV;
635  using Base::m_info;
636  using Base::m_isAllocated;
637  using Base::m_isInitialized;
638  using Base::m_matrixU;
639  using Base::m_matrixV;
646 
649  "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
650  "Use the ColPivHouseholderQR preconditioner instead.")
651 
652  template <typename MatrixType__, int Options__, bool IsComplex_>
653  friend struct internal::svd_precondition_2x2_block_to_be_real;
654  template <typename MatrixType__, int Options__, int QRPreconditioner_, int Case_, bool DoAnything_>
655  friend struct internal::qr_preconditioner_impl;
656 
662 };
663 
664 template <typename MatrixType, int Options>
666  unsigned int computationOptions) {
667  using std::abs;
668 
669  allocate(matrix.rows(), matrix.cols(), computationOptions);
670 
671  // currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number
672  // of iterations, only worsening the precision of U and V as we accumulate more rotations
673  const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();
674 
675  // limit for denormal numbers to be considered zero in order to avoid infinite loops (see bug 286)
676  const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
677 
678  // Scaling factor to reduce over/under-flows
679  RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
680  if (!(numext::isfinite)(scale)) {
681  m_isInitialized = true;
684  return *this;
685  }
686  if (numext::is_exactly_zero(scale)) scale = RealScalar(1);
687 
688  /*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
689 
690  if (rows() != cols()) {
691  m_qr_precond_morecols.run(*this, matrix / scale);
692  m_qr_precond_morerows.run(*this, matrix / scale);
693  } else {
694  m_workMatrix =
695  matrix.template topLeftCorner<DiagSizeAtCompileTime, DiagSizeAtCompileTime>(diagSize(), diagSize()) / scale;
696  if (m_computeFullU) m_matrixU.setIdentity(rows(), rows());
697  if (m_computeThinU) m_matrixU.setIdentity(rows(), diagSize());
698  if (m_computeFullV) m_matrixV.setIdentity(cols(), cols());
699  if (m_computeThinV) m_matrixV.setIdentity(cols(), diagSize());
700  }
701 
702  /*** step 2. The main Jacobi SVD iteration. ***/
703  RealScalar maxDiagEntry = m_workMatrix.cwiseAbs().diagonal().maxCoeff();
704 
705  bool finished = false;
706  while (!finished) {
707  finished = true;
708 
709  // do a sweep: for all index pairs (p,q), perform SVD of the corresponding 2x2 sub-matrix
710 
711  for (Index p = 1; p < diagSize(); ++p) {
712  for (Index q = 0; q < p; ++q) {
713  // if this 2x2 sub-matrix is not diagonal already...
714  // notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
715  // keep us iterating forever. Similarly, small denormal numbers are considered zero.
716  RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
718  finished = false;
719  // perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
720  // the complex to real operation returns true if the updated 2x2 block is not already diagonal
722  maxDiagEntry)) {
723  JacobiRotation<RealScalar> j_left, j_right;
724  internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
725 
726  // accumulate resulting Jacobi rotations
727  m_workMatrix.applyOnTheLeft(p, q, j_left);
728  if (computeU()) m_matrixU.applyOnTheRight(p, q, j_left.transpose());
729 
730  m_workMatrix.applyOnTheRight(p, q, j_right);
731  if (computeV()) m_matrixV.applyOnTheRight(p, q, j_right);
732 
733  // keep track of the largest diagonal coefficient
734  maxDiagEntry = numext::maxi<RealScalar>(
735  maxDiagEntry, numext::maxi<RealScalar>(abs(m_workMatrix.coeff(p, p)), abs(m_workMatrix.coeff(q, q))));
736  }
737  }
738  }
739  }
740  }
741 
742  /*** step 3. The work matrix is now diagonal, so ensure it's positive so its diagonal entries are the singular values
743  * ***/
744 
745  for (Index i = 0; i < diagSize(); ++i) {
746  // For a complex matrix, some diagonal coefficients might note have been
747  // treated by svd_precondition_2x2_block_to_be_real, and the imaginary part
748  // of some diagonal entry might not be null.
749  if (NumTraits<Scalar>::IsComplex && abs(numext::imag(m_workMatrix.coeff(i, i))) > considerAsZero) {
751  m_singularValues.coeffRef(i) = abs(a);
752  if (computeU()) m_matrixU.col(i) *= m_workMatrix.coeff(i, i) / a;
753  } else {
754  // m_workMatrix.coeff(i,i) is already real, no difficulty:
756  m_singularValues.coeffRef(i) = abs(a);
757  if (computeU() && (a < RealScalar(0))) m_matrixU.col(i) = -m_matrixU.col(i);
758  }
759  }
760 
761  m_singularValues *= scale;
762 
763  /*** step 4. Sort singular values in descending order and compute the number of nonzero singular values ***/
764 
766  for (Index i = 0; i < diagSize(); i++) {
767  Index pos;
768  RealScalar maxRemainingSingularValue = m_singularValues.tail(diagSize() - i).maxCoeff(&pos);
769  if (numext::is_exactly_zero(maxRemainingSingularValue)) {
771  break;
772  }
773  if (pos) {
774  pos += i;
775  std::swap(m_singularValues.coeffRef(i), m_singularValues.coeffRef(pos));
776  if (computeU()) m_matrixU.col(pos).swap(m_matrixU.col(i));
777  if (computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
778  }
779  }
780 
781  m_isInitialized = true;
782  return *this;
783 }
784 
792 template <typename Derived>
793 template <int Options>
795  return JacobiSVD<PlainObject, Options>(*this);
796 }
797 
798 template <typename Derived>
799 template <int Options>
801  unsigned int computationOptions) const {
802  return JacobiSVD<PlainObject, Options>(*this, computationOptions);
803 }
804 
805 } // end namespace Eigen
806 
807 #endif // EIGEN_JACOBISVD_H
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
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<< "Here is the matrix m:"<< endl<< m<< endl;JacobiSVD< MatrixXf, ComputeThinU|ComputeThinV > svd(m)
#define EIGEN_DEPRECATED
Definition: Macros.h:931
#define eigen_assert(x)
Definition: Macros.h:910
float * p
Definition: Tutorial_Map_using.cpp:9
Scalar * b
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
Rotation given by a cosine-sine pair.
Definition: Jacobi.h:38
EIGEN_DEVICE_FUNC JacobiRotation transpose() const
Definition: Jacobi.h:61
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition: JacobiSVD.h:500
EIGEN_DEPRECATED JacobiSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix, as specified by the computationOptions parameter...
Definition: JacobiSVD.h:602
Base::RealScalar RealScalar
Definition: JacobiSVD.h:506
Base::SingularValuesType SingularValuesType
Definition: JacobiSVD.h:521
Base::MatrixVType MatrixVType
Definition: JacobiSVD.h:520
SVDBase< JacobiSVD > Base
Definition: JacobiSVD.h:501
JacobiSVD()
Default Constructor.
Definition: JacobiSVD.h:531
EIGEN_DEPRECATED JacobiSVD(Index rows, Index cols, unsigned int computationOptions)
Default Constructor with memory preallocation.
Definition: JacobiSVD.h:556
int Options__
Definition: JacobiSVD.h:652
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition: EigenBase.h:61
EIGEN_STATIC_ASSERT(!(ShouldComputeThinU &&int(QRPreconditioner)==int(FullPivHouseholderQRPreconditioner)) &&!(ShouldComputeThinU &&int(QRPreconditioner)==int(FullPivHouseholderQRPreconditioner)), "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. " "Use the ColPivHouseholderQR preconditioner instead.") template< typename MatrixType__
Base::Scalar Scalar
Definition: JacobiSVD.h:505
JacobiSVD(const MatrixType &matrix, unsigned int computationOptions)
Constructor performing the decomposition of given matrix using specified options for computing unitar...
Definition: JacobiSVD.h:581
JacobiSVD & compute_impl(const MatrixType &matrix, unsigned int computationOptions)
Definition: JacobiSVD.h:665
Base::MatrixUType MatrixUType
Definition: JacobiSVD.h:519
JacobiSVD(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition: JacobiSVD.h:540
internal::qr_preconditioner_impl< MatrixType, Options, QRPreconditioner, internal::PreconditionIfMoreColsThanRows > m_qr_precond_morecols
Definition: JacobiSVD.h:658
JacobiSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix. Computes Thin/Full unitaries U/V if specified us...
Definition: JacobiSVD.h:591
JacobiSVD(const MatrixType &matrix)
Constructor performing the decomposition of given matrix, using the custom options specified with the...
Definition: JacobiSVD.h:566
internal::qr_preconditioner_impl< MatrixType, Options, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols > m_qr_precond_morerows
Definition: JacobiSVD.h:660
MatrixType_ MatrixType
Definition: JacobiSVD.h:504
void allocate(Index rows_, Index cols_, unsigned int computationOptions)
Definition: JacobiSVD.h:614
Matrix< Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime, MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime > WorkMatrixType
Definition: JacobiSVD.h:524
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: EigenBase.h:59
WorkMatrixType m_workMatrix
Definition: JacobiSVD.h:661
@ ColsAtCompileTime
Definition: JacobiSVD.h:511
@ MaxColsAtCompileTime
Definition: JacobiSVD.h:514
@ Options
Definition: JacobiSVD.h:508
@ MaxRowsAtCompileTime
Definition: JacobiSVD.h:513
@ DiagSizeAtCompileTime
Definition: JacobiSVD.h:512
@ MatrixOptions
Definition: JacobiSVD.h:516
@ RowsAtCompileTime
Definition: JacobiSVD.h:510
@ MaxDiagSizeAtCompileTime
Definition: JacobiSVD.h:515
@ QRPreconditioner
Definition: JacobiSVD.h:509
JacobiSVD< PlainObject, Options > jacobiSvd() const
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar & coeffRef(Index rowId, Index colId)
Definition: PlainObjectBase.h:217
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const Scalar & coeff(Index rowId, Index colId) const
Definition: PlainObjectBase.h:198
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseBase< OtherDerived > &other)
Override DenseBase::swap() since for dynamic-sized matrices of same type it is enough to swap the dat...
Definition: PlainObjectBase.h:898
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
bool m_usePrescribedThreshold
Definition: SVDBase.h:335
bool m_computeFullV
Definition: SVDBase.h:337
static constexpr bool ShouldComputeThinV
Definition: SVDBase.h:132
Index rank() const
Definition: SVDBase.h:217
ComputationInfo m_info
Definition: SVDBase.h:334
bool m_computeThinU
Definition: SVDBase.h:336
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
RealScalar threshold() const
Definition: SVDBase.h:265
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
RealScalar m_prescribedThreshold
Definition: SVDBase.h:343
static constexpr bool ShouldComputeThinU
Definition: SVDBase.h:130
bool m_computeThinV
Definition: SVDBase.h:337
bool m_computeFullU
Definition: SVDBase.h:336
bool allocate(Index rows, Index cols, unsigned int computationOptions)
Definition: SVDBase.h:403
Index diagSize() const
Definition: SVDBase.h:279
internal::traits< Derived >::MatrixType MatrixType
Definition: SVDBase.h:124
MatrixUType m_matrixU
Definition: SVDBase.h:331
bool m_isAllocated
Definition: SVDBase.h:335
Definition: XprHelper.h:352
Matrix< Scalar, 1, WorkspaceSize, RowMajor, 1, MaxWorkspaceSize > WorkspaceType
Definition: JacobiSVD.h:158
internal::make_proper_matrix_type< Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MaxRowsAtCompileTime >::type TransposeTypeWithSameStorageOrder
Definition: JacobiSVD.h:214
Matrix< Scalar, WorkspaceSize, 1, ColMajor, MaxWorkspaceSize, 1 > WorkspaceType
Definition: JacobiSVD.h:210
Matrix< Scalar, 1, WorkspaceSize, RowMajor, 1, MaxWorkspaceSize > WorkspaceType
Definition: JacobiSVD.h:72
internal::make_proper_matrix_type< Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MaxRowsAtCompileTime >::type TransposeTypeWithSameStorageOrder
Definition: JacobiSVD.h:116
Matrix< Scalar, 1, WorkspaceSize, RowMajor, 1, MaxWorkspaceSize > WorkspaceType
Definition: JacobiSVD.h:264
Matrix< Scalar, WorkspaceSize, 1, ColMajor, MaxWorkspaceSize, 1 > WorkspaceType
Definition: JacobiSVD.h:315
internal::make_proper_matrix_type< Scalar, ColsAtCompileTime, RowsAtCompileTime, MatrixOptions, MaxColsAtCompileTime, MaxRowsAtCompileTime >::type TransposeTypeWithSameStorageOrder
Definition: JacobiSVD.h:319
void allocate(const JacobiSVD< MatrixType, Options > &)
Definition: JacobiSVD.h:54
bool run(JacobiSVD< MatrixType, Options > &, const Xpr &)
Definition: JacobiSVD.h:56
@ IsComplex
Definition: common.h:73
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
float real
Definition: datatypes.h:10
#define min(a, b)
Definition: datatypes.h:22
@ NoQRPreconditioner
Definition: Constants.h:423
@ HouseholderQRPreconditioner
Definition: Constants.h:425
@ ColPivHouseholderQRPreconditioner
Definition: Constants.h:421
@ FullPivHouseholderQRPreconditioner
Definition: Constants.h:427
@ InvalidInput
Definition: Constants.h:447
Eigen::DenseIndex ret
Definition: level1_cplx_impl.h:43
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117
EIGEN_BLAS_FUNC() rot(int *n, Scalar *px, int *incx, Scalar *py, int *incy, Scalar *pc, Scalar *ps)
Definition: level1_real_impl.h:88
const Scalar * a
Definition: level2_cplx_impl.h:32
constexpr int get_qr_preconditioner(int options)
Definition: SVDBase.h:32
EIGEN_DEVICE_FUNC T * construct_at(T *p, Args &&... args)
Definition: Memory.h:1321
EIGEN_DEVICE_FUNC void destroy_at(T *p)
Definition: Memory.h:1335
void real_2x2_jacobi_svd(const MatrixType &matrix, Index p, Index q, JacobiRotation< RealScalar > *j_left, JacobiRotation< RealScalar > *j_right)
Definition: RealSvd2x2.h:22
constexpr int get_computation_options(int options)
Definition: SVDBase.h:34
@ PreconditionIfMoreColsThanRows
Definition: JacobiSVD.h:33
@ PreconditionIfMoreRowsThanCols
Definition: JacobiSVD.h:33
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool() isfinite(const Eigen::bfloat16 &h)
Definition: BFloat16.h:752
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_zero(const X &x)
Definition: Meta.h:592
EIGEN_DEVICE_FUNC const Scalar & q
Definition: SpecialFunctionsImpl.h:2019
EIGEN_DEVICE_FUNC bool abs2(bool x)
Definition: MathFunctions.h:1102
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 AutoDiffScalar< DerType > & conj(const AutoDiffScalar< DerType > &x)
Definition: AutoDiffScalar.h:482
const int Dynamic
Definition: Constants.h:25
int Case
What case are we considering: Choose one from the enumeration Cases.
Definition: common_young_laplace_stuff.h:53
bool finished
Definition: MergeRestartFiles.py:79
type
Definition: compute_granudrum_aor.py:141
Definition: Eigen_Colamd.h:49
double epsilon
Definition: osc_ring_sarah_asymptotics.h:43
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:43
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
Definition: XprHelper.h:758
Definition: JacobiSVD.h:49
JacobiSVD< MatrixType, Options > SVD
Definition: JacobiSVD.h:364
static bool run(typename SVD::WorkMatrixType &, SVD &, Index, Index, RealScalar &)
Definition: JacobiSVD.h:366
static bool run(typename SVD::WorkMatrixType &work_matrix, SVD &svd, Index p, Index q, RealScalar &maxDiagEntry)
Definition: JacobiSVD.h:374
JacobiSVD< MatrixType, Options > SVD
Definition: JacobiSVD.h:371
Definition: SVDBase.h:68
MatrixType_ MatrixType
Definition: JacobiSVD.h:429
Definition: ForwardDeclarations.h:21