UpperBidiagonalization.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2013-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #ifndef EIGEN_BIDIAGONALIZATION_H
12 #define EIGEN_BIDIAGONALIZATION_H
13 
14 namespace Eigen {
15 
16 namespace internal {
17 // UpperBidiagonalization will probably be replaced by a Bidiagonalization class, don't want to make it stable API.
18 // 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 
20 template<typename _MatrixType> class UpperBidiagonalization
21 {
22  public:
23 
24  typedef _MatrixType MatrixType;
25  enum {
26  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
27  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
29  };
30  typedef typename MatrixType::Scalar Scalar;
31  typedef typename MatrixType::RealScalar RealScalar;
32  typedef Eigen::Index Index;
38  typedef HouseholderSequence<
39  const MatrixType,
42  typedef HouseholderSequence<
47 
55 
56  explicit UpperBidiagonalization(const MatrixType& matrix)
57  : m_householder(matrix.rows(), matrix.cols()),
58  m_bidiagonal(matrix.cols(), matrix.cols()),
59  m_isInitialized(false)
60  {
61  compute(matrix);
62  }
63 
64  UpperBidiagonalization& compute(const MatrixType& matrix);
65  UpperBidiagonalization& computeUnblocked(const MatrixType& matrix);
66 
67  const MatrixType& householder() const { return m_householder; }
68  const BidiagonalType& bidiagonal() const { return m_bidiagonal; }
69 
71  {
72  eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
73  return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
74  }
75 
76  const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
77  {
78  eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
79  return HouseholderVSequenceType(m_householder.conjugate(), m_householder.const_derived().template diagonal<1>())
80  .setLength(m_householder.cols()-1)
81  .setShift(1);
82  }
83 
84  protected:
85  MatrixType m_householder;
86  BidiagonalType m_bidiagonal;
88 };
89 
90 // Standard upper bidiagonalization without fancy optimizations
91 // This version should be faster for small matrix size
92 template<typename MatrixType>
94  typename MatrixType::RealScalar *diagonal,
95  typename MatrixType::RealScalar *upper_diagonal,
96  typename MatrixType::Scalar* tempData = 0)
97 {
98  typedef typename MatrixType::Scalar Scalar;
99 
100  Index rows = mat.rows();
101  Index cols = mat.cols();
102 
104  TempType tempVector;
105  if(tempData==0)
106  {
107  tempVector.resize(rows);
108  tempData = tempVector.data();
109  }
110 
111  for (Index k = 0; /* breaks at k==cols-1 below */ ; ++k)
112  {
113  Index remainingRows = rows - k;
114  Index remainingCols = cols - k - 1;
115 
116  // construct left householder transform in-place in A
117  mat.col(k).tail(remainingRows)
118  .makeHouseholderInPlace(mat.coeffRef(k,k), diagonal[k]);
119  // apply householder transform to remaining part of A on the left
120  mat.bottomRightCorner(remainingRows, remainingCols)
121  .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), mat.coeff(k,k), tempData);
122 
123  if(k == cols-1) break;
124 
125  // construct right householder transform in-place in mat
126  mat.row(k).tail(remainingCols)
127  .makeHouseholderInPlace(mat.coeffRef(k,k+1), upper_diagonal[k]);
128  // apply householder transform to remaining part of mat on the left
129  mat.bottomRightCorner(remainingRows-1, remainingCols)
130  .applyHouseholderOnTheRight(mat.row(k).tail(remainingCols-1).transpose(), mat.coeff(k,k+1), tempData);
131  }
132 }
133 
151 template<typename MatrixType>
153  typename MatrixType::RealScalar *diagonal,
154  typename MatrixType::RealScalar *upper_diagonal,
155  Index bs,
156  Ref<Matrix<typename MatrixType::Scalar, Dynamic, Dynamic,
158  Ref<Matrix<typename MatrixType::Scalar, Dynamic, Dynamic,
160 {
161  typedef typename MatrixType::Scalar Scalar;
162  typedef typename MatrixType::RealScalar RealScalar;
163  typedef typename NumTraits<RealScalar>::Literal Literal;
164  enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
167  typedef Ref<Matrix<Scalar, Dynamic, 1>, 0, ColInnerStride> SubColumnType;
168  typedef Ref<Matrix<Scalar, 1, Dynamic>, 0, RowInnerStride> SubRowType;
170 
171  Index brows = A.rows();
172  Index bcols = A.cols();
173 
174  Scalar tau_u, tau_u_prev(0), tau_v;
175 
176  for(Index k = 0; k < bs; ++k)
177  {
178  Index remainingRows = brows - k;
179  Index remainingCols = bcols - k - 1;
180 
181  SubMatType X_k1( X.block(k,0, remainingRows,k) );
182  SubMatType V_k1( A.block(k,0, remainingRows,k) );
183 
184  // 1 - update the k-th column of A
185  SubColumnType v_k = A.col(k).tail(remainingRows);
186  v_k -= V_k1 * Y.row(k).head(k).adjoint();
187  if(k) v_k -= X_k1 * A.col(k).head(k);
188 
189  // 2 - construct left Householder transform in-place
190  v_k.makeHouseholderInPlace(tau_v, diagonal[k]);
191 
192  if(k+1<bcols)
193  {
194  SubMatType Y_k ( Y.block(k+1,0, remainingCols, k+1) );
195  SubMatType U_k1 ( A.block(0,k+1, k,remainingCols) );
196 
197  // this eases the application of Householder transforAions
198  // A(k,k) will store tau_v later
199  A(k,k) = Scalar(1);
200 
201  // 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  {
203  SubColumnType y_k( Y.col(k).tail(remainingCols) );
204 
205  // let's use the begining of column k of Y as a temporary vector
206  SubColumnType tmp( Y.col(k).head(k) );
207  y_k.noalias() = A.block(k,k+1, remainingRows,remainingCols).adjoint() * v_k; // bottleneck
208  tmp.noalias() = V_k1.adjoint() * v_k;
209  y_k.noalias() -= Y_k.leftCols(k) * tmp;
210  tmp.noalias() = X_k1.adjoint() * v_k;
211  y_k.noalias() -= U_k1.adjoint() * tmp;
212  y_k *= numext::conj(tau_v);
213  }
214 
215  // 4 - update k-th row of A (it will become u_k)
216  SubRowType u_k( A.row(k).tail(remainingCols) );
217  u_k = u_k.conjugate();
218  {
219  u_k -= Y_k * A.row(k).head(k+1).adjoint();
220  if(k) u_k -= U_k1.adjoint() * X.row(k).head(k).adjoint();
221  }
222 
223  // 5 - construct right Householder transform in-place
224  u_k.makeHouseholderInPlace(tau_u, upper_diagonal[k]);
225 
226  // this eases the application of Householder transformations
227  // A(k,k+1) will store tau_u later
228  A(k,k+1) = Scalar(1);
229 
230  // 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  {
232  SubColumnType x_k ( X.col(k).tail(remainingRows-1) );
233 
234  // let's use the begining of column k of X as a temporary vectors
235  // note that tmp0 and tmp1 overlaps
236  SubColumnType tmp0 ( X.col(k).head(k) ),
237  tmp1 ( X.col(k).head(k+1) );
238 
239  x_k.noalias() = A.block(k+1,k+1, remainingRows-1,remainingCols) * u_k.transpose(); // bottleneck
240  tmp0.noalias() = U_k1 * u_k.transpose();
241  x_k.noalias() -= X_k1.bottomRows(remainingRows-1) * tmp0;
242  tmp1.noalias() = Y_k.adjoint() * u_k.transpose();
243  x_k.noalias() -= A.block(k+1,0, remainingRows-1,k+1) * tmp1;
244  x_k *= numext::conj(tau_u);
245  tau_u = numext::conj(tau_u);
246  u_k = u_k.conjugate();
247  }
248 
249  if(k>0) A.coeffRef(k-1,k) = tau_u_prev;
250  tau_u_prev = tau_u;
251  }
252  else
253  A.coeffRef(k-1,k) = tau_u_prev;
254 
255  A.coeffRef(k,k) = tau_v;
256  }
257 
258  if(bs<bcols)
259  A.coeffRef(bs-1,bs) = tau_u_prev;
260 
261  // update A22
262  if(bcols>bs && brows>bs)
263  {
264  SubMatType A11( A.bottomRightCorner(brows-bs,bcols-bs) );
265  SubMatType A10( A.block(bs,0, brows-bs,bs) );
266  SubMatType A01( A.block(0,bs, bs,bcols-bs) );
267  Scalar tmp = A01(bs-1,0);
268  A01(bs-1,0) = Literal(1);
269  A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint();
270  A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01;
271  A01(bs-1,0) = tmp;
272  }
273 }
274 
283 template<typename MatrixType, typename BidiagType>
285  Index maxBlockSize=32,
286  typename MatrixType::Scalar* /*tempData*/ = 0)
287 {
288  typedef typename MatrixType::Scalar Scalar;
289  typedef Block<MatrixType,Dynamic,Dynamic> BlockType;
290 
291  Index rows = A.rows();
292  Index cols = A.cols();
293  Index size = (std::min)(rows, cols);
294 
295  // X and Y are work space
296  enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
297  Matrix<Scalar,
298  MatrixType::RowsAtCompileTime,
299  Dynamic,
300  StorageOrder,
301  MatrixType::MaxRowsAtCompileTime> X(rows,maxBlockSize);
302  Matrix<Scalar,
303  MatrixType::ColsAtCompileTime,
304  Dynamic,
305  StorageOrder,
306  MatrixType::MaxColsAtCompileTime> Y(cols,maxBlockSize);
307  Index blockSize = (std::min)(maxBlockSize,size);
308 
309  Index k = 0;
310  for(k = 0; k < size; k += blockSize)
311  {
312  Index bs = (std::min)(size-k,blockSize); // actual size of the block
313  Index brows = rows - k; // rows of the block
314  Index bcols = cols - k; // columns of the block
315 
316  // partition the matrix A:
317  //
318  // | A00 A01 A02 |
319  // | |
320  // A = | A10 A11 A12 |
321  // | |
322  // | A20 A21 A22 |
323  //
324  // where A11 is a bs x bs diagonal block,
325  // and let:
326  // | A11 A12 |
327  // B = | |
328  // | A21 A22 |
329 
330  BlockType B = A.block(k,k,brows,bcols);
331 
332  // This stage performs the bidiagonalization of A11, A21, A12, and updating of A22.
333  // Finally, the algorithm continue on the updated A22.
334  //
335  // However, if B is too small, or A22 empty, then let's use an unblocked strategy
336  if(k+bs==cols || bcols<48) // somewhat arbitrary threshold
337  {
339  &(bidiagonal.template diagonal<0>().coeffRef(k)),
340  &(bidiagonal.template diagonal<1>().coeffRef(k)),
341  X.data()
342  );
343  break; // We're done
344  }
345  else
346  {
347  upperbidiagonalization_blocked_helper<BlockType>( B,
348  &(bidiagonal.template diagonal<0>().coeffRef(k)),
349  &(bidiagonal.template diagonal<1>().coeffRef(k)),
350  bs,
351  X.topLeftCorner(brows,bs),
352  Y.topLeftCorner(bcols,bs)
353  );
354  }
355  }
356 }
357 
358 template<typename _MatrixType>
360 {
361  Index rows = matrix.rows();
362  Index cols = matrix.cols();
364 
365  eigen_assert(rows >= cols && "UpperBidiagonalization is only for Arices satisfying rows>=cols.");
366 
367  m_householder = matrix;
368 
369  ColVectorType temp(rows);
370 
372  &(m_bidiagonal.template diagonal<0>().coeffRef(0)),
373  &(m_bidiagonal.template diagonal<1>().coeffRef(0)),
374  temp.data());
375 
376  m_isInitialized = true;
377  return *this;
378 }
379 
380 template<typename _MatrixType>
382 {
383  Index rows = matrix.rows();
384  Index cols = matrix.cols();
387 
388  eigen_assert(rows >= cols && "UpperBidiagonalization is only for Arices satisfying rows>=cols.");
389 
390  m_householder = matrix;
392 
393  m_isInitialized = true;
394  return *this;
395 }
396 
397 #if 0
398 
402 template<typename Derived>
405 {
407 }
408 #endif
409 
410 } // end namespace internal
411 
412 } // end namespace Eigen
413 
414 #endif // EIGEN_BIDIAGONALIZATION_H
Matrix< Scalar, 1, ColsAtCompileTime > RowVectorType
const BidiagonalType & bidiagonal() const
const AutoDiffScalar< DerType > & conj(const AutoDiffScalar< DerType > &x)
const HouseholderUSequenceType householderU() const
const HouseholderVSequenceType householderV()
void upperbidiagonalization_inplace_unblocked(MatrixType &mat, typename MatrixType::RealScalar *diagonal, typename MatrixType::RealScalar *upper_diagonal, typename MatrixType::Scalar *tempData=0)
UpperBidiagonalization & compute(const MatrixType &matrix)
void 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)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar * data() const
Definition: LDLT.h:16
static constexpr size_t size(Tuple< Args... > &)
Provides access to the number of elements in a tuple as a compile-time constant expression.
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:150
HouseholderSequence< const typename internal::remove_all< typename MatrixType::ConjugateReturnType >::type, Diagonal< const MatrixType, 1 >, OnTheRight > HouseholderVSequenceType
const unsigned int RowMajorBit
Definition: Constants.h:61
Sequence of Householder reflections acting on subspaces with decreasing size.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
HouseholderSequence< const MatrixType, const typename internal::remove_all< typename Diagonal< const MatrixType, 0 >::ConjugateReturnType >::type > HouseholderUSequenceType
Convenience specialization of Stride to specify only an inner stride See class Map for some examples...
Definition: Stride.h:90
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
#define eigen_assert(x)
Definition: Macros.h:577
Matrix< Scalar, RowsAtCompileTime, 1 > ColVectorType
Matrix< Scalar, ColsAtCompileTime, 1 > DiagVectorType
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:190
Matrix< Scalar, ColsAtCompileTimeMinusOne, 1 > SuperDiagVectorType
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:103
void upperbidiagonalization_inplace_blocked(MatrixType &A, BidiagType &bidiagonal, Index maxBlockSize=32, typename MatrixType::Scalar *=0)
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition: Diagonal.h:63
const int Dynamic
Definition: Constants.h:21
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:178
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
UpperBidiagonalization & computeUnblocked(const MatrixType &matrix)
BandMatrix< RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0, RowMajor > BidiagonalType
UpperBidiagonalization(const MatrixType &matrix)
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
Definition: Macros.h:589


hebiros
Author(s): Xavier Artache , Matthew Tesch
autogenerated on Thu Sep 3 2020 04:09:46