xref: /aosp_15_r20/external/eigen/Eigen/src/SVD/UpperBidiagonalization.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) 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_BIDIAGONALIZATION_H
12*bf2c3715SXin Li #define EIGEN_BIDIAGONALIZATION_H
13*bf2c3715SXin Li 
14*bf2c3715SXin Li namespace Eigen {
15*bf2c3715SXin Li 
16*bf2c3715SXin Li namespace internal {
17*bf2c3715SXin Li // UpperBidiagonalization will probably be replaced by a Bidiagonalization class, don't want to make it stable API.
18*bf2c3715SXin Li // At the same time, it's useful to keep for now as it's about the only thing that is testing the BandMatrix class.
19*bf2c3715SXin Li 
20*bf2c3715SXin Li template<typename _MatrixType> class UpperBidiagonalization
21*bf2c3715SXin Li {
22*bf2c3715SXin Li   public:
23*bf2c3715SXin Li 
24*bf2c3715SXin Li     typedef _MatrixType MatrixType;
25*bf2c3715SXin Li     enum {
26*bf2c3715SXin Li       RowsAtCompileTime = MatrixType::RowsAtCompileTime,
27*bf2c3715SXin Li       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
28*bf2c3715SXin Li       ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::ret
29*bf2c3715SXin Li     };
30*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
31*bf2c3715SXin Li     typedef typename MatrixType::RealScalar RealScalar;
32*bf2c3715SXin Li     typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
33*bf2c3715SXin Li     typedef Matrix<Scalar, 1, ColsAtCompileTime> RowVectorType;
34*bf2c3715SXin Li     typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType;
35*bf2c3715SXin Li     typedef BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0, RowMajor> BidiagonalType;
36*bf2c3715SXin Li     typedef Matrix<Scalar, ColsAtCompileTime, 1> DiagVectorType;
37*bf2c3715SXin Li     typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType;
38*bf2c3715SXin Li     typedef HouseholderSequence<
39*bf2c3715SXin Li               const MatrixType,
40*bf2c3715SXin Li               const typename internal::remove_all<typename Diagonal<const MatrixType,0>::ConjugateReturnType>::type
41*bf2c3715SXin Li             > HouseholderUSequenceType;
42*bf2c3715SXin Li     typedef HouseholderSequence<
43*bf2c3715SXin Li               const typename internal::remove_all<typename MatrixType::ConjugateReturnType>::type,
44*bf2c3715SXin Li               Diagonal<const MatrixType,1>,
45*bf2c3715SXin Li               OnTheRight
46*bf2c3715SXin Li             > HouseholderVSequenceType;
47*bf2c3715SXin Li 
48*bf2c3715SXin Li     /**
49*bf2c3715SXin Li     * \brief Default Constructor.
50*bf2c3715SXin Li     *
51*bf2c3715SXin Li     * The default constructor is useful in cases in which the user intends to
52*bf2c3715SXin Li     * perform decompositions via Bidiagonalization::compute(const MatrixType&).
53*bf2c3715SXin Li     */
UpperBidiagonalization()54*bf2c3715SXin Li     UpperBidiagonalization() : m_householder(), m_bidiagonal(), m_isInitialized(false) {}
55*bf2c3715SXin Li 
UpperBidiagonalization(const MatrixType & matrix)56*bf2c3715SXin Li     explicit UpperBidiagonalization(const MatrixType& matrix)
57*bf2c3715SXin Li       : m_householder(matrix.rows(), matrix.cols()),
58*bf2c3715SXin Li         m_bidiagonal(matrix.cols(), matrix.cols()),
59*bf2c3715SXin Li         m_isInitialized(false)
60*bf2c3715SXin Li     {
61*bf2c3715SXin Li       compute(matrix);
62*bf2c3715SXin Li     }
63*bf2c3715SXin Li 
64*bf2c3715SXin Li     UpperBidiagonalization& compute(const MatrixType& matrix);
65*bf2c3715SXin Li     UpperBidiagonalization& computeUnblocked(const MatrixType& matrix);
66*bf2c3715SXin Li 
householder()67*bf2c3715SXin Li     const MatrixType& householder() const { return m_householder; }
bidiagonal()68*bf2c3715SXin Li     const BidiagonalType& bidiagonal() const { return m_bidiagonal; }
69*bf2c3715SXin Li 
householderU()70*bf2c3715SXin Li     const HouseholderUSequenceType householderU() const
71*bf2c3715SXin Li     {
72*bf2c3715SXin Li       eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
73*bf2c3715SXin Li       return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
74*bf2c3715SXin Li     }
75*bf2c3715SXin Li 
householderV()76*bf2c3715SXin Li     const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
77*bf2c3715SXin Li     {
78*bf2c3715SXin Li       eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
79*bf2c3715SXin Li       return HouseholderVSequenceType(m_householder.conjugate(), m_householder.const_derived().template diagonal<1>())
80*bf2c3715SXin Li              .setLength(m_householder.cols()-1)
81*bf2c3715SXin Li              .setShift(1);
82*bf2c3715SXin Li     }
83*bf2c3715SXin Li 
84*bf2c3715SXin Li   protected:
85*bf2c3715SXin Li     MatrixType m_householder;
86*bf2c3715SXin Li     BidiagonalType m_bidiagonal;
87*bf2c3715SXin Li     bool m_isInitialized;
88*bf2c3715SXin Li };
89*bf2c3715SXin Li 
90*bf2c3715SXin Li // Standard upper bidiagonalization without fancy optimizations
91*bf2c3715SXin Li // This version should be faster for small matrix size
92*bf2c3715SXin Li template<typename MatrixType>
93*bf2c3715SXin Li void upperbidiagonalization_inplace_unblocked(MatrixType& mat,
94*bf2c3715SXin Li                                               typename MatrixType::RealScalar *diagonal,
95*bf2c3715SXin Li                                               typename MatrixType::RealScalar *upper_diagonal,
96*bf2c3715SXin Li                                               typename MatrixType::Scalar* tempData = 0)
97*bf2c3715SXin Li {
98*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
99*bf2c3715SXin Li 
100*bf2c3715SXin Li   Index rows = mat.rows();
101*bf2c3715SXin Li   Index cols = mat.cols();
102*bf2c3715SXin Li 
103*bf2c3715SXin Li   typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixType::MaxRowsAtCompileTime,1> TempType;
104*bf2c3715SXin Li   TempType tempVector;
105*bf2c3715SXin Li   if(tempData==0)
106*bf2c3715SXin Li   {
107*bf2c3715SXin Li     tempVector.resize(rows);
108*bf2c3715SXin Li     tempData = tempVector.data();
109*bf2c3715SXin Li   }
110*bf2c3715SXin Li 
111*bf2c3715SXin Li   for (Index k = 0; /* breaks at k==cols-1 below */ ; ++k)
112*bf2c3715SXin Li   {
113*bf2c3715SXin Li     Index remainingRows = rows - k;
114*bf2c3715SXin Li     Index remainingCols = cols - k - 1;
115*bf2c3715SXin Li 
116*bf2c3715SXin Li     // construct left householder transform in-place in A
117*bf2c3715SXin Li     mat.col(k).tail(remainingRows)
118*bf2c3715SXin Li        .makeHouseholderInPlace(mat.coeffRef(k,k), diagonal[k]);
119*bf2c3715SXin Li     // apply householder transform to remaining part of A on the left
120*bf2c3715SXin Li     mat.bottomRightCorner(remainingRows, remainingCols)
121*bf2c3715SXin Li        .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), mat.coeff(k,k), tempData);
122*bf2c3715SXin Li 
123*bf2c3715SXin Li     if(k == cols-1) break;
124*bf2c3715SXin Li 
125*bf2c3715SXin Li     // construct right householder transform in-place in mat
126*bf2c3715SXin Li     mat.row(k).tail(remainingCols)
127*bf2c3715SXin Li        .makeHouseholderInPlace(mat.coeffRef(k,k+1), upper_diagonal[k]);
128*bf2c3715SXin Li     // apply householder transform to remaining part of mat on the left
129*bf2c3715SXin Li     mat.bottomRightCorner(remainingRows-1, remainingCols)
130*bf2c3715SXin Li        .applyHouseholderOnTheRight(mat.row(k).tail(remainingCols-1).adjoint(), mat.coeff(k,k+1), tempData);
131*bf2c3715SXin Li   }
132*bf2c3715SXin Li }
133*bf2c3715SXin Li 
134*bf2c3715SXin Li /** \internal
135*bf2c3715SXin Li   * Helper routine for the block reduction to upper bidiagonal form.
136*bf2c3715SXin Li   *
137*bf2c3715SXin Li   * Let's partition the matrix A:
138*bf2c3715SXin Li   *
139*bf2c3715SXin Li   *      | A00 A01 |
140*bf2c3715SXin Li   *  A = |         |
141*bf2c3715SXin Li   *      | A10 A11 |
142*bf2c3715SXin Li   *
143*bf2c3715SXin Li   * This function reduces to bidiagonal form the left \c rows x \a blockSize vertical panel [A00/A10]
144*bf2c3715SXin Li   * and the \a blockSize x \c cols horizontal panel [A00 A01] of the matrix \a A. The bottom-right block A11
145*bf2c3715SXin Li   * is updated using matrix-matrix products:
146*bf2c3715SXin Li   *   A22 -= V * Y^T - X * U^T
147*bf2c3715SXin Li   * where V and U contains the left and right Householder vectors. U and V are stored in A10, and A01
148*bf2c3715SXin Li   * respectively, and the update matrices X and Y are computed during the reduction.
149*bf2c3715SXin Li   *
150*bf2c3715SXin Li   */
151*bf2c3715SXin Li template<typename MatrixType>
upperbidiagonalization_blocked_helper(MatrixType & A,typename MatrixType::RealScalar * diagonal,typename MatrixType::RealScalar * upper_diagonal,Index bs,Ref<Matrix<typename MatrixType::Scalar,Dynamic,Dynamic,traits<MatrixType>::Flags & RowMajorBit>> X,Ref<Matrix<typename MatrixType::Scalar,Dynamic,Dynamic,traits<MatrixType>::Flags & RowMajorBit>> Y)152*bf2c3715SXin Li void upperbidiagonalization_blocked_helper(MatrixType& A,
153*bf2c3715SXin Li                                            typename MatrixType::RealScalar *diagonal,
154*bf2c3715SXin Li                                            typename MatrixType::RealScalar *upper_diagonal,
155*bf2c3715SXin Li                                            Index bs,
156*bf2c3715SXin Li                                            Ref<Matrix<typename MatrixType::Scalar, Dynamic, Dynamic,
157*bf2c3715SXin Li                                                       traits<MatrixType>::Flags & RowMajorBit> > X,
158*bf2c3715SXin Li                                            Ref<Matrix<typename MatrixType::Scalar, Dynamic, Dynamic,
159*bf2c3715SXin Li                                                       traits<MatrixType>::Flags & RowMajorBit> > Y)
160*bf2c3715SXin Li {
161*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
162*bf2c3715SXin Li   typedef typename MatrixType::RealScalar RealScalar;
163*bf2c3715SXin Li   typedef typename NumTraits<RealScalar>::Literal Literal;
164*bf2c3715SXin Li   enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
165*bf2c3715SXin Li   typedef InnerStride<int(StorageOrder) == int(ColMajor) ? 1 : Dynamic> ColInnerStride;
166*bf2c3715SXin Li   typedef InnerStride<int(StorageOrder) == int(ColMajor) ? Dynamic : 1> RowInnerStride;
167*bf2c3715SXin Li   typedef Ref<Matrix<Scalar, Dynamic, 1>, 0, ColInnerStride>    SubColumnType;
168*bf2c3715SXin Li   typedef Ref<Matrix<Scalar, 1, Dynamic>, 0, RowInnerStride>    SubRowType;
169*bf2c3715SXin Li   typedef Ref<Matrix<Scalar, Dynamic, Dynamic, StorageOrder > > SubMatType;
170*bf2c3715SXin Li 
171*bf2c3715SXin Li   Index brows = A.rows();
172*bf2c3715SXin Li   Index bcols = A.cols();
173*bf2c3715SXin Li 
174*bf2c3715SXin Li   Scalar tau_u, tau_u_prev(0), tau_v;
175*bf2c3715SXin Li 
176*bf2c3715SXin Li   for(Index k = 0; k < bs; ++k)
177*bf2c3715SXin Li   {
178*bf2c3715SXin Li     Index remainingRows = brows - k;
179*bf2c3715SXin Li     Index remainingCols = bcols - k - 1;
180*bf2c3715SXin Li 
181*bf2c3715SXin Li     SubMatType X_k1( X.block(k,0, remainingRows,k) );
182*bf2c3715SXin Li     SubMatType V_k1( A.block(k,0, remainingRows,k) );
183*bf2c3715SXin Li 
184*bf2c3715SXin Li     // 1 - update the k-th column of A
185*bf2c3715SXin Li     SubColumnType v_k = A.col(k).tail(remainingRows);
186*bf2c3715SXin Li           v_k -= V_k1 * Y.row(k).head(k).adjoint();
187*bf2c3715SXin Li     if(k) v_k -= X_k1 * A.col(k).head(k);
188*bf2c3715SXin Li 
189*bf2c3715SXin Li     // 2 - construct left Householder transform in-place
190*bf2c3715SXin Li     v_k.makeHouseholderInPlace(tau_v, diagonal[k]);
191*bf2c3715SXin Li 
192*bf2c3715SXin Li     if(k+1<bcols)
193*bf2c3715SXin Li     {
194*bf2c3715SXin Li       SubMatType Y_k  ( Y.block(k+1,0, remainingCols, k+1) );
195*bf2c3715SXin Li       SubMatType U_k1 ( A.block(0,k+1, k,remainingCols) );
196*bf2c3715SXin Li 
197*bf2c3715SXin Li       // this eases the application of Householder transforAions
198*bf2c3715SXin Li       // A(k,k) will store tau_v later
199*bf2c3715SXin Li       A(k,k) = Scalar(1);
200*bf2c3715SXin Li 
201*bf2c3715SXin Li       // 3 - Compute y_k^T = tau_v * ( A^T*v_k - Y_k-1*V_k-1^T*v_k - U_k-1*X_k-1^T*v_k )
202*bf2c3715SXin Li       {
203*bf2c3715SXin Li         SubColumnType y_k( Y.col(k).tail(remainingCols) );
204*bf2c3715SXin Li 
205*bf2c3715SXin Li         // let's use the beginning of column k of Y as a temporary vector
206*bf2c3715SXin Li         SubColumnType tmp( Y.col(k).head(k) );
207*bf2c3715SXin Li         y_k.noalias()  = A.block(k,k+1, remainingRows,remainingCols).adjoint() * v_k; // bottleneck
208*bf2c3715SXin Li         tmp.noalias()  = V_k1.adjoint()  * v_k;
209*bf2c3715SXin Li         y_k.noalias() -= Y_k.leftCols(k) * tmp;
210*bf2c3715SXin Li         tmp.noalias()  = X_k1.adjoint()  * v_k;
211*bf2c3715SXin Li         y_k.noalias() -= U_k1.adjoint()  * tmp;
212*bf2c3715SXin Li         y_k *= numext::conj(tau_v);
213*bf2c3715SXin Li       }
214*bf2c3715SXin Li 
215*bf2c3715SXin Li       // 4 - update k-th row of A (it will become u_k)
216*bf2c3715SXin Li       SubRowType u_k( A.row(k).tail(remainingCols) );
217*bf2c3715SXin Li       u_k = u_k.conjugate();
218*bf2c3715SXin Li       {
219*bf2c3715SXin Li         u_k -= Y_k * A.row(k).head(k+1).adjoint();
220*bf2c3715SXin Li         if(k) u_k -= U_k1.adjoint() * X.row(k).head(k).adjoint();
221*bf2c3715SXin Li       }
222*bf2c3715SXin Li 
223*bf2c3715SXin Li       // 5 - construct right Householder transform in-place
224*bf2c3715SXin Li       u_k.makeHouseholderInPlace(tau_u, upper_diagonal[k]);
225*bf2c3715SXin Li 
226*bf2c3715SXin Li       // this eases the application of Householder transformations
227*bf2c3715SXin Li       // A(k,k+1) will store tau_u later
228*bf2c3715SXin Li       A(k,k+1) = Scalar(1);
229*bf2c3715SXin Li 
230*bf2c3715SXin Li       // 6 - Compute x_k = tau_u * ( A*u_k - X_k-1*U_k-1^T*u_k - V_k*Y_k^T*u_k )
231*bf2c3715SXin Li       {
232*bf2c3715SXin Li         SubColumnType x_k ( X.col(k).tail(remainingRows-1) );
233*bf2c3715SXin Li 
234*bf2c3715SXin Li         // let's use the beginning of column k of X as a temporary vectors
235*bf2c3715SXin Li         // note that tmp0 and tmp1 overlaps
236*bf2c3715SXin Li         SubColumnType tmp0 ( X.col(k).head(k) ),
237*bf2c3715SXin Li                       tmp1 ( X.col(k).head(k+1) );
238*bf2c3715SXin Li 
239*bf2c3715SXin Li         x_k.noalias()   = A.block(k+1,k+1, remainingRows-1,remainingCols) * u_k.transpose(); // bottleneck
240*bf2c3715SXin Li         tmp0.noalias()  = U_k1 * u_k.transpose();
241*bf2c3715SXin Li         x_k.noalias()  -= X_k1.bottomRows(remainingRows-1) * tmp0;
242*bf2c3715SXin Li         tmp1.noalias()  = Y_k.adjoint() * u_k.transpose();
243*bf2c3715SXin Li         x_k.noalias()  -= A.block(k+1,0, remainingRows-1,k+1) * tmp1;
244*bf2c3715SXin Li         x_k *= numext::conj(tau_u);
245*bf2c3715SXin Li         tau_u = numext::conj(tau_u);
246*bf2c3715SXin Li         u_k = u_k.conjugate();
247*bf2c3715SXin Li       }
248*bf2c3715SXin Li 
249*bf2c3715SXin Li       if(k>0) A.coeffRef(k-1,k) = tau_u_prev;
250*bf2c3715SXin Li       tau_u_prev = tau_u;
251*bf2c3715SXin Li     }
252*bf2c3715SXin Li     else
253*bf2c3715SXin Li       A.coeffRef(k-1,k) = tau_u_prev;
254*bf2c3715SXin Li 
255*bf2c3715SXin Li     A.coeffRef(k,k) = tau_v;
256*bf2c3715SXin Li   }
257*bf2c3715SXin Li 
258*bf2c3715SXin Li   if(bs<bcols)
259*bf2c3715SXin Li     A.coeffRef(bs-1,bs) = tau_u_prev;
260*bf2c3715SXin Li 
261*bf2c3715SXin Li   // update A22
262*bf2c3715SXin Li   if(bcols>bs && brows>bs)
263*bf2c3715SXin Li   {
264*bf2c3715SXin Li     SubMatType A11( A.bottomRightCorner(brows-bs,bcols-bs) );
265*bf2c3715SXin Li     SubMatType A10( A.block(bs,0, brows-bs,bs) );
266*bf2c3715SXin Li     SubMatType A01( A.block(0,bs, bs,bcols-bs) );
267*bf2c3715SXin Li     Scalar tmp = A01(bs-1,0);
268*bf2c3715SXin Li     A01(bs-1,0) = Literal(1);
269*bf2c3715SXin Li     A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint();
270*bf2c3715SXin Li     A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01;
271*bf2c3715SXin Li     A01(bs-1,0) = tmp;
272*bf2c3715SXin Li   }
273*bf2c3715SXin Li }
274*bf2c3715SXin Li 
275*bf2c3715SXin Li /** \internal
276*bf2c3715SXin Li   *
277*bf2c3715SXin Li   * Implementation of a block-bidiagonal reduction.
278*bf2c3715SXin Li   * It is based on the following paper:
279*bf2c3715SXin Li   *   The Design of a Parallel Dense Linear Algebra Software Library: Reduction to Hessenberg, Tridiagonal, and Bidiagonal Form.
280*bf2c3715SXin Li   *   by Jaeyoung Choi, Jack J. Dongarra, David W. Walker. (1995)
281*bf2c3715SXin Li   *   section 3.3
282*bf2c3715SXin Li   */
283*bf2c3715SXin Li template<typename MatrixType, typename BidiagType>
284*bf2c3715SXin Li void upperbidiagonalization_inplace_blocked(MatrixType& A, BidiagType& bidiagonal,
285*bf2c3715SXin Li                                             Index maxBlockSize=32,
286*bf2c3715SXin Li                                             typename MatrixType::Scalar* /*tempData*/ = 0)
287*bf2c3715SXin Li {
288*bf2c3715SXin Li   typedef typename MatrixType::Scalar Scalar;
289*bf2c3715SXin Li   typedef Block<MatrixType,Dynamic,Dynamic> BlockType;
290*bf2c3715SXin Li 
291*bf2c3715SXin Li   Index rows = A.rows();
292*bf2c3715SXin Li   Index cols = A.cols();
293*bf2c3715SXin Li   Index size = (std::min)(rows, cols);
294*bf2c3715SXin Li 
295*bf2c3715SXin Li   // X and Y are work space
296*bf2c3715SXin Li   enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
297*bf2c3715SXin Li   Matrix<Scalar,
298*bf2c3715SXin Li          MatrixType::RowsAtCompileTime,
299*bf2c3715SXin Li          Dynamic,
300*bf2c3715SXin Li          StorageOrder,
301*bf2c3715SXin Li          MatrixType::MaxRowsAtCompileTime> X(rows,maxBlockSize);
302*bf2c3715SXin Li   Matrix<Scalar,
303*bf2c3715SXin Li          MatrixType::ColsAtCompileTime,
304*bf2c3715SXin Li          Dynamic,
305*bf2c3715SXin Li          StorageOrder,
306*bf2c3715SXin Li          MatrixType::MaxColsAtCompileTime> Y(cols,maxBlockSize);
307*bf2c3715SXin Li   Index blockSize = (std::min)(maxBlockSize,size);
308*bf2c3715SXin Li 
309*bf2c3715SXin Li   Index k = 0;
310*bf2c3715SXin Li   for(k = 0; k < size; k += blockSize)
311*bf2c3715SXin Li   {
312*bf2c3715SXin Li     Index bs = (std::min)(size-k,blockSize);  // actual size of the block
313*bf2c3715SXin Li     Index brows = rows - k;                   // rows of the block
314*bf2c3715SXin Li     Index bcols = cols - k;                   // columns of the block
315*bf2c3715SXin Li 
316*bf2c3715SXin Li     // partition the matrix A:
317*bf2c3715SXin Li     //
318*bf2c3715SXin Li     //      | A00 A01 A02 |
319*bf2c3715SXin Li     //      |             |
320*bf2c3715SXin Li     // A  = | A10 A11 A12 |
321*bf2c3715SXin Li     //      |             |
322*bf2c3715SXin Li     //      | A20 A21 A22 |
323*bf2c3715SXin Li     //
324*bf2c3715SXin Li     // where A11 is a bs x bs diagonal block,
325*bf2c3715SXin Li     // and let:
326*bf2c3715SXin Li     //      | A11 A12 |
327*bf2c3715SXin Li     //  B = |         |
328*bf2c3715SXin Li     //      | A21 A22 |
329*bf2c3715SXin Li 
330*bf2c3715SXin Li     BlockType B = A.block(k,k,brows,bcols);
331*bf2c3715SXin Li 
332*bf2c3715SXin Li     // This stage performs the bidiagonalization of A11, A21, A12, and updating of A22.
333*bf2c3715SXin Li     // Finally, the algorithm continue on the updated A22.
334*bf2c3715SXin Li     //
335*bf2c3715SXin Li     // However, if B is too small, or A22 empty, then let's use an unblocked strategy
336*bf2c3715SXin Li     if(k+bs==cols || bcols<48) // somewhat arbitrary threshold
337*bf2c3715SXin Li     {
338*bf2c3715SXin Li       upperbidiagonalization_inplace_unblocked(B,
339*bf2c3715SXin Li                                                &(bidiagonal.template diagonal<0>().coeffRef(k)),
340*bf2c3715SXin Li                                                &(bidiagonal.template diagonal<1>().coeffRef(k)),
341*bf2c3715SXin Li                                                X.data()
342*bf2c3715SXin Li                                               );
343*bf2c3715SXin Li       break; // We're done
344*bf2c3715SXin Li     }
345*bf2c3715SXin Li     else
346*bf2c3715SXin Li     {
347*bf2c3715SXin Li       upperbidiagonalization_blocked_helper<BlockType>( B,
348*bf2c3715SXin Li                                                         &(bidiagonal.template diagonal<0>().coeffRef(k)),
349*bf2c3715SXin Li                                                         &(bidiagonal.template diagonal<1>().coeffRef(k)),
350*bf2c3715SXin Li                                                         bs,
351*bf2c3715SXin Li                                                         X.topLeftCorner(brows,bs),
352*bf2c3715SXin Li                                                         Y.topLeftCorner(bcols,bs)
353*bf2c3715SXin Li                                                       );
354*bf2c3715SXin Li     }
355*bf2c3715SXin Li   }
356*bf2c3715SXin Li }
357*bf2c3715SXin Li 
358*bf2c3715SXin Li template<typename _MatrixType>
computeUnblocked(const _MatrixType & matrix)359*bf2c3715SXin Li UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::computeUnblocked(const _MatrixType& matrix)
360*bf2c3715SXin Li {
361*bf2c3715SXin Li   Index rows = matrix.rows();
362*bf2c3715SXin Li   Index cols = matrix.cols();
363*bf2c3715SXin Li   EIGEN_ONLY_USED_FOR_DEBUG(cols);
364*bf2c3715SXin Li 
365*bf2c3715SXin Li   eigen_assert(rows >= cols && "UpperBidiagonalization is only for Arices satisfying rows>=cols.");
366*bf2c3715SXin Li 
367*bf2c3715SXin Li   m_householder = matrix;
368*bf2c3715SXin Li 
369*bf2c3715SXin Li   ColVectorType temp(rows);
370*bf2c3715SXin Li 
371*bf2c3715SXin Li   upperbidiagonalization_inplace_unblocked(m_householder,
372*bf2c3715SXin Li                                            &(m_bidiagonal.template diagonal<0>().coeffRef(0)),
373*bf2c3715SXin Li                                            &(m_bidiagonal.template diagonal<1>().coeffRef(0)),
374*bf2c3715SXin Li                                            temp.data());
375*bf2c3715SXin Li 
376*bf2c3715SXin Li   m_isInitialized = true;
377*bf2c3715SXin Li   return *this;
378*bf2c3715SXin Li }
379*bf2c3715SXin Li 
380*bf2c3715SXin Li template<typename _MatrixType>
compute(const _MatrixType & matrix)381*bf2c3715SXin Li UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::compute(const _MatrixType& matrix)
382*bf2c3715SXin Li {
383*bf2c3715SXin Li   Index rows = matrix.rows();
384*bf2c3715SXin Li   Index cols = matrix.cols();
385*bf2c3715SXin Li   EIGEN_ONLY_USED_FOR_DEBUG(rows);
386*bf2c3715SXin Li   EIGEN_ONLY_USED_FOR_DEBUG(cols);
387*bf2c3715SXin Li 
388*bf2c3715SXin Li   eigen_assert(rows >= cols && "UpperBidiagonalization is only for Arices satisfying rows>=cols.");
389*bf2c3715SXin Li 
390*bf2c3715SXin Li   m_householder = matrix;
391*bf2c3715SXin Li   upperbidiagonalization_inplace_blocked(m_householder, m_bidiagonal);
392*bf2c3715SXin Li 
393*bf2c3715SXin Li   m_isInitialized = true;
394*bf2c3715SXin Li   return *this;
395*bf2c3715SXin Li }
396*bf2c3715SXin Li 
397*bf2c3715SXin Li #if 0
398*bf2c3715SXin Li /** \return the Householder QR decomposition of \c *this.
399*bf2c3715SXin Li   *
400*bf2c3715SXin Li   * \sa class Bidiagonalization
401*bf2c3715SXin Li   */
402*bf2c3715SXin Li template<typename Derived>
403*bf2c3715SXin Li const UpperBidiagonalization<typename MatrixBase<Derived>::PlainObject>
404*bf2c3715SXin Li MatrixBase<Derived>::bidiagonalization() const
405*bf2c3715SXin Li {
406*bf2c3715SXin Li   return UpperBidiagonalization<PlainObject>(eval());
407*bf2c3715SXin Li }
408*bf2c3715SXin Li #endif
409*bf2c3715SXin Li 
410*bf2c3715SXin Li } // end namespace internal
411*bf2c3715SXin Li 
412*bf2c3715SXin Li } // end namespace Eigen
413*bf2c3715SXin Li 
414*bf2c3715SXin Li #endif // EIGEN_BIDIAGONALIZATION_H
415