// L=============================================================================
// L This software is distributed under the MIT license.
// L Copyright 2021 Péter Kardos
// L=============================================================================
#pragma once
#include "../Common/MathUtil.hpp"
#include "../Transforms/IdentityBuilder.hpp"
#include "../Transforms/ZeroBuilder.hpp"
namespace mathter {
/// A utility class that can do common operations with the QR decomposition,
/// i.e. solving equation systems.
template
class DecompositionQR {
using MatrixT = Matrix;
public:
// DecompositionQR(Matrix Q,
// Matrix R) : Q(Q), R(R) {}
Matrix Q;
Matrix R;
};
/// Calculates the QR decomposition of the matrix using Householder transforms.
/// The matrix must have Rows <= Columns. It's a full QR decomposition, not a thin one.
template
auto DecomposeQR(Matrix m) {
static_assert(Rows >= Columns);
Matrix Q;
Matrix R;
R = m;
Q = Identity();
Matrix Qi;
Vector u;
Matrix v;
for (int col = 0; col < m.ColumnCount(); ++col) {
u = R.Column(col);
for (int i = 0; i < col; ++i) {
u(i) = T(0);
}
T alpha = impl::sign(R(col, col)) * LengthPrecise(u);
u(col) -= alpha;
T norm = LengthPrecise(u);
if (norm == 0) {
continue;
}
u /= norm;
v = u;
Qi = (T(-2) * v) * Transpose(v);
for (int i = 0; i < Q.ColumnCount(); ++i) {
Qi(i, i) += T(1);
}
R = Qi * R;
Q = Qi * Q;
}
Q = Transpose(Q);
return DecompositionQR{ Q, R };
}
} // namespace mathter