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 | // |
---|
6 | // This Source Code Form is subject to the terms of the Mozilla |
---|
7 | // Public License v. 2.0. If a copy of the MPL was not distributed |
---|
8 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
---|
9 | |
---|
10 | #ifndef EIGEN_BIDIAGONALIZATION_H |
---|
11 | #define EIGEN_BIDIAGONALIZATION_H |
---|
12 | |
---|
13 | namespace Eigen { |
---|
14 | |
---|
15 | namespace internal { |
---|
16 | // UpperBidiagonalization will probably be replaced by a Bidiagonalization class, don't want to make it stable API. |
---|
17 | // At the same time, it's useful to keep for now as it's about the only thing that is testing the BandMatrix class. |
---|
18 | |
---|
19 | template<typename _MatrixType> class UpperBidiagonalization |
---|
20 | { |
---|
21 | public: |
---|
22 | |
---|
23 | typedef _MatrixType MatrixType; |
---|
24 | enum { |
---|
25 | RowsAtCompileTime = MatrixType::RowsAtCompileTime, |
---|
26 | ColsAtCompileTime = MatrixType::ColsAtCompileTime, |
---|
27 | ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::ret |
---|
28 | }; |
---|
29 | typedef typename MatrixType::Scalar Scalar; |
---|
30 | typedef typename MatrixType::RealScalar RealScalar; |
---|
31 | typedef typename MatrixType::Index Index; |
---|
32 | typedef Matrix<Scalar, 1, ColsAtCompileTime> RowVectorType; |
---|
33 | typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType; |
---|
34 | typedef BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0> BidiagonalType; |
---|
35 | typedef Matrix<Scalar, ColsAtCompileTime, 1> DiagVectorType; |
---|
36 | typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType; |
---|
37 | typedef HouseholderSequence< |
---|
38 | const MatrixType, |
---|
39 | CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Diagonal<const MatrixType,0> > |
---|
40 | > HouseholderUSequenceType; |
---|
41 | typedef HouseholderSequence< |
---|
42 | const MatrixType, |
---|
43 | Diagonal<const MatrixType,1>, |
---|
44 | OnTheRight |
---|
45 | > HouseholderVSequenceType; |
---|
46 | |
---|
47 | /** |
---|
48 | * \brief Default Constructor. |
---|
49 | * |
---|
50 | * The default constructor is useful in cases in which the user intends to |
---|
51 | * perform decompositions via Bidiagonalization::compute(const MatrixType&). |
---|
52 | */ |
---|
53 | UpperBidiagonalization() : m_householder(), m_bidiagonal(), m_isInitialized(false) {} |
---|
54 | |
---|
55 | UpperBidiagonalization(const MatrixType& matrix) |
---|
56 | : m_householder(matrix.rows(), matrix.cols()), |
---|
57 | m_bidiagonal(matrix.cols(), matrix.cols()), |
---|
58 | m_isInitialized(false) |
---|
59 | { |
---|
60 | compute(matrix); |
---|
61 | } |
---|
62 | |
---|
63 | UpperBidiagonalization& compute(const MatrixType& matrix); |
---|
64 | |
---|
65 | const MatrixType& householder() const { return m_householder; } |
---|
66 | const BidiagonalType& bidiagonal() const { return m_bidiagonal; } |
---|
67 | |
---|
68 | const HouseholderUSequenceType householderU() const |
---|
69 | { |
---|
70 | eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized."); |
---|
71 | return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate()); |
---|
72 | } |
---|
73 | |
---|
74 | const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy |
---|
75 | { |
---|
76 | eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized."); |
---|
77 | return HouseholderVSequenceType(m_householder, m_householder.const_derived().template diagonal<1>()) |
---|
78 | .setLength(m_householder.cols()-1) |
---|
79 | .setShift(1); |
---|
80 | } |
---|
81 | |
---|
82 | protected: |
---|
83 | MatrixType m_householder; |
---|
84 | BidiagonalType m_bidiagonal; |
---|
85 | bool m_isInitialized; |
---|
86 | }; |
---|
87 | |
---|
88 | template<typename _MatrixType> |
---|
89 | UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::compute(const _MatrixType& matrix) |
---|
90 | { |
---|
91 | Index rows = matrix.rows(); |
---|
92 | Index cols = matrix.cols(); |
---|
93 | |
---|
94 | eigen_assert(rows >= cols && "UpperBidiagonalization is only for matrices satisfying rows>=cols."); |
---|
95 | |
---|
96 | m_householder = matrix; |
---|
97 | |
---|
98 | ColVectorType temp(rows); |
---|
99 | |
---|
100 | for (Index k = 0; /* breaks at k==cols-1 below */ ; ++k) |
---|
101 | { |
---|
102 | Index remainingRows = rows - k; |
---|
103 | Index remainingCols = cols - k - 1; |
---|
104 | |
---|
105 | // construct left householder transform in-place in m_householder |
---|
106 | m_householder.col(k).tail(remainingRows) |
---|
107 | .makeHouseholderInPlace(m_householder.coeffRef(k,k), |
---|
108 | m_bidiagonal.template diagonal<0>().coeffRef(k)); |
---|
109 | // apply householder transform to remaining part of m_householder on the left |
---|
110 | m_householder.bottomRightCorner(remainingRows, remainingCols) |
---|
111 | .applyHouseholderOnTheLeft(m_householder.col(k).tail(remainingRows-1), |
---|
112 | m_householder.coeff(k,k), |
---|
113 | temp.data()); |
---|
114 | |
---|
115 | if(k == cols-1) break; |
---|
116 | |
---|
117 | // construct right householder transform in-place in m_householder |
---|
118 | m_householder.row(k).tail(remainingCols) |
---|
119 | .makeHouseholderInPlace(m_householder.coeffRef(k,k+1), |
---|
120 | m_bidiagonal.template diagonal<1>().coeffRef(k)); |
---|
121 | // apply householder transform to remaining part of m_householder on the left |
---|
122 | m_householder.bottomRightCorner(remainingRows-1, remainingCols) |
---|
123 | .applyHouseholderOnTheRight(m_householder.row(k).tail(remainingCols-1).transpose(), |
---|
124 | m_householder.coeff(k,k+1), |
---|
125 | temp.data()); |
---|
126 | } |
---|
127 | m_isInitialized = true; |
---|
128 | return *this; |
---|
129 | } |
---|
130 | |
---|
131 | #if 0 |
---|
132 | /** \return the Householder QR decomposition of \c *this. |
---|
133 | * |
---|
134 | * \sa class Bidiagonalization |
---|
135 | */ |
---|
136 | template<typename Derived> |
---|
137 | const UpperBidiagonalization<typename MatrixBase<Derived>::PlainObject> |
---|
138 | MatrixBase<Derived>::bidiagonalization() const |
---|
139 | { |
---|
140 | return UpperBidiagonalization<PlainObject>(eval()); |
---|
141 | } |
---|
142 | #endif |
---|
143 | |
---|
144 | } // end namespace internal |
---|
145 | |
---|
146 | } // end namespace Eigen |
---|
147 | |
---|
148 | #endif // EIGEN_BIDIAGONALIZATION_H |
---|