MOAB  4.9.3pre
BDCSVD.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 // 
00004 // We used the "A Divide-And-Conquer Algorithm for the Bidiagonal SVD"
00005 // research report written by Ming Gu and Stanley C.Eisenstat
00006 // The code variable names correspond to the names they used in their 
00007 // report
00008 //
00009 // Copyright (C) 2013 Gauthier Brun <[email protected]>
00010 // Copyright (C) 2013 Nicolas Carre <[email protected]>
00011 // Copyright (C) 2013 Jean Ceccato <[email protected]>
00012 // Copyright (C) 2013 Pierre Zoppitelli <[email protected]>
00013 // Copyright (C) 2013 Jitse Niesen <[email protected]>
00014 // Copyright (C) 2014 Gael Guennebaud <[email protected]>
00015 //
00016 // Source Code Form is subject to the terms of the Mozilla
00017 // Public License v. 2.0. If a copy of the MPL was not distributed
00018 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00019 
00020 #ifndef EIGEN_BDCSVD_H
00021 #define EIGEN_BDCSVD_H
00022 // #define EIGEN_BDCSVD_DEBUG_VERBOSE
00023 // #define EIGEN_BDCSVD_SANITY_CHECKS
00024 namespace Eigen {
00025 
00026 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00027 IOFormat bdcsvdfmt(8, 0, ", ", "\n", "  [", "]");
00028 #endif
00029   
00030 template<typename _MatrixType> class BDCSVD;
00031 
00032 namespace internal {
00033 
00034 template<typename _MatrixType> 
00035 struct traits<BDCSVD<_MatrixType> >
00036 {
00037   typedef _MatrixType MatrixType;
00038 };  
00039 
00040 } // end namespace internal
00041   
00042   
00053 template<typename _MatrixType> 
00054 class BDCSVD : public SVDBase<BDCSVD<_MatrixType> >
00055 {
00056   typedef SVDBase<BDCSVD> Base;
00057     
00058 public:
00059   using Base::rows;
00060   using Base::cols;
00061   using Base::computeU;
00062   using Base::computeV;
00063   
00064   typedef _MatrixType MatrixType;
00065   typedef typename MatrixType::Scalar Scalar;
00066   typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
00067   enum {
00068     RowsAtCompileTime = MatrixType::RowsAtCompileTime, 
00069     ColsAtCompileTime = MatrixType::ColsAtCompileTime, 
00070     DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime, ColsAtCompileTime), 
00071     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 
00072     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, 
00073     MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime, MaxColsAtCompileTime), 
00074     MatrixOptions = MatrixType::Options
00075   };
00076 
00077   typedef typename Base::MatrixUType MatrixUType;
00078   typedef typename Base::MatrixVType MatrixVType;
00079   typedef typename Base::SingularValuesType SingularValuesType;
00080   
00081   typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> MatrixX;
00082   typedef Matrix<RealScalar, Dynamic, Dynamic, ColMajor> MatrixXr;
00083   typedef Matrix<RealScalar, Dynamic, 1> VectorType;
00084   typedef Array<RealScalar, Dynamic, 1> ArrayXr;
00085   typedef Array<Index,1,Dynamic> ArrayXi;
00086   typedef Ref<ArrayXr> ArrayRef;
00087   typedef Ref<ArrayXi> IndicesRef;
00088 
00094   BDCSVD() : m_algoswap(16), m_numIters(0)
00095   {}
00096 
00097 
00104   BDCSVD(Index p_rows, Index p_cols, unsigned int computationOptions = 0)
00105     : m_algoswap(16), m_numIters(0)
00106   {
00107     allocate(p_rows, p_cols, computationOptions);
00108   }
00109 
00120   BDCSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
00121     : m_algoswap(16), m_numIters(0)
00122   {
00123     compute(matrix, computationOptions);
00124   }
00125 
00126   ~BDCSVD() 
00127   {
00128   }
00129   
00140   BDCSVD& compute(const MatrixType& matrix, unsigned int computationOptions);
00141 
00148   BDCSVD& compute(const MatrixType& matrix)
00149   {
00150     return compute(matrix, this->m_computationOptions);
00151   }
00152 
00153   void setSwitchSize(int s) 
00154   {
00155     eigen_assert(s>3 && "BDCSVD the size of the algo switch has to be greater than 3");
00156     m_algoswap = s;
00157   }
00158  
00159 private:
00160   void allocate(Index rows, Index cols, unsigned int computationOptions);
00161   void divide(Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift);
00162   void computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V);
00163   void computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, VectorType& singVals, ArrayRef shifts, ArrayRef mus);
00164   void perturbCol0(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat);
00165   void computeSingVecs(const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef& perm, const VectorType& singVals, const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V);
00166   void deflation43(Index firstCol, Index shift, Index i, Index size);
00167   void deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size);
00168   void deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift);
00169   template<typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
00170   void copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naivev);
00171   void structured_update(Block<MatrixXr,Dynamic,Dynamic> A, const MatrixXr &B, Index n1);
00172   static RealScalar secularEq(RealScalar x, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift);
00173 
00174 protected:
00175   MatrixXr m_naiveU, m_naiveV;
00176   MatrixXr m_computed;
00177   Index m_nRec;
00178   ArrayXr m_workspace;
00179   ArrayXi m_workspaceI;
00180   int m_algoswap;
00181   bool m_isTranspose, m_compU, m_compV;
00182   
00183   using Base::m_singularValues;
00184   using Base::m_diagSize;
00185   using Base::m_computeFullU;
00186   using Base::m_computeFullV;
00187   using Base::m_computeThinU;
00188   using Base::m_computeThinV;
00189   using Base::m_matrixU;
00190   using Base::m_matrixV;
00191   using Base::m_isInitialized;
00192   using Base::m_nonzeroSingularValues;
00193 
00194 public:  
00195   int m_numIters;
00196 }; //end class BDCSVD
00197 
00198 
00199 // Method to allocate and initialize matrix and attributes
00200 template<typename MatrixType>
00201 void BDCSVD<MatrixType>::allocate(Index p_rows, Index p_cols, unsigned int computationOptions)
00202 {
00203   m_isTranspose = (p_cols > p_rows);
00204 
00205   if (Base::allocate(p_rows, p_cols, computationOptions))
00206     return;
00207   
00208   m_computed = MatrixXr::Zero(m_diagSize + 1, m_diagSize );
00209   m_compU = computeV();
00210   m_compV = computeU();
00211   if (m_isTranspose)
00212     std::swap(m_compU, m_compV);
00213   
00214   if (m_compU) m_naiveU = MatrixXr::Zero(m_diagSize + 1, m_diagSize + 1 );
00215   else         m_naiveU = MatrixXr::Zero(2, m_diagSize + 1 );
00216   
00217   if (m_compV) m_naiveV = MatrixXr::Zero(m_diagSize, m_diagSize);
00218   
00219   m_workspace.resize((m_diagSize+1)*(m_diagSize+1)*3);
00220   m_workspaceI.resize(3*m_diagSize);
00221 }// end allocate
00222 
00223 template<typename MatrixType>
00224 BDCSVD<MatrixType>& BDCSVD<MatrixType>::compute(const MatrixType& matrix, unsigned int computationOptions) 
00225 {
00226 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00227   std::cout << "\n\n\n======================================================================================================================\n\n\n";
00228 #endif
00229   allocate(matrix.rows(), matrix.cols(), computationOptions);
00230   using std::abs;
00231   
00232   //**** step -1 - If the problem is too small, directly falls back to JacobiSVD and return
00233   if(matrix.cols() < m_algoswap)
00234   {
00235     // FIXME this line involves temporaries
00236     JacobiSVD<MatrixType> jsvd(matrix,computationOptions);
00237     if(computeU()) m_matrixU = jsvd.matrixU();
00238     if(computeV()) m_matrixV = jsvd.matrixV();
00239     m_singularValues = jsvd.singularValues();
00240     m_nonzeroSingularValues = jsvd.nonzeroSingularValues();
00241     m_isInitialized = true;
00242     return *this;
00243   }
00244   
00245   //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows
00246   RealScalar scale = matrix.cwiseAbs().maxCoeff();
00247   if(scale==RealScalar(0)) scale = RealScalar(1);
00248   MatrixX copy;
00249   if (m_isTranspose) copy = matrix.adjoint()/scale;
00250   else               copy = matrix/scale;
00251   
00252   //**** step 1 - Bidiagonalization
00253   // FIXME this line involves temporaries
00254   internal::UpperBidiagonalization<MatrixX> bid(copy);
00255 
00256   //**** step 2 - Divide & Conquer
00257   m_naiveU.setZero();
00258   m_naiveV.setZero();
00259   // FIXME this line involves a temporary matrix
00260   m_computed.topRows(m_diagSize) = bid.bidiagonal().toDenseMatrix().transpose();
00261   m_computed.template bottomRows<1>().setZero();
00262   divide(0, m_diagSize - 1, 0, 0, 0);
00263 
00264   //**** step 3 - Copy singular values and vectors
00265   for (int i=0; i<m_diagSize; i++)
00266   {
00267     RealScalar a = abs(m_computed.coeff(i, i));
00268     m_singularValues.coeffRef(i) = a * scale;
00269     if (a == 0)
00270     {
00271       m_nonzeroSingularValues = i;
00272       m_singularValues.tail(m_diagSize - i - 1).setZero();
00273       break;
00274     }
00275     else if (i == m_diagSize - 1)
00276     {
00277       m_nonzeroSingularValues = i + 1;
00278       break;
00279     }
00280   }
00281 
00282 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00283 //   std::cout << "m_naiveU\n" << m_naiveU << "\n\n";
00284 //   std::cout << "m_naiveV\n" << m_naiveV << "\n\n";
00285 #endif
00286   if(m_isTranspose) copyUV(bid.householderV(), bid.householderU(), m_naiveV, m_naiveU);
00287   else              copyUV(bid.householderU(), bid.householderV(), m_naiveU, m_naiveV);
00288 
00289   m_isInitialized = true;
00290   return *this;
00291 }// end compute
00292 
00293 
00294 template<typename MatrixType>
00295 template<typename HouseholderU, typename HouseholderV, typename NaiveU, typename NaiveV>
00296 void BDCSVD<MatrixType>::copyUV(const HouseholderU &householderU, const HouseholderV &householderV, const NaiveU &naiveU, const NaiveV &naiveV)
00297 {
00298   // Note exchange of U and V: m_matrixU is set from m_naiveV and vice versa
00299   if (computeU())
00300   {
00301     Index Ucols = m_computeThinU ? m_diagSize : householderU.cols();
00302     m_matrixU = MatrixX::Identity(householderU.cols(), Ucols);
00303     m_matrixU.topLeftCorner(m_diagSize, m_diagSize) = naiveV.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
00304     householderU.applyThisOnTheLeft(m_matrixU); // FIXME this line involves a temporary buffer
00305   }
00306   if (computeV())
00307   {
00308     Index Vcols = m_computeThinV ? m_diagSize : householderV.cols();
00309     m_matrixV = MatrixX::Identity(householderV.cols(), Vcols);
00310     m_matrixV.topLeftCorner(m_diagSize, m_diagSize) = naiveU.template cast<Scalar>().topLeftCorner(m_diagSize, m_diagSize);
00311     householderV.applyThisOnTheLeft(m_matrixV); // FIXME this line involves a temporary buffer
00312   }
00313 }
00314 
00323 template<typename MatrixType>
00324 void BDCSVD<MatrixType>::structured_update(Block<MatrixXr,Dynamic,Dynamic> A, const MatrixXr &B, Index n1)
00325 {
00326   Index n = A.rows();
00327   if(n>100)
00328   {
00329     // If the matrices are large enough, let's exploit the sparse structure of A by
00330     // splitting it in half (wrt n1), and packing the non-zero columns.
00331     Index n2 = n - n1;
00332     Map<MatrixXr> A1(m_workspace.data()      , n1, n);
00333     Map<MatrixXr> A2(m_workspace.data()+ n1*n, n2, n);
00334     Map<MatrixXr> B1(m_workspace.data()+  n*n, n,  n);
00335     Map<MatrixXr> B2(m_workspace.data()+2*n*n, n,  n);
00336     Index k1=0, k2=0;
00337     for(Index j=0; j<n; ++j)
00338     {
00339       if( (A.col(j).head(n1).array()!=0).any() )
00340       {
00341         A1.col(k1) = A.col(j).head(n1);
00342         B1.row(k1) = B.row(j);
00343         ++k1;
00344       }
00345       if( (A.col(j).tail(n2).array()!=0).any() )
00346       {
00347         A2.col(k2) = A.col(j).tail(n2);
00348         B2.row(k2) = B.row(j);
00349         ++k2;
00350       }
00351     }
00352   
00353     A.topRows(n1).noalias()    = A1.leftCols(k1) * B1.topRows(k1);
00354     A.bottomRows(n2).noalias() = A2.leftCols(k2) * B2.topRows(k2);
00355   }
00356   else
00357   {
00358     Map<MatrixXr,Aligned> tmp(m_workspace.data(),n,n);
00359     tmp.noalias() = A*B;
00360     A = tmp;
00361   }
00362 }
00363 
00364 // The divide algorithm is done "in place", we are always working on subsets of the same matrix. The divide methods takes as argument the 
00365 // place of the submatrix we are currently working on.
00366 
00367 //@param firstCol : The Index of the first column of the submatrix of m_computed and for m_naiveU;
00368 //@param lastCol : The Index of the last column of the submatrix of m_computed and for m_naiveU; 
00369 // lastCol + 1 - firstCol is the size of the submatrix.
00370 //@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)
00371 //@param firstRowW : Same as firstRowW with the column.
00372 //@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 
00373 // to become the first column (*coeff) and to shift all the other columns to the right. There are more details on the reference paper.
00374 template<typename MatrixType>
00375 void BDCSVD<MatrixType>::divide (Index firstCol, Index lastCol, Index firstRowW, Index firstColW, Index shift)
00376 {
00377   // requires rows = cols + 1;
00378   using std::pow;
00379   using std::sqrt;
00380   using std::abs;
00381   const Index n = lastCol - firstCol + 1;
00382   const Index k = n/2;
00383   RealScalar alphaK;
00384   RealScalar betaK; 
00385   RealScalar r0; 
00386   RealScalar lambda, phi, c0, s0;
00387   VectorType l, f;
00388   // We use the other algorithm which is more efficient for small 
00389   // matrices.
00390   if (n < m_algoswap)
00391   {
00392     // FIXME this line involves temporaries
00393     JacobiSVD<MatrixXr> b(m_computed.block(firstCol, firstCol, n + 1, n), ComputeFullU | (m_compV ? ComputeFullV : 0));
00394     if (m_compU)
00395       m_naiveU.block(firstCol, firstCol, n + 1, n + 1).real() = b.matrixU();
00396     else 
00397     {
00398       m_naiveU.row(0).segment(firstCol, n + 1).real() = b.matrixU().row(0);
00399       m_naiveU.row(1).segment(firstCol, n + 1).real() = b.matrixU().row(n);
00400     }
00401     if (m_compV) m_naiveV.block(firstRowW, firstColW, n, n).real() = b.matrixV();
00402     m_computed.block(firstCol + shift, firstCol + shift, n + 1, n).setZero();
00403     m_computed.diagonal().segment(firstCol + shift, n) = b.singularValues().head(n);
00404     return;
00405   }
00406   // We use the divide and conquer algorithm
00407   alphaK =  m_computed(firstCol + k, firstCol + k);
00408   betaK = m_computed(firstCol + k + 1, firstCol + k);
00409   // The divide must be done in that order in order to have good results. Divide change the data inside the submatrices
00410   // and the divide of the right submatrice reads one column of the left submatrice. That's why we need to treat the 
00411   // right submatrix before the left one. 
00412   divide(k + 1 + firstCol, lastCol, k + 1 + firstRowW, k + 1 + firstColW, shift);
00413   divide(firstCol, k - 1 + firstCol, firstRowW, firstColW + 1, shift + 1);
00414 
00415   if (m_compU)
00416   {
00417     lambda = m_naiveU(firstCol + k, firstCol + k);
00418     phi = m_naiveU(firstCol + k + 1, lastCol + 1);
00419   } 
00420   else 
00421   {
00422     lambda = m_naiveU(1, firstCol + k);
00423     phi = m_naiveU(0, lastCol + 1);
00424   }
00425   r0 = sqrt((abs(alphaK * lambda) * abs(alphaK * lambda)) + abs(betaK * phi) * abs(betaK * phi));
00426   if (m_compU)
00427   {
00428     l = m_naiveU.row(firstCol + k).segment(firstCol, k);
00429     f = m_naiveU.row(firstCol + k + 1).segment(firstCol + k + 1, n - k - 1);
00430   } 
00431   else 
00432   {
00433     l = m_naiveU.row(1).segment(firstCol, k);
00434     f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
00435   }
00436   if (m_compV) m_naiveV(firstRowW+k, firstColW) = 1;
00437   if (r0 == 0)
00438   {
00439     c0 = 1;
00440     s0 = 0;
00441   }
00442   else
00443   {
00444     c0 = alphaK * lambda / r0;
00445     s0 = betaK * phi / r0;
00446   }
00447   
00448 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00449   assert(m_naiveU.allFinite());
00450   assert(m_naiveV.allFinite());
00451   assert(m_computed.allFinite());
00452 #endif
00453   
00454   if (m_compU)
00455   {
00456     MatrixXr q1 (m_naiveU.col(firstCol + k).segment(firstCol, k + 1));     
00457     // we shiftW Q1 to the right
00458     for (Index i = firstCol + k - 1; i >= firstCol; i--) 
00459       m_naiveU.col(i + 1).segment(firstCol, k + 1) = m_naiveU.col(i).segment(firstCol, k + 1);
00460     // we shift q1 at the left with a factor c0
00461     m_naiveU.col(firstCol).segment( firstCol, k + 1) = (q1 * c0);
00462     // last column = q1 * - s0
00463     m_naiveU.col(lastCol + 1).segment(firstCol, k + 1) = (q1 * ( - s0));
00464     // first column = q2 * s0
00465     m_naiveU.col(firstCol).segment(firstCol + k + 1, n - k) = m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) * s0; 
00466     // q2 *= c0
00467     m_naiveU.col(lastCol + 1).segment(firstCol + k + 1, n - k) *= c0;
00468   } 
00469   else 
00470   {
00471     RealScalar q1 = m_naiveU(0, firstCol + k);
00472     // we shift Q1 to the right
00473     for (Index i = firstCol + k - 1; i >= firstCol; i--) 
00474       m_naiveU(0, i + 1) = m_naiveU(0, i);
00475     // we shift q1 at the left with a factor c0
00476     m_naiveU(0, firstCol) = (q1 * c0);
00477     // last column = q1 * - s0
00478     m_naiveU(0, lastCol + 1) = (q1 * ( - s0));
00479     // first column = q2 * s0
00480     m_naiveU(1, firstCol) = m_naiveU(1, lastCol + 1) *s0; 
00481     // q2 *= c0
00482     m_naiveU(1, lastCol + 1) *= c0;
00483     m_naiveU.row(1).segment(firstCol + 1, k).setZero();
00484     m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1).setZero();
00485   }
00486   
00487 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00488   assert(m_naiveU.allFinite());
00489   assert(m_naiveV.allFinite());
00490   assert(m_computed.allFinite());
00491 #endif
00492   
00493   m_computed(firstCol + shift, firstCol + shift) = r0;
00494   m_computed.col(firstCol + shift).segment(firstCol + shift + 1, k) = alphaK * l.transpose().real();
00495   m_computed.col(firstCol + shift).segment(firstCol + shift + k + 1, n - k - 1) = betaK * f.transpose().real();
00496 
00497 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00498   ArrayXr tmp1 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
00499 #endif
00500   // Second part: try to deflate singular values in combined matrix
00501   deflation(firstCol, lastCol, k, firstRowW, firstColW, shift);
00502 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00503   ArrayXr tmp2 = (m_computed.block(firstCol+shift, firstCol+shift, n, n)).jacobiSvd().singularValues();
00504   std::cout << "\n\nj1 = " << tmp1.transpose().format(bdcsvdfmt) << "\n";
00505   std::cout << "j2 = " << tmp2.transpose().format(bdcsvdfmt) << "\n\n";
00506   std::cout << "err:      " << ((tmp1-tmp2).abs()>1e-12*tmp2.abs()).transpose() << "\n";
00507   static int count = 0;
00508   std::cout << "# " << ++count << "\n\n";
00509   assert((tmp1-tmp2).matrix().norm() < 1e-14*tmp2.matrix().norm());
00510 //   assert(count<681);
00511 //   assert(((tmp1-tmp2).abs()<1e-13*tmp2.abs()).all());
00512 #endif
00513   
00514   // Third part: compute SVD of combined matrix
00515   MatrixXr UofSVD, VofSVD;
00516   VectorType singVals;
00517   computeSVDofM(firstCol + shift, n, UofSVD, singVals, VofSVD);
00518   
00519 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00520   assert(UofSVD.allFinite());
00521   assert(VofSVD.allFinite());
00522 #endif
00523   
00524   if (m_compU)
00525     structured_update(m_naiveU.block(firstCol, firstCol, n + 1, n + 1), UofSVD, (n+2)/2);
00526   else
00527   {
00528     Map<Matrix<RealScalar,2,Dynamic>,Aligned> tmp(m_workspace.data(),2,n+1);
00529     tmp.noalias() = m_naiveU.middleCols(firstCol, n+1) * UofSVD;
00530     m_naiveU.middleCols(firstCol, n + 1) = tmp;
00531   }
00532   
00533   if (m_compV)  structured_update(m_naiveV.block(firstRowW, firstColW, n, n), VofSVD, (n+1)/2);
00534   
00535 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00536   assert(m_naiveU.allFinite());
00537   assert(m_naiveV.allFinite());
00538   assert(m_computed.allFinite());
00539 #endif
00540   
00541   m_computed.block(firstCol + shift, firstCol + shift, n, n).setZero();
00542   m_computed.block(firstCol + shift, firstCol + shift, n, n).diagonal() = singVals;
00543 }// end divide
00544 
00545 // Compute SVD of m_computed.block(firstCol, firstCol, n + 1, n); this block only has non-zeros in
00546 // the first column and on the diagonal and has undergone deflation, so diagonal is in increasing
00547 // order except for possibly the (0,0) entry. The computed SVD is stored U, singVals and V, except
00548 // that if m_compV is false, then V is not computed. Singular values are sorted in decreasing order.
00549 //
00550 // TODO Opportunities for optimization: better root finding algo, better stopping criterion, better
00551 // handling of round-off errors, be consistent in ordering
00552 // For instance, to solve the secular equation using FMM, see http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf
00553 template <typename MatrixType>
00554 void BDCSVD<MatrixType>::computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V)
00555 {
00556   ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n);
00557   m_workspace.head(n) =  m_computed.block(firstCol, firstCol, n, n).diagonal();
00558   ArrayRef diag = m_workspace.head(n);
00559   diag(0) = 0;
00560 
00561   // Allocate space for singular values and vectors
00562   singVals.resize(n);
00563   U.resize(n+1, n+1);
00564   if (m_compV) V.resize(n, n);
00565 
00566 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00567   if (col0.hasNaN() || diag.hasNaN())
00568     std::cout << "\n\nHAS NAN\n\n";
00569 #endif
00570   
00571   // Many singular values might have been deflated, the zero ones have been moved to the end,
00572   // but others are interleaved and we must ignore them at this stage.
00573   // To this end, let's compute a permutation skipping them:
00574   Index actual_n = n;
00575   while(actual_n>1 && diag(actual_n-1)==0) --actual_n;
00576   Index m = 0; // size of the deflated problem
00577   for(Index k=0;k<actual_n;++k)
00578     if(col0(k)!=0)
00579       m_workspaceI(m++) = k;
00580   Map<ArrayXi> perm(m_workspaceI.data(),m);
00581   
00582   Map<ArrayXr> shifts(m_workspace.data()+1*n, n);
00583   Map<ArrayXr> mus(m_workspace.data()+2*n, n);
00584   Map<ArrayXr> zhat(m_workspace.data()+3*n, n);
00585 
00586 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00587   std::cout << "computeSVDofM using:\n";
00588   std::cout << "  z: " << col0.transpose() << "\n";
00589   std::cout << "  d: " << diag.transpose() << "\n";
00590 #endif
00591   
00592   // Compute singVals, shifts, and mus
00593   computeSingVals(col0, diag, perm, singVals, shifts, mus);
00594   
00595 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00596   std::cout << "  j:        " << (m_computed.block(firstCol, firstCol, n, n)).jacobiSvd().singularValues().transpose().reverse() << "\n\n";
00597   std::cout << "  sing-val: " << singVals.transpose() << "\n";
00598   std::cout << "  mu:       " << mus.transpose() << "\n";
00599   std::cout << "  shift:    " << shifts.transpose() << "\n";
00600   
00601   {
00602     Index actual_n = n;
00603     while(actual_n>1 && col0(actual_n-1)==0) --actual_n;
00604     std::cout << "\n\n    mus:    " << mus.head(actual_n).transpose() << "\n\n";
00605     std::cout << "    check1 (expect0) : " << ((singVals.array()-(shifts+mus)) / singVals.array()).head(actual_n).transpose() << "\n\n";
00606     std::cout << "    check2 (>0)      : " << ((singVals.array()-diag) / singVals.array()).head(actual_n).transpose() << "\n\n";
00607     std::cout << "    check3 (>0)      : " << ((diag.segment(1,actual_n-1)-singVals.head(actual_n-1).array()) / singVals.head(actual_n-1).array()).transpose() << "\n\n\n";
00608     std::cout << "    check4 (>0)      : " << ((singVals.segment(1,actual_n-1)-singVals.head(actual_n-1))).transpose() << "\n\n\n";
00609   }
00610 #endif
00611   
00612 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00613   assert(singVals.allFinite());
00614   assert(mus.allFinite());
00615   assert(shifts.allFinite());
00616 #endif
00617   
00618   // Compute zhat
00619   perturbCol0(col0, diag, perm, singVals, shifts, mus, zhat);
00620 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
00621   std::cout << "  zhat: " << zhat.transpose() << "\n";
00622 #endif
00623   
00624 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00625   assert(zhat.allFinite());
00626 #endif
00627   
00628   computeSingVecs(zhat, diag, perm, singVals, shifts, mus, U, V);
00629   
00630 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
00631   std::cout << "U^T U: " << (U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() << "\n";
00632   std::cout << "V^T V: " << (V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() << "\n";
00633 #endif
00634   
00635 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
00636   assert(U.allFinite());
00637   assert(V.allFinite());
00638   assert((U.transpose() * U - MatrixXr(MatrixXr::Identity(U.cols(),U.cols()))).norm() < 1e-14 * n);
00639   assert((V.transpose() * V - MatrixXr(MatrixXr::Identity(V.cols(),V.cols()))).norm() < 1e-14 * n);
00640   assert(m_naiveU.allFinite());
00641   assert(m_naiveV.allFinite());
00642   assert(m_computed.allFinite());
00643 #endif
00644   
00645   // Because of deflation, the singular values might not be completely sorted.
00646   // Fortunately, reordering them is a O(n) problem
00647   for(Index i=0; i<actual_n-1; ++i)
00648   {
00649     if(singVals(i)>singVals(i+1))
00650     {
00651       using std::swap;
00652       swap(singVals(i),singVals(i+1));
00653       U.col(i).swap(U.col(i+1));
00654       if(m_compV) V.col(i).swap(V.col(i+1));
00655     }
00656   }
00657   
00658   // Reverse order so that singular values in increased order
00659   // Because of deflation, the zeros singular-values are already at the end
00660   singVals.head(actual_n).reverseInPlace();
00661   U.leftCols(actual_n).rowwise().reverseInPlace();
00662   if (m_compV) V.leftCols(actual_n).rowwise().reverseInPlace();
00663   
00664 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00665   JacobiSVD<MatrixXr> jsvd(m_computed.block(firstCol, firstCol, n, n) );
00666   std::cout << "  * j:        " << jsvd.singularValues().transpose() << "\n\n";
00667   std::cout << "  * sing-val: " << singVals.transpose() << "\n";
00668 //   std::cout << "  * err:      " << ((jsvd.singularValues()-singVals)>1e-13*singVals.norm()).transpose() << "\n";
00669 #endif
00670 }
00671 
00672 template <typename MatrixType>
00673 typename BDCSVD<MatrixType>::RealScalar BDCSVD<MatrixType>::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift)
00674 {
00675   Index m = perm.size();
00676   RealScalar res = 1;
00677   for(Index i=0; i<m; ++i)
00678   {
00679     Index j = perm(i);
00680     res += numext::abs2(col0(j)) / ((diagShifted(j) - mu) * (diag(j) + shift + mu));
00681   }
00682   return res;
00683 }
00684 
00685 template <typename MatrixType>
00686 void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm,
00687                                          VectorType& singVals, ArrayRef shifts, ArrayRef mus)
00688 {
00689   using std::abs;
00690   using std::swap;
00691 
00692   Index n = col0.size();
00693   Index actual_n = n;
00694   while(actual_n>1 && col0(actual_n-1)==0) --actual_n;
00695 
00696   for (Index k = 0; k < n; ++k)
00697   {
00698     if (col0(k) == 0 || actual_n==1)
00699     {
00700       // if col0(k) == 0, then entry is deflated, so singular value is on diagonal
00701       // if actual_n==1, then the deflated problem is already diagonalized
00702       singVals(k) = k==0 ? col0(0) : diag(k);
00703       mus(k) = 0;
00704       shifts(k) = k==0 ? col0(0) : diag(k);
00705       continue;
00706     } 
00707 
00708     // otherwise, use secular equation to find singular value
00709     RealScalar left = diag(k);
00710     RealScalar right; // was: = (k != actual_n-1) ? diag(k+1) : (diag(actual_n-1) + col0.matrix().norm());
00711     if(k==actual_n-1)
00712       right = (diag(actual_n-1) + col0.matrix().norm());
00713     else
00714     {
00715       // Skip deflated singular values
00716       Index l = k+1;
00717       while(col0(l)==0) { ++l; eigen_internal_assert(l<actual_n); }
00718       right = diag(l);
00719     }
00720 
00721     // first decide whether it's closer to the left end or the right end
00722     RealScalar mid = left + (right-left) / 2;
00723     RealScalar fMid = secularEq(mid, col0, diag, perm, diag, 0);
00724 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00725     std::cout << right-left << "\n";
00726     std::cout << "fMid = " << fMid << " " << secularEq(mid-left, col0, diag, perm, diag-left, left) << " " << secularEq(mid-right, col0, diag, perm, diag-right, right)   << "\n";
00727     std::cout << "     = " << secularEq(0.1*(left+right), col0, diag, perm, diag, 0)
00728               << " "       << secularEq(0.2*(left+right), col0, diag, perm, diag, 0)
00729               << " "       << secularEq(0.3*(left+right), col0, diag, perm, diag, 0)
00730               << " "       << secularEq(0.4*(left+right), col0, diag, perm, diag, 0)
00731               << " "       << secularEq(0.49*(left+right), col0, diag, perm, diag, 0)
00732               << " "       << secularEq(0.5*(left+right), col0, diag, perm, diag, 0)
00733               << " "       << secularEq(0.51*(left+right), col0, diag, perm, diag, 0)
00734               << " "       << secularEq(0.6*(left+right), col0, diag, perm, diag, 0)
00735               << " "       << secularEq(0.7*(left+right), col0, diag, perm, diag, 0)
00736               << " "       << secularEq(0.8*(left+right), col0, diag, perm, diag, 0)
00737               << " "       << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) << "\n";
00738 #endif
00739     RealScalar shift = (k == actual_n-1 || fMid > 0) ? left : right;
00740     
00741     // measure everything relative to shift
00742     Map<ArrayXr> diagShifted(m_workspace.data()+4*n, n);
00743     diagShifted = diag - shift;
00744     
00745     // initial guess
00746     RealScalar muPrev, muCur;
00747     if (shift == left)
00748     {
00749       muPrev = (right - left) * 0.1;
00750       if (k == actual_n-1) muCur = right - left;
00751       else                 muCur = (right - left) * 0.5; 
00752     }
00753     else
00754     {
00755       muPrev = -(right - left) * 0.1;
00756       muCur = -(right - left) * 0.5;
00757     }
00758 
00759     RealScalar fPrev = secularEq(muPrev, col0, diag, perm, diagShifted, shift);
00760     RealScalar fCur = secularEq(muCur, col0, diag, perm, diagShifted, shift);
00761     if (abs(fPrev) < abs(fCur))
00762     {
00763       swap(fPrev, fCur);
00764       swap(muPrev, muCur);
00765     }
00766 
00767     // rational interpolation: fit a function of the form a / mu + b through the two previous
00768     // iterates and use its zero to compute the next iterate
00769     bool useBisection = fPrev*fCur>0;
00770     while (fCur!=0 && abs(muCur - muPrev) > 8 * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits<RealScalar>::epsilon() && !useBisection)
00771     {
00772       ++m_numIters;
00773 
00774       // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples.
00775       RealScalar a = (fCur - fPrev) / (1/muCur - 1/muPrev);
00776       RealScalar b = fCur - a / muCur;
00777       // And find mu such that f(mu)==0:
00778       RealScalar muZero = -a/b;
00779       RealScalar fZero = secularEq(muZero, col0, diag, perm, diagShifted, shift);
00780       
00781       muPrev = muCur;
00782       fPrev = fCur;
00783       muCur = muZero;
00784       fCur = fZero;
00785       
00786       
00787       if (shift == left  && (muCur < 0 || muCur > right - left)) useBisection = true;
00788       if (shift == right && (muCur < -(right - left) || muCur > 0)) useBisection = true;
00789       if (abs(fCur)>abs(fPrev)) useBisection = true;
00790     }
00791 
00792     // fall back on bisection method if rational interpolation did not work
00793     if (useBisection)
00794     {
00795 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
00796       std::cout << "useBisection for k = " << k << ", actual_n = " << actual_n << "\n";
00797 #endif
00798       RealScalar leftShifted, rightShifted;
00799       if (shift == left)
00800       {
00801         leftShifted = RealScalar(1)/NumTraits<RealScalar>::highest();
00802         // I don't understand why the case k==0 would be special there:
00803         // if (k == 0) rightShifted = right - left; else 
00804         rightShifted = (k==actual_n-1) ? right : ((right - left) * 0.6); // theoretically we can take 0.5, but let's be safe
00805       }
00806       else
00807       {
00808         leftShifted = -(right - left) * 0.6;
00809         rightShifted = -RealScalar(1)/NumTraits<RealScalar>::highest();
00810       }
00811       
00812       RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift);
00813 
00814 #if defined EIGEN_INTERNAL_DEBUGGING || defined EIGEN_BDCSVD_DEBUG_VERBOSE
00815       RealScalar fRight = secularEq(rightShifted, col0, diag, perm, diagShifted, shift);
00816 #endif
00817 
00818 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
00819       if(!(fLeft * fRight<0))
00820         std::cout << k << " : " <<  fLeft << " * " << fRight << " == " << fLeft * fRight << "  ;  " << left << " - " << right << " -> " <<  leftShifted << " " << rightShifted << "   shift=" << shift << "\n";
00821 #endif
00822       eigen_internal_assert(fLeft * fRight < 0);
00823       
00824       while (rightShifted - leftShifted > 2 * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted)))
00825       {
00826         RealScalar midShifted = (leftShifted + rightShifted) / 2;
00827         fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
00828         if (fLeft * fMid < 0)
00829         {
00830           rightShifted = midShifted;
00831         }
00832         else
00833         {
00834           leftShifted = midShifted;
00835           fLeft = fMid;
00836         }
00837       }
00838 
00839       muCur = (leftShifted + rightShifted) / 2;
00840     }
00841       
00842     singVals[k] = shift + muCur;
00843     shifts[k] = shift;
00844     mus[k] = muCur;
00845 
00846     // perturb singular value slightly if it equals diagonal entry to avoid division by zero later
00847     // (deflation is supposed to avoid this from happening)
00848     // - this does no seem to be necessary anymore -
00849 //     if (singVals[k] == left) singVals[k] *= 1 + NumTraits<RealScalar>::epsilon();
00850 //     if (singVals[k] == right) singVals[k] *= 1 - NumTraits<RealScalar>::epsilon();
00851   }
00852 }
00853 
00854 
00855 // zhat is perturbation of col0 for which singular vectors can be computed stably (see Section 3.1)
00856 template <typename MatrixType>
00857 void BDCSVD<MatrixType>::perturbCol0
00858    (const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const VectorType& singVals,
00859     const ArrayRef& shifts, const ArrayRef& mus, ArrayRef zhat)
00860 {
00861   using std::sqrt;
00862   Index n = col0.size();
00863   Index m = perm.size();
00864   if(m==0)
00865   {
00866     zhat.setZero();
00867     return;
00868   }
00869   Index last = perm(m-1);
00870   // The offset permits to skip deflated entries while computing zhat
00871   for (Index k = 0; k < n; ++k)
00872   {
00873     if (col0(k) == 0) // deflated
00874       zhat(k) = 0;
00875     else
00876     {
00877       // see equation (3.6)
00878       RealScalar dk = diag(k);
00879       RealScalar prod = (singVals(last) + dk) * (mus(last) + (shifts(last) - dk));
00880 
00881       for(Index l = 0; l<m; ++l)
00882       {
00883         Index i = perm(l);
00884         if(i!=k)
00885         {
00886           Index j = i<k ? i : perm(l-1);
00887           prod *= ((singVals(j)+dk) / ((diag(i)+dk))) * ((mus(j)+(shifts(j)-dk)) / ((diag(i)-dk)));
00888 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00889           if(i!=k && std::abs(((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) - 1) > 0.9 )
00890             std::cout << "     " << ((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) << " == (" << (singVals(j)+dk) << " * " << (mus(j)+(shifts(j)-dk))
00891                        << ") / (" << (diag(i)+dk) << " * " << (diag(i)-dk) << ")\n";
00892 #endif
00893         }
00894       }
00895 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
00896       std::cout << "zhat(" << k << ") =  sqrt( " << prod << ")  ;  " << (singVals(last) + dk) << " * " << mus(last) + shifts(last) << " - " << dk << "\n";
00897 #endif
00898       RealScalar tmp = sqrt(prod);
00899       zhat(k) = col0(k) > 0 ? tmp : -tmp;
00900     }
00901   }
00902 }
00903 
00904 // compute singular vectors
00905 template <typename MatrixType>
00906 void BDCSVD<MatrixType>::computeSingVecs
00907    (const ArrayRef& zhat, const ArrayRef& diag, const IndicesRef &perm, const VectorType& singVals,
00908     const ArrayRef& shifts, const ArrayRef& mus, MatrixXr& U, MatrixXr& V)
00909 {
00910   Index n = zhat.size();
00911   Index m = perm.size();
00912   
00913   for (Index k = 0; k < n; ++k)
00914   {
00915     if (zhat(k) == 0)
00916     {
00917       U.col(k) = VectorType::Unit(n+1, k);
00918       if (m_compV) V.col(k) = VectorType::Unit(n, k);
00919     }
00920     else
00921     {
00922       U.col(k).setZero();
00923       for(Index l=0;l<m;++l)
00924       {
00925         Index i = perm(l);
00926         U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
00927       }
00928       U(n,k) = 0;      
00929       U.col(k).normalize();
00930     
00931       if (m_compV)
00932       {
00933         V.col(k).setZero();
00934         for(Index l=1;l<m;++l)
00935         {
00936           Index i = perm(l);
00937           V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
00938         }
00939         V(0,k) = -1;
00940         V.col(k).normalize();
00941       }
00942     }
00943   }
00944   U.col(n) = VectorType::Unit(n+1, n);
00945 }
00946 
00947 
00948 // page 12_13
00949 // i >= 1, di almost null and zi non null.
00950 // We use a rotation to zero out zi applied to the left of M
00951 template <typename MatrixType>
00952 void BDCSVD<MatrixType>::deflation43(Index firstCol, Index shift, Index i, Index size)
00953 {
00954   using std::abs;
00955   using std::sqrt;
00956   using std::pow;
00957   Index start = firstCol + shift;
00958   RealScalar c = m_computed(start, start);
00959   RealScalar s = m_computed(start+i, start);
00960   RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s));
00961   if (r == 0)
00962   {
00963     m_computed(start+i, start+i) = 0;
00964     return;
00965   }
00966   m_computed(start,start) = r;  
00967   m_computed(start+i, start) = 0;
00968   m_computed(start+i, start+i) = 0;
00969   
00970   JacobiRotation<RealScalar> J(c/r,-s/r);
00971   if (m_compU)  m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J);
00972   else          m_naiveU.applyOnTheRight(firstCol, firstCol+i, J);
00973 }// end deflation 43
00974 
00975 
00976 // page 13
00977 // i,j >= 1, i!=j and |di - dj| < epsilon * norm2(M)
00978 // We apply two rotations to have zj = 0;
00979 // TODO deflation44 is still broken and not properly tested
00980 template <typename MatrixType>
00981 void BDCSVD<MatrixType>::deflation44(Index firstColu , Index firstColm, Index firstRowW, Index firstColW, Index i, Index j, Index size)
00982 {
00983   using std::abs;
00984   using std::sqrt;
00985   using std::conj;
00986   using std::pow;
00987   RealScalar c = m_computed(firstColm+i, firstColm);
00988   RealScalar s = m_computed(firstColm+j, firstColm);
00989   RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s));
00990 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
00991   std::cout << "deflation 4.4: " << i << "," << j << " -> " << c << " " << s << " " << r << " ; "
00992     << m_computed(firstColm + i-1, firstColm)  << " "
00993     << m_computed(firstColm + i, firstColm)  << " "
00994     << m_computed(firstColm + i+1, firstColm) << " "
00995     << m_computed(firstColm + i+2, firstColm) << "\n";
00996   std::cout << m_computed(firstColm + i-1, firstColm + i-1)  << " "
00997     << m_computed(firstColm + i, firstColm+i)  << " "
00998     << m_computed(firstColm + i+1, firstColm+i+1) << " "
00999     << m_computed(firstColm + i+2, firstColm+i+2) << "\n";
01000 #endif
01001   if (r==0)
01002   {
01003     m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
01004     return;
01005   }
01006   c/=r;
01007   s/=r;
01008   m_computed(firstColm + i, firstColm) = r;  
01009   m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
01010   m_computed(firstColm + j, firstColm) = 0;
01011 
01012   JacobiRotation<RealScalar> J(c,-s);
01013   if (m_compU)  m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J);
01014   else          m_naiveU.applyOnTheRight(firstColu+i, firstColu+j, J);
01015   if (m_compV)  m_naiveV.middleRows(firstRowW, size).applyOnTheRight(firstColW + i, firstColW + j, J);
01016 }// end deflation 44
01017 
01018 
01019 // acts on block from (firstCol+shift, firstCol+shift) to (lastCol+shift, lastCol+shift) [inclusive]
01020 template <typename MatrixType>
01021 void BDCSVD<MatrixType>::deflation(Index firstCol, Index lastCol, Index k, Index firstRowW, Index firstColW, Index shift)
01022 {
01023   using std::sqrt;
01024   using std::abs;
01025   const Index length = lastCol + 1 - firstCol;
01026   
01027   Block<MatrixXr,Dynamic,1> col0(m_computed, firstCol+shift, firstCol+shift, length, 1);
01028   Diagonal<MatrixXr> fulldiag(m_computed);
01029   VectorBlock<Diagonal<MatrixXr>,Dynamic> diag(fulldiag, firstCol+shift, length);
01030   
01031   RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff();
01032   RealScalar epsilon_strict = NumTraits<RealScalar>::epsilon() * maxDiag;
01033   RealScalar epsilon_coarse = 8 * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
01034   
01035 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
01036   assert(m_naiveU.allFinite());
01037   assert(m_naiveV.allFinite());
01038   assert(m_computed.allFinite());
01039 #endif
01040 
01041 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE  
01042   std::cout << "\ndeflate:" << diag.head(k+1).transpose() << "  |  " << diag.segment(k+1,length-k-1).transpose() << "\n";
01043 #endif
01044   
01045   //condition 4.1
01046   if (diag(0) < epsilon_coarse)
01047   { 
01048 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
01049     std::cout << "deflation 4.1, because " << diag(0) << " < " << epsilon_coarse << "\n";
01050 #endif
01051     diag(0) = epsilon_coarse;
01052   }
01053 
01054   //condition 4.2
01055   for (Index i=1;i<length;++i)
01056     if (abs(col0(i)) < epsilon_strict)
01057     {
01058 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
01059       std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << "  (diag(" << i << ")=" << diag(i) << ")\n";
01060 #endif
01061       col0(i) = 0;
01062     }
01063 
01064   //condition 4.3
01065   for (Index i=1;i<length; i++)
01066     if (diag(i) < epsilon_coarse)
01067     {
01068 #ifdef  EIGEN_BDCSVD_DEBUG_VERBOSE
01069       std::cout << "deflation 4.3, cancel z(" << i << ")=" << col0(i) << " because diag(" << i << ")=" << diag(i) << " < " << epsilon_coarse << "\n";
01070 #endif
01071       deflation43(firstCol, shift, i, length);
01072     }
01073 
01074 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
01075   assert(m_naiveU.allFinite());
01076   assert(m_naiveV.allFinite());
01077   assert(m_computed.allFinite());
01078 #endif
01079 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
01080   std::cout << "to be sorted: " << diag.transpose() << "\n\n";
01081 #endif
01082   {
01083     // Check for total deflation
01084     // If we have a total deflation, then we have to consider col0(0)==diag(0) as a singular value during sorting
01085     bool total_deflation = (col0.tail(length-1).array()==RealScalar(0)).all();
01086     
01087     // Sort the diagonal entries, since diag(1:k-1) and diag(k:length) are already sorted, let's do a sorted merge.
01088     // First, compute the respective permutation.
01089     Index *permutation = m_workspaceI.data();
01090     {
01091       permutation[0] = 0;
01092       Index p = 1;
01093       
01094       // Move deflated diagonal entries at the end.
01095       for(Index i=1; i<length; ++i)
01096         if(diag(i)==0)
01097           permutation[p++] = i;
01098         
01099       Index i=1, j=k+1;
01100       for( ; p < length; ++p)
01101       {
01102              if (i > k)             permutation[p] = j++;
01103         else if (j >= length)       permutation[p] = i++;
01104         else if (diag(i) < diag(j)) permutation[p] = j++;
01105         else                        permutation[p] = i++;
01106       }
01107     }
01108     
01109     // If we have a total deflation, then we have to insert diag(0) at the right place
01110     if(total_deflation)
01111     {
01112       for(Index i=1; i<length; ++i)
01113       {
01114         Index pi = permutation[i];
01115         if(diag(pi)==0 || diag(0)<diag(pi))
01116           permutation[i-1] = permutation[i];
01117         else
01118         {
01119           permutation[i-1] = 0;
01120           break;
01121         }
01122       }
01123     }
01124     
01125     // Current index of each col, and current column of each index
01126     Index *realInd = m_workspaceI.data()+length;
01127     Index *realCol = m_workspaceI.data()+2*length;
01128     
01129     for(int pos = 0; pos< length; pos++)
01130     {
01131       realCol[pos] = pos;
01132       realInd[pos] = pos;
01133     }
01134     
01135     for(Index i = total_deflation?0:1; i < length; i++)
01136     {
01137       const Index pi = permutation[length - (total_deflation ? i+1 : i)];
01138       const Index J = realCol[pi];
01139       
01140       using std::swap;
01141       // swap diagonal and first column entries:
01142       swap(diag(i), diag(J));
01143       if(i!=0 && J!=0) swap(col0(i), col0(J));
01144 
01145       // change columns
01146       if (m_compU) m_naiveU.col(firstCol+i).segment(firstCol, length + 1).swap(m_naiveU.col(firstCol+J).segment(firstCol, length + 1));
01147       else         m_naiveU.col(firstCol+i).segment(0, 2)                .swap(m_naiveU.col(firstCol+J).segment(0, 2));
01148       if (m_compV) m_naiveV.col(firstColW + i).segment(firstRowW, length).swap(m_naiveV.col(firstColW + J).segment(firstRowW, length));
01149 
01150       //update real pos
01151       const Index realI = realInd[i];
01152       realCol[realI] = J;
01153       realCol[pi] = i;
01154       realInd[J] = realI;
01155       realInd[i] = pi;
01156     }
01157   }
01158 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
01159   std::cout << "sorted: " << diag.transpose().format(bdcsvdfmt) << "\n";
01160   std::cout << "      : " << col0.transpose() << "\n\n";
01161 #endif
01162     
01163   //condition 4.4
01164   {
01165     Index i = length-1;
01166     while(i>0 && (diag(i)==0 || col0(i)==0)) --i;
01167     for(; i>1;--i)
01168        if( (diag(i) - diag(i-1)) < NumTraits<RealScalar>::epsilon()*maxDiag )
01169       {
01170 #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
01171         std::cout << "deflation 4.4 with i = " << i << " because " << (diag(i) - diag(i-1)) << " < " << NumTraits<RealScalar>::epsilon()*diag(i) << "\n";
01172 #endif
01173         eigen_internal_assert(abs(diag(i) - diag(i-1))<epsilon_coarse && " diagonal entries are not properly sorted");
01174         deflation44(firstCol, firstCol + shift, firstRowW, firstColW, i-1, i, length);
01175       }
01176   }
01177   
01178 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
01179   for(Index j=2;j<length;++j)
01180     assert(diag(j-1)<=diag(j) || diag(j)==0);
01181 #endif
01182   
01183 #ifdef EIGEN_BDCSVD_SANITY_CHECKS
01184   assert(m_naiveU.allFinite());
01185   assert(m_naiveV.allFinite());
01186   assert(m_computed.allFinite());
01187 #endif
01188 }//end deflation
01189 
01190 #ifndef __CUDACC__
01191 
01197 template<typename Derived>
01198 BDCSVD<typename MatrixBase<Derived>::PlainObject>
01199 MatrixBase<Derived>::bdcSvd(unsigned int computationOptions) const
01200 {
01201   return BDCSVD<PlainObject>(*this, computationOptions);
01202 }
01203 #endif
01204 
01205 } // end namespace Eigen
01206 
01207 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines