New norms and division by scalar
Some checks failed
Merge-Checker / build_and_test (pull_request) Failing after 21s

This commit is contained in:
2025-06-02 16:19:23 -04:00
parent 60a2b12b5f
commit 64820553c7
5 changed files with 40 additions and 23 deletions

View File

@@ -337,6 +337,22 @@ Matrix<rows, columns> Matrix<rows, columns>::operator*(float scalar) const {
return buffer; 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 rows, uint8_t columns>
template <uint8_t vector_size> template <uint8_t vector_size>
float Matrix<rows, columns>::DotProduct(const Matrix<1, vector_size> &vec1, 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> template <uint8_t rows, uint8_t columns>
Matrix<rows, columns> Matrix<rows, columns>::EuclideanNorm() const { float Matrix<rows, columns>::EuclideanNorm() const {
float sum{0}; float sum{0};
for (uint8_t row_idx{0}; row_idx < rows; row_idx++) { 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{}; return sqrt(sum);
if (sum == 0) { }
// this wouldn't do anything anyways template <uint8_t rows, uint8_t columns>
result.Fill(0); float Matrix<rows, columns>::L2Norm() const {
return result; float sum{0};
Matrix<rows, 1> columnMatrix{};
for (uint8_t column = 0; column < columns; column++) {
this.GetColumn(column, columnMatrix);
sum += columnMatrix.EuclideanNorm();
} }
return sqrt(sum);
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;
} }
template <uint8_t rows, uint8_t columns> 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 * @brief reduce the matrix so the sum of its elements equal 1
* @param result a buffer to store the result into * @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 * @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;
Matrix<rows, columns> operator/(float scalar) const;
template <uint8_t sub_rows, uint8_t sub_columns, uint8_t row_offset, template <uint8_t sub_rows, uint8_t sub_columns, uint8_t row_offset,
uint8_t column_offset> uint8_t column_offset>
Matrix<sub_rows, sub_columns> SubMatrix() const; Matrix<sub_rows, sub_columns> SubMatrix() const;

View File

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

View File

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

View File

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