Path Tracer
BDCSVD.h
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 namespace Eigen {
31 
32 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
33 IOFormat bdcsvdfmt(8, 0, ", ", "\n", " [", "]");
34 #endif
35 
36 template<typename _MatrixType> class BDCSVD;
37 
38 namespace internal {
39 
40 template<typename _MatrixType>
41 struct traits<BDCSVD<_MatrixType> >
42  : traits<_MatrixType>
43 {
44  typedef _MatrixType MatrixType;
45 };
46 
47 } // end namespace internal
48 
49 
72 template<typename _MatrixType>
73 class BDCSVD : public SVDBase<BDCSVD<_MatrixType> >
74 {
75  typedef SVDBase<BDCSVD> Base;
76 
77 public:
78  using Base::rows;
79  using Base::cols;
80  using Base::computeU;
81  using Base::computeV;
82 
83  typedef _MatrixType MatrixType;
84  typedef typename MatrixType::Scalar Scalar;
85  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
86  typedef typename NumTraits<RealScalar>::Literal Literal;
87  enum {
88  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
89  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
90  DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime, ColsAtCompileTime),
91  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
92  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
93  MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime, MaxColsAtCompileTime),
94  MatrixOptions = MatrixType::Options
95  };
96 
97  typedef typename Base::MatrixUType MatrixUType;
98  typedef typename Base::MatrixVType MatrixVType;
100 
106  typedef Ref<ArrayXr> ArrayRef;
107  typedef Ref<ArrayXi> IndicesRef;
108 
114  BDCSVD() : m_algoswap(16), m_isTranspose(false), m_compU(false), m_compV(false), m_numIters(0)
115  {}
116 
117 
124  BDCSVD(Index rows, Index cols, unsigned int computationOptions = 0)
125  : m_algoswap(16), m_numIters(0)
126  {
127  allocate(rows, cols, computationOptions);
128  }
129 
140  BDCSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
141  : m_algoswap(16), m_numIters(0)
142  {
143  compute(matrix, computationOptions);
144  }
145 
146  ~BDCSVD()
147  {
148  }
149 
160  BDCSVD& compute(const MatrixType& matrix, unsigned int computationOptions);
161 
168  BDCSVD& compute(const MatrixType& matrix)
169  {
170  return compute(matrix, this->m_computationOptions);
171  }
172 
173  void setSwitchSize(int s)
174  {
175  eigen_assert(s>3 && "BDCSVD the size of the algo switch has to be greater than 3");
176  m_algoswap = s;
177  }
178 
179 private:
180  void allocate(Index rows, Index cols, unsigned int computationOptions);
181  void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift);
182  void computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V);
183  void computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, VectorType& singVals, ArrayRef shifts, ArrayRef mus);
184  void perturbCol0(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat);
185  void computeSingVecs(const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V);
186  void deflation43(Index firstCol, Index shift, Index i, Index size);
187  void deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size);
188  void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift);
189  template<typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
190  void copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naivev);
191  void structured_update(Block<MatrixXr,Dynamic,Dynamic> A, const MatrixXr &B, Index n1);
192  static RealScalar secularEq(RealScalar x, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift);
193 
194 protected:
195  MatrixXr m_naiveU, m_naiveV;
196  MatrixXr m_computed;
197  Index m_nRec;
198  ArrayXr m_workspace;
199  ArrayXi m_workspaceI;
200  int m_algoswap;
201  bool m_isTranspose, m_compU, m_compV;
202 
203  using Base::m_singularValues;
204  using Base::m_diagSize;
205  using Base::m_computeFullU;
206  using Base::m_computeFullV;
207  using Base::m_computeThinU;
208  using Base::m_computeThinV;
209  using Base::m_matrixU;
210  using Base::m_matrixV;
211  using Base::m_isInitialized;
212  using Base::m_nonzeroSingularValues;
213 
214 public:
215  int m_numIters;
216 }; //end class BDCSVD
217 
218 
219 // Method to allocate and initialize matrix and attributes
220 template<typename MatrixType>
221 void BDCSVD<MatrixType>::allocate(Eigen::Index rows, Eigen::Index cols, unsigned int computationOptions)
222 {
223  m_isTranspose = (cols > rows);
224 
225  if (Base::allocate(rows, cols, computationOptions))
226  return;
227 
228  m_computed = MatrixXr::Zero(m_diagSize + 1, m_diagSize );
229  m_compU = computeV();
230  m_compV = computeU();
231  if (m_isTranspose)
232  std::swap(m_compU, m_compV);
233 
234  if (m_compU) m_naiveU = MatrixXr::Zero(m_diagSize + 1, m_diagSize + 1 );
235  else m_naiveU = MatrixXr::Zero(2, m_diagSize + 1 );
236 
237  if (m_compV) m_naiveV = MatrixXr::Zero(m_diagSize, m_diagSize);
238 
239  m_workspace.resize((m_diagSize+1)*(m_diagSize+1)*3);
240  m_workspaceI.resize(3*m_diagSize);
241 }// end allocate
242 
243 template<typename MatrixType>
244 BDCSVD<MatrixType>& BDCSVD<MatrixType>::compute(const MatrixType& matrix, unsigned int computationOptions)
245 {
246 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
247  std::cout << "\n\n\n======================================================================================================================\n\n\n";
248 #endif
249  allocate(matrix.rows(), matrix.cols(), computationOptions);
250  using std::abs;
251 
252  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
253 
254  //**** step -1 - If the problem is too small, directly falls back to JacobiSVD and return
255  if(matrix.cols() < m_algoswap)
256  {
257  // FIXME this line involves temporaries
258  JacobiSVD<MatrixType> jsvd(matrix,computationOptions);
259  if(computeU()) m_matrixU = jsvd.matrixU();
260  if(computeV()) m_matrixV = jsvd.matrixV();
261  m_singularValues = jsvd.singularValues();
262  m_nonzeroSingularValues = jsvd.nonzeroSingularValues();
263  m_isInitialized = true;
264  return *this;
265  }
266 
267  //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows
268  RealScalar scale = matrix.cwiseAbs().maxCoeff();
269  if(scale==Literal(0)) scale = Literal(1);
270  MatrixX copy;
271  if (m_isTranspose) copy = matrix.adjoint()/scale;
272  else copy = matrix/scale;
273 
274  //**** step 1 - Bidiagonalization
275  // FIXME this line involves temporaries
277 
278  //**** step 2 - Divide & Conquer
279  m_naiveU.setZero();
280  m_naiveV.setZero();
281  // FIXME this line involves a temporary matrix
282  m_computed.topRows(m_diagSize) = bid.bidiagonal().toDenseMatrix().transpose();
283  m_computed.template bottomRows<1>().setZero();
284  divide(0, m_diagSize - 1, 0, 0, 0);
285 
286  //**** step 3 - Copy singular values and vectors
287  for (int i=0; i<m_diagSize; i++)
288  {
289  RealScalar a = abs(m_computed.coeff(i, i));
290  m_singularValues.coeffRef(i) = a * scale;
291  if (a<considerZero)
292  {
293  m_nonzeroSingularValues = i;
294  m_singularValues.tail(m_diagSize - i - 1).setZero();
295  break;
296  }
297  else if (i == m_diagSize - 1)
298  {
299  m_nonzeroSingularValues = i + 1;
300  break;
301  }
302  }
303 
304 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
305 // std::cout << "m_naiveU\n" << m_naiveU << "\n\n";
306 // std::cout << "m_naiveV\n" << m_naiveV << "\n\n";
307 #endif
308  if(m_isTranspose) copyUV(bid.householderV(), bid.householderU(), m_naiveV, m_naiveU);
309  else copyUV(bid.householderU(), bid.householderV(), m_naiveU, m_naiveV);
310 
311  m_isInitialized = true;
312  return *this;
313 }// end compute
314 
315 
316 template<typename MatrixType>
317 template<typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
318 void BDCSVD<MatrixType>::copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naiveV)
319 {
320  // Note exchange of U and V: m_matrixU is set from m_naiveV and vice versa
321  if (computeU())
322  {
323  Index Ucols = m_computeThinU ? m_diagSize : householderU.cols();
324  m_matrixU = MatrixX::Identity(householderU.cols(), Ucols);
325  m_matrixU.topLeftCorner(m_diagSize, m_diagSize) = naiveV.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
326  householderU.applyThisOnTheLeft(m_matrixU); // FIXME this line involves a temporary buffer
327  }
328  if (computeV())
329  {
330  Index Vcols = m_computeThinV ? m_diagSize : householderV.cols();
331  m_matrixV = MatrixX::Identity(householderV.cols(), Vcols);
332  m_matrixV.topLeftCorner(m_diagSize, m_diagSize) = naiveU.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
333  householderV.applyThisOnTheLeft(m_matrixV); // FIXME this line involves a temporary buffer
334  }
335 }
336 
345 template<typename MatrixType>
346 void BDCSVD<MatrixType>::structured_update(Block<MatrixXr,Dynamic,Dynamic> A, const MatrixXr &B, Index n1)
347 {
348  Index n = A.rows();
349  if(n>100)
350  {
351  // If the matrices are large enough, let's exploit the sparse structure of A by
352  // splitting it in half (wrt n1), and packing the non-zero columns.
353  Index n2 = n - n1;
354  Map<MatrixXr> A1(m_workspace.data() , n1, n);
355  Map<MatrixXr> A2(m_workspace.data()+ n1*n, n2, n);
356  Map<MatrixXr> B1(m_workspace.data()+ n*n, n, n);
357  Map<MatrixXr> B2(m_workspace.data()+2*n*n, n, n);
358  Index k1=0, k2=0;
359  for(Index j=0; j<n; ++j)
360  {
361  if( (A.col(j).head(n1).array()!=Literal(0)).any() )
362  {
363  A1.col(k1) = A.col(j).head(n1);
364  B1.row(k1) = B.row(j);
365  ++k1;
366  }
367  if( (A.col(j).tail(n2).array()!=Literal(0)).any() )
368  {
369  A2.col(k2) = A.col(j).tail(n2);
370  B2.row(k2) = B.row(j);
371  ++k2;
372  }
373  }
374 
375  A.topRows(n1).noalias() = A1.leftCols(k1) * B1.topRows(k1);
376  A.bottomRows(n2).noalias() = A2.leftCols(k2) * B2.topRows(k2);
377  }
378  else
379  {
380  Map<MatrixXr,Aligned> tmp(m_workspace.data(),n,n);
381  tmp.noalias() = A*B;
382  A = tmp;
383  }
384 }
385 
386 // The divide algorithm is done "in place", we are always working on subsets of the same matrix. The divide methods takes as argument the
387 // place of the submatrix we are currently working on.
388 
389 //@param firstCol : The Index of the first column of the submatrix of m_computed and for m_naiveU;
390 //@param lastCol : The Index of the last column of the submatrix of m_computed and for m_naiveU;
391 // lastCol + 1 - firstCol is the size of the submatrix.
392 //@param firstRowW : The Index of the first row of the matrix W that we are to change. (see the reference paper section 1 for more information on W)
393 //@param firstRowW : Same as firstRowW with the column.
394 //@param shift : Each time one takes the left submatrix, one must add 1 to the shift. Why? Because! We actually want the last column of the U submatrix
395 // to become the first column (*coeff) and to shift all the other columns to the right. There are more details on the reference paper.
396 template<typename MatrixType>
397 void BDCSVD<MatrixType>::divide (Eigen::Index firstCol, Eigen::Index lastCol, Eigen::Index firstRowW, Eigen::Index firstColW, Eigen::Index shift)
398 {
399  // requires rows = cols + 1;
400  using std::pow;
401  using std::sqrt;
402  using std::abs;
403  const Index n = lastCol - firstCol + 1;
404  const Index k = n/2;
405  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
406  RealScalar alphaK;
407  RealScalar betaK;
408  RealScalar r0;
409  RealScalar lambda, phi, c0, s0;
410  VectorType l, f;
411  // We use the other algorithm which is more efficient for small
412  // matrices.
413  if (n < m_algoswap)
414  {
415  // FIXME this line involves temporaries
416  JacobiSVD<MatrixXr> b(m_computed.block(firstCol, firstCol, n + 1, n), ComputeFullU | (m_compV ? ComputeFullV : 0));
417  if (m_compU)
418  m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() = b.matrixU();
419  else
420  {
421  m_naiveU.row(0).segment(firstCol, n + 1).real() = b.matrixU().row(0);
422  m_naiveU.row(1).segment(firstCol, n + 1).real() = b.matrixU().row(n);
423  }
424  if (m_compV) m_naiveV.block(firstRowW, firstColW, n, n).real() = b.matrixV();
425  m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
426  m_computed.diagonal().segment(firstCol + shift, n) = b.singularValues().head(n);
427  return;
428  }
429  // We use the divide and conquer algorithm
430  alphaK = m_computed(firstCol + k, firstCol + k);
431  betaK = m_computed(firstCol + k + 1, firstCol + k);
432  // The divide must be done in that order in order to have good results. Divide change the data inside the submatrices
433  // and the divide of the right submatrice reads one column of the left submatrice. That's why we need to treat the
434  // right submatrix before the left one.
435  divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
436  divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
437 
438  if (m_compU)
439  {
440  lambda = m_naiveU(firstCol + k, firstCol + k);
441  phi = m_naiveU(firstCol + k + 1, lastCol + 1);
442  }
443  else
444  {
445  lambda = m_naiveU(1, firstCol + k);
446  phi = m_naiveU(0, lastCol + 1);
447  }
448  r0 = sqrt((abs(alphaK * lambda) * abs(alphaK * lambda)) + abs(betaK * phi) * abs(betaK * phi));
449  if (m_compU)
450  {
451  l = m_naiveU.row(firstCol + k).segment(firstCol, k);
452  f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1, n - k - 1);
453  }
454  else
455  {
456  l = m_naiveU.row(1).segment(firstCol, k);
457  f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
458  }
459  if (m_compV) m_naiveV(firstRowW+k, firstColW) = Literal(1);
460  if (r0<considerZero)
461  {
462  c0 = Literal(1);
463  s0 = Literal(0);
464  }
465  else
466  {
467  c0 = alphaK * lambda / r0;
468  s0 = betaK * phi / r0;
469  }
470 
471 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
472  assert(m_naiveU.allFinite());
473  assert(m_naiveV.allFinite());
474  assert(m_computed.allFinite());
475 #endif
476 
477  if (m_compU)
478  {
479  MatrixXr q1 (m_naiveU.col(firstCol + k).segment(firstCol, k + 1));
480  // we shiftW Q1 to the right
481  for (Index i = firstCol + k - 1; i >= firstCol; i--)
482  m_naiveU.col(i + 1).segment(firstCol, k + 1) = m_naiveU.col(i).segment(firstCol, k + 1);
483  // we shift q1 at the left with a factor c0
484  m_naiveU.col(firstCol).segment( firstCol, k + 1) = (q1 * c0);
485  // last column = q1 * - s0
486  m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (q1 * ( - s0));
487  // first column = q2 * s0
488  m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) = m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) * s0;
489  // q2 *= c0
490  m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *= c0;
491  }
492  else
493  {
494  RealScalar q1 = m_naiveU(0, firstCol + k);
495  // we shift Q1 to the right
496  for (Index i = firstCol + k - 1; i >= firstCol; i--)
497  m_naiveU(0, i + 1) = m_naiveU(0, i);
498  // we shift q1 at the left with a factor c0
499  m_naiveU(0, firstCol) = (q1 * c0);
500  // last column = q1 * - s0
501  m_naiveU(0, lastCol + 1) = (q1 * ( - s0));
502  // first column = q2 * s0
503  m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) *s0;
504  // q2 *= c0
505  m_naiveU(1, lastCol + 1) *= c0;
506  m_naiveU.row(1).segment(firstCol + 1, k).setZero();
507  m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1).setZero();
508  }
509 
510 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
511  assert(m_naiveU.allFinite());
512  assert(m_naiveV.allFinite());
513  assert(m_computed.allFinite());
514 #endif
515 
516  m_computed(firstCol + shift, firstCol + shift) = r0;
517  m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) = alphaK * l.transpose().real();
518  m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1, n - k - 1) = betaK * f.transpose().real();
519 
520 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
521  ArrayXr tmp1 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
522 #endif
523  // Second part: try to deflate singular values in combined matrix
524  deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
525 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
526  ArrayXr tmp2 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
527  std::cout << "\n\nj1 = " << tmp1.transpose().format(bdcsvdfmt) << "\n";
528  std::cout << "j2 = " << tmp2.transpose().format(bdcsvdfmt) << "\n\n";
529  std::cout << "err: " << ((tmp1-tmp2).abs()>1e-12*tmp2.abs()).transpose() << "\n";
530  static int count = 0;
531  std::cout << "# " << ++count << "\n\n";
532  assert((tmp1-tmp2).matrix().norm() < 1e-14*tmp2.matrix().norm());
533 // assert(count<681);
534 // assert(((tmp1-tmp2).abs()<1e-13*tmp2.abs()).all());
535 #endif
536 
537  // Third part: compute SVD of combined matrix
538  MatrixXr UofSVD, VofSVD;
539  VectorType singVals;
540  computeSVDofM(firstCol + shift, n, UofSVD, singVals, VofSVD);
541 
542 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
543  assert(UofSVD.allFinite());
544  assert(VofSVD.allFinite());
545 #endif
546 
547  if (m_compU)
548  structured_update(m_naiveU.block(firstCol, firstCol, n + 1, n + 1), UofSVD, (n+2)/2);
549  else
550  {
551  Map<Matrix<RealScalar,2,Dynamic>,Aligned> tmp(m_workspace.data(),2,n+1);
552  tmp.noalias() = m_naiveU.middleCols(firstCol, n+1) * UofSVD;
553  m_naiveU.middleCols(firstCol, n + 1) = tmp;
554  }
555 
556  if (m_compV) structured_update(m_naiveV.block(firstRowW, firstColW, n, n), VofSVD, (n+1)/2);
557 
558 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
559  assert(m_naiveU.allFinite());
560  assert(m_naiveV.allFinite());
561  assert(m_computed.allFinite());
562 #endif
563 
564  m_computed.block(firstCol + shift, firstCol + shift, n, n).setZero();
565  m_computed.block(firstCol + shift, firstCol + shift, n, n).diagonal() = singVals;
566 }// end divide
567 
568 // Compute SVD of m_computed.block(firstCol, firstCol, n + 1, n); this block only has non-zeros in
569 // the first column and on the diagonal and has undergone deflation, so diagonal is in increasing
570 // order except for possibly the (0,0) entry. The computed SVD is stored U, singVals and V, except
571 // that if m_compV is false, then V is not computed. Singular values are sorted in decreasing order.
572 //
573 // TODO Opportunities for optimization: better root finding algo, better stopping criterion, better
574 // handling of round-off errors, be consistent in ordering
575 // For instance, to solve the secular equation using FMM, see http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf
576 template <typename MatrixType>
577 void BDCSVD<MatrixType>::computeSVDofM(Eigen::Index firstCol, Eigen::Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V)
578 {
579  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
580  using std::abs;
581  ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n);
582  m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal();
583  ArrayRef diag = m_workspace.head(n);
584  diag(0) = Literal(0);
585 
586  // Allocate space for singular values and vectors
587  singVals.resize(n);
588  U.resize(n+1, n+1);
589  if (m_compV) V.resize(n, n);
590 
591 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
592  if (col0.hasNaN() || diag.hasNaN())
593  std::cout << "\n\nHAS NAN\n\n";
594 #endif
595 
596  // Many singular values might have been deflated, the zero ones have been moved to the end,
597  // but others are interleaved and we must ignore them at this stage.
598  // To this end, let's compute a permutation skipping them:
599  Index actual_n = n;
600  while(actual_n>1 && diag(actual_n-1)==Literal(0)) {--actual_n; eigen_internal_assert(col0(actual_n)==Literal(0)); }
601  Index m = 0; // size of the deflated problem
602  for(Index k=0;k<actual_n;++k)
603  if(abs(col0(k))>considerZero)
604  m_workspaceI(m++) = k;
605  Map<ArrayXi> perm(m_workspaceI.data(),m);
606 
607  Map<ArrayXr> shifts(m_workspace.data()+1*n, n);
608  Map<ArrayXr> mus(m_workspace.data()+2*n, n);
609  Map<ArrayXr> zhat(m_workspace.data()+3*n, n);
610 
611 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
612  std::cout << "computeSVDofM using:\n";
613  std::cout << " z: " << col0.transpose() << "\n";
614  std::cout << " d: " << diag.transpose() << "\n";
615 #endif
616 
617  // Compute singVals, shifts, and mus
618  computeSingVals(col0, diag, perm, singVals, shifts, mus);
619 
620 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
621  std::cout << " j: " << (m_computed.block(firstCol, firstCol, n, n)).jacobiSvd().singularValues().transpose().reverse() << "\n\n";
622  std::cout << " sing-val: " << singVals.transpose() << "\n";
623  std::cout << " mu: " << mus.transpose() << "\n";
624  std::cout << " shift: " << shifts.transpose() << "\n";
625 
626  {
627  std::cout << "\n\n mus: " << mus.head(actual_n).transpose() << "\n\n";
628  std::cout << " check1 (expect0) : " << ((singVals.array()-(shifts+mus)) / singVals.array()).head(actual_n).transpose() << "\n\n";
629  assert((((singVals.array()-(shifts+mus)) / singVals.array()).head(actual_n) >= 0).all());
630  std::cout << " check2 (>0) : " << ((singVals.array()-diag) / singVals.array()).head(actual_n).transpose() << "\n\n";
631  assert((((singVals.array()-diag) / singVals.array()).head(actual_n) >= 0).all());
632  }
633 #endif
634 
635 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
636  assert(singVals.allFinite());
637  assert(mus.allFinite());
638  assert(shifts.allFinite());
639 #endif
640 
641  // Compute zhat
642  perturbCol0(col0, diag, perm, singVals, shifts, mus, zhat);
643 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
644  std::cout << " zhat: " << zhat.transpose() << "\n";
645 #endif
646 
647 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
648  assert(zhat.allFinite());
649 #endif
650 
651  computeSingVecs(zhat, diag, perm, singVals, shifts, mus, U, V);
652 
653 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
654  std::cout << "U^T U: " << (U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() << "\n";
655  std::cout << "V^T V: " << (V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() << "\n";
656 #endif
657 
658 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
659  assert(m_naiveU.allFinite());
660  assert(m_naiveV.allFinite());
661  assert(m_computed.allFinite());
662  assert(U.allFinite());
663  assert(V.allFinite());
664 // assert((U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() < 100*NumTraits<RealScalar>::epsilon() * n);
665 // assert((V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() < 100*NumTraits<RealScalar>::epsilon() * n);
666 #endif
667 
668  // Because of deflation, the singular values might not be completely sorted.
669  // Fortunately, reordering them is a O(n) problem
670  for(Index i=0; i<actual_n-1; ++i)
671  {
672  if(singVals(i)>singVals(i+1))
673  {
674  using std::swap;
675  swap(singVals(i),singVals(i+1));
676  U.col(i).swap(U.col(i+1));
677  if(m_compV) V.col(i).swap(V.col(i+1));
678  }
679  }
680 
681 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
682  {
683  bool singular_values_sorted = (((singVals.segment(1,actual_n-1)-singVals.head(actual_n-1))).array() >= 0).all();
684  if(!singular_values_sorted)
685  std::cout << "Singular values are not sorted: " << singVals.segment(1,actual_n).transpose() << "\n";
686  assert(singular_values_sorted);
687  }
688 #endif
689 
690  // Reverse order so that singular values in increased order
691  // Because of deflation, the zeros singular-values are already at the end
692  singVals.head(actual_n).reverseInPlace();
693  U.leftCols(actual_n).rowwise().reverseInPlace();
694  if (m_compV) V.leftCols(actual_n).rowwise().reverseInPlace();
695 
696 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
697  JacobiSVD<MatrixXr> jsvd(m_computed.block(firstCol, firstCol, n, n) );
698  std::cout << " * j: " << jsvd.singularValues().transpose() << "\n\n";
699  std::cout << " * sing-val: " << singVals.transpose() << "\n";
700 // std::cout << " * err: " << ((jsvd.singularValues()-singVals)>1e-13*singVals.norm()).transpose() << "\n";
701 #endif
702 }
703 
704 template <typename MatrixType>
705 typename BDCSVD<MatrixType>::RealScalar BDCSVD<MatrixType>::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift)
706 {
707  Index m = perm.size();
708  RealScalar res = Literal(1);
709  for(Index i=0; i<m; ++i)
710  {
711  Index j = perm(i);
712  // The following expression could be rewritten to involve only a single division,
713  // but this would make the expression more sensitive to overflow.
714  res += (col0(j) / (diagShifted(j) - mu)) * (col0(j) / (diag(j) + shift + mu));
715  }
716  return res;
717 
718 }
719 
720 template <typename MatrixType>
721 void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm,
722  VectorType& singVals, ArrayRef shifts, ArrayRef mus)
723 {
724  using std::abs;
725  using std::swap;
726  using std::sqrt;
727 
728  Index n = col0.size();
729  Index actual_n = n;
730  // Note that here actual_n is computed based on col0(i)==0 instead of diag(i)==0 as above
731  // because 1) we have diag(i)==0 => col0(i)==0 and 2) if col0(i)==0, then diag(i) is already a singular value.
732  while(actual_n>1 && col0(actual_n-1)==Literal(0)) --actual_n;
733 
734  for (Index k = 0; k < n; ++k)
735  {
736  if (col0(k) == Literal(0) || actual_n==1)
737  {
738  // if col0(k) == 0, then entry is deflated, so singular value is on diagonal
739  // if actual_n==1, then the deflated problem is already diagonalized
740  singVals(k) = k==0 ? col0(0) : diag(k);
741  mus(k) = Literal(0);
742  shifts(k) = k==0 ? col0(0) : diag(k);
743  continue;
744  }
745 
746  // otherwise, use secular equation to find singular value
747  RealScalar left = diag(k);
748  RealScalar right; // was: = (k != actual_n-1) ? diag(k+1) : (diag(actual_n-1) + col0.matrix().norm());
749  if(k==actual_n-1)
750  right = (diag(actual_n-1) + col0.matrix().norm());
751  else
752  {
753  // Skip deflated singular values,
754  // recall that at this stage we assume that z[j]!=0 and all entries for which z[j]==0 have been put aside.
755  // This should be equivalent to using perm[]
756  Index l = k+1;
757  while(col0(l)==Literal(0)) { ++l; eigen_internal_assert(l<actual_n); }
758  right = diag(l);
759  }
760 
761  // first decide whether it's closer to the left end or the right end
762  RealScalar mid = left + (right-left) / Literal(2);
763  RealScalar fMid = secularEq(mid, col0, diag, perm, diag, Literal(0));
764 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
765  std::cout << "right-left = " << right-left << "\n";
766 // std::cout << "fMid = " << fMid << " " << secularEq(mid-left, col0, diag, perm, ArrayXr(diag-left), left)
767 // << " " << secularEq(mid-right, col0, diag, perm, ArrayXr(diag-right), right) << "\n";
768  std::cout << " = " << secularEq(left+RealScalar(0.000001)*(right-left), col0, diag, perm, diag, 0)
769  << " " << secularEq(left+RealScalar(0.1) *(right-left), col0, diag, perm, diag, 0)
770  << " " << secularEq(left+RealScalar(0.2) *(right-left), col0, diag, perm, diag, 0)
771  << " " << secularEq(left+RealScalar(0.3) *(right-left), col0, diag, perm, diag, 0)
772  << " " << secularEq(left+RealScalar(0.4) *(right-left), col0, diag, perm, diag, 0)
773  << " " << secularEq(left+RealScalar(0.49) *(right-left), col0, diag, perm, diag, 0)
774  << " " << secularEq(left+RealScalar(0.5) *(right-left), col0, diag, perm, diag, 0)
775  << " " << secularEq(left+RealScalar(0.51) *(right-left), col0, diag, perm, diag, 0)
776  << " " << secularEq(left+RealScalar(0.6) *(right-left), col0, diag, perm, diag, 0)
777  << " " << secularEq(left+RealScalar(0.7) *(right-left), col0, diag, perm, diag, 0)
778  << " " << secularEq(left+RealScalar(0.8) *(right-left), col0, diag, perm, diag, 0)
779  << " " << secularEq(left+RealScalar(0.9) *(right-left), col0, diag, perm, diag, 0)
780  << " " << secularEq(left+RealScalar(0.999999)*(right-left), col0, diag, perm, diag, 0) << "\n";
781 #endif
782  RealScalar shift = (k == actual_n-1 || fMid > Literal(0)) ? left : right;
783 
784  // measure everything relative to shift
785  Map<ArrayXr> diagShifted(m_workspace.data()+4*n, n);
786  diagShifted = diag - shift;
787 
788  if(k!=actual_n-1)
789  {
790  // check that after the shift, f(mid) is still negative:
791  RealScalar midShifted = (right - left) / RealScalar(2);
792  if(shift==right)
793  midShifted = -midShifted;
794  RealScalar fMidShifted = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
795  if(fMidShifted>0)
796  {
797  // fMid was erroneous, fix it:
798  shift = fMidShifted > Literal(0) ? left : right;
799  diagShifted = diag - shift;
800  }
801  }
802 
803  // initial guess
804  RealScalar muPrev, muCur;
805  if (shift == left)
806  {
807  muPrev = (right - left) * RealScalar(0.1);
808  if (k == actual_n-1) muCur = right - left;
809  else muCur = (right - left) * RealScalar(0.5);
810  }
811  else
812  {
813  muPrev = -(right - left) * RealScalar(0.1);
814  muCur = -(right - left) * RealScalar(0.5);
815  }
816 
817  RealScalar fPrev = secularEq(muPrev, col0, diag, perm, diagShifted, shift);
818  RealScalar fCur = secularEq(muCur, col0, diag, perm, diagShifted, shift);
819  if (abs(fPrev) < abs(fCur))
820  {
821  swap(fPrev, fCur);
822  swap(muPrev, muCur);
823  }
824 
825  // rational interpolation: fit a function of the form a / mu + b through the two previous
826  // iterates and use its zero to compute the next iterate
827  bool useBisection = fPrev*fCur>Literal(0);
828  while (fCur!=Literal(0) && abs(muCur - muPrev) > Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits<RealScalar>::epsilon() && !useBisection)
829  {
830  ++m_numIters;
831 
832  // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples.
833  RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev);
834  RealScalar b = fCur - a / muCur;
835  // And find mu such that f(mu)==0:
836  RealScalar muZero = -a/b;
837  RealScalar fZero = secularEq(muZero, col0, diag, perm, diagShifted, shift);
838 
839 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
840  assert((numext::isfinite)(fZero));
841 #endif
842 
843  muPrev = muCur;
844  fPrev = fCur;
845  muCur = muZero;
846  fCur = fZero;
847 
848  if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection = true;
849  if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true;
850  if (abs(fCur)>abs(fPrev)) useBisection = true;
851  }
852 
853  // fall back on bisection method if rational interpolation did not work
854  if (useBisection)
855  {
856 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
857  std::cout << "useBisection for k = " << k << ", actual_n = " << actual_n << "\n";
858 #endif
859  RealScalar leftShifted, rightShifted;
860  if (shift == left)
861  {
862  // to avoid overflow, we must have mu > max(real_min, |z(k)|/sqrt(real_max)),
863  // the factor 2 is to be more conservative
864  leftShifted = numext::maxi<RealScalar>( (std::numeric_limits<RealScalar>::min)(), Literal(2) * abs(col0(k)) / sqrt((std::numeric_limits<RealScalar>::max)()) );
865 
866  // check that we did it right:
867  eigen_internal_assert( (numext::isfinite)( (col0(k)/leftShifted)*(col0(k)/(diag(k)+shift+leftShifted)) ) );
868  // I don't understand why the case k==0 would be special there:
869  // if (k == 0) rightShifted = right - left; else
870  rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe
871  }
872  else
873  {
874  leftShifted = -(right - left) * RealScalar(0.51);
875  if(k+1<n)
876  rightShifted = -numext::maxi<RealScalar>( (std::numeric_limits<RealScalar>::min)(), abs(col0(k+1)) / sqrt((std::numeric_limits<RealScalar>::max)()) );
877  else
878  rightShifted = -(std::numeric_limits<RealScalar>::min)();
879  }
880 
881  RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift);
882  eigen_internal_assert(fLeft<Literal(0));
883 
884 #if defined EIGEN_INTERNAL_DEBUGGING || defined EIGEN_BDCSVD_SANITY_CHECKS
885  RealScalar fRight = secularEq(rightShifted, col0, diag, perm, diagShifted, shift);
886 #endif
887 
888 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
889  if(!(numext::isfinite)(fLeft))
890  std::cout << "f(" << leftShifted << ") =" << fLeft << " ; " << left << " " << shift << " " << right << "\n";
891  assert((numext::isfinite)(fLeft));
892 
893  if(!(numext::isfinite)(fRight))
894  std::cout << "f(" << rightShifted << ") =" << fRight << " ; " << left << " " << shift << " " << right << "\n";
895  // assert((numext::isfinite)(fRight));
896 #endif
897 
898 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
899  if(!(fLeft * fRight<0))
900  {
901  std::cout << "f(leftShifted) using leftShifted=" << leftShifted << " ; diagShifted(1:10):" << diagShifted.head(10).transpose() << "\n ; "
902  << "left==shift=" << bool(left==shift) << " ; left-shift = " << (left-shift) << "\n";
903  std::cout << "k=" << k << ", " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; "
904  << "[" << left << " .. " << right << "] -> [" << leftShifted << " " << rightShifted << "], shift=" << shift
905  << " , f(right)=" << secularEq(0, col0, diag, perm, diagShifted, shift)
906  << " == " << secularEq(right, col0, diag, perm, diag, 0) << " == " << fRight << "\n";
907  }
908 #endif
909  eigen_internal_assert(fLeft * fRight < Literal(0));
910 
911  if(fLeft<Literal(0))
912  {
913  while (rightShifted - leftShifted > Literal(2) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted)))
914  {
915  RealScalar midShifted = (leftShifted + rightShifted) / Literal(2);
916  fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
917  eigen_internal_assert((numext::isfinite)(fMid));
918 
919  if (fLeft * fMid < Literal(0))
920  {
921  rightShifted = midShifted;
922  }
923  else
924  {
925  leftShifted = midShifted;
926  fLeft = fMid;
927  }
928  }
929  muCur = (leftShifted + rightShifted) / Literal(2);
930  }
931  else
932  {
933  // We have a problem as shifting on the left or right give either a positive or negative value
934  // at the middle of [left,right]...
935  // Instead fo abbording or entering an infinite loop,
936  // let's just use the middle as the estimated zero-crossing:
937  muCur = (right - left) * RealScalar(0.5);
938  if(shift == right)
939  muCur = -muCur;
940  }
941  }
942 
943  singVals[k] = shift + muCur;
944  shifts[k] = shift;
945  mus[k] = muCur;
946 
947 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
948  if(k+1<n)
949  std::cout << "found " << singVals[k] << " == " << shift << " + " << muCur << " from " << diag(k) << " .. " << diag(k+1) << "\n";
950 #endif
951 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
952  assert(k==0 || singVals[k]>=singVals[k-1]);
953  assert(singVals[k]>=diag(k));
954 #endif
955 
956  // perturb singular value slightly if it equals diagonal entry to avoid division by zero later
957  // (deflation is supposed to avoid this from happening)
958  // - this does no seem to be necessary anymore -
959 // if (singVals[k] == left) singVals[k] *= 1 + NumTraits<RealScalar>::epsilon();
960 // if (singVals[k] == right) singVals[k] *= 1 - NumTraits<RealScalar>::epsilon();
961  }
962 }
963 
964 
965 // zhat is perturbation of col0 for which singular vectors can be computed stably (see Section 3.1)
966 template <typename MatrixType>
967 void BDCSVD<MatrixType>::perturbCol0
968  (const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const VectorType& singVals,
969  const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat)
970 {
971  using std::sqrt;
972  Index n = col0.size();
973  Index m = perm.size();
974  if(m==0)
975  {
976  zhat.setZero();
977  return;
978  }
979  Index lastIdx = perm(m-1);
980  // The offset permits to skip deflated entries while computing zhat
981  for (Index k = 0; k < n; ++k)
982  {
983  if (col0(k) == Literal(0)) // deflated
984  zhat(k) = Literal(0);
985  else
986  {
987  // see equation (3.6)
988  RealScalar dk = diag(k);
989  RealScalar prod = (singVals(lastIdx) + dk) * (mus(lastIdx) + (shifts(lastIdx) - dk));
990 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
991  if(prod<0) {
992  std::cout << "k = " << k << " ; z(k)=" << col0(k) << ", diag(k)=" << dk << "\n";
993  std::cout << "prod = " << "(" << singVals(lastIdx) << " + " << dk << ") * (" << mus(lastIdx) << " + (" << shifts(lastIdx) << " - " << dk << "))" << "\n";
994  std::cout << " = " << singVals(lastIdx) + dk << " * " << mus(lastIdx) + (shifts(lastIdx) - dk) << "\n";
995  }
996  assert(prod>=0);
997 #endif
998 
999  for(Index l = 0; l<m; ++l)
1000  {
1001  Index i = perm(l);
1002  if(i!=k)
1003  {
1004 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1005  if(i>=k && (l==0 || l-1>=m))
1006  {
1007  std::cout << "Error in perturbCol0\n";
1008  std::cout << " " << k << "/" << n << " " << l << "/" << m << " " << i << "/" << n << " ; " << col0(k) << " " << diag(k) << " " << "\n";
1009  std::cout << " " <<diag(i) << "\n";
1010  Index j = (i<k /*|| l==0*/) ? i : perm(l-1);
1011  std::cout << " " << "j=" << j << "\n";
1012  }
1013 #endif
1014  Index j = i<k ? i : perm(l-1);
1015 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1016  if(!(dk!=Literal(0) || diag(i)!=Literal(0)))
1017  {
1018  std::cout << "k=" << k << ", i=" << i << ", l=" << l << ", perm.size()=" << perm.size() << "\n";
1019  }
1020  assert(dk!=Literal(0) || diag(i)!=Literal(0));
1021 #endif
1022  prod *= ((singVals(j)+dk) / ((diag(i)+dk))) * ((mus(j)+(shifts(j)-dk)) / ((diag(i)-dk)));
1023 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1024  assert(prod>=0);
1025 #endif
1026 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1027  if(i!=k && numext::abs(((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) - 1) > 0.9 )
1028  std::cout << " " << ((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) << " == (" << (singVals(j)+dk) << " * " << (mus(j)+(shifts(j)-dk))
1029  << ") / (" << (diag(i)+dk) << " * " << (diag(i)-dk) << ")\n";
1030 #endif
1031  }
1032  }
1033 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1034  std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(lastIdx) + dk) << " * " << mus(lastIdx) + shifts(lastIdx) << " - " << dk << "\n";
1035 #endif
1036  RealScalar tmp = sqrt(prod);
1037 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1038  assert((numext::isfinite)(tmp));
1039 #endif
1040  zhat(k) = col0(k) > Literal(0) ? RealScalar(tmp) : RealScalar(-tmp);
1041  }
1042  }
1043 }
1044 
1045 // compute singular vectors
1046 template <typename MatrixType>
1047 void BDCSVD<MatrixType>::computeSingVecs
1048  (const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef &perm, const VectorType& singVals,
1049  const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V)
1050 {
1051  Index n = zhat.size();
1052  Index m = perm.size();
1053 
1054  for (Index k = 0; k < n; ++k)
1055  {
1056  if (zhat(k) == Literal(0))
1057  {
1058  U.col(k) = VectorType::Unit(n+1, k);
1059  if (m_compV) V.col(k) = VectorType::Unit(n, k);
1060  }
1061  else
1062  {
1063  U.col(k).setZero();
1064  for(Index l=0;l<m;++l)
1065  {
1066  Index i = perm(l);
1067  U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
1068  }
1069  U(n,k) = Literal(0);
1070  U.col(k).normalize();
1071 
1072  if (m_compV)
1073  {
1074  V.col(k).setZero();
1075  for(Index l=1;l<m;++l)
1076  {
1077  Index i = perm(l);
1078  V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
1079  }
1080  V(0,k) = Literal(-1);
1081  V.col(k).normalize();
1082  }
1083  }
1084  }
1085  U.col(n) = VectorType::Unit(n+1, n);
1086 }
1087 
1088 
1089 // page 12_13
1090 // i >= 1, di almost null and zi non null.
1091 // We use a rotation to zero out zi applied to the left of M
1092 template <typename MatrixType>
1093 void BDCSVD<MatrixType>::deflation43(Eigen::Index firstCol, Eigen::Index shift, Eigen::Index i, Eigen::Index size)
1094 {
1095  using std::abs;
1096  using std::sqrt;
1097  using std::pow;
1098  Index start = firstCol + shift;
1099  RealScalar c = m_computed(start, start);
1100  RealScalar s = m_computed(start+i, start);
1101  RealScalar r = numext::hypot(c,s);
1102  if (r == Literal(0))
1103  {
1104  m_computed(start+i, start+i) = Literal(0);
1105  return;
1106  }
1107  m_computed(start,start) = r;
1108  m_computed(start+i, start) = Literal(0);
1109  m_computed(start+i, start+i) = Literal(0);
1110 
1111  JacobiRotation<RealScalar> J(c/r,-s/r);
1112  if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J);
1113  else m_naiveU.applyOnTheRight(firstCol, firstCol+i, J);
1114 }// end deflation 43
1115 
1116 
1117 // page 13
1118 // i,j >= 1, i!=j and |di - dj| < epsilon * norm2(M)
1119 // We apply two rotations to have zj = 0;
1120 // TODO deflation44 is still broken and not properly tested
1121 template <typename MatrixType>
1122 void BDCSVD<MatrixType>::deflation44(Eigen::Index firstColu , Eigen::Index firstColm, Eigen::Index firstRowW, Eigen::Index firstColW, Eigen::Index i, Eigen::Index j, Eigen::Index size)
1123 {
1124  using std::abs;
1125  using std::sqrt;
1126  using std::conj;
1127  using std::pow;
1128  RealScalar c = m_computed(firstColm+i, firstColm);
1129  RealScalar s = m_computed(firstColm+j, firstColm);
1130  RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s));
1131 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1132  std::cout << "deflation 4.4: " << i << "," << j << " -> " << c << " " << s << " " << r << " ; "
1133  << m_computed(firstColm + i-1, firstColm) << " "
1134  << m_computed(firstColm + i, firstColm) << " "
1135  << m_computed(firstColm + i+1, firstColm) << " "
1136  << m_computed(firstColm + i+2, firstColm) << "\n";
1137  std::cout << m_computed(firstColm + i-1, firstColm + i-1) << " "
1138  << m_computed(firstColm + i, firstColm+i) << " "
1139  << m_computed(firstColm + i+1, firstColm+i+1) << " "
1140  << m_computed(firstColm + i+2, firstColm+i+2) << "\n";
1141 #endif
1142  if (r==Literal(0))
1143  {
1144  m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
1145  return;
1146  }
1147  c/=r;
1148  s/=r;
1149  m_computed(firstColm + i, firstColm) = r;
1150  m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
1151  m_computed(firstColm + j, firstColm) = Literal(0);
1152 
1153  JacobiRotation<RealScalar> J(c,-s);
1154  if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J);
1155  else m_naiveU.applyOnTheRight(firstColu+i, firstColu+j, J);
1156  if (m_compV) m_naiveV.middleRows(firstRowW, size).applyOnTheRight(firstColW + i, firstColW + j, J);
1157 }// end deflation 44
1158 
1159 
1160 // acts on block from (firstCol+shift, firstCol+shift) to (lastCol+shift, lastCol+shift) [inclusive]
1161 template <typename MatrixType>
1162 void BDCSVD<MatrixType>::deflation(Eigen::Index firstCol, Eigen::Index lastCol, Eigen::Index k, Eigen::Index firstRowW, Eigen::Index firstColW, Eigen::Index shift)
1163 {
1164  using std::sqrt;
1165  using std::abs;
1166  const Index length = lastCol + 1 - firstCol;
1167 
1168  Block<MatrixXr,Dynamic,1> col0(m_computed, firstCol+shift, firstCol+shift, length, 1);
1169  Diagonal<MatrixXr> fulldiag(m_computed);
1170  VectorBlock<Diagonal<MatrixXr>,Dynamic> diag(fulldiag, firstCol+shift, length);
1171 
1172  const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
1173  RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff();
1174  RealScalar epsilon_strict = numext::maxi<RealScalar>(considerZero,NumTraits<RealScalar>::epsilon() * maxDiag);
1175  RealScalar epsilon_coarse = Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
1176 
1177 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1178  assert(m_naiveU.allFinite());
1179  assert(m_naiveV.allFinite());
1180  assert(m_computed.allFinite());
1181 #endif
1182 
1183 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1184  std::cout << "\ndeflate:" << diag.head(k+1).transpose() << " | " << diag.segment(k+1,length-k-1).transpose() << "\n";
1185 #endif
1186 
1187  //condition 4.1
1188  if (diag(0) < epsilon_coarse)
1189  {
1190 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1191  std::cout << "deflation 4.1, because " << diag(0) << " < " << epsilon_coarse << "\n";
1192 #endif
1193  diag(0) = epsilon_coarse;
1194  }
1195 
1196  //condition 4.2
1197  for (Index i=1;i<length;++i)
1198  if (abs(col0(i)) < epsilon_strict)
1199  {
1200 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1201  std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << " (diag(" << i << ")=" << diag(i) << ")\n";
1202 #endif
1203  col0(i) = Literal(0);
1204  }
1205 
1206  //condition 4.3
1207  for (Index i=1;i<length; i++)
1208  if (diag(i) < epsilon_coarse)
1209  {
1210 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1211  std::cout << "deflation 4.3, cancel z(" << i << ")=" << col0(i) << " because diag(" << i << ")=" << diag(i) << " < " << epsilon_coarse << "\n";
1212 #endif
1213  deflation43(firstCol, shift, i, length);
1214  }
1215 
1216 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1217  assert(m_naiveU.allFinite());
1218  assert(m_naiveV.allFinite());
1219  assert(m_computed.allFinite());
1220 #endif
1221 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1222  std::cout << "to be sorted: " << diag.transpose() << "\n\n";
1223  std::cout << " : " << col0.transpose() << "\n\n";
1224 #endif
1225  {
1226  // Check for total deflation
1227  // If we have a total deflation, then we have to consider col0(0)==diag(0) as a singular value during sorting
1228  bool total_deflation = (col0.tail(length-1).array()<considerZero).all();
1229 
1230  // Sort the diagonal entries, since diag(1:k-1) and diag(k:length) are already sorted, let's do a sorted merge.
1231  // First, compute the respective permutation.
1232  Index *permutation = m_workspaceI.data();
1233  {
1234  permutation[0] = 0;
1235  Index p = 1;
1236 
1237  // Move deflated diagonal entries at the end.
1238  for(Index i=1; i<length; ++i)
1239  if(abs(diag(i))<considerZero)
1240  permutation[p++] = i;
1241 
1242  Index i=1, j=k+1;
1243  for( ; p < length; ++p)
1244  {
1245  if (i > k) permutation[p] = j++;
1246  else if (j >= length) permutation[p] = i++;
1247  else if (diag(i) < diag(j)) permutation[p] = j++;
1248  else permutation[p] = i++;
1249  }
1250  }
1251 
1252  // If we have a total deflation, then we have to insert diag(0) at the right place
1253  if(total_deflation)
1254  {
1255  for(Index i=1; i<length; ++i)
1256  {
1257  Index pi = permutation[i];
1258  if(abs(diag(pi))<considerZero || diag(0)<diag(pi))
1259  permutation[i-1] = permutation[i];
1260  else
1261  {
1262  permutation[i-1] = 0;
1263  break;
1264  }
1265  }
1266  }
1267 
1268  // Current index of each col, and current column of each index
1269  Index *realInd = m_workspaceI.data()+length;
1270  Index *realCol = m_workspaceI.data()+2*length;
1271 
1272  for(int pos = 0; pos< length; pos++)
1273  {
1274  realCol[pos] = pos;
1275  realInd[pos] = pos;
1276  }
1277 
1278  for(Index i = total_deflation?0:1; i < length; i++)
1279  {
1280  const Index pi = permutation[length - (total_deflation ? i+1 : i)];
1281  const Index J = realCol[pi];
1282 
1283  using std::swap;
1284  // swap diagonal and first column entries:
1285  swap(diag(i), diag(J));
1286  if(i!=0 && J!=0) swap(col0(i), col0(J));
1287 
1288  // change columns
1289  if (m_compU) m_naiveU.col(firstCol+i).segment(firstCol, length + 1).swap(m_naiveU.col(firstCol+J).segment(firstCol, length + 1));
1290  else m_naiveU.col(firstCol+i).segment(0, 2) .swap(m_naiveU.col(firstCol+J).segment(0, 2));
1291  if (m_compV) m_naiveV.col(firstColW + i).segment(firstRowW, length).swap(m_naiveV.col(firstColW + J).segment(firstRowW, length));
1292 
1293  //update real pos
1294  const Index realI = realInd[i];
1295  realCol[realI] = J;
1296  realCol[pi] = i;
1297  realInd[J] = realI;
1298  realInd[i] = pi;
1299  }
1300  }
1301 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1302  std::cout << "sorted: " << diag.transpose().format(bdcsvdfmt) << "\n";
1303  std::cout << " : " << col0.transpose() << "\n\n";
1304 #endif
1305 
1306  //condition 4.4
1307  {
1308  Index i = length-1;
1309  while(i>0 && (abs(diag(i))<considerZero || abs(col0(i))<considerZero)) --i;
1310  for(; i>1;--i)
1311  if( (diag(i) - diag(i-1)) < NumTraits<RealScalar>::epsilon()*maxDiag )
1312  {
1313 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
1314  std::cout << "deflation 4.4 with i = " << i << " because " << diag(i) << " - " << diag(i-1) << " == " << (diag(i) - diag(i-1)) << " < " << NumTraits<RealScalar>::epsilon()*/*diag(i)*/maxDiag << "\n";
1315 #endif
1316  eigen_internal_assert(abs(diag(i) - diag(i-1))<epsilon_coarse && " diagonal entries are not properly sorted");
1317  deflation44(firstCol, firstCol + shift, firstRowW, firstColW, i-1, i, length);
1318  }
1319  }
1320 
1321 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1322  for(Index j=2;j<length;++j)
1323  assert(diag(j-1)<=diag(j) || abs(diag(j))<considerZero);
1324 #endif
1325 
1326 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
1327  assert(m_naiveU.allFinite());
1328  assert(m_naiveV.allFinite());
1329  assert(m_computed.allFinite());
1330 #endif
1331 }//end deflation
1332 
1333 #if !defined(EIGEN_GPUCC)
1334 
1340 template<typename Derived>
1341 BDCSVD<typename MatrixBase<Derived>::PlainObject>
1342 MatrixBase<Derived>::bdcSvd(unsigned int computationOptions) const
1343 {
1344  return BDCSVD<PlainObject>(*this, computationOptions);
1345 }
1346 #endif
1347 
1348 } // end namespace Eigen
1349 
1350 #endif
Eigen
Namespace containing all symbols from the Eigen library.
Definition: LDLT.h:16
Eigen::ComputeFullV
@ ComputeFullV
Definition: Constants.h:396
Eigen::SVDBase
Base class of SVD algorithms.
Definition: SVDBase.h:61
Eigen::BDCSVD::BDCSVD
BDCSVD(const MatrixType &matrix, unsigned int computationOptions=0)
Constructor performing the decomposition of given matrix.
Definition: BDCSVD.h:140
Eigen::ComputeFullU
@ ComputeFullU
Definition: Constants.h:392
Eigen::BDCSVD::BDCSVD
BDCSVD(Index rows, Index cols, unsigned int computationOptions=0)
Default Constructor with memory preallocation.
Definition: BDCSVD.h:124
Eigen::Array< RealScalar, Dynamic, 1 >
Eigen::internal::true_type
Definition: Meta.h:63
Eigen::BDCSVD
class Bidiagonal Divide and Conquer SVD
Definition: BDCSVD.h:74
Eigen::Dynamic
const int Dynamic
Definition: Constants.h:21
Eigen::SVDBase::computeU
bool computeU() const
Definition: SVDBase.h:205
Eigen::BDCSVD::compute
BDCSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix using custom options.
Definition: BDCSVD.h:244
Eigen::BDCSVD::BDCSVD
BDCSVD()
Default Constructor.
Definition: BDCSVD.h:114
Eigen::MatrixBase::bdcSvd
BDCSVD< PlainObject > bdcSvd(unsigned int computationOptions=0) const
Definition: BDCSVD.h:1342
Eigen::SVDBase::computeV
bool computeV() const
Definition: SVDBase.h:207
Eigen::JacobiSVD
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition: JacobiSVD.h:490
Eigen::Ref
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:197
Eigen::internal::traits
Definition: ForwardDeclarations.h:17
Eigen::BDCSVD::compute
BDCSVD & compute(const MatrixType &matrix)
Method performing the decomposition of given matrix using current options.
Definition: BDCSVD.h:168
Eigen::Matrix< Scalar, RowsAtCompileTime, RowsAtCompileTime, MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime >
Eigen::internal::UpperBidiagonalization
Definition: UpperBidiagonalization.h:21
Eigen::NumTraits
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:213
Eigen::Index
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:42
Eigen::Aligned
@ Aligned
Definition: Constants.h:239