From e32cae733028a8600b6a07a281d4d889307eda9b Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 27 Jan 2023 02:07:01 +0100 Subject: [PATCH] Proper initial MLPPMatrix implementation. --- mlpp/lin_alg/mlpp_matrix.cpp | 31 ++- mlpp/lin_alg/mlpp_matrix.h | 500 ++++++++++++++++++++++------------- 2 files changed, 336 insertions(+), 195 deletions(-) diff --git a/mlpp/lin_alg/mlpp_matrix.cpp b/mlpp/lin_alg/mlpp_matrix.cpp index 21c567d..5ec5747 100644 --- a/mlpp/lin_alg/mlpp_matrix.cpp +++ b/mlpp/lin_alg/mlpp_matrix.cpp @@ -2,33 +2,32 @@ #include "mlpp_matrix.h" void MLPPMatrix::_bind_methods() { - ClassDB::bind_method(D_METHOD("push_back", "elem"), &MLPPMatrix::push_back); - ClassDB::bind_method(D_METHOD("remove", "index"), &MLPPMatrix::remove); + ClassDB::bind_method(D_METHOD("add_row", "row"), &MLPPMatrix::add_row_pool_vector); + ClassDB::bind_method(D_METHOD("remove_row", "index"), &MLPPMatrix::remove_row); ClassDB::bind_method(D_METHOD("remove_unordered", "index"), &MLPPMatrix::remove_unordered); - ClassDB::bind_method(D_METHOD("erase", "val"), &MLPPMatrix::erase); - ClassDB::bind_method(D_METHOD("erase_multiple_unordered", "val"), &MLPPMatrix::erase_multiple_unordered); - ClassDB::bind_method(D_METHOD("invert"), &MLPPMatrix::invert); + ClassDB::bind_method(D_METHOD("swap_row", "index_1", "index_2"), &MLPPMatrix::swap_row); + ClassDB::bind_method(D_METHOD("clear"), &MLPPMatrix::clear); ClassDB::bind_method(D_METHOD("reset"), &MLPPMatrix::reset); ClassDB::bind_method(D_METHOD("empty"), &MLPPMatrix::empty); ClassDB::bind_method(D_METHOD("data_size"), &MLPPMatrix::data_size); - ClassDB::bind_method(D_METHOD("resize_data", "size"), &MLPPMatrix::resize_data); + ClassDB::bind_method(D_METHOD("size"), &MLPPMatrix::size); - ClassDB::bind_method(D_METHOD("get_element", "index"), &MLPPMatrix::get_element_bind); - ClassDB::bind_method(D_METHOD("set_element", "index", "val"), &MLPPMatrix::set_element_bind); + ClassDB::bind_method(D_METHOD("resize", "size"), &MLPPMatrix::resize); + + ClassDB::bind_method(D_METHOD("get_element", "index_x", "index_y"), &MLPPMatrix::get_element_bind); + ClassDB::bind_method(D_METHOD("set_element", "index_x", "index_y", "val"), &MLPPMatrix::set_element_bind); + + ClassDB::bind_method(D_METHOD("set_row_pool_vector", "index_y", "row"), &MLPPMatrix::set_row_pool_vector); ClassDB::bind_method(D_METHOD("fill", "val"), &MLPPMatrix::fill); - ClassDB::bind_method(D_METHOD("insert", "pos", "val"), &MLPPMatrix::insert); - ClassDB::bind_method(D_METHOD("find", "val", "from"), &MLPPMatrix::find, 0); - ClassDB::bind_method(D_METHOD("sort"), &MLPPMatrix::sort); - ClassDB::bind_method(D_METHOD("ordered_insert", "val"), &MLPPMatrix::ordered_insert); - ClassDB::bind_method(D_METHOD("to_pool_vector"), &MLPPMatrix::to_pool_vector); - ClassDB::bind_method(D_METHOD("to_byte_array"), &MLPPMatrix::to_byte_array); + ClassDB::bind_method(D_METHOD("to_flat_pool_vector"), &MLPPMatrix::to_flat_pool_vector); + ClassDB::bind_method(D_METHOD("to_flat_byte_array"), &MLPPMatrix::to_flat_byte_array); ClassDB::bind_method(D_METHOD("duplicate"), &MLPPMatrix::duplicate); - ClassDB::bind_method(D_METHOD("set_from_mlpp_vector", "from"), &MLPPMatrix::set_from_mlpp_vector); - ClassDB::bind_method(D_METHOD("set_from_pool_vector", "from"), &MLPPMatrix::set_from_pool_vector); + ClassDB::bind_method(D_METHOD("set_from_mlpp_vectors_array", "from"), &MLPPMatrix::set_from_mlpp_vectors_array); + ClassDB::bind_method(D_METHOD("set_from_arrays", "from"), &MLPPMatrix::set_from_arrays); } diff --git a/mlpp/lin_alg/mlpp_matrix.h b/mlpp/lin_alg/mlpp_matrix.h index 2090146..1e613f7 100644 --- a/mlpp/lin_alg/mlpp_matrix.h +++ b/mlpp/lin_alg/mlpp_matrix.h @@ -5,13 +5,16 @@ #include "core/containers/sort_array.h" #include "core/containers/vector.h" #include "core/error/error_macros.h" -#include "core/os/memory.h" #include "core/math/vector2i.h" +#include "core/os/memory.h" #include "core/object/reference.h" #include "mlpp_vector.h" +// Matrices are stored as rows first +// [x][y] + class MLPPMatrix : public Reference { GDCLASS(MLPPMatrix, Reference); @@ -24,186 +27,215 @@ public: return _data; } - _FORCE_INLINE_ void push_back(double p_elem) { - ++_data_size; - - _data = (double *)memrealloc(_data, _data_size * sizeof(double)); - CRASH_COND_MSG(!_data, "Out of memory"); - - _data[_data_size - 1] = p_elem; - } - - void remove(double p_index) { - ERR_FAIL_INDEX(p_index, _data_size); - - --_data_size; - - for (int i = p_index; i < _data_size; i++) { - _data[i] = _data[i + 1]; + _FORCE_INLINE_ void add_row(const Vector &p_row) { + if (_size.x == 0) { + _size.x = p_row.size(); } - _data = (double *)memrealloc(_data, _data_size * sizeof(double)); + ERR_FAIL_COND(_size.x != p_row.size()); + + int ci = data_size(); + + ++_size.y; + + _data = (double *)memrealloc(_data, data_size() * sizeof(double)); + CRASH_COND_MSG(!_data, "Out of memory"); + + const double *row_arr = p_row.ptr(); + + for (int i = 0; i < p_row.size(); ++i) { + _data[ci + i] = row_arr[i]; + } + } + + _FORCE_INLINE_ void add_row_pool_vector(const PoolRealArray &p_row) { + if (_size.x == 0) { + _size.x = p_row.size(); + } + + ERR_FAIL_COND(_size.x != p_row.size()); + + int ci = data_size(); + + ++_size.y; + + _data = (double *)memrealloc(_data, data_size() * sizeof(double)); + CRASH_COND_MSG(!_data, "Out of memory"); + + PoolRealArray::Read rread = p_row.read(); + const real_t *row_arr = rread.ptr(); + + for (int i = 0; i < p_row.size(); ++i) { + _data[ci + i] = row_arr[i]; + } + } + + void remove_row(double p_index) { + ERR_FAIL_INDEX(p_index, _size.y); + + --_size.y; + + int ds = data_size(); + + if (ds == 0) { + memfree(_data); + _data = NULL; + return; + } + + for (int i = p_index * _size.x; i < ds; ++i) { + _data[i] = _data[i + _size.x]; + } + + _data = (double *)memrealloc(_data, data_size() * sizeof(double)); CRASH_COND_MSG(!_data, "Out of memory"); } // Removes the item copying the last value into the position of the one to // remove. It's generally faster than `remove`. void remove_unordered(int p_index) { - ERR_FAIL_INDEX(p_index, _data_size); - _data_size--; + ERR_FAIL_INDEX(p_index, _size.y); - if (_data_size > p_index) { - _data[p_index] = _data[_data_size]; + --_size.y; + + int ds = data_size(); + + if (ds == 0) { + memfree(_data); + _data = NULL; + return; } - _data = (double *)memrealloc(_data, _data_size * sizeof(double)); + int start_ind = p_index * _size.x; + int end_ind = (p_index + 1) * _size.x; + + for (int i = start_ind; i < end_ind; ++i) { + _data[i] = _data[ds + i]; + } + + _data = (double *)memrealloc(_data, data_size() * sizeof(double)); CRASH_COND_MSG(!_data, "Out of memory"); } - void erase(const double &p_val) { - int idx = find(p_val); - if (idx >= 0) { - remove(idx); + void swap_row(int p_index_1, int p_index_2) { + ERR_FAIL_INDEX(p_index_1, _size.y); + ERR_FAIL_INDEX(p_index_2, _size.y); + + int ind1_start = p_index_1 * _size.x; + int ind2_start = p_index_2 * _size.x; + + for (int i = 0; i < _size.x; ++i) { + SWAP(_data[ind1_start + i], _data[ind2_start + i]); } } - int erase_multiple_unordered(const double &p_val) { - int from = 0; - int count = 0; - while (true) { - int64_t idx = find(p_val, from); - - if (idx == -1) { - break; - } - remove_unordered(idx); - from = idx; - count++; - } - return count; - } - - void invert() { - for (int i = 0; i < _data_size / 2; i++) { - SWAP(_data[i], _data[_data_size - i - 1]); - } - } - - _FORCE_INLINE_ void clear() { resize_data(0); } + _FORCE_INLINE_ void clear() { resize(Size2i()); } _FORCE_INLINE_ void reset() { clear(); if (_data) { memfree(_data); _data = NULL; - _data_size = 0; + _size = Vector2i(); } } - _FORCE_INLINE_ bool empty() const { return _data_size == 0; } - _FORCE_INLINE_ int data_size() const { return _data_size; } + _FORCE_INLINE_ bool empty() const { return data_size() == 0; } + _FORCE_INLINE_ int data_size() const { return _size.x * _size.y; } + _FORCE_INLINE_ Size2i size() const { return _size; } - void resize_data(int p_size) { - _data_size = p_size; + void resize(const Size2i &p_size) { + _size = p_size; - _data = (double *)memrealloc(_data, _data_size * sizeof(double)); + _data = (double *)memrealloc(_data, data_size() * sizeof(double)); CRASH_COND_MSG(!_data, "Out of memory"); } _FORCE_INLINE_ const double &operator[](int p_index) const { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); + CRASH_BAD_INDEX(p_index, data_size()); return _data[p_index]; } _FORCE_INLINE_ double &operator[](int p_index) { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); + CRASH_BAD_INDEX(p_index, data_size()); return _data[p_index]; } - _FORCE_INLINE_ double get_element(int p_index) const { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); - return _data[p_index]; + _FORCE_INLINE_ double get_element(int p_index_x, int p_index_y) const { + ERR_FAIL_INDEX_V(p_index_x, _size.x, 0); + ERR_FAIL_INDEX_V(p_index_y, _size.y, 0); + + return _data[p_index_x * p_index_y]; } - _FORCE_INLINE_ double get_element(int p_index) { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); - return _data[p_index]; + _FORCE_INLINE_ double get_element(int p_index_x, int p_index_y) { + ERR_FAIL_INDEX_V(p_index_x, _size.x, 0); + ERR_FAIL_INDEX_V(p_index_y, _size.y, 0); + + return _data[p_index_x * p_index_y]; } - _FORCE_INLINE_ real_t get_element_bind(int p_index) const { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); - return static_cast(_data[p_index]); + _FORCE_INLINE_ real_t get_element_bind(int p_index_x, int p_index_y) const { + ERR_FAIL_INDEX_V(p_index_x, _size.x, 0); + ERR_FAIL_INDEX_V(p_index_y, _size.y, 0); + + return static_cast(_data[p_index_x * p_index_y]); } - _FORCE_INLINE_ void set_element(int p_index, double p_val) { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); - _data[p_index] = p_val; + _FORCE_INLINE_ void set_element(int p_index_x, int p_index_y, double p_val) { + ERR_FAIL_INDEX(p_index_x, _size.x); + ERR_FAIL_INDEX(p_index_y, _size.y); + + _data[p_index_x * p_index_y] = p_val; } - _FORCE_INLINE_ void set_element_bind(int p_index, real_t p_val) { - CRASH_BAD_UNSIGNED_INDEX(p_index, _data_size); - _data[p_index] = p_val; + _FORCE_INLINE_ void set_element_bind(int p_index_x, int p_index_y, real_t p_val) { + ERR_FAIL_INDEX(p_index_x, _size.x); + ERR_FAIL_INDEX(p_index_y, _size.y); + + _data[p_index_x * p_index_y] = p_val; + } + + _FORCE_INLINE_ void set_row_vector(int p_index_y, const Vector &p_row) { + ERR_FAIL_COND(p_row.size() != _size.x); + ERR_FAIL_INDEX(p_index_y, _size.y); + + int ind_start = p_index_y * _size.x; + + const double *row_ptr = p_row.ptr(); + + for (int i = 0; i < _size.x; ++i) { + _data[ind_start + i] = row_ptr[i]; + } + } + + _FORCE_INLINE_ void set_row_pool_vector(int p_index_y, const PoolRealArray &p_row) { + ERR_FAIL_COND(p_row.size() != _size.x); + ERR_FAIL_INDEX(p_index_y, _size.y); + + int ind_start = p_index_y * _size.x; + + PoolRealArray::Read r = p_row.read(); + const real_t *row_ptr = r.ptr(); + + for (int i = 0; i < _size.x; ++i) { + _data[ind_start + i] = row_ptr[i]; + } } void fill(double p_val) { - for (int i = 0; i < _data_size; i++) { + int ds = data_size(); + for (int i = 0; i < ds; i++) { _data[i] = p_val; } } - void insert(int p_pos, double p_val) { - ERR_FAIL_INDEX(p_pos, _data_size + 1); - if (p_pos == _data_size) { - push_back(p_val); - } else { - resize_data(_data_size + 1); - for (int i = _data_size - 1; i > p_pos; i--) { - _data[i] = _data[i - 1]; - } - _data[p_pos] = p_val; - } - } - - int find(const double &p_val, int p_from = 0) const { - for (int i = p_from; i < _data_size; i++) { - if (_data[i] == p_val) { - return i; - } - } - return -1; - } - - template - void sort_custom() { - int len = _data_size; - if (len == 0) { - return; - } - - SortArray sorter; - sorter.sort(_data, len); - } - - void sort() { - sort_custom<_DefaultComparator>(); - } - - void ordered_insert(double p_val) { - int i; - for (i = 0; i < _data_size; i++) { - if (p_val < _data[i]) { - break; - } - } - insert(i, p_val); - } - - Vector to_vector() const { + Vector to_flat_vector() const { Vector ret; ret.resize(data_size()); double *w = ret.ptrw(); - memcpy(w, _data, sizeof(double) * _data_size); + memcpy(w, _data, sizeof(double) * data_size()); return ret; } - PoolRealArray to_pool_vector() const { + PoolRealArray to_flat_pool_vector() const { PoolRealArray pl; if (data_size()) { pl.resize(data_size()); @@ -217,11 +249,11 @@ public: return pl; } - Vector to_byte_array() const { + Vector to_flat_byte_array() const { Vector ret; - ret.resize(_data_size * sizeof(double)); + ret.resize(data_size() * sizeof(double)); uint8_t *w = ret.ptrw(); - memcpy(w, _data, sizeof(double) * _data_size); + memcpy(w, _data, sizeof(double) * data_size()); return ret; } @@ -235,77 +267,159 @@ public: } _FORCE_INLINE_ void set_from_mlpp_matrixr(const MLPPMatrix &p_from) { - resize_data(p_from.data_size()); - for (int i = 0; i < p_from._data_size; i++) { + resize(p_from.size()); + for (int i = 0; i < p_from.data_size(); i++) { _data[i] = p_from._data[i]; } } - _FORCE_INLINE_ void set_from_mlpp_vectorr(const MLPPVector &p_from) { - resize_data(p_from.size()); - const double *from_ptr = p_from.ptr(); - for (int i = 0; i < p_from.size(); i++) { - _data[i] = from_ptr[i]; + _FORCE_INLINE_ void set_from_mlpp_vectors(const Vector> &p_from) { + if (p_from.size() == 0) { + reset(); + return; + } + + if (!p_from[0].is_valid()) { + reset(); + return; + } + + resize(Size2i(p_from[0]->size(), p_from.size())); + + if (data_size() == 0) { + reset(); + return; + } + + for (int i = 0; i < p_from.size(); ++i) { + const Ref &r = p_from[i]; + + ERR_CONTINUE(!r.is_valid()); + ERR_CONTINUE(r->size() != _size.x); + + int start_index = i * _size.x; + + const double *from_ptr = r->ptr(); + for (int j = 0; j < _size.x; j++) { + _data[start_index + j] = from_ptr[j]; + } } } - _FORCE_INLINE_ void set_from_mlpp_vector(const Ref &p_from) { - ERR_FAIL_COND(!p_from.is_valid()); - resize_data(p_from->size()); - const double *from_ptr = p_from->ptr(); - for (int i = 0; i < p_from->size(); i++) { - _data[i] = from_ptr[i]; + _FORCE_INLINE_ void set_from_mlpp_vectors_array(const Array &p_from) { + if (p_from.size() == 0) { + reset(); + return; + } + + Ref v0 = p_from[0]; + + if (!v0.is_valid()) { + reset(); + return; + } + + resize(Size2i(v0->size(), p_from.size())); + + if (data_size() == 0) { + reset(); + return; + } + + for (int i = 0; i < p_from.size(); ++i) { + Ref r = p_from[i]; + + ERR_CONTINUE(!r.is_valid()); + ERR_CONTINUE(r->size() != _size.x); + + int start_index = i * _size.x; + + const double *from_ptr = r->ptr(); + for (int j = 0; j < _size.x; j++) { + _data[start_index + j] = from_ptr[j]; + } } } - _FORCE_INLINE_ void set_from_vector(const Vector &p_from) { - resize_data(p_from.size()); - for (int i = 0; i < _data_size; i++) { - _data[i] = p_from[i]; + _FORCE_INLINE_ void set_from_vectors(const Vector> &p_from) { + if (p_from.size() == 0) { + reset(); + return; + } + + resize(Size2i(p_from[0].size(), p_from.size())); + + if (data_size() == 0) { + reset(); + return; + } + + for (int i = 0; i < p_from.size(); ++i) { + const Vector &r = p_from[i]; + + ERR_CONTINUE(r.size() != _size.x); + + int start_index = i * _size.x; + + const double *from_ptr = r.ptr(); + for (int j = 0; j < _size.x; j++) { + _data[start_index + j] = from_ptr[j]; + } } } - _FORCE_INLINE_ void set_from_pool_vector(const PoolRealArray &p_from) { - resize_data(p_from.size()); - typename PoolRealArray::Read r = p_from.read(); - for (int i = 0; i < _data_size; i++) { - _data[i] = r[i]; + _FORCE_INLINE_ void set_from_arrays(const Array &p_from) { + if (p_from.size() == 0) { + reset(); + return; + } + + PoolRealArray p0arr = p_from[0]; + + resize(Size2i(p0arr.size(), p_from.size())); + + if (data_size() == 0) { + reset(); + return; + } + + for (int i = 0; i < p_from.size(); ++i) { + PoolRealArray r = p_from[i]; + + ERR_CONTINUE(r.size() != _size.x); + + int start_index = i * _size.x; + + PoolRealArray::Read read = r.read(); + const real_t *from_ptr = read.ptr(); + for (int j = 0; j < _size.x; j++) { + _data[start_index + j] = from_ptr[j]; + } } } _FORCE_INLINE_ MLPPMatrix() { - _data_size = 0; _data = NULL; } _FORCE_INLINE_ MLPPMatrix(const MLPPMatrix &p_from) { - _data_size = 0; _data = NULL; - resize_data(p_from.data_size()); - for (int i = 0; i < p_from._data_size; i++) { + resize(p_from.size()); + for (int i = 0; i < p_from.data_size(); ++i) { _data[i] = p_from._data[i]; } } - MLPPMatrix(const Vector &p_from) { - _data_size = 0; + MLPPMatrix(const Vector> &p_from) { _data = NULL; - resize_data(p_from.size()); - for (int i = 0; i < _data_size; i++) { - _data[i] = p_from[i]; - } + set_from_vectors(p_from); } - MLPPMatrix(const PoolRealArray &p_from) { - _data_size = 0; + MLPPMatrix(const Array &p_from) { _data = NULL; - resize_data(p_from.size()); - typename PoolRealArray::Read r = p_from.read(); - for (int i = 0; i < _data_size; i++) { - _data[i] = r[i]; - } + set_from_arrays(p_from); } _FORCE_INLINE_ ~MLPPMatrix() { @@ -315,29 +429,58 @@ public: } // TODO: These are temporary - std::vector to_std_vector() const { + std::vector to_flat_std_vector() const { std::vector ret; ret.resize(data_size()); double *w = &ret[0]; - memcpy(w, _data, sizeof(double) * _data_size); + memcpy(w, _data, sizeof(double) * data_size()); return ret; } - _FORCE_INLINE_ void set_from_std_vector(const std::vector &p_from) { - resize_data(p_from.size()); - for (int i = 0; i < _data_size; i++) { - _data[i] = p_from[i]; + _FORCE_INLINE_ void set_from_std_vectors(const std::vector> &p_from) { + if (p_from.size() == 0) { + reset(); + return; + } + + resize(Size2i(p_from[0].size(), p_from.size())); + + if (data_size() == 0) { + reset(); + return; + } + + for (uint32_t i = 0; i < p_from.size(); ++i) { + const std::vector &r = p_from[i]; + + ERR_CONTINUE(r.size() != static_cast(_size.x)); + + int start_index = i * _size.x; + + const double *from_ptr = &r[0]; + for (int j = 0; j < _size.x; j++) { + _data[start_index + j] = from_ptr[j]; + } } } - MLPPMatrix(const std::vector &p_from) { - _data_size = 0; + _FORCE_INLINE_ void set_row_std_vector(int p_index_y, const std::vector &p_row) { + ERR_FAIL_COND(p_row.size() != static_cast(_size.x)); + ERR_FAIL_INDEX(p_index_y, _size.y); + + int ind_start = p_index_y * _size.x; + + const double *row_ptr = &p_row[0]; + + for (int i = 0; i < _size.x; ++i) { + _data[ind_start + i] = row_ptr[i]; + } + } + + MLPPMatrix(const std::vector> &p_from) { _data = NULL; - resize_data(p_from.size()); - for (int i = 0; i < _data_size; i++) { - _data[i] = p_from[i]; - } + set_from_std_vectors(p_from); } protected: @@ -345,7 +488,6 @@ protected: protected: Size2i _size; - int _data_size; double *_data; };