From 7a291b451af0df390bee4136a29293f92ea2e011 Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 27 Jan 2023 02:57:33 +0100 Subject: [PATCH] Added some extremely basic tests for the new Matrix and Vector classes. Also fixed a few smaller issues. --- mlpp/lin_alg/mlpp_matrix.cpp | 21 +++++++ mlpp/lin_alg/mlpp_matrix.h | 12 +++- mlpp/lin_alg/mlpp_vector.cpp | 15 +++++ mlpp/lin_alg/mlpp_vector.h | 8 +++ test/mlpp_tests.cpp | 114 ++++++++++++++++++++++++++++++++++- test/mlpp_tests.h | 9 +++ 6 files changed, 176 insertions(+), 3 deletions(-) diff --git a/mlpp/lin_alg/mlpp_matrix.cpp b/mlpp/lin_alg/mlpp_matrix.cpp index 5ec5747..c8f4be9 100644 --- a/mlpp/lin_alg/mlpp_matrix.cpp +++ b/mlpp/lin_alg/mlpp_matrix.cpp @@ -1,6 +1,27 @@ #include "mlpp_matrix.h" +String MLPPMatrix::to_string() { + String str; + + str += "[MLPPMatrix: \n"; + + for (int y = 0; y < _size.y; ++y) { + str += " [ "; + + for (int x = 0; x < _size.x; ++x) { + str += String::num(_data[_size.x * y + x]); + str += " "; + } + + str += "]\n"; + } + + str += "]"; + + return str; +} + void MLPPMatrix::_bind_methods() { ClassDB::bind_method(D_METHOD("add_row", "row"), &MLPPMatrix::add_row_pool_vector); ClassDB::bind_method(D_METHOD("remove_row", "index"), &MLPPMatrix::remove_row); diff --git a/mlpp/lin_alg/mlpp_matrix.h b/mlpp/lin_alg/mlpp_matrix.h index 1e613f7..8a7eeca 100644 --- a/mlpp/lin_alg/mlpp_matrix.h +++ b/mlpp/lin_alg/mlpp_matrix.h @@ -146,7 +146,15 @@ public: void resize(const Size2i &p_size) { _size = p_size; - _data = (double *)memrealloc(_data, data_size() * sizeof(double)); + int ds = data_size(); + + if (ds == 0) { + memfree(_data); + _data = NULL; + return; + } + + _data = (double *)memrealloc(_data, ds * sizeof(double)); CRASH_COND_MSG(!_data, "Out of memory"); } @@ -398,6 +406,8 @@ public: } } + String to_string(); + _FORCE_INLINE_ MLPPMatrix() { _data = NULL; } diff --git a/mlpp/lin_alg/mlpp_vector.cpp b/mlpp/lin_alg/mlpp_vector.cpp index f03efe2..8eac4f3 100644 --- a/mlpp/lin_alg/mlpp_vector.cpp +++ b/mlpp/lin_alg/mlpp_vector.cpp @@ -1,6 +1,21 @@ #include "mlpp_vector.h" +String MLPPVector::to_string() { + String str; + + str += "[MLPPVector: "; + + for (int x = 0; x < _size; ++x) { + str += String::num(_data[x]); + str += " "; + } + + str += "]"; + + return str; +} + void MLPPVector::_bind_methods() { ClassDB::bind_method(D_METHOD("push_back", "elem"), &MLPPVector::push_back); ClassDB::bind_method(D_METHOD("remove", "index"), &MLPPVector::remove); diff --git a/mlpp/lin_alg/mlpp_vector.h b/mlpp/lin_alg/mlpp_vector.h index 3f9c212..69b450d 100644 --- a/mlpp/lin_alg/mlpp_vector.h +++ b/mlpp/lin_alg/mlpp_vector.h @@ -105,6 +105,12 @@ public: void resize(int p_size) { _size = p_size; + if (_size == 0) { + memfree(_data); + _data = NULL; + return; + } + _data = (double *)memrealloc(_data, _size * sizeof(double)); CRASH_COND_MSG(!_data, "Out of memory"); } @@ -264,6 +270,8 @@ public: } } + String to_string(); + _FORCE_INLINE_ MLPPVector() { _size = 0; _data = NULL; diff --git a/test/mlpp_tests.cpp b/test/mlpp_tests.cpp index 34d2440..9d8d30b 100644 --- a/test/mlpp_tests.cpp +++ b/test/mlpp_tests.cpp @@ -9,6 +9,9 @@ #include #include +#include "../mlpp/lin_alg/mlpp_matrix.h" +#include "../mlpp/lin_alg/mlpp_vector.h" + #include "../mlpp/activation/activation.h" #include "../mlpp/ann/ann.h" #include "../mlpp/auto_encoder/auto_encoder.h" @@ -888,8 +891,8 @@ void MLPPTests::test_numerical_analysis() { std::vector> h = conv.harrisCornerDetection(A); - for (int i = 0; i < h.size(); i++) { - for (int j = 0; j < h[i].size(); j++) { + for (uint32_t i = 0; i < h.size(); i++) { + for (uint32_t j = 0; j < h[i].size(); j++) { std::cout << h[i][j] << " "; } std::cout << std::endl; @@ -918,6 +921,46 @@ void MLPPTests::test_support_vector_classification_kernel(bool ui) { std::cout << "True of false: linearly independent?: " << std::boolalpha << alg.linearIndependenceChecker(linearlyIndependentMat) << std::endl; } +void MLPPTests::test_mlpp_vector() { + std::vector a = { 4, 3, 1, 3 }; + + Ref rv; + rv.instance(); + rv->set_from_std_vector(a); + + Ref rv2; + rv2.instance(); + rv2->set_from_std_vector(a); + + is_approx_equals_vec(rv, rv2, "set_from_std_vectors test."); + + rv2->set_from_std_vector(a); + + is_approx_equals_vec(rv, rv2, "re-set_from_std_vectors test."); +} +void MLPPTests::test_mlpp_matrix() { + std::vector> A = { + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }; + + Ref rmat; + rmat.instance(); + rmat->set_from_std_vectors(A); + + Ref rmat2; + rmat2.instance(); + rmat2->set_from_std_vectors(A); + + is_approx_equals_mat(rmat, rmat2, "set_from_std_vectors test."); + + rmat2->set_from_std_vectors(A); + + is_approx_equals_mat(rmat, rmat2, "re-set_from_std_vectors test."); +} + void MLPPTests::is_approx_equalsd(double a, double b, const String &str) { if (!Math::is_equal_approx(a, b)) { ERR_PRINT("TEST FAILED: " + str + " Got: " + String::num(a) + " Should be: " + String::num(b)); @@ -1017,6 +1060,70 @@ IAEDMAT_FAILED: ERR_PRINT(fail_str); } +void MLPPTests::is_approx_equals_mat(Ref a, Ref b, const String &str) { + ERR_FAIL_COND(!a.is_valid()); + ERR_FAIL_COND(!b.is_valid()); + + int ds = a->data_size(); + + const double *aa = a->ptr(); + const double *bb = b->ptr(); + + if (a->size() != b->size()) { + goto IAEMAT_FAILED; + } + + ERR_FAIL_COND(!aa); + ERR_FAIL_COND(!bb); + + for (int i = 0; i < ds; ++i) { + if (!Math::is_equal_approx(aa[i], bb[i])) { + goto IAEMAT_FAILED; + } + } + + return; + +IAEMAT_FAILED: + + String fail_str = "TEST FAILED: "; + fail_str += str; + fail_str += "\nGot:\n"; + fail_str += a->to_string(); + fail_str += "\nShould be:\n"; + fail_str += b->to_string(); + + ERR_PRINT(fail_str); +} +void MLPPTests::is_approx_equals_vec(Ref a, Ref b, const String &str) { + ERR_FAIL_COND(!a.is_valid()); + ERR_FAIL_COND(!b.is_valid()); + + if (a->size() != b->size()) { + goto IAEDVEC_FAILED; + } + + for (int i = 0; i < a->size(); ++i) { + if (!Math::is_equal_approx(a->get_element(i), b->get_element(i))) { + goto IAEDVEC_FAILED; + } + } + + return; + +IAEDVEC_FAILED: + + String fail_str = "TEST FAILED: "; + fail_str += str; + fail_str += "\nGot:\n"; + fail_str += a->to_string(); + fail_str += "\nShould be:\n"; + fail_str += b->to_string(); + fail_str += "\n."; + + ERR_PRINT(fail_str); +} + MLPPTests::MLPPTests() { _breast_cancer_data_path = "res://datasets/BreastCancer.csv"; _breast_cancer_svm_data_path = "res://datasets/BreastCancerSVM.csv"; @@ -1077,4 +1184,7 @@ void MLPPTests::_bind_methods() { ClassDB::bind_method(D_METHOD("test_numerical_analysis"), &MLPPTests::test_numerical_analysis); ClassDB::bind_method(D_METHOD("test_support_vector_classification_kernel", "ui"), &MLPPTests::test_support_vector_classification_kernel, false); + + ClassDB::bind_method(D_METHOD("test_mlpp_vector"), &MLPPTests::test_mlpp_vector); + ClassDB::bind_method(D_METHOD("test_mlpp_matrix"), &MLPPTests::test_mlpp_matrix); } diff --git a/test/mlpp_tests.h b/test/mlpp_tests.h index 735d93d..dcdd96c 100644 --- a/test/mlpp_tests.h +++ b/test/mlpp_tests.h @@ -10,6 +10,9 @@ #include "core/string/ustring.h" +class MLPPMatrix; +class MLPPVector; + class MLPPTests : public Reference { GDCLASS(MLPPTests, Reference); @@ -58,10 +61,16 @@ public: void test_numerical_analysis(); void test_support_vector_classification_kernel(bool ui = false); + void test_mlpp_vector(); + void test_mlpp_matrix(); + void is_approx_equalsd(double a, double b, const String &str); void is_approx_equals_dvec(const Vector &a, const Vector &b, const String &str); void is_approx_equals_dmat(const Vector> &a, const Vector> &b, const String &str); + void is_approx_equals_mat(Ref a, Ref b, const String &str); + void is_approx_equals_vec(Ref a, Ref b, const String &str); + MLPPTests(); ~MLPPTests();