12#ifndef EIGEN_BIDIAGONALIZATION_H
13#define EIGEN_BIDIAGONALIZATION_H
16#include "./InternalHeaderCheck.h"
24template <
typename MatrixType_>
25class UpperBidiagonalization {
27 using MatrixType = MatrixType_;
29 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
30 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
31 ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::value
33 using Scalar =
typename MatrixType::Scalar;
34 using RealScalar =
typename MatrixType::RealScalar;
35 using Index = Eigen::Index;
36 using RowVectorType = Matrix<Scalar, 1, ColsAtCompileTime>;
37 using ColVectorType = Matrix<Scalar, RowsAtCompileTime, 1>;
38 using BidiagonalType = BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0, RowMajor>;
39 using DiagVectorType = Matrix<Scalar, ColsAtCompileTime, 1>;
40 using SuperDiagVectorType = Matrix<Scalar, ColsAtCompileTimeMinusOne, 1>;
41 using HouseholderUSequenceType =
42 HouseholderSequence<
const MatrixType,
43 const internal::remove_all_t<typename Diagonal<const MatrixType, 0>::ConjugateReturnType>>;
44 using HouseholderVSequenceType =
45 HouseholderSequence<const internal::remove_all_t<typename MatrixType::ConjugateReturnType>,
54 UpperBidiagonalization()
55 : m_householder(), m_bidiagonal(m_householder.cols(), m_householder.cols()), m_isInitialized(false) {}
57 explicit UpperBidiagonalization(
const MatrixType& matrix)
58 : m_householder(matrix.rows(), matrix.cols()),
59 m_bidiagonal(matrix.cols(), matrix.cols()),
60 m_isInitialized(false) {
64 UpperBidiagonalization(Index rows, Index cols)
65 : m_householder(rows, cols), m_bidiagonal(cols, cols), m_isInitialized(false) {}
67 UpperBidiagonalization& compute(
const MatrixType& matrix);
68 UpperBidiagonalization& computeUnblocked(
const MatrixType& matrix);
70 const MatrixType& householder()
const {
return m_householder; }
71 const BidiagonalType& bidiagonal()
const {
return m_bidiagonal; }
73 const HouseholderUSequenceType householderU()
const {
74 eigen_assert(m_isInitialized &&
"UpperBidiagonalization is not initialized.");
75 return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
78 const HouseholderVSequenceType householderV()
80 eigen_assert(m_isInitialized &&
"UpperBidiagonalization is not initialized.");
81 return HouseholderVSequenceType(m_householder.conjugate(), m_householder.const_derived().template diagonal<1>())
82 .setLength(m_householder.cols() - 1)
87 MatrixType m_householder;
88 BidiagonalType m_bidiagonal;
94template <
typename MatrixType>
95void upperbidiagonalization_inplace_unblocked(MatrixType& mat,
typename MatrixType::RealScalar* diagonal,
96 typename MatrixType::RealScalar* upper_diagonal,
97 typename MatrixType::Scalar* tempData = 0) {
98 using Scalar =
typename MatrixType::Scalar;
100 Index rows = mat.rows();
101 Index cols = mat.cols();
103 using TempType = Matrix<Scalar, Dynamic, 1, ColMajor, MatrixType::MaxRowsAtCompileTime, 1>;
106 tempVector.resize(rows);
107 tempData = tempVector.data();
110 for (Index k = 0; ; ++k) {
111 Index remainingRows = rows - k;
112 Index remainingCols = cols - k - 1;
115 mat.col(k).tail(remainingRows).makeHouseholderInPlace(mat.coeffRef(k, k), diagonal[k]);
117 mat.bottomRightCorner(remainingRows, remainingCols)
118 .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows - 1), mat.coeff(k, k), tempData);
120 if (k == cols - 1)
break;
123 mat.row(k).tail(remainingCols).makeHouseholderInPlace(mat.coeffRef(k, k + 1), upper_diagonal[k]);
125 mat.bottomRightCorner(remainingRows - 1, remainingCols)
126 .applyHouseholderOnTheRight(mat.row(k).tail(remainingCols - 1).adjoint(), mat.coeff(k, k + 1), tempData);
147template <
typename MatrixType>
148void upperbidiagonalization_blocked_helper(
149 MatrixType& A,
typename MatrixType::RealScalar* diagonal,
typename MatrixType::RealScalar* upper_diagonal, Index bs,
150 Ref<Matrix<
typename MatrixType::Scalar, Dynamic, Dynamic, traits<MatrixType>::Flags &
RowMajorBit> > X,
151 Ref<Matrix<
typename MatrixType::Scalar, Dynamic, Dynamic, traits<MatrixType>::Flags &
RowMajorBit> > Y) {
152 using Scalar =
typename MatrixType::Scalar;
153 using RealScalar =
typename MatrixType::RealScalar;
154 using Literal =
typename NumTraits<RealScalar>::Literal;
156 using ColInnerStride = InnerStride<StorageOrder == ColMajor ? 1 : Dynamic>;
157 using RowInnerStride = InnerStride<StorageOrder == ColMajor ? Dynamic : 1>;
158 using SubColumnType = Ref<Matrix<Scalar, Dynamic, 1>, 0, ColInnerStride>;
159 using SubRowType = Ref<Matrix<Scalar, 1, Dynamic>, 0, RowInnerStride>;
160 using SubMatType = Ref<Matrix<Scalar, Dynamic, Dynamic, StorageOrder>>;
162 Index brows = A.rows();
163 Index bcols = A.cols();
165 Scalar tau_u, tau_u_prev(0), tau_v;
167 for (Index k = 0; k < bs; ++k) {
168 Index remainingRows = brows - k;
169 Index remainingCols = bcols - k - 1;
171 SubMatType X_k1(X.block(k, 0, remainingRows, k));
172 SubMatType V_k1(A.block(k, 0, remainingRows, k));
175 SubColumnType v_k = A.col(k).tail(remainingRows);
177 v_k.noalias() -= V_k1 * Y.row(k).head(k).adjoint();
178 v_k.noalias() -= X_k1 * A.col(k).head(k);
182 v_k.makeHouseholderInPlace(tau_v, diagonal[k]);
185 SubMatType Y_k(Y.block(k + 1, 0, remainingCols, k + 1));
186 SubMatType U_k1(A.block(0, k + 1, k, remainingCols));
194 SubColumnType y_k(Y.col(k).tail(remainingCols));
197 SubColumnType tmp(Y.col(k).head(k));
198 y_k.noalias() = A.block(k, k + 1, remainingRows, remainingCols).adjoint() * v_k;
199 tmp.noalias() = V_k1.adjoint() * v_k;
200 y_k.noalias() -= Y_k.leftCols(k) * tmp;
201 tmp.noalias() = X_k1.adjoint() * v_k;
202 y_k.noalias() -= U_k1.adjoint() * tmp;
203 y_k *= numext::conj(tau_v);
207 SubRowType u_k(A.row(k).tail(remainingCols));
208 u_k = u_k.conjugate();
210 u_k.noalias() -= Y_k * A.row(k).head(k + 1).adjoint();
211 if (k) u_k.noalias() -= U_k1.adjoint() * X.row(k).head(k).adjoint();
215 u_k.makeHouseholderInPlace(tau_u, upper_diagonal[k]);
219 A(k, k + 1) = Scalar(1);
223 SubColumnType x_k(X.col(k).tail(remainingRows - 1));
227 SubColumnType tmp0(X.col(k).head(k)), tmp1(X.col(k).head(k + 1));
229 x_k.noalias() = A.block(k + 1, k + 1, remainingRows - 1, remainingCols) * u_k.transpose();
230 tmp0.noalias() = U_k1 * u_k.transpose();
231 x_k.noalias() -= X_k1.bottomRows(remainingRows - 1) * tmp0;
232 tmp1.noalias() = Y_k.adjoint() * u_k.transpose();
233 x_k.noalias() -= A.block(k + 1, 0, remainingRows - 1, k + 1) * tmp1;
234 x_k *= numext::conj(tau_u);
235 tau_u = numext::conj(tau_u);
236 u_k = u_k.conjugate();
239 if (k > 0) A.coeffRef(k - 1, k) = tau_u_prev;
242 A.coeffRef(k - 1, k) = tau_u_prev;
244 A.coeffRef(k, k) = tau_v;
247 if (bs < bcols) A.coeffRef(bs - 1, bs) = tau_u_prev;
250 if (bcols > bs && brows > bs) {
251 SubMatType A11(A.bottomRightCorner(brows - bs, bcols - bs));
252 SubMatType A10(A.block(bs, 0, brows - bs, bs));
253 SubMatType A01(A.block(0, bs, bs, bcols - bs));
254 Scalar tmp = A01(bs - 1, 0);
255 A01(bs - 1, 0) = Literal(1);
256 A11.noalias() -= A10 * Y.topLeftCorner(bcols, bs).bottomRows(bcols - bs).adjoint();
257 A11.noalias() -= X.topLeftCorner(brows, bs).bottomRows(brows - bs) * A01;
258 A01(bs - 1, 0) = tmp;
269template <
typename MatrixType,
typename B
idiagType>
270void upperbidiagonalization_inplace_blocked(MatrixType& A, BidiagType& bidiagonal, Index maxBlockSize = 16,
271 typename MatrixType::Scalar* = 0) {
272 using Scalar =
typename MatrixType::Scalar;
273 using BlockType = Block<MatrixType, Dynamic, Dynamic>;
275 Index rows = A.rows();
276 Index cols = A.cols();
277 Index size = (std::min)(rows, cols);
281 Matrix<Scalar, MatrixType::RowsAtCompileTime, Dynamic, StorageOrder, MatrixType::MaxRowsAtCompileTime> X(
283 Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic, StorageOrder, MatrixType::MaxColsAtCompileTime> Y(
285 Index blockSize = (std::min)(maxBlockSize, size);
288 for (k = 0; k < size; k += blockSize) {
289 Index bs = (std::min)(size - k, blockSize);
290 Index brows = rows - k;
291 Index bcols = cols - k;
307 BlockType B = A.block(k, k, brows, bcols);
314 auto upper_diagonal = bidiagonal.template diagonal<1>();
315 typename MatrixType::RealScalar* upper_diagonal_ptr =
316 upper_diagonal.size() > 0 ? &upper_diagonal.coeffRef(k) :
nullptr;
318 if (k + bs == cols || bcols < 2 * blockSize)
320 upperbidiagonalization_inplace_unblocked(B, &(bidiagonal.template diagonal<0>().coeffRef(k)), upper_diagonal_ptr,
324 upperbidiagonalization_blocked_helper<BlockType>(B, &(bidiagonal.template diagonal<0>().coeffRef(k)),
325 upper_diagonal_ptr, bs, X.topLeftCorner(brows, bs),
326 Y.topLeftCorner(bcols, bs));
331template <
typename MatrixType_>
332UpperBidiagonalization<MatrixType_>& UpperBidiagonalization<MatrixType_>::computeUnblocked(
const MatrixType_& matrix) {
333 Index rows = matrix.rows();
334 Index cols = matrix.cols();
335 EIGEN_ONLY_USED_FOR_DEBUG(cols);
337 eigen_assert(rows >= cols &&
"UpperBidiagonalization is only for matrices satisfying rows>=cols.");
339 m_householder = matrix;
341 ColVectorType temp(rows);
343 upperbidiagonalization_inplace_unblocked(m_householder, &(m_bidiagonal.template diagonal<0>().coeffRef(0)),
344 &(m_bidiagonal.template diagonal<1>().coeffRef(0)), temp.data());
346 m_isInitialized =
true;
350template <
typename MatrixType_>
351UpperBidiagonalization<MatrixType_>& UpperBidiagonalization<MatrixType_>::compute(
const MatrixType_& matrix) {
352 Index rows = matrix.rows();
353 Index cols = matrix.cols();
354 EIGEN_ONLY_USED_FOR_DEBUG(rows);
355 EIGEN_ONLY_USED_FOR_DEBUG(cols);
357 eigen_assert(rows >= cols &&
"UpperBidiagonalization is only for matrices satisfying rows>=cols.");
359 m_householder = matrix;
360 upperbidiagonalization_inplace_blocked(m_householder, m_bidiagonal);
362 m_isInitialized =
true;
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
@ OnTheRight
Definition Constants.h:334
constexpr unsigned int RowMajorBit
Definition Constants.h:71