xref: /aosp_15_r20/external/eigen/Eigen/src/SVD/JacobiSVD.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2009-2010 Benoit Jacob <[email protected]>
5*bf2c3715SXin Li // Copyright (C) 2013-2014 Gael Guennebaud <[email protected]>
6*bf2c3715SXin Li //
7*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
8*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
9*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10*bf2c3715SXin Li 
11*bf2c3715SXin Li #ifndef EIGEN_JACOBISVD_H
12*bf2c3715SXin Li #define EIGEN_JACOBISVD_H
13*bf2c3715SXin Li 
14*bf2c3715SXin Li namespace Eigen {
15*bf2c3715SXin Li 
16*bf2c3715SXin Li namespace internal {
17*bf2c3715SXin Li // forward declaration (needed by ICC)
18*bf2c3715SXin Li // the empty body is required by MSVC
19*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner,
20*bf2c3715SXin Li          bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
21*bf2c3715SXin Li struct svd_precondition_2x2_block_to_be_real {};
22*bf2c3715SXin Li 
23*bf2c3715SXin Li /*** QR preconditioners (R-SVD)
24*bf2c3715SXin Li  ***
25*bf2c3715SXin Li  *** Their role is to reduce the problem of computing the SVD to the case of a square matrix.
26*bf2c3715SXin Li  *** This approach, known as R-SVD, is an optimization for rectangular-enough matrices, and is a requirement for
27*bf2c3715SXin Li  *** JacobiSVD which by itself is only able to work on square matrices.
28*bf2c3715SXin Li  ***/
29*bf2c3715SXin Li 
30*bf2c3715SXin Li enum { PreconditionIfMoreColsThanRows, PreconditionIfMoreRowsThanCols };
31*bf2c3715SXin Li 
32*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner, int Case>
33*bf2c3715SXin Li struct qr_preconditioner_should_do_anything
34*bf2c3715SXin Li {
35*bf2c3715SXin Li   enum { a = MatrixType::RowsAtCompileTime != Dynamic &&
36*bf2c3715SXin Li              MatrixType::ColsAtCompileTime != Dynamic &&
37*bf2c3715SXin Li              MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
38*bf2c3715SXin Li          b = MatrixType::RowsAtCompileTime != Dynamic &&
39*bf2c3715SXin Li              MatrixType::ColsAtCompileTime != Dynamic &&
40*bf2c3715SXin Li              MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
41*bf2c3715SXin Li          ret = !( (QRPreconditioner == NoQRPreconditioner) ||
42*bf2c3715SXin Li                   (Case == PreconditionIfMoreColsThanRows && bool(a)) ||
43*bf2c3715SXin Li                   (Case == PreconditionIfMoreRowsThanCols && bool(b)) )
44*bf2c3715SXin Li   };
45*bf2c3715SXin Li };
46*bf2c3715SXin Li 
47*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner, int Case,
48*bf2c3715SXin Li          bool DoAnything = qr_preconditioner_should_do_anything<MatrixType, QRPreconditioner, Case>::ret
49*bf2c3715SXin Li > struct qr_preconditioner_impl {};
50*bf2c3715SXin Li 
51*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner, int Case>
52*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
53*bf2c3715SXin Li {
54*bf2c3715SXin Li public:
allocate(const JacobiSVD<MatrixType,QRPreconditioner> &)55*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, QRPreconditioner>&) {}
run(JacobiSVD<MatrixType,QRPreconditioner> &,const MatrixType &)56*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, QRPreconditioner>&, const MatrixType&)
57*bf2c3715SXin Li   {
58*bf2c3715SXin Li     return false;
59*bf2c3715SXin Li   }
60*bf2c3715SXin Li };
61*bf2c3715SXin Li 
62*bf2c3715SXin Li /*** preconditioner using FullPivHouseholderQR ***/
63*bf2c3715SXin Li 
64*bf2c3715SXin Li template<typename MatrixType>
65*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
66*bf2c3715SXin Li {
67*bf2c3715SXin Li public:
68*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
69*bf2c3715SXin Li   enum
70*bf2c3715SXin Li   {
71*bf2c3715SXin Li     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
72*bf2c3715SXin Li     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
73*bf2c3715SXin Li   };
74*bf2c3715SXin Li   typedef Matrix<Scalar, 1, RowsAtCompileTime, RowMajor, 1, MaxRowsAtCompileTime> WorkspaceType;
75*bf2c3715SXin Li 
allocate(const JacobiSVD<MatrixType,FullPivHouseholderQRPreconditioner> & svd)76*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
77*bf2c3715SXin Li   {
78*bf2c3715SXin Li     if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
79*bf2c3715SXin Li     {
80*bf2c3715SXin Li       m_qr.~QRType();
81*bf2c3715SXin Li       ::new (&m_qr) QRType(svd.rows(), svd.cols());
82*bf2c3715SXin Li     }
83*bf2c3715SXin Li     if (svd.m_computeFullU) m_workspace.resize(svd.rows());
84*bf2c3715SXin Li   }
85*bf2c3715SXin Li 
run(JacobiSVD<MatrixType,FullPivHouseholderQRPreconditioner> & svd,const MatrixType & matrix)86*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
87*bf2c3715SXin Li   {
88*bf2c3715SXin Li     if(matrix.rows() > matrix.cols())
89*bf2c3715SXin Li     {
90*bf2c3715SXin Li       m_qr.compute(matrix);
91*bf2c3715SXin Li       svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
92*bf2c3715SXin Li       if(svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace);
93*bf2c3715SXin Li       if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
94*bf2c3715SXin Li       return true;
95*bf2c3715SXin Li     }
96*bf2c3715SXin Li     return false;
97*bf2c3715SXin Li   }
98*bf2c3715SXin Li private:
99*bf2c3715SXin Li   typedef FullPivHouseholderQR<MatrixType> QRType;
100*bf2c3715SXin Li   QRType m_qr;
101*bf2c3715SXin Li   WorkspaceType m_workspace;
102*bf2c3715SXin Li };
103*bf2c3715SXin Li 
104*bf2c3715SXin Li template<typename MatrixType>
105*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
106*bf2c3715SXin Li {
107*bf2c3715SXin Li public:
108*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
109*bf2c3715SXin Li   enum
110*bf2c3715SXin Li   {
111*bf2c3715SXin Li     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
112*bf2c3715SXin Li     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
113*bf2c3715SXin Li     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
114*bf2c3715SXin Li     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
115*bf2c3715SXin Li     Options = MatrixType::Options
116*bf2c3715SXin Li   };
117*bf2c3715SXin Li 
118*bf2c3715SXin Li   typedef typename internal::make_proper_matrix_type<
119*bf2c3715SXin Li     Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime
120*bf2c3715SXin Li   >::type TransposeTypeWithSameStorageOrder;
121*bf2c3715SXin Li 
allocate(const JacobiSVD<MatrixType,FullPivHouseholderQRPreconditioner> & svd)122*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
123*bf2c3715SXin Li   {
124*bf2c3715SXin Li     if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
125*bf2c3715SXin Li     {
126*bf2c3715SXin Li       m_qr.~QRType();
127*bf2c3715SXin Li       ::new (&m_qr) QRType(svd.cols(), svd.rows());
128*bf2c3715SXin Li     }
129*bf2c3715SXin Li     m_adjoint.resize(svd.cols(), svd.rows());
130*bf2c3715SXin Li     if (svd.m_computeFullV) m_workspace.resize(svd.cols());
131*bf2c3715SXin Li   }
132*bf2c3715SXin Li 
run(JacobiSVD<MatrixType,FullPivHouseholderQRPreconditioner> & svd,const MatrixType & matrix)133*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
134*bf2c3715SXin Li   {
135*bf2c3715SXin Li     if(matrix.cols() > matrix.rows())
136*bf2c3715SXin Li     {
137*bf2c3715SXin Li       m_adjoint = matrix.adjoint();
138*bf2c3715SXin Li       m_qr.compute(m_adjoint);
139*bf2c3715SXin Li       svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
140*bf2c3715SXin Li       if(svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace);
141*bf2c3715SXin Li       if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
142*bf2c3715SXin Li       return true;
143*bf2c3715SXin Li     }
144*bf2c3715SXin Li     else return false;
145*bf2c3715SXin Li   }
146*bf2c3715SXin Li private:
147*bf2c3715SXin Li   typedef FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
148*bf2c3715SXin Li   QRType m_qr;
149*bf2c3715SXin Li   TransposeTypeWithSameStorageOrder m_adjoint;
150*bf2c3715SXin Li   typename internal::plain_row_type<MatrixType>::type m_workspace;
151*bf2c3715SXin Li };
152*bf2c3715SXin Li 
153*bf2c3715SXin Li /*** preconditioner using ColPivHouseholderQR ***/
154*bf2c3715SXin Li 
155*bf2c3715SXin Li template<typename MatrixType>
156*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
157*bf2c3715SXin Li {
158*bf2c3715SXin Li public:
allocate(const JacobiSVD<MatrixType,ColPivHouseholderQRPreconditioner> & svd)159*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
160*bf2c3715SXin Li   {
161*bf2c3715SXin Li     if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
162*bf2c3715SXin Li     {
163*bf2c3715SXin Li       m_qr.~QRType();
164*bf2c3715SXin Li       ::new (&m_qr) QRType(svd.rows(), svd.cols());
165*bf2c3715SXin Li     }
166*bf2c3715SXin Li     if (svd.m_computeFullU) m_workspace.resize(svd.rows());
167*bf2c3715SXin Li     else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
168*bf2c3715SXin Li   }
169*bf2c3715SXin Li 
run(JacobiSVD<MatrixType,ColPivHouseholderQRPreconditioner> & svd,const MatrixType & matrix)170*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
171*bf2c3715SXin Li   {
172*bf2c3715SXin Li     if(matrix.rows() > matrix.cols())
173*bf2c3715SXin Li     {
174*bf2c3715SXin Li       m_qr.compute(matrix);
175*bf2c3715SXin Li       svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
176*bf2c3715SXin Li       if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
177*bf2c3715SXin Li       else if(svd.m_computeThinU)
178*bf2c3715SXin Li       {
179*bf2c3715SXin Li         svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
180*bf2c3715SXin Li         m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
181*bf2c3715SXin Li       }
182*bf2c3715SXin Li       if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
183*bf2c3715SXin Li       return true;
184*bf2c3715SXin Li     }
185*bf2c3715SXin Li     return false;
186*bf2c3715SXin Li   }
187*bf2c3715SXin Li 
188*bf2c3715SXin Li private:
189*bf2c3715SXin Li   typedef ColPivHouseholderQR<MatrixType> QRType;
190*bf2c3715SXin Li   QRType m_qr;
191*bf2c3715SXin Li   typename internal::plain_col_type<MatrixType>::type m_workspace;
192*bf2c3715SXin Li };
193*bf2c3715SXin Li 
194*bf2c3715SXin Li template<typename MatrixType>
195*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
196*bf2c3715SXin Li {
197*bf2c3715SXin Li public:
198*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
199*bf2c3715SXin Li   enum
200*bf2c3715SXin Li   {
201*bf2c3715SXin Li     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
202*bf2c3715SXin Li     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
203*bf2c3715SXin Li     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
204*bf2c3715SXin Li     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
205*bf2c3715SXin Li     Options = MatrixType::Options
206*bf2c3715SXin Li   };
207*bf2c3715SXin Li 
208*bf2c3715SXin Li   typedef typename internal::make_proper_matrix_type<
209*bf2c3715SXin Li     Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime
210*bf2c3715SXin Li   >::type TransposeTypeWithSameStorageOrder;
211*bf2c3715SXin Li 
allocate(const JacobiSVD<MatrixType,ColPivHouseholderQRPreconditioner> & svd)212*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
213*bf2c3715SXin Li   {
214*bf2c3715SXin Li     if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
215*bf2c3715SXin Li     {
216*bf2c3715SXin Li       m_qr.~QRType();
217*bf2c3715SXin Li       ::new (&m_qr) QRType(svd.cols(), svd.rows());
218*bf2c3715SXin Li     }
219*bf2c3715SXin Li     if (svd.m_computeFullV) m_workspace.resize(svd.cols());
220*bf2c3715SXin Li     else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
221*bf2c3715SXin Li     m_adjoint.resize(svd.cols(), svd.rows());
222*bf2c3715SXin Li   }
223*bf2c3715SXin Li 
run(JacobiSVD<MatrixType,ColPivHouseholderQRPreconditioner> & svd,const MatrixType & matrix)224*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
225*bf2c3715SXin Li   {
226*bf2c3715SXin Li     if(matrix.cols() > matrix.rows())
227*bf2c3715SXin Li     {
228*bf2c3715SXin Li       m_adjoint = matrix.adjoint();
229*bf2c3715SXin Li       m_qr.compute(m_adjoint);
230*bf2c3715SXin Li 
231*bf2c3715SXin Li       svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
232*bf2c3715SXin Li       if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
233*bf2c3715SXin Li       else if(svd.m_computeThinV)
234*bf2c3715SXin Li       {
235*bf2c3715SXin Li         svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
236*bf2c3715SXin Li         m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
237*bf2c3715SXin Li       }
238*bf2c3715SXin Li       if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
239*bf2c3715SXin Li       return true;
240*bf2c3715SXin Li     }
241*bf2c3715SXin Li     else return false;
242*bf2c3715SXin Li   }
243*bf2c3715SXin Li 
244*bf2c3715SXin Li private:
245*bf2c3715SXin Li   typedef ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
246*bf2c3715SXin Li   QRType m_qr;
247*bf2c3715SXin Li   TransposeTypeWithSameStorageOrder m_adjoint;
248*bf2c3715SXin Li   typename internal::plain_row_type<MatrixType>::type m_workspace;
249*bf2c3715SXin Li };
250*bf2c3715SXin Li 
251*bf2c3715SXin Li /*** preconditioner using HouseholderQR ***/
252*bf2c3715SXin Li 
253*bf2c3715SXin Li template<typename MatrixType>
254*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
255*bf2c3715SXin Li {
256*bf2c3715SXin Li public:
allocate(const JacobiSVD<MatrixType,HouseholderQRPreconditioner> & svd)257*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
258*bf2c3715SXin Li   {
259*bf2c3715SXin Li     if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
260*bf2c3715SXin Li     {
261*bf2c3715SXin Li       m_qr.~QRType();
262*bf2c3715SXin Li       ::new (&m_qr) QRType(svd.rows(), svd.cols());
263*bf2c3715SXin Li     }
264*bf2c3715SXin Li     if (svd.m_computeFullU) m_workspace.resize(svd.rows());
265*bf2c3715SXin Li     else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
266*bf2c3715SXin Li   }
267*bf2c3715SXin Li 
run(JacobiSVD<MatrixType,HouseholderQRPreconditioner> & svd,const MatrixType & matrix)268*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
269*bf2c3715SXin Li   {
270*bf2c3715SXin Li     if(matrix.rows() > matrix.cols())
271*bf2c3715SXin Li     {
272*bf2c3715SXin Li       m_qr.compute(matrix);
273*bf2c3715SXin Li       svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
274*bf2c3715SXin Li       if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
275*bf2c3715SXin Li       else if(svd.m_computeThinU)
276*bf2c3715SXin Li       {
277*bf2c3715SXin Li         svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
278*bf2c3715SXin Li         m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
279*bf2c3715SXin Li       }
280*bf2c3715SXin Li       if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
281*bf2c3715SXin Li       return true;
282*bf2c3715SXin Li     }
283*bf2c3715SXin Li     return false;
284*bf2c3715SXin Li   }
285*bf2c3715SXin Li private:
286*bf2c3715SXin Li   typedef HouseholderQR<MatrixType> QRType;
287*bf2c3715SXin Li   QRType m_qr;
288*bf2c3715SXin Li   typename internal::plain_col_type<MatrixType>::type m_workspace;
289*bf2c3715SXin Li };
290*bf2c3715SXin Li 
291*bf2c3715SXin Li template<typename MatrixType>
292*bf2c3715SXin Li class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
293*bf2c3715SXin Li {
294*bf2c3715SXin Li public:
295*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
296*bf2c3715SXin Li   enum
297*bf2c3715SXin Li   {
298*bf2c3715SXin Li     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
299*bf2c3715SXin Li     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
300*bf2c3715SXin Li     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
301*bf2c3715SXin Li     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
302*bf2c3715SXin Li     Options = MatrixType::Options
303*bf2c3715SXin Li   };
304*bf2c3715SXin Li 
305*bf2c3715SXin Li   typedef typename internal::make_proper_matrix_type<
306*bf2c3715SXin Li     Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime
307*bf2c3715SXin Li   >::type TransposeTypeWithSameStorageOrder;
308*bf2c3715SXin Li 
allocate(const JacobiSVD<MatrixType,HouseholderQRPreconditioner> & svd)309*bf2c3715SXin Li   void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
310*bf2c3715SXin Li   {
311*bf2c3715SXin Li     if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
312*bf2c3715SXin Li     {
313*bf2c3715SXin Li       m_qr.~QRType();
314*bf2c3715SXin Li       ::new (&m_qr) QRType(svd.cols(), svd.rows());
315*bf2c3715SXin Li     }
316*bf2c3715SXin Li     if (svd.m_computeFullV) m_workspace.resize(svd.cols());
317*bf2c3715SXin Li     else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
318*bf2c3715SXin Li     m_adjoint.resize(svd.cols(), svd.rows());
319*bf2c3715SXin Li   }
320*bf2c3715SXin Li 
run(JacobiSVD<MatrixType,HouseholderQRPreconditioner> & svd,const MatrixType & matrix)321*bf2c3715SXin Li   bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
322*bf2c3715SXin Li   {
323*bf2c3715SXin Li     if(matrix.cols() > matrix.rows())
324*bf2c3715SXin Li     {
325*bf2c3715SXin Li       m_adjoint = matrix.adjoint();
326*bf2c3715SXin Li       m_qr.compute(m_adjoint);
327*bf2c3715SXin Li 
328*bf2c3715SXin Li       svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
329*bf2c3715SXin Li       if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
330*bf2c3715SXin Li       else if(svd.m_computeThinV)
331*bf2c3715SXin Li       {
332*bf2c3715SXin Li         svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
333*bf2c3715SXin Li         m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
334*bf2c3715SXin Li       }
335*bf2c3715SXin Li       if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
336*bf2c3715SXin Li       return true;
337*bf2c3715SXin Li     }
338*bf2c3715SXin Li     else return false;
339*bf2c3715SXin Li   }
340*bf2c3715SXin Li 
341*bf2c3715SXin Li private:
342*bf2c3715SXin Li   typedef HouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
343*bf2c3715SXin Li   QRType m_qr;
344*bf2c3715SXin Li   TransposeTypeWithSameStorageOrder m_adjoint;
345*bf2c3715SXin Li   typename internal::plain_row_type<MatrixType>::type m_workspace;
346*bf2c3715SXin Li };
347*bf2c3715SXin Li 
348*bf2c3715SXin Li /*** 2x2 SVD implementation
349*bf2c3715SXin Li  ***
350*bf2c3715SXin Li  *** JacobiSVD consists in performing a series of 2x2 SVD subproblems
351*bf2c3715SXin Li  ***/
352*bf2c3715SXin Li 
353*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner>
354*bf2c3715SXin Li struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false>
355*bf2c3715SXin Li {
356*bf2c3715SXin Li   typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
357*bf2c3715SXin Li   typedef typename MatrixType::RealScalar RealScalar;
358*bf2c3715SXin Li   static bool run(typename SVD::WorkMatrixType&, SVD&, Index, Index, RealScalar&) { return true; }
359*bf2c3715SXin Li };
360*bf2c3715SXin Li 
361*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner>
362*bf2c3715SXin Li struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
363*bf2c3715SXin Li {
364*bf2c3715SXin Li   typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
365*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
366*bf2c3715SXin Li   typedef typename MatrixType::RealScalar RealScalar;
367*bf2c3715SXin Li   static bool run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q, RealScalar& maxDiagEntry)
368*bf2c3715SXin Li   {
369*bf2c3715SXin Li     using std::sqrt;
370*bf2c3715SXin Li     using std::abs;
371*bf2c3715SXin Li     Scalar z;
372*bf2c3715SXin Li     JacobiRotation<Scalar> rot;
373*bf2c3715SXin Li     RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
374*bf2c3715SXin Li 
375*bf2c3715SXin Li     const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
376*bf2c3715SXin Li     const RealScalar precision = NumTraits<Scalar>::epsilon();
377*bf2c3715SXin Li 
378*bf2c3715SXin Li     if(n==0)
379*bf2c3715SXin Li     {
380*bf2c3715SXin Li       // make sure first column is zero
381*bf2c3715SXin Li       work_matrix.coeffRef(p,p) = work_matrix.coeffRef(q,p) = Scalar(0);
382*bf2c3715SXin Li 
383*bf2c3715SXin Li       if(abs(numext::imag(work_matrix.coeff(p,q)))>considerAsZero)
384*bf2c3715SXin Li       {
385*bf2c3715SXin Li         // work_matrix.coeff(p,q) can be zero if work_matrix.coeff(q,p) is not zero but small enough to underflow when computing n
386*bf2c3715SXin Li         z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
387*bf2c3715SXin Li         work_matrix.row(p) *= z;
388*bf2c3715SXin Li         if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
389*bf2c3715SXin Li       }
390*bf2c3715SXin Li       if(abs(numext::imag(work_matrix.coeff(q,q)))>considerAsZero)
391*bf2c3715SXin Li       {
392*bf2c3715SXin Li         z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
393*bf2c3715SXin Li         work_matrix.row(q) *= z;
394*bf2c3715SXin Li         if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
395*bf2c3715SXin Li       }
396*bf2c3715SXin Li       // otherwise the second row is already zero, so we have nothing to do.
397*bf2c3715SXin Li     }
398*bf2c3715SXin Li     else
399*bf2c3715SXin Li     {
400*bf2c3715SXin Li       rot.c() = conj(work_matrix.coeff(p,p)) / n;
401*bf2c3715SXin Li       rot.s() = work_matrix.coeff(q,p) / n;
402*bf2c3715SXin Li       work_matrix.applyOnTheLeft(p,q,rot);
403*bf2c3715SXin Li       if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
404*bf2c3715SXin Li       if(abs(numext::imag(work_matrix.coeff(p,q)))>considerAsZero)
405*bf2c3715SXin Li       {
406*bf2c3715SXin Li         z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
407*bf2c3715SXin Li         work_matrix.col(q) *= z;
408*bf2c3715SXin Li         if(svd.computeV()) svd.m_matrixV.col(q) *= z;
409*bf2c3715SXin Li       }
410*bf2c3715SXin Li       if(abs(numext::imag(work_matrix.coeff(q,q)))>considerAsZero)
411*bf2c3715SXin Li       {
412*bf2c3715SXin Li         z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
413*bf2c3715SXin Li         work_matrix.row(q) *= z;
414*bf2c3715SXin Li         if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
415*bf2c3715SXin Li       }
416*bf2c3715SXin Li     }
417*bf2c3715SXin Li 
418*bf2c3715SXin Li     // update largest diagonal entry
419*bf2c3715SXin Li     maxDiagEntry = numext::maxi<RealScalar>(maxDiagEntry,numext::maxi<RealScalar>(abs(work_matrix.coeff(p,p)), abs(work_matrix.coeff(q,q))));
420*bf2c3715SXin Li     // and check whether the 2x2 block is already diagonal
421*bf2c3715SXin Li     RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
422*bf2c3715SXin Li     return abs(work_matrix.coeff(p,q))>threshold || abs(work_matrix.coeff(q,p)) > threshold;
423*bf2c3715SXin Li   }
424*bf2c3715SXin Li };
425*bf2c3715SXin Li 
426*bf2c3715SXin Li template<typename _MatrixType, int QRPreconditioner>
427*bf2c3715SXin Li struct traits<JacobiSVD<_MatrixType,QRPreconditioner> >
428*bf2c3715SXin Li         : traits<_MatrixType>
429*bf2c3715SXin Li {
430*bf2c3715SXin Li   typedef _MatrixType MatrixType;
431*bf2c3715SXin Li };
432*bf2c3715SXin Li 
433*bf2c3715SXin Li } // end namespace internal
434*bf2c3715SXin Li 
435*bf2c3715SXin Li /** \ingroup SVD_Module
436*bf2c3715SXin Li   *
437*bf2c3715SXin Li   *
438*bf2c3715SXin Li   * \class JacobiSVD
439*bf2c3715SXin Li   *
440*bf2c3715SXin Li   * \brief Two-sided Jacobi SVD decomposition of a rectangular matrix
441*bf2c3715SXin Li   *
442*bf2c3715SXin Li   * \tparam _MatrixType the type of the matrix of which we are computing the SVD decomposition
443*bf2c3715SXin Li   * \tparam QRPreconditioner this optional parameter allows to specify the type of QR decomposition that will be used internally
444*bf2c3715SXin Li   *                        for the R-SVD step for non-square matrices. See discussion of possible values below.
445*bf2c3715SXin Li   *
446*bf2c3715SXin Li   * SVD decomposition consists in decomposing any n-by-p matrix \a A as a product
447*bf2c3715SXin Li   *   \f[ A = U S V^* \f]
448*bf2c3715SXin Li   * where \a U is a n-by-n unitary, \a V is a p-by-p unitary, and \a S is a n-by-p real positive matrix which is zero outside of its main diagonal;
449*bf2c3715SXin Li   * the diagonal entries of S are known as the \em singular \em values of \a A and the columns of \a U and \a V are known as the left
450*bf2c3715SXin Li   * and right \em singular \em vectors of \a A respectively.
451*bf2c3715SXin Li   *
452*bf2c3715SXin Li   * Singular values are always sorted in decreasing order.
453*bf2c3715SXin Li   *
454*bf2c3715SXin Li   * This JacobiSVD decomposition computes only the singular values by default. If you want \a U or \a V, you need to ask for them explicitly.
455*bf2c3715SXin Li   *
456*bf2c3715SXin Li   * You can ask for only \em thin \a U or \a V to be computed, meaning the following. In case of a rectangular n-by-p matrix, letting \a m be the
457*bf2c3715SXin Li   * smaller value among \a n and \a p, there are only \a m singular vectors; the remaining columns of \a U and \a V do not correspond to actual
458*bf2c3715SXin Li   * singular vectors. Asking for \em thin \a U or \a V means asking for only their \a m first columns to be formed. So \a U is then a n-by-m matrix,
459*bf2c3715SXin Li   * and \a V is then a p-by-m matrix. Notice that thin \a U and \a V are all you need for (least squares) solving.
460*bf2c3715SXin Li   *
461*bf2c3715SXin Li   * Here's an example demonstrating basic usage:
462*bf2c3715SXin Li   * \include JacobiSVD_basic.cpp
463*bf2c3715SXin Li   * Output: \verbinclude JacobiSVD_basic.out
464*bf2c3715SXin Li   *
465*bf2c3715SXin Li   * This JacobiSVD class is a two-sided Jacobi R-SVD decomposition, ensuring optimal reliability and accuracy. The downside is that it's slower than
466*bf2c3715SXin Li   * bidiagonalizing SVD algorithms for large square matrices; however its complexity is still \f$ O(n^2p) \f$ where \a n is the smaller dimension and
467*bf2c3715SXin Li   * \a p is the greater dimension, meaning that it is still of the same order of complexity as the faster bidiagonalizing R-SVD algorithms.
468*bf2c3715SXin Li   * In particular, like any R-SVD, it takes advantage of non-squareness in that its complexity is only linear in the greater dimension.
469*bf2c3715SXin Li   *
470*bf2c3715SXin Li   * If the input matrix has inf or nan coefficients, the result of the computation is undefined, but the computation is guaranteed to
471*bf2c3715SXin Li   * terminate in finite (and reasonable) time.
472*bf2c3715SXin Li   *
473*bf2c3715SXin Li   * The possible values for QRPreconditioner are:
474*bf2c3715SXin Li   * \li ColPivHouseholderQRPreconditioner is the default. In practice it's very safe. It uses column-pivoting QR.
475*bf2c3715SXin Li   * \li FullPivHouseholderQRPreconditioner, is the safest and slowest. It uses full-pivoting QR.
476*bf2c3715SXin Li   *     Contrary to other QRs, it doesn't allow computing thin unitaries.
477*bf2c3715SXin Li   * \li HouseholderQRPreconditioner is the fastest, and less safe and accurate than the pivoting variants. It uses non-pivoting QR.
478*bf2c3715SXin Li   *     This is very similar in safety and accuracy to the bidiagonalization process used by bidiagonalizing SVD algorithms (since bidiagonalization
479*bf2c3715SXin Li   *     is inherently non-pivoting). However the resulting SVD is still more reliable than bidiagonalizing SVDs because the Jacobi-based iterarive
480*bf2c3715SXin Li   *     process is more reliable than the optimized bidiagonal SVD iterations.
481*bf2c3715SXin Li   * \li NoQRPreconditioner allows not to use a QR preconditioner at all. This is useful if you know that you will only be computing
482*bf2c3715SXin Li   *     JacobiSVD decompositions of square matrices. Non-square matrices require a QR preconditioner. Using this option will result in
483*bf2c3715SXin Li   *     faster compilation and smaller executable code. It won't significantly speed up computation, since JacobiSVD is always checking
484*bf2c3715SXin Li   *     if QR preconditioning is needed before applying it anyway.
485*bf2c3715SXin Li   *
486*bf2c3715SXin Li   * \sa MatrixBase::jacobiSvd()
487*bf2c3715SXin Li   */
488*bf2c3715SXin Li template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
489*bf2c3715SXin Li  : public SVDBase<JacobiSVD<_MatrixType,QRPreconditioner> >
490*bf2c3715SXin Li {
491*bf2c3715SXin Li     typedef SVDBase<JacobiSVD> Base;
492*bf2c3715SXin Li   public:
493*bf2c3715SXin Li 
494*bf2c3715SXin Li     typedef _MatrixType MatrixType;
495*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
496*bf2c3715SXin Li     typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
497*bf2c3715SXin Li     enum {
498*bf2c3715SXin Li       RowsAtCompileTime = MatrixType::RowsAtCompileTime,
499*bf2c3715SXin Li       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
500*bf2c3715SXin Li       DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
501*bf2c3715SXin Li       MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
502*bf2c3715SXin Li       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
503*bf2c3715SXin Li       MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
504*bf2c3715SXin Li       MatrixOptions = MatrixType::Options
505*bf2c3715SXin Li     };
506*bf2c3715SXin Li 
507*bf2c3715SXin Li     typedef typename Base::MatrixUType MatrixUType;
508*bf2c3715SXin Li     typedef typename Base::MatrixVType MatrixVType;
509*bf2c3715SXin Li     typedef typename Base::SingularValuesType SingularValuesType;
510*bf2c3715SXin Li 
511*bf2c3715SXin Li     typedef typename internal::plain_row_type<MatrixType>::type RowType;
512*bf2c3715SXin Li     typedef typename internal::plain_col_type<MatrixType>::type ColType;
513*bf2c3715SXin Li     typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
514*bf2c3715SXin Li                    MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
515*bf2c3715SXin Li             WorkMatrixType;
516*bf2c3715SXin Li 
517*bf2c3715SXin Li     /** \brief Default Constructor.
518*bf2c3715SXin Li       *
519*bf2c3715SXin Li       * The default constructor is useful in cases in which the user intends to
520*bf2c3715SXin Li       * perform decompositions via JacobiSVD::compute(const MatrixType&).
521*bf2c3715SXin Li       */
522*bf2c3715SXin Li     JacobiSVD()
523*bf2c3715SXin Li     {}
524*bf2c3715SXin Li 
525*bf2c3715SXin Li 
526*bf2c3715SXin Li     /** \brief Default Constructor with memory preallocation
527*bf2c3715SXin Li       *
528*bf2c3715SXin Li       * Like the default constructor but with preallocation of the internal data
529*bf2c3715SXin Li       * according to the specified problem size.
530*bf2c3715SXin Li       * \sa JacobiSVD()
531*bf2c3715SXin Li       */
532*bf2c3715SXin Li     JacobiSVD(Index rows, Index cols, unsigned int computationOptions = 0)
533*bf2c3715SXin Li     {
534*bf2c3715SXin Li       allocate(rows, cols, computationOptions);
535*bf2c3715SXin Li     }
536*bf2c3715SXin Li 
537*bf2c3715SXin Li     /** \brief Constructor performing the decomposition of given matrix.
538*bf2c3715SXin Li      *
539*bf2c3715SXin Li      * \param matrix the matrix to decompose
540*bf2c3715SXin Li      * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
541*bf2c3715SXin Li      *                           By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
542*bf2c3715SXin Li      *                           #ComputeFullV, #ComputeThinV.
543*bf2c3715SXin Li      *
544*bf2c3715SXin Li      * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
545*bf2c3715SXin Li      * available with the (non-default) FullPivHouseholderQR preconditioner.
546*bf2c3715SXin Li      */
547*bf2c3715SXin Li     explicit JacobiSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
548*bf2c3715SXin Li     {
549*bf2c3715SXin Li       compute(matrix, computationOptions);
550*bf2c3715SXin Li     }
551*bf2c3715SXin Li 
552*bf2c3715SXin Li     /** \brief Method performing the decomposition of given matrix using custom options.
553*bf2c3715SXin Li      *
554*bf2c3715SXin Li      * \param matrix the matrix to decompose
555*bf2c3715SXin Li      * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
556*bf2c3715SXin Li      *                           By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
557*bf2c3715SXin Li      *                           #ComputeFullV, #ComputeThinV.
558*bf2c3715SXin Li      *
559*bf2c3715SXin Li      * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
560*bf2c3715SXin Li      * available with the (non-default) FullPivHouseholderQR preconditioner.
561*bf2c3715SXin Li      */
562*bf2c3715SXin Li     JacobiSVD& compute(const MatrixType& matrix, unsigned int computationOptions);
563*bf2c3715SXin Li 
564*bf2c3715SXin Li     /** \brief Method performing the decomposition of given matrix using current options.
565*bf2c3715SXin Li      *
566*bf2c3715SXin Li      * \param matrix the matrix to decompose
567*bf2c3715SXin Li      *
568*bf2c3715SXin Li      * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
569*bf2c3715SXin Li      */
570*bf2c3715SXin Li     JacobiSVD& compute(const MatrixType& matrix)
571*bf2c3715SXin Li     {
572*bf2c3715SXin Li       return compute(matrix, m_computationOptions);
573*bf2c3715SXin Li     }
574*bf2c3715SXin Li 
575*bf2c3715SXin Li     using Base::computeU;
576*bf2c3715SXin Li     using Base::computeV;
577*bf2c3715SXin Li     using Base::rows;
578*bf2c3715SXin Li     using Base::cols;
579*bf2c3715SXin Li     using Base::rank;
580*bf2c3715SXin Li 
581*bf2c3715SXin Li   private:
582*bf2c3715SXin Li     void allocate(Index rows, Index cols, unsigned int computationOptions);
583*bf2c3715SXin Li 
584*bf2c3715SXin Li   protected:
585*bf2c3715SXin Li     using Base::m_matrixU;
586*bf2c3715SXin Li     using Base::m_matrixV;
587*bf2c3715SXin Li     using Base::m_singularValues;
588*bf2c3715SXin Li     using Base::m_info;
589*bf2c3715SXin Li     using Base::m_isInitialized;
590*bf2c3715SXin Li     using Base::m_isAllocated;
591*bf2c3715SXin Li     using Base::m_usePrescribedThreshold;
592*bf2c3715SXin Li     using Base::m_computeFullU;
593*bf2c3715SXin Li     using Base::m_computeThinU;
594*bf2c3715SXin Li     using Base::m_computeFullV;
595*bf2c3715SXin Li     using Base::m_computeThinV;
596*bf2c3715SXin Li     using Base::m_computationOptions;
597*bf2c3715SXin Li     using Base::m_nonzeroSingularValues;
598*bf2c3715SXin Li     using Base::m_rows;
599*bf2c3715SXin Li     using Base::m_cols;
600*bf2c3715SXin Li     using Base::m_diagSize;
601*bf2c3715SXin Li     using Base::m_prescribedThreshold;
602*bf2c3715SXin Li     WorkMatrixType m_workMatrix;
603*bf2c3715SXin Li 
604*bf2c3715SXin Li     template<typename __MatrixType, int _QRPreconditioner, bool _IsComplex>
605*bf2c3715SXin Li     friend struct internal::svd_precondition_2x2_block_to_be_real;
606*bf2c3715SXin Li     template<typename __MatrixType, int _QRPreconditioner, int _Case, bool _DoAnything>
607*bf2c3715SXin Li     friend struct internal::qr_preconditioner_impl;
608*bf2c3715SXin Li 
609*bf2c3715SXin Li     internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows> m_qr_precond_morecols;
610*bf2c3715SXin Li     internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols> m_qr_precond_morerows;
611*bf2c3715SXin Li     MatrixType m_scaledMatrix;
612*bf2c3715SXin Li };
613*bf2c3715SXin Li 
614*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner>
615*bf2c3715SXin Li void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Eigen::Index rows, Eigen::Index cols, unsigned int computationOptions)
616*bf2c3715SXin Li {
617*bf2c3715SXin Li   eigen_assert(rows >= 0 && cols >= 0);
618*bf2c3715SXin Li 
619*bf2c3715SXin Li   if (m_isAllocated &&
620*bf2c3715SXin Li       rows == m_rows &&
621*bf2c3715SXin Li       cols == m_cols &&
622*bf2c3715SXin Li       computationOptions == m_computationOptions)
623*bf2c3715SXin Li   {
624*bf2c3715SXin Li     return;
625*bf2c3715SXin Li   }
626*bf2c3715SXin Li 
627*bf2c3715SXin Li   m_rows = rows;
628*bf2c3715SXin Li   m_cols = cols;
629*bf2c3715SXin Li   m_info = Success;
630*bf2c3715SXin Li   m_isInitialized = false;
631*bf2c3715SXin Li   m_isAllocated = true;
632*bf2c3715SXin Li   m_computationOptions = computationOptions;
633*bf2c3715SXin Li   m_computeFullU = (computationOptions & ComputeFullU) != 0;
634*bf2c3715SXin Li   m_computeThinU = (computationOptions & ComputeThinU) != 0;
635*bf2c3715SXin Li   m_computeFullV = (computationOptions & ComputeFullV) != 0;
636*bf2c3715SXin Li   m_computeThinV = (computationOptions & ComputeThinV) != 0;
637*bf2c3715SXin Li   eigen_assert(!(m_computeFullU && m_computeThinU) && "JacobiSVD: you can't ask for both full and thin U");
638*bf2c3715SXin Li   eigen_assert(!(m_computeFullV && m_computeThinV) && "JacobiSVD: you can't ask for both full and thin V");
639*bf2c3715SXin Li   eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) &&
640*bf2c3715SXin Li               "JacobiSVD: thin U and V are only available when your matrix has a dynamic number of columns.");
641*bf2c3715SXin Li   if (QRPreconditioner == FullPivHouseholderQRPreconditioner)
642*bf2c3715SXin Li   {
643*bf2c3715SXin Li       eigen_assert(!(m_computeThinU || m_computeThinV) &&
644*bf2c3715SXin Li               "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
645*bf2c3715SXin Li               "Use the ColPivHouseholderQR preconditioner instead.");
646*bf2c3715SXin Li   }
647*bf2c3715SXin Li   m_diagSize = (std::min)(m_rows, m_cols);
648*bf2c3715SXin Li   m_singularValues.resize(m_diagSize);
649*bf2c3715SXin Li   if(RowsAtCompileTime==Dynamic)
650*bf2c3715SXin Li     m_matrixU.resize(m_rows, m_computeFullU ? m_rows
651*bf2c3715SXin Li                             : m_computeThinU ? m_diagSize
652*bf2c3715SXin Li                             : 0);
653*bf2c3715SXin Li   if(ColsAtCompileTime==Dynamic)
654*bf2c3715SXin Li     m_matrixV.resize(m_cols, m_computeFullV ? m_cols
655*bf2c3715SXin Li                             : m_computeThinV ? m_diagSize
656*bf2c3715SXin Li                             : 0);
657*bf2c3715SXin Li   m_workMatrix.resize(m_diagSize, m_diagSize);
658*bf2c3715SXin Li 
659*bf2c3715SXin Li   if(m_cols>m_rows)   m_qr_precond_morecols.allocate(*this);
660*bf2c3715SXin Li   if(m_rows>m_cols)   m_qr_precond_morerows.allocate(*this);
661*bf2c3715SXin Li   if(m_rows!=m_cols)  m_scaledMatrix.resize(rows,cols);
662*bf2c3715SXin Li }
663*bf2c3715SXin Li 
664*bf2c3715SXin Li template<typename MatrixType, int QRPreconditioner>
665*bf2c3715SXin Li JacobiSVD<MatrixType, QRPreconditioner>&
666*bf2c3715SXin Li JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
667*bf2c3715SXin Li {
668*bf2c3715SXin Li   using std::abs;
669*bf2c3715SXin Li   allocate(matrix.rows(), matrix.cols(), computationOptions);
670*bf2c3715SXin Li 
671*bf2c3715SXin Li   // currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
672*bf2c3715SXin Li   // only worsening the precision of U and V as we accumulate more rotations
673*bf2c3715SXin Li   const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();
674*bf2c3715SXin Li 
675*bf2c3715SXin Li   // limit for denormal numbers to be considered zero in order to avoid infinite loops (see bug 286)
676*bf2c3715SXin Li   const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
677*bf2c3715SXin Li 
678*bf2c3715SXin Li   // Scaling factor to reduce over/under-flows
679*bf2c3715SXin Li   RealScalar scale = matrix.cwiseAbs().template maxCoeff<PropagateNaN>();
680*bf2c3715SXin Li   if (!(numext::isfinite)(scale)) {
681*bf2c3715SXin Li     m_isInitialized = true;
682*bf2c3715SXin Li     m_info = InvalidInput;
683*bf2c3715SXin Li     return *this;
684*bf2c3715SXin Li   }
685*bf2c3715SXin Li   if(scale==RealScalar(0)) scale = RealScalar(1);
686*bf2c3715SXin Li 
687*bf2c3715SXin Li   /*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
688*bf2c3715SXin Li 
689*bf2c3715SXin Li   if(m_rows!=m_cols)
690*bf2c3715SXin Li   {
691*bf2c3715SXin Li     m_scaledMatrix = matrix / scale;
692*bf2c3715SXin Li     m_qr_precond_morecols.run(*this, m_scaledMatrix);
693*bf2c3715SXin Li     m_qr_precond_morerows.run(*this, m_scaledMatrix);
694*bf2c3715SXin Li   }
695*bf2c3715SXin Li   else
696*bf2c3715SXin Li   {
697*bf2c3715SXin Li     m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize) / scale;
698*bf2c3715SXin Li     if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
699*bf2c3715SXin Li     if(m_computeThinU) m_matrixU.setIdentity(m_rows,m_diagSize);
700*bf2c3715SXin Li     if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
701*bf2c3715SXin Li     if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
702*bf2c3715SXin Li   }
703*bf2c3715SXin Li 
704*bf2c3715SXin Li   /*** step 2. The main Jacobi SVD iteration. ***/
705*bf2c3715SXin Li   RealScalar maxDiagEntry = m_workMatrix.cwiseAbs().diagonal().maxCoeff();
706*bf2c3715SXin Li 
707*bf2c3715SXin Li   bool finished = false;
708*bf2c3715SXin Li   while(!finished)
709*bf2c3715SXin Li   {
710*bf2c3715SXin Li     finished = true;
711*bf2c3715SXin Li 
712*bf2c3715SXin Li     // do a sweep: for all index pairs (p,q), perform SVD of the corresponding 2x2 sub-matrix
713*bf2c3715SXin Li 
714*bf2c3715SXin Li     for(Index p = 1; p < m_diagSize; ++p)
715*bf2c3715SXin Li     {
716*bf2c3715SXin Li       for(Index q = 0; q < p; ++q)
717*bf2c3715SXin Li       {
718*bf2c3715SXin Li         // if this 2x2 sub-matrix is not diagonal already...
719*bf2c3715SXin Li         // notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
720*bf2c3715SXin Li         // keep us iterating forever. Similarly, small denormal numbers are considered zero.
721*bf2c3715SXin Li         RealScalar threshold = numext::maxi<RealScalar>(considerAsZero, precision * maxDiagEntry);
722*bf2c3715SXin Li         if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
723*bf2c3715SXin Li         {
724*bf2c3715SXin Li           finished = false;
725*bf2c3715SXin Li           // perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
726*bf2c3715SXin Li           // the complex to real operation returns true if the updated 2x2 block is not already diagonal
727*bf2c3715SXin Li           if(internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q, maxDiagEntry))
728*bf2c3715SXin Li           {
729*bf2c3715SXin Li             JacobiRotation<RealScalar> j_left, j_right;
730*bf2c3715SXin Li             internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
731*bf2c3715SXin Li 
732*bf2c3715SXin Li             // accumulate resulting Jacobi rotations
733*bf2c3715SXin Li             m_workMatrix.applyOnTheLeft(p,q,j_left);
734*bf2c3715SXin Li             if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
735*bf2c3715SXin Li 
736*bf2c3715SXin Li             m_workMatrix.applyOnTheRight(p,q,j_right);
737*bf2c3715SXin Li             if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
738*bf2c3715SXin Li 
739*bf2c3715SXin Li             // keep track of the largest diagonal coefficient
740*bf2c3715SXin Li             maxDiagEntry = numext::maxi<RealScalar>(maxDiagEntry,numext::maxi<RealScalar>(abs(m_workMatrix.coeff(p,p)), abs(m_workMatrix.coeff(q,q))));
741*bf2c3715SXin Li           }
742*bf2c3715SXin Li         }
743*bf2c3715SXin Li       }
744*bf2c3715SXin Li     }
745*bf2c3715SXin Li   }
746*bf2c3715SXin Li 
747*bf2c3715SXin Li   /*** step 3. The work matrix is now diagonal, so ensure it's positive so its diagonal entries are the singular values ***/
748*bf2c3715SXin Li 
749*bf2c3715SXin Li   for(Index i = 0; i < m_diagSize; ++i)
750*bf2c3715SXin Li   {
751*bf2c3715SXin Li     // For a complex matrix, some diagonal coefficients might note have been
752*bf2c3715SXin Li     // treated by svd_precondition_2x2_block_to_be_real, and the imaginary part
753*bf2c3715SXin Li     // of some diagonal entry might not be null.
754*bf2c3715SXin Li     if(NumTraits<Scalar>::IsComplex && abs(numext::imag(m_workMatrix.coeff(i,i)))>considerAsZero)
755*bf2c3715SXin Li     {
756*bf2c3715SXin Li       RealScalar a = abs(m_workMatrix.coeff(i,i));
757*bf2c3715SXin Li       m_singularValues.coeffRef(i) = abs(a);
758*bf2c3715SXin Li       if(computeU()) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/a;
759*bf2c3715SXin Li     }
760*bf2c3715SXin Li     else
761*bf2c3715SXin Li     {
762*bf2c3715SXin Li       // m_workMatrix.coeff(i,i) is already real, no difficulty:
763*bf2c3715SXin Li       RealScalar a = numext::real(m_workMatrix.coeff(i,i));
764*bf2c3715SXin Li       m_singularValues.coeffRef(i) = abs(a);
765*bf2c3715SXin Li       if(computeU() && (a<RealScalar(0))) m_matrixU.col(i) = -m_matrixU.col(i);
766*bf2c3715SXin Li     }
767*bf2c3715SXin Li   }
768*bf2c3715SXin Li 
769*bf2c3715SXin Li   m_singularValues *= scale;
770*bf2c3715SXin Li 
771*bf2c3715SXin Li   /*** step 4. Sort singular values in descending order and compute the number of nonzero singular values ***/
772*bf2c3715SXin Li 
773*bf2c3715SXin Li   m_nonzeroSingularValues = m_diagSize;
774*bf2c3715SXin Li   for(Index i = 0; i < m_diagSize; i++)
775*bf2c3715SXin Li   {
776*bf2c3715SXin Li     Index pos;
777*bf2c3715SXin Li     RealScalar maxRemainingSingularValue = m_singularValues.tail(m_diagSize-i).maxCoeff(&pos);
778*bf2c3715SXin Li     if(maxRemainingSingularValue == RealScalar(0))
779*bf2c3715SXin Li     {
780*bf2c3715SXin Li       m_nonzeroSingularValues = i;
781*bf2c3715SXin Li       break;
782*bf2c3715SXin Li     }
783*bf2c3715SXin Li     if(pos)
784*bf2c3715SXin Li     {
785*bf2c3715SXin Li       pos += i;
786*bf2c3715SXin Li       std::swap(m_singularValues.coeffRef(i), m_singularValues.coeffRef(pos));
787*bf2c3715SXin Li       if(computeU()) m_matrixU.col(pos).swap(m_matrixU.col(i));
788*bf2c3715SXin Li       if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
789*bf2c3715SXin Li     }
790*bf2c3715SXin Li   }
791*bf2c3715SXin Li 
792*bf2c3715SXin Li   m_isInitialized = true;
793*bf2c3715SXin Li   return *this;
794*bf2c3715SXin Li }
795*bf2c3715SXin Li 
796*bf2c3715SXin Li /** \svd_module
797*bf2c3715SXin Li   *
798*bf2c3715SXin Li   * \return the singular value decomposition of \c *this computed by two-sided
799*bf2c3715SXin Li   * Jacobi transformations.
800*bf2c3715SXin Li   *
801*bf2c3715SXin Li   * \sa class JacobiSVD
802*bf2c3715SXin Li   */
803*bf2c3715SXin Li template<typename Derived>
804*bf2c3715SXin Li JacobiSVD<typename MatrixBase<Derived>::PlainObject>
805*bf2c3715SXin Li MatrixBase<Derived>::jacobiSvd(unsigned int computationOptions) const
806*bf2c3715SXin Li {
807*bf2c3715SXin Li   return JacobiSVD<PlainObject>(*this, computationOptions);
808*bf2c3715SXin Li }
809*bf2c3715SXin Li 
810*bf2c3715SXin Li } // end namespace Eigen
811*bf2c3715SXin Li 
812*bf2c3715SXin Li #endif // EIGEN_JACOBISVD_H
813