00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_QR_H
00026 #define EIGEN_QR_H
00027
00042 template<typename MatrixType> class QR
00043 {
00044 public:
00045
00046 typedef typename MatrixType::Scalar Scalar;
00047 typedef typename MatrixType::RealScalar RealScalar;
00048 typedef Block<MatrixType, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixRBlockType;
00049 typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixTypeR;
00050 typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
00051
00058 QR() : m_qr(), m_hCoeffs(), m_isInitialized(false) {}
00059
00060 QR(const MatrixType& matrix)
00061 : m_qr(matrix.rows(), matrix.cols()),
00062 m_hCoeffs(matrix.cols()),
00063 m_isInitialized(false)
00064 {
00065 compute(matrix);
00066 }
00067
00074 EIGEN_DEPRECATED bool isFullRank() const
00075 {
00076 ei_assert(m_isInitialized && "QR is not initialized.");
00077 return rank() == m_qr.cols();
00078 }
00079
00085 int rank() const;
00086
00092 inline int dimensionOfKernel() const
00093 {
00094 ei_assert(m_isInitialized && "QR is not initialized.");
00095 return m_qr.cols() - rank();
00096 }
00097
00104 inline bool isInjective() const
00105 {
00106 ei_assert(m_isInitialized && "QR is not initialized.");
00107 return rank() == m_qr.cols();
00108 }
00109
00116 inline bool isSurjective() const
00117 {
00118 ei_assert(m_isInitialized && "QR is not initialized.");
00119 return rank() == m_qr.rows();
00120 }
00121
00127 inline bool isInvertible() const
00128 {
00129 ei_assert(m_isInitialized && "QR is not initialized.");
00130 return isInjective() && isSurjective();
00131 }
00132
00134 const Part<NestByValue<MatrixRBlockType>, UpperTriangular>
00135 matrixR(void) const
00136 {
00137 ei_assert(m_isInitialized && "QR is not initialized.");
00138 int cols = m_qr.cols();
00139 return MatrixRBlockType(m_qr, 0, 0, cols, cols).nestByValue().template part<UpperTriangular>();
00140 }
00141
00165 template<typename OtherDerived, typename ResultType>
00166 bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const;
00167
00168 MatrixType matrixQ(void) const;
00169
00170 void compute(const MatrixType& matrix);
00171
00172 protected:
00173 MatrixType m_qr;
00174 VectorType m_hCoeffs;
00175 mutable int m_rank;
00176 mutable bool m_rankIsUptodate;
00177 bool m_isInitialized;
00178 };
00179
00181 template<typename MatrixType>
00182 int QR<MatrixType>::rank() const
00183 {
00184 ei_assert(m_isInitialized && "QR is not initialized.");
00185 if (!m_rankIsUptodate)
00186 {
00187 RealScalar maxCoeff = m_qr.diagonal().cwise().abs().maxCoeff();
00188 int n = m_qr.cols();
00189 m_rank = 0;
00190 while(m_rank<n && !ei_isMuchSmallerThan(m_qr.diagonal().coeff(m_rank), maxCoeff))
00191 ++m_rank;
00192 m_rankIsUptodate = true;
00193 }
00194 return m_rank;
00195 }
00196
00197 #ifndef EIGEN_HIDE_HEAVY_CODE
00198
00199 template<typename MatrixType>
00200 void QR<MatrixType>::compute(const MatrixType& matrix)
00201 {
00202 m_rankIsUptodate = false;
00203 m_qr = matrix;
00204 m_hCoeffs.resize(matrix.cols());
00205
00206 int rows = matrix.rows();
00207 int cols = matrix.cols();
00208 RealScalar eps2 = precision<RealScalar>()*precision<RealScalar>();
00209
00210 for (int k = 0; k < cols; ++k)
00211 {
00212 int remainingSize = rows-k;
00213
00214 RealScalar beta;
00215 Scalar v0 = m_qr.col(k).coeff(k);
00216
00217 if (remainingSize==1)
00218 {
00219 if (NumTraits<Scalar>::IsComplex)
00220 {
00221
00222 beta = ei_abs(v0);
00223 if (ei_real(v0)>0)
00224 beta = -beta;
00225 m_qr.coeffRef(k,k) = beta;
00226 m_hCoeffs.coeffRef(k) = (beta - v0) / beta;
00227 }
00228 else
00229 {
00230 m_hCoeffs.coeffRef(k) = 0;
00231 }
00232 }
00233 else if ((beta=m_qr.col(k).end(remainingSize-1).squaredNorm())>eps2)
00234
00235 {
00236
00237 beta = ei_sqrt(ei_abs2(v0)+beta);
00238 if (ei_real(v0)>=0.)
00239 beta = -beta;
00240 m_qr.col(k).end(remainingSize-1) /= v0-beta;
00241 m_qr.coeffRef(k,k) = beta;
00242 Scalar h = m_hCoeffs.coeffRef(k) = (beta - v0) / beta;
00243
00244
00245
00246 int remainingCols = cols - k -1;
00247 if (remainingCols>0)
00248 {
00249 m_qr.coeffRef(k,k) = Scalar(1);
00250 m_qr.corner(BottomRight, remainingSize, remainingCols) -= ei_conj(h) * m_qr.col(k).end(remainingSize)
00251 * (m_qr.col(k).end(remainingSize).adjoint() * m_qr.corner(BottomRight, remainingSize, remainingCols));
00252 m_qr.coeffRef(k,k) = beta;
00253 }
00254 }
00255 else
00256 {
00257 m_hCoeffs.coeffRef(k) = 0;
00258 }
00259 }
00260 m_isInitialized = true;
00261 }
00262
00263 template<typename MatrixType>
00264 template<typename OtherDerived, typename ResultType>
00265 bool QR<MatrixType>::solve(
00266 const MatrixBase<OtherDerived>& b,
00267 ResultType *result
00268 ) const
00269 {
00270 ei_assert(m_isInitialized && "QR is not initialized.");
00271 const int rows = m_qr.rows();
00272 ei_assert(b.rows() == rows);
00273
00274 rank();
00275
00276 result->resize(m_qr.cols(), b.cols());
00277
00278
00279
00280 *result = matrixQ().transpose()*b;
00281
00282 if(m_rank==0)
00283 return result->isZero();
00284
00285 if(!isSurjective())
00286 {
00287
00288 RealScalar biggest_in_res = result->corner(TopLeft, m_rank, result->cols()).cwise().abs().maxCoeff();
00289 for(int col = 0; col < result->cols(); ++col)
00290 for(int row = m_rank; row < result->rows(); ++row)
00291 if(!ei_isMuchSmallerThan(result->coeff(row,col), biggest_in_res))
00292 return false;
00293 }
00294 m_qr.corner(TopLeft, m_rank, m_rank)
00295 .template marked<UpperTriangular>()
00296 .solveTriangularInPlace(result->corner(TopLeft, m_rank, result->cols()));
00297
00298 return true;
00299 }
00300
00302 template<typename MatrixType>
00303 MatrixType QR<MatrixType>::matrixQ() const
00304 {
00305 ei_assert(m_isInitialized && "QR is not initialized.");
00306
00307
00308
00309 int rows = m_qr.rows();
00310 int cols = m_qr.cols();
00311 MatrixType res = MatrixType::Identity(rows, cols);
00312 for (int k = cols-1; k >= 0; k--)
00313 {
00314
00315
00316 Scalar beta = m_qr.coeff(k,k);
00317 m_qr.const_cast_derived().coeffRef(k,k) = 1;
00318 int endLength = rows-k;
00319 res.corner(BottomRight,endLength, cols-k) -= ((m_hCoeffs.coeff(k) * m_qr.col(k).end(endLength))
00320 * (m_qr.col(k).end(endLength).adjoint() * res.corner(BottomRight,endLength, cols-k)).lazy()).lazy();
00321 m_qr.const_cast_derived().coeffRef(k,k) = beta;
00322 }
00323 return res;
00324 }
00325
00326 #endif // EIGEN_HIDE_HEAVY_CODE
00327
00332 template<typename Derived>
00333 const QR<typename MatrixBase<Derived>::PlainMatrixType>
00334 MatrixBase<Derived>::qr() const
00335 {
00336 return QR<PlainMatrixType>(eval());
00337 }
00338
00339
00340 #endif // EIGEN_QR_H