11#ifndef EIGEN_BIDIAGONALIZATION_H
12#define EIGEN_BIDIAGONALIZATION_H
15#include "./InternalHeaderCheck.h"
23template <
typename MatrixType_>
24class UpperBidiagonalization {
26 typedef MatrixType_ MatrixType;
28 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
29 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
30 ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::ret
32 typedef typename MatrixType::Scalar Scalar;
33 typedef typename MatrixType::RealScalar RealScalar;
35 typedef Matrix<Scalar, 1, ColsAtCompileTime> RowVectorType;
36 typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType;
37 typedef BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0, RowMajor> BidiagonalType;
38 typedef Matrix<Scalar, ColsAtCompileTime, 1> DiagVectorType;
39 typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType;
40 typedef HouseholderSequence<
41 const MatrixType,
const internal::remove_all_t<typename Diagonal<const MatrixType, 0>::ConjugateReturnType> >
42 HouseholderUSequenceType;
43 typedef HouseholderSequence<const internal::remove_all_t<typename MatrixType::ConjugateReturnType>,
45 HouseholderVSequenceType;
53 UpperBidiagonalization() : m_householder(), m_bidiagonal(0, 0), m_isInitialized(false) {}
55 explicit UpperBidiagonalization(
const MatrixType& matrix)
56 : m_householder(matrix.rows(), matrix.cols()),
57 m_bidiagonal(matrix.cols(), matrix.cols()),
58 m_isInitialized(false) {
62 UpperBidiagonalization(Index rows, Index cols)
63 : m_householder(rows, cols), m_bidiagonal(cols, cols), m_isInitialized(false) {}
65 UpperBidiagonalization& compute(
const MatrixType& matrix);
66 UpperBidiagonalization& computeUnblocked(
const MatrixType& matrix);
68 const MatrixType& householder()
const {
return m_householder; }
69 const BidiagonalType& bidiagonal()
const {
return m_bidiagonal; }
71 const HouseholderUSequenceType householderU()
const {
72 eigen_assert(m_isInitialized &&
"UpperBidiagonalization is not initialized.");
73 return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
76 const HouseholderVSequenceType householderV()
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)
85 MatrixType m_householder;
86 BidiagonalType m_bidiagonal;
92template <
typename MatrixType>
93void upperbidiagonalization_inplace_unblocked(MatrixType& mat,
typename MatrixType::RealScalar* diagonal,
94 typename MatrixType::RealScalar* upper_diagonal,
95 typename MatrixType::Scalar* tempData = 0) {
96 typedef typename MatrixType::Scalar Scalar;
98 Index rows = mat.rows();
99 Index cols = mat.cols();
101 typedef Matrix<Scalar, Dynamic, 1, ColMajor, MatrixType::MaxRowsAtCompileTime, 1> TempType;
104 tempVector.resize(rows);
105 tempData = tempVector.data();
108 for (Index k = 0; ; ++k) {
109 Index remainingRows = rows - k;
110 Index remainingCols = cols - k - 1;
113 mat.col(k).tail(remainingRows).makeHouseholderInPlace(mat.coeffRef(k, k), diagonal[k]);
115 mat.bottomRightCorner(remainingRows, remainingCols)
116 .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows - 1), mat.coeff(k, k), tempData);
118 if (k == cols - 1)
break;
121 mat.row(k).tail(remainingCols).makeHouseholderInPlace(mat.coeffRef(k, k + 1), upper_diagonal[k]);
123 mat.bottomRightCorner(remainingRows - 1, remainingCols)
124 .applyHouseholderOnTheRight(mat.row(k).tail(remainingCols - 1).adjoint(), mat.coeff(k, k + 1), tempData);
145template <
typename MatrixType>
146void upperbidiagonalization_blocked_helper(
147 MatrixType& A,
typename MatrixType::RealScalar* diagonal,
typename MatrixType::RealScalar* upper_diagonal, Index bs,
150 typedef typename MatrixType::Scalar Scalar;
151 typedef typename MatrixType::RealScalar RealScalar;
152 typedef typename NumTraits<RealScalar>::Literal Literal;
154 typedef InnerStride<StorageOrder == ColMajor ? 1 : Dynamic> ColInnerStride;
155 typedef InnerStride<StorageOrder == ColMajor ? Dynamic : 1> RowInnerStride;
156 typedef Ref<Matrix<Scalar, Dynamic, 1>, 0, ColInnerStride> SubColumnType;
157 typedef Ref<Matrix<Scalar, 1, Dynamic>, 0, RowInnerStride> SubRowType;
158 typedef Ref<Matrix<Scalar, Dynamic, Dynamic, StorageOrder> > SubMatType;
160 Index brows = A.rows();
161 Index bcols = A.cols();
163 Scalar tau_u, tau_u_prev(0), tau_v;
165 for (Index k = 0; k < bs; ++k) {
166 Index remainingRows = brows - k;
167 Index remainingCols = bcols - k - 1;
169 SubMatType X_k1(X.block(k, 0, remainingRows, k));
170 SubMatType V_k1(A.block(k, 0, remainingRows, k));
173 SubColumnType v_k = A.col(k).tail(remainingRows);
174 v_k -= V_k1 * Y.row(k).head(k).adjoint();
175 if (k) v_k -= X_k1 * A.col(k).head(k);
178 v_k.makeHouseholderInPlace(tau_v, diagonal[k]);
181 SubMatType Y_k(Y.block(k + 1, 0, remainingCols, k + 1));
182 SubMatType U_k1(A.block(0, k + 1, k, remainingCols));
190 SubColumnType y_k(Y.col(k).tail(remainingCols));
193 SubColumnType tmp(Y.col(k).head(k));
194 y_k.noalias() = A.block(k, k + 1, remainingRows, remainingCols).adjoint() * v_k;
195 tmp.noalias() = V_k1.adjoint() * v_k;
196 y_k.noalias() -= Y_k.leftCols(k) * tmp;
197 tmp.noalias() = X_k1.adjoint() * v_k;
198 y_k.noalias() -= U_k1.adjoint() * tmp;
199 y_k *= numext::conj(tau_v);
203 SubRowType u_k(A.row(k).tail(remainingCols));
204 u_k = u_k.conjugate();
206 u_k -= Y_k * A.row(k).head(k + 1).adjoint();
207 if (k) u_k -= U_k1.adjoint() * X.row(k).head(k).adjoint();
211 u_k.makeHouseholderInPlace(tau_u, upper_diagonal[k]);
215 A(k, k + 1) = Scalar(1);
219 SubColumnType x_k(X.col(k).tail(remainingRows - 1));
223 SubColumnType tmp0(X.col(k).head(k)), tmp1(X.col(k).head(k + 1));
225 x_k.noalias() = A.block(k + 1, k + 1, remainingRows - 1, remainingCols) * u_k.transpose();
226 tmp0.noalias() = U_k1 * u_k.transpose();
227 x_k.noalias() -= X_k1.bottomRows(remainingRows - 1) * tmp0;
228 tmp1.noalias() = Y_k.adjoint() * u_k.transpose();
229 x_k.noalias() -= A.block(k + 1, 0, remainingRows - 1, k + 1) * tmp1;
230 x_k *= numext::conj(tau_u);
231 tau_u = numext::conj(tau_u);
232 u_k = u_k.conjugate();
235 if (k > 0) A.coeffRef(k - 1, k) = tau_u_prev;
238 A.coeffRef(k - 1, k) = tau_u_prev;
240 A.coeffRef(k, k) = tau_v;
243 if (bs < bcols) A.coeffRef(bs - 1, bs) = tau_u_prev;
246 if (bcols > bs && brows > bs) {
247 SubMatType A11(A.bottomRightCorner(brows - bs, bcols - bs));
248 SubMatType A10(A.block(bs, 0, brows - bs, bs));
249 SubMatType A01(A.block(0, bs, bs, bcols - bs));
250 Scalar tmp = A01(bs - 1, 0);
251 A01(bs - 1, 0) = Literal(1);
252 A11.noalias() -= A10 * Y.topLeftCorner(bcols, bs).bottomRows(bcols - bs).adjoint();
253 A11.noalias() -= X.topLeftCorner(brows, bs).bottomRows(brows - bs) * A01;
254 A01(bs - 1, 0) = tmp;
265template <
typename MatrixType,
typename B
idiagType>
266void upperbidiagonalization_inplace_blocked(MatrixType& A, BidiagType& bidiagonal, Index maxBlockSize = 32,
267 typename MatrixType::Scalar* = 0) {
268 typedef typename MatrixType::Scalar Scalar;
269 typedef Block<MatrixType, Dynamic, Dynamic> BlockType;
271 Index rows = A.rows();
272 Index cols = A.cols();
273 Index size = (std::min)(rows, cols);
277 Matrix<Scalar, MatrixType::RowsAtCompileTime, Dynamic, StorageOrder, MatrixType::MaxRowsAtCompileTime> X(
279 Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic, StorageOrder, MatrixType::MaxColsAtCompileTime> Y(
281 Index blockSize = (std::min)(maxBlockSize, size);
284 for (k = 0; k < size; k += blockSize) {
285 Index bs = (std::min)(size - k, blockSize);
286 Index brows = rows - k;
287 Index bcols = cols - k;
303 BlockType B = A.block(k, k, brows, bcols);
310 auto upper_diagonal = bidiagonal.template diagonal<1>();
311 typename MatrixType::RealScalar* upper_diagonal_ptr =
312 upper_diagonal.size() > 0 ? &upper_diagonal.coeffRef(k) :
nullptr;
314 if (k + bs == cols || bcols < 48)
316 upperbidiagonalization_inplace_unblocked(B, &(bidiagonal.template diagonal<0>().coeffRef(k)), upper_diagonal_ptr,
320 upperbidiagonalization_blocked_helper<BlockType>(B, &(bidiagonal.template diagonal<0>().coeffRef(k)),
321 upper_diagonal_ptr, bs, X.topLeftCorner(brows, bs),
322 Y.topLeftCorner(bcols, bs));
327template <
typename MatrixType_>
328UpperBidiagonalization<MatrixType_>& UpperBidiagonalization<MatrixType_>::computeUnblocked(
const MatrixType_& matrix) {
329 Index rows = matrix.rows();
330 Index cols = matrix.cols();
331 EIGEN_ONLY_USED_FOR_DEBUG(cols);
333 eigen_assert(rows >= cols &&
"UpperBidiagonalization is only for Arices satisfying rows>=cols.");
335 m_householder = matrix;
337 ColVectorType temp(rows);
339 upperbidiagonalization_inplace_unblocked(m_householder, &(m_bidiagonal.template diagonal<0>().coeffRef(0)),
340 &(m_bidiagonal.template diagonal<1>().coeffRef(0)), temp.data());
342 m_isInitialized =
true;
346template <
typename MatrixType_>
347UpperBidiagonalization<MatrixType_>& UpperBidiagonalization<MatrixType_>::compute(
const MatrixType_& matrix) {
348 Index rows = matrix.rows();
349 Index cols = matrix.cols();
350 EIGEN_ONLY_USED_FOR_DEBUG(rows);
351 EIGEN_ONLY_USED_FOR_DEBUG(cols);
353 eigen_assert(rows >= cols &&
"UpperBidiagonalization is only for Arices satisfying rows>=cols.");
355 m_householder = matrix;
356 upperbidiagonalization_inplace_blocked(m_householder, m_bidiagonal);
358 m_isInitialized =
true;
367template<
typename Derived>
368const UpperBidiagonalization<typename MatrixBase<Derived>::PlainObject>
369MatrixBase<Derived>::bidiagonalization()
const
371 return UpperBidiagonalization<PlainObject>(eval());
@ ColMajor
Definition Constants.h:318
@ RowMajor
Definition Constants.h:320
@ OnTheRight
Definition Constants.h:333
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition Core:137
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25