ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkQRDecomposition.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkQRDecomposition_h
19#define itkQRDecomposition_h
20
21#include "itkMacro.h"
22#include "vnl/vnl_matrix.h"
23#include "vnl/vnl_vector.h"
24#include "itk_eigen.h"
25#include ITK_EIGEN(Dense)
26
27namespace itk
28{
29
41template <typename T>
43{
44public:
45 using MatrixType = vnl_matrix<T>;
46 using VectorType = vnl_vector<T>;
47
48 explicit QRDecomposition(const MatrixType & A)
49 {
50 itkAssertOrThrowMacro(A.rows() > 0 && A.cols() > 0, "QRDecomposition requires a non-empty matrix");
51 using RowMajor = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
52 using ColMajor = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
53 const unsigned int rows = A.rows();
54 const unsigned int cols = A.cols();
55
56 Eigen::Map<const RowMajor> aMap(A.data_block(), rows, cols);
57 const Eigen::HouseholderQR<ColMajor> qr(aMap);
58
59 const ColMajor qFull = qr.householderQ();
60 const ColMajor rFull = qr.matrixQR().template triangularView<Eigen::Upper>();
61
62 m_Q.set_size(rows, rows);
63 Eigen::Map<RowMajor>(m_Q.data_block(), rows, rows) = qFull;
64 m_R.set_size(rows, cols);
65 Eigen::Map<RowMajor>(m_R.data_block(), rows, cols) = rFull;
66
67 m_Square = (rows == cols);
68 m_Determinant = m_Square ? static_cast<T>(aMap.determinant()) : T{};
69 }
70
72 const MatrixType &
73 GetQ() const
74 {
75 return m_Q;
76 }
77
79 const MatrixType &
80 GetR() const
81 {
82 return m_R;
83 }
84
88 Solve(const VectorType & b) const
89 {
90 using RowMajor = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
91 using Vector = Eigen::Matrix<T, Eigen::Dynamic, 1>;
92 const unsigned int rows = m_Q.rows();
93 const unsigned int cols = m_R.cols();
94 itkAssertOrThrowMacro(b.size() == rows, "QRDecomposition::Solve requires b length to match the row count");
95 if (cols > rows)
96 {
97 itkGenericExceptionMacro("QRDecomposition::Solve supports square or overdetermined systems only (rows >= cols)");
98 }
99
100 Eigen::Map<const RowMajor> qMap(m_Q.data_block(), rows, rows);
101 Eigen::Map<const RowMajor> rMap(m_R.data_block(), rows, cols);
102 Eigen::Map<const Vector> bMap(b.data_block(), rows);
103
104 const Vector qtb = qMap.adjoint() * bMap;
105 const Vector x = rMap.topLeftCorner(cols, cols).template triangularView<Eigen::Upper>().solve(qtb.head(cols));
106
107 VectorType out(cols);
108 Eigen::Map<Vector>(out.data_block(), cols) = x;
109 return out;
110 }
111
113 T
115 {
116 return m_Determinant;
117 }
118
119private:
123 bool m_Square{ false };
124};
125
126} // namespace itk
127
128#endif // itkQRDecomposition_h
const MatrixType & GetR() const
VectorType Solve(const VectorType &b) const
QRDecomposition(const MatrixType &A)
const MatrixType & GetQ() const
vnl_matrix< T > MatrixType
vnl_vector< T > VectorType
A templated class holding a n-Dimensional vector.
Definition itkVector.h:63
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....