Working on adding efficient eigenvector and value calculations #2

Merged
Cynopolis merged 11 commits from eigenvector-and-values into main 2025-06-06 22:32:19 +00:00
5 changed files with 40 additions and 23 deletions
Showing only changes of commit 64820553c7 - Show all commits

View File

@@ -337,6 +337,22 @@ Matrix<rows, columns> Matrix<rows, columns>::operator*(float scalar) const {
return buffer;
}
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns> Matrix<rows, columns>::operator/(float scalar) const {
Matrix<rows, columns> buffer = *this;
if (scalar == 0) {
buffer.Fill(1e+10);
return buffer;
}
for (uint8_t row = 0; row < rows; row++) {
for (uint8_t column = 0; column < columns; column++) {
buffer[row][column] /= scalar;
}
}
return buffer;
}
template <uint8_t rows, uint8_t columns>
template <uint8_t vector_size>
float Matrix<rows, columns>::DotProduct(const Matrix<1, vector_size> &vec1,
@@ -423,7 +439,7 @@ Matrix<rows, columns>::adjugate(Matrix<rows, columns> &result) const {
}
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns> Matrix<rows, columns>::EuclideanNorm() const {
float Matrix<rows, columns>::EuclideanNorm() const {
float sum{0};
for (uint8_t row_idx{0}; row_idx < rows; row_idx++) {
@@ -433,21 +449,17 @@ Matrix<rows, columns> Matrix<rows, columns>::EuclideanNorm() const {
}
}
Matrix<rows, columns> result{};
if (sum == 0) {
// this wouldn't do anything anyways
result.Fill(0);
return result;
return sqrt(sum);
}
template <uint8_t rows, uint8_t columns>
float Matrix<rows, columns>::L2Norm() const {
float sum{0};
Matrix<rows, 1> columnMatrix{};
for (uint8_t column = 0; column < columns; column++) {
this.GetColumn(column, columnMatrix);
sum += columnMatrix.EuclideanNorm();
}
sum = sqrt(sum);
for (uint8_t row_idx{0}; row_idx < rows; row_idx++) {
for (uint8_t column_idx{0}; column_idx < columns; column_idx++) {
result[row_idx][column_idx] = this->Get(row_idx, column_idx) / sum;
}
}
return result;
return sqrt(sum);
}
template <uint8_t rows, uint8_t columns>

View File

@@ -132,7 +132,9 @@ public:
* @brief reduce the matrix so the sum of its elements equal 1
* @param result a buffer to store the result into
*/
Matrix<rows, columns> EuclideanNorm() const;
float EuclideanNorm() const;
float L2Norm() const;
/**
* @brief Get a row from the matrix
@@ -201,6 +203,8 @@ public:
Matrix<rows, columns> operator*(float scalar) const;
Matrix<rows, columns> operator/(float scalar) const;
template <uint8_t sub_rows, uint8_t sub_columns, uint8_t row_offset,
uint8_t column_offset>
Matrix<sub_rows, sub_columns> SubMatrix() const;

View File

@@ -9,8 +9,7 @@
Quaternion Quaternion::FromAngleAndAxis(float angle, const Matrix<1, 3> &axis) {
const float halfAngle = angle / 2;
const float sinHalfAngle = sin(halfAngle);
Matrix<1, 3> normalizedAxis{};
normalizedAxis = axis.EuclideanNorm();
Matrix<1, 3> normalizedAxis = axis / axis.EuclideanNorm();
return Quaternion{static_cast<float>(cos(halfAngle)),
normalizedAxis.Get(0, 0) * sinHalfAngle,
normalizedAxis.Get(0, 1) * sinHalfAngle,

View File

@@ -373,13 +373,15 @@ float matrixSum(const Matrix<rows, columns> &matrix) {
return std::sqrt(sum);
}
// TODO: Add test for scalar division
TEST_CASE("Normalization", "Matrix") {
SECTION("2x2 Normalize") {
Matrix<2, 2> mat1{1, 2, 3, 4};
Matrix<2, 2> mat2{};
mat2 = mat1.EuclideanNorm();
mat2 = mat1 / mat1.EuclideanNorm();
float sqrt_30{static_cast<float>(sqrt(30.0f))};
@@ -394,7 +396,7 @@ TEST_CASE("Normalization", "Matrix") {
SECTION("2x1 (Vector) Normalize") {
Matrix<2, 1> mat1{-0.878877044, 2.92092276};
Matrix<2, 1> mat2{};
mat2 = mat1.EuclideanNorm();
mat2 = mat1 / mat1.EuclideanNorm();
REQUIRE_THAT(mat2.Get(0, 0),
Catch::Matchers::WithinRel(-0.288129855179f, 1e-6f));
@@ -408,13 +410,13 @@ TEST_CASE("Normalization", "Matrix") {
SECTION("Normalized vectors sum to 1") {
Matrix<9, 1> mat1{1, 2, 3, 4, 5, 6, 7, 8, 9};
Matrix<9, 1> mat2;
mat2 = mat1.EuclideanNorm();
mat2 = mat1 / mat1.EuclideanNorm();
float sum = matrixSum(mat2);
REQUIRE_THAT(sum, Catch::Matchers::WithinRel(1.0f, 1e-6f));
Matrix<2, 3> mat3{1, 2, 3, 4, 5, 6};
Matrix<2, 3> mat4{};
mat4 = mat3.EuclideanNorm();
mat4 = mat3 / mat3.EuclideanNorm();
sum = matrixSum(mat4);
REQUIRE_THAT(sum, Catch::Matchers::WithinRel(1.0f, 1e-6f));
}

View File

@@ -99,7 +99,7 @@ TEST_CASE("Timing Tests", "Matrix") {
SECTION("Normalize") {
for (uint32_t i{0}; i < 10000; i++) {
mat3 = mat1.EuclideanNorm();
mat3 = mat1 / mat1.EuclideanNorm();
}
}