Working on getting the QR decomposition to compile
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -70,7 +70,8 @@
|
|||||||
"thread": "cpp",
|
"thread": "cpp",
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"variant": "cpp",
|
"variant": "cpp",
|
||||||
"shared_mutex": "cpp"
|
"shared_mutex": "cpp",
|
||||||
|
"complex": "cpp"
|
||||||
},
|
},
|
||||||
"clangd.enable": false,
|
"clangd.enable": false,
|
||||||
"C_Cpp.dimInactiveRegions": false
|
"C_Cpp.dimInactiveRegions": false
|
||||||
|
|||||||
97
Matrix.cpp
97
Matrix.cpp
@@ -17,6 +17,16 @@ Matrix<rows, columns>::Matrix(const std::array<float, rows * columns> &array) {
|
|||||||
this->setMatrixToArray(array);
|
this->setMatrixToArray(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint8_t rows, uint8_t columns>
|
||||||
|
Matrix<rows, columns>::Matrix(const Matrix<rows, columns> &other) {
|
||||||
|
for (uint8_t row_idx{0}; row_idx < rows; row_idx++) {
|
||||||
|
for (uint8_t column_idx{0}; column_idx < columns; column_idx++) {
|
||||||
|
this->matrix[row_idx * columns + column_idx] =
|
||||||
|
other.Get(row_idx, column_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <uint8_t rows, uint8_t columns>
|
template <uint8_t rows, uint8_t columns>
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
Matrix<rows, columns>::Matrix(Args... args) {
|
Matrix<rows, columns>::Matrix(Args... args) {
|
||||||
@@ -30,16 +40,6 @@ Matrix<rows, columns>::Matrix(Args... args) {
|
|||||||
memcpy(this->matrix.begin(), initList.begin(), minSize * sizeof(float));
|
memcpy(this->matrix.begin(), initList.begin(), minSize * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint8_t rows, uint8_t columns>
|
|
||||||
Matrix<rows, columns>::Matrix(const Matrix<rows, columns> &other) {
|
|
||||||
for (uint8_t row_idx{0}; row_idx < rows; row_idx++) {
|
|
||||||
for (uint8_t column_idx{0}; column_idx < columns; column_idx++) {
|
|
||||||
this->matrix[row_idx * columns + column_idx] =
|
|
||||||
other.Get(row_idx, column_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <uint8_t rows, uint8_t columns>
|
template <uint8_t rows, uint8_t columns>
|
||||||
void Matrix<rows, columns>::setMatrixToArray(
|
void Matrix<rows, columns>::setMatrixToArray(
|
||||||
const std::array<float, rows * columns> &array) {
|
const std::array<float, rows * columns> &array) {
|
||||||
@@ -86,7 +86,7 @@ Matrix<rows, columns>::Sub(const Matrix<rows, columns> &other,
|
|||||||
|
|
||||||
template <uint8_t rows, uint8_t columns>
|
template <uint8_t rows, uint8_t columns>
|
||||||
template <uint8_t other_columns>
|
template <uint8_t other_columns>
|
||||||
Matrix<rows, columns> &
|
Matrix<rows, other_columns> &
|
||||||
Matrix<rows, columns>::Mult(const Matrix<columns, other_columns> &other,
|
Matrix<rows, columns>::Mult(const Matrix<columns, other_columns> &other,
|
||||||
Matrix<rows, other_columns> &result) const {
|
Matrix<rows, other_columns> &result) const {
|
||||||
// allocate some buffers for all of our dot products
|
// allocate some buffers for all of our dot products
|
||||||
@@ -353,11 +353,7 @@ float Matrix<rows, columns>::dotProduct(const Matrix<vector_size, 1> &vec1,
|
|||||||
|
|
||||||
template <uint8_t rows, uint8_t columns>
|
template <uint8_t rows, uint8_t columns>
|
||||||
void Matrix<rows, columns>::Fill(float value) {
|
void Matrix<rows, columns>::Fill(float value) {
|
||||||
for (uint8_t row_idx{0}; row_idx < rows; row_idx++) {
|
this->matrix.fill(value);
|
||||||
for (uint8_t column_idx{0}; column_idx < columns; column_idx++) {
|
|
||||||
this->matrix[row_idx * columns + column_idx] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint8_t rows, uint8_t columns>
|
template <uint8_t rows, uint8_t columns>
|
||||||
@@ -440,4 +436,73 @@ Matrix<rows, columns>::Normalize(Matrix<rows, columns> &result) const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint8_t rows, uint8_t columns>
|
||||||
|
Matrix<rows, rows> Matrix<rows, columns>::Eye() {
|
||||||
|
Matrix<rows, rows> i_matrix;
|
||||||
|
i_matrix.Fill(0);
|
||||||
|
for (uint8_t i{0}; i < rows; i++) {
|
||||||
|
i_matrix[i][i] = 1;
|
||||||
|
}
|
||||||
|
return i_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <uint8_t rows, uint8_t columns>
|
||||||
|
void Matrix<rows, columns>::QR_Decomposition(Matrix<rows, columns> &Q,
|
||||||
|
Matrix<rows, columns> &R) const {
|
||||||
|
Q = Matrix<rows, columns>::Eye(); // Q starts as the identity matrix
|
||||||
|
R = *this; // R starts as a copy of this matrix (For this algorithm we'll call
|
||||||
|
// this matrix A)
|
||||||
|
|
||||||
|
for (uint8_t row{0}; row < rows; row++) {
|
||||||
|
// compute the householder vector
|
||||||
|
const uint8_t houseHoldVectorSize{rows - row};
|
||||||
|
const uint8_t subMatrixSize{columns - row};
|
||||||
|
Matrix<houseHoldVectorSize, 1> x{};
|
||||||
|
this->SubMatrix(row, row, x);
|
||||||
|
|
||||||
|
Matrix<houseHoldVectorSize, 1> e1{};
|
||||||
|
e1.Fill(0);
|
||||||
|
if (x[0][0] >= 0) {
|
||||||
|
e1[0][0] = x.Norm();
|
||||||
|
} else {
|
||||||
|
e1[0][0] = -x.Norm();
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix<houseHoldVectorSize, 1> v = x + e1;
|
||||||
|
v = v * (1 / v.Norm()); // normalize V
|
||||||
|
|
||||||
|
// ************************************
|
||||||
|
// Apply the reflection to the R matrix
|
||||||
|
// ************************************
|
||||||
|
// initialize R's submatrix
|
||||||
|
Matrix<houseHoldVectorSize, subMatrixSize> R_subMatrix{};
|
||||||
|
R.SubMatrix(row, row, R_subMatrix);
|
||||||
|
// create some temporary buffers
|
||||||
|
Matrix<1, subMatrixSize> vR{};
|
||||||
|
Matrix<1, houseHoldVectorSize> v_T{};
|
||||||
|
v.Transpose(v_T);
|
||||||
|
Matrix<houseHoldVectorSize, subMatrixSize> vR_outer{};
|
||||||
|
// calculate the reflection
|
||||||
|
R_subMatrix =
|
||||||
|
R_subMatrix - 2 * Matrix<rows, columns>::OuterProduct(
|
||||||
|
v_T, v_T.Mult(R_subMatrix, vR), vR_outer);
|
||||||
|
// save the reflection back to R
|
||||||
|
R.CopySubMatrixInto(row, row, R_subMatrix);
|
||||||
|
|
||||||
|
// ************************************
|
||||||
|
// Apply the reflection to the Q matrix
|
||||||
|
// ************************************
|
||||||
|
// initialize Q's submatrix
|
||||||
|
Matrix<rows, houseHoldVectorSize> Q_subMatrix{};
|
||||||
|
Q.SubMatrix(0, row, Q_subMatrix);
|
||||||
|
// create some temporary buffers
|
||||||
|
Matrix<rows, 1> Qv{};
|
||||||
|
Matrix<rows, houseHoldVectorSize> Qv_outer{};
|
||||||
|
|
||||||
|
Q_subMatrix = Q_subMatrix - 2 * Matrix<rows, columns>::OuterProduct(
|
||||||
|
Q_subMatrix.Mult(v, Qv), v, Qv_outer);
|
||||||
|
Q.CopySubMatrixInto(0, row, Q_subMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // MATRIX_H_
|
#endif // MATRIX_H_
|
||||||
69
Matrix.hpp
69
Matrix.hpp
@@ -35,6 +35,7 @@ public:
|
|||||||
* @brief Initialize a matrix directly with any number of arguments
|
* @brief Initialize a matrix directly with any number of arguments
|
||||||
*/
|
*/
|
||||||
template <typename... Args> Matrix(Args... args);
|
template <typename... Args> Matrix(Args... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set all elements in this to value
|
* @brief Set all elements in this to value
|
||||||
*/
|
*/
|
||||||
@@ -64,8 +65,8 @@ public:
|
|||||||
* @param result A buffer to store the result into
|
* @param result A buffer to store the result into
|
||||||
*/
|
*/
|
||||||
template <uint8_t other_columns>
|
template <uint8_t other_columns>
|
||||||
Matrix<rows, columns> &Mult(const Matrix<columns, other_columns> &other,
|
Matrix<rows, other_columns> &Mult(const Matrix<columns, other_columns> &other,
|
||||||
Matrix<rows, other_columns> &result) const;
|
Matrix<rows, other_columns> &result) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Multiply the matrix by a scalar
|
* @brief Multiply the matrix by a scalar
|
||||||
@@ -125,6 +126,66 @@ public:
|
|||||||
*/
|
*/
|
||||||
Matrix<rows, columns> &Normalize(Matrix<rows, columns> &result) const;
|
Matrix<rows, columns> &Normalize(Matrix<rows, columns> &result) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return an identity matrix of the specified size
|
||||||
|
*/
|
||||||
|
static Matrix<rows, rows> Eye();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief write a copy of a sub matrix into the given result matrix.
|
||||||
|
* @param rowIndex The row index to start the copy from
|
||||||
|
* @param columnIndex the column index to start the copy from
|
||||||
|
* @param result the matrix buffer to write the sub matrix into. The size of
|
||||||
|
* the matrix buffer allows the function to determine the end indices of the
|
||||||
|
* sub matrix
|
||||||
|
*/
|
||||||
|
template <uint8_t subRows, uint8_t subColumns>
|
||||||
|
Matrix<subRows, subColumns> &
|
||||||
|
SubMatrix(uint8_t rowIndex, uint8_t columnIndex,
|
||||||
|
Matrix<subRows, subColumns> &result) const {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief write a copy of a sub matrix into this matrix starting at the given
|
||||||
|
* idnex.
|
||||||
|
* @param rowIndex The row index to start the copy from
|
||||||
|
* @param columnIndex the column index to start the copy from
|
||||||
|
* @param subMatrix The submatrix to copy into this matrix. The size of
|
||||||
|
* the matrix buffer allows the function to determine the end indices of the
|
||||||
|
* sub matrix
|
||||||
|
*/
|
||||||
|
template <uint8_t subRows, uint8_t subColumns>
|
||||||
|
void CopySubMatrixInto(uint8_t rowIndex, uint8_t columnIndex,
|
||||||
|
const Matrix<subRows, subColumns> &subMatrix) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the norm of the matrix
|
||||||
|
*/
|
||||||
|
float Norm() { return 0; }
|
||||||
|
|
||||||
|
template <uint8_t vec1Length, uint8_t vec2Length>
|
||||||
|
static Matrix<vec1Length, vec2Length> &
|
||||||
|
OuterProduct(const Matrix<1, vec1Length> &vec1,
|
||||||
|
const Matrix<1, vec2Length> &vec2,
|
||||||
|
Matrix<vec1Length, vec2Length> &result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <uint8_t vec1Length, uint8_t vec2Length>
|
||||||
|
static Matrix<vec1Length, vec2Length> &
|
||||||
|
OuterProduct(const Matrix<vec1Length, 1> &vec1,
|
||||||
|
const Matrix<vec2Length, 1> &vec2,
|
||||||
|
Matrix<vec1Length, vec2Length> &result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Calulcate the QR decomposition of a matrix
|
||||||
|
* @param Q the
|
||||||
|
*/
|
||||||
|
void QR_Decomposition(Matrix<rows, columns> &Q,
|
||||||
|
Matrix<rows, columns> &R) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a row from the matrix
|
* @brief Get a row from the matrix
|
||||||
* @param row_index the row index to get
|
* @param row_index the row index to get
|
||||||
@@ -160,6 +221,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
float Get(uint8_t row_index, uint8_t column_index) const;
|
float Get(uint8_t row_index, uint8_t column_index) const;
|
||||||
|
|
||||||
|
// *******************************************************
|
||||||
|
// ************** OPERATOR OVERRIDES *********************
|
||||||
|
// *******************************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the specified row of the matrix returned as a reference to the
|
* @brief get the specified row of the matrix returned as a reference to the
|
||||||
* internal array
|
* internal array
|
||||||
|
|||||||
@@ -182,6 +182,18 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") {
|
|||||||
REQUIRE(minorMat4.Get(1, 0) == 4);
|
REQUIRE(minorMat4.Get(1, 0) == 4);
|
||||||
REQUIRE(minorMat4.Get(1, 1) == 5);
|
REQUIRE(minorMat4.Get(1, 1) == 5);
|
||||||
}
|
}
|
||||||
|
SECTION("Identity Matrix") {
|
||||||
|
Matrix<3, 3> mat4{Matrix<3, 3>::Eye()};
|
||||||
|
REQUIRE(mat4.Get(0, 0) == 1);
|
||||||
|
REQUIRE(mat4.Get(0, 1) == 0);
|
||||||
|
REQUIRE(mat4.Get(0, 2) == 0);
|
||||||
|
REQUIRE(mat4.Get(1, 0) == 0);
|
||||||
|
REQUIRE(mat4.Get(1, 1) == 1);
|
||||||
|
REQUIRE(mat4.Get(1, 2) == 0);
|
||||||
|
REQUIRE(mat4.Get(2, 0) == 0);
|
||||||
|
REQUIRE(mat4.Get(2, 1) == 0);
|
||||||
|
REQUIRE(mat4.Get(2, 2) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Determinant") {
|
SECTION("Determinant") {
|
||||||
float det1 = mat1.Det();
|
float det1 = mat1.Det();
|
||||||
|
|||||||
Reference in New Issue
Block a user