diff --git a/mlpp/lin_alg/mlpp_matrix.cpp b/mlpp/lin_alg/mlpp_matrix.cpp index b4cdeeb..884faa4 100644 --- a/mlpp/lin_alg/mlpp_matrix.cpp +++ b/mlpp/lin_alg/mlpp_matrix.cpp @@ -1,12 +1,33 @@ #include "mlpp_matrix.h" -MLPPMatrix::MLPPMatrix() { -} - -MLPPMatrix::~MLPPMatrix() { -} - void MLPPMatrix::_bind_methods() { - //ClassDB::bind_method(D_METHOD(""), &MLPPMatrix::); + 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("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("clear"), &MLPPMatrix::clear); + ClassDB::bind_method(D_METHOD("reset"), &MLPPMatrix::reset); + ClassDB::bind_method(D_METHOD("empty"), &MLPPMatrix::empty); + + 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("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("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); } diff --git a/mlpp/lin_alg/mlpp_matrix.h b/mlpp/lin_alg/mlpp_matrix.h index b12cdd6..6562a81 100644 --- a/mlpp/lin_alg/mlpp_matrix.h +++ b/mlpp/lin_alg/mlpp_matrix.h @@ -1,17 +1,350 @@ #ifndef MLPP_MATRIX_H #define MLPP_MATRIX_H +#include "core/containers/pool_vector.h" +#include "core/containers/sort_array.h" +#include "core/containers/vector.h" +#include "core/error/error_macros.h" +#include "core/os/memory.h" + #include "core/object/reference.h" +#include "mlpp_vector.h" + class MLPPMatrix : public Reference { GDCLASS(MLPPMatrix, Reference); public: - MLPPMatrix(); - ~MLPPMatrix(); + double *ptr() { + return _data; + } + + const double *ptr() const { + return _data; + } + + _FORCE_INLINE_ void push_back(double p_elem) { + ++_size; + + _data = (double *)memrealloc(_data, _size * sizeof(double)); + CRASH_COND_MSG(!_data, "Out of memory"); + + _data[_size - 1] = p_elem; + } + + void remove(double p_index) { + ERR_FAIL_INDEX(p_index, _size); + + --_size; + + for (int i = p_index; i < _size; i++) { + _data[i] = _data[i + 1]; + } + + _data = (double *)memrealloc(_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, _size); + _size--; + + if (_size > p_index) { + _data[p_index] = _data[_size]; + } + + _data = (double *)memrealloc(_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); + } + } + + 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 < _size / 2; i++) { + SWAP(_data[i], _data[_size - i - 1]); + } + } + + _FORCE_INLINE_ void clear() { resize(0); } + _FORCE_INLINE_ void reset() { + clear(); + if (_data) { + memfree(_data); + _data = NULL; + _size = 0; + } + } + + _FORCE_INLINE_ bool empty() const { return _size == 0; } + _FORCE_INLINE_ int size() const { return _size; } + + void resize(int p_size) { + _size = p_size; + + _data = (double *)memrealloc(_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, _size); + return _data[p_index]; + } + _FORCE_INLINE_ double &operator[](int p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, _size); + return _data[p_index]; + } + + _FORCE_INLINE_ double get_element(int p_index) const { + CRASH_BAD_UNSIGNED_INDEX(p_index, _size); + return _data[p_index]; + } + _FORCE_INLINE_ double get_element(int p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, _size); + return _data[p_index]; + } + + _FORCE_INLINE_ real_t get_element_bind(int p_index) const { + CRASH_BAD_UNSIGNED_INDEX(p_index, _size); + return static_cast(_data[p_index]); + } + + _FORCE_INLINE_ void set_element(int p_index, double p_val) { + CRASH_BAD_UNSIGNED_INDEX(p_index, _size); + _data[p_index] = p_val; + } + + _FORCE_INLINE_ void set_element_bind(int p_index, real_t p_val) { + CRASH_BAD_UNSIGNED_INDEX(p_index, _size); + _data[p_index] = p_val; + } + + void fill(double p_val) { + for (int i = 0; i < _size; i++) { + _data[i] = p_val; + } + } + + void insert(int p_pos, double p_val) { + ERR_FAIL_INDEX(p_pos, _size + 1); + if (p_pos == _size) { + push_back(p_val); + } else { + resize(_size + 1); + for (int i = _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 < _size; i++) { + if (_data[i] == p_val) { + return i; + } + } + return -1; + } + + template + void sort_custom() { + int len = _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 < _size; i++) { + if (p_val < _data[i]) { + break; + } + } + insert(i, p_val); + } + + Vector to_vector() const { + Vector ret; + ret.resize(size()); + double *w = ret.ptrw(); + memcpy(w, _data, sizeof(double) * _size); + return ret; + } + + PoolRealArray to_pool_vector() const { + PoolRealArray pl; + if (size()) { + pl.resize(size()); + typename PoolRealArray::Write w = pl.write(); + real_t *dest = w.ptr(); + + for (int i = 0; i < size(); ++i) { + dest[i] = static_cast(_data[i]); + } + } + return pl; + } + + Vector to_byte_array() const { + Vector ret; + ret.resize(_size * sizeof(double)); + uint8_t *w = ret.ptrw(); + memcpy(w, _data, sizeof(double) * _size); + return ret; + } + + Ref duplicate() const { + Ref ret; + ret.instance(); + + ret->set_from_mlpp_matrixr(*this); + + return ret; + } + + _FORCE_INLINE_ void set_from_mlpp_matrixr(const MLPPMatrix &p_from) { + resize(p_from.size()); + for (int i = 0; i < p_from._size; i++) { + _data[i] = p_from._data[i]; + } + } + + _FORCE_INLINE_ void set_from_mlpp_vectorr(const MLPPVector &p_from) { + resize(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_vector(const Ref &p_from) { + ERR_FAIL_COND(!p_from.is_valid()); + resize(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_vector(const Vector &p_from) { + resize(p_from.size()); + for (int i = 0; i < _size; i++) { + _data[i] = p_from[i]; + } + } + + _FORCE_INLINE_ void set_from_pool_vector(const PoolRealArray &p_from) { + resize(p_from.size()); + typename PoolRealArray::Read r = p_from.read(); + for (int i = 0; i < _size; i++) { + _data[i] = r[i]; + } + } + + _FORCE_INLINE_ MLPPMatrix() { + _size = 0; + _data = NULL; + } + _FORCE_INLINE_ MLPPMatrix(const MLPPMatrix &p_from) { + _size = 0; + _data = NULL; + + resize(p_from.size()); + for (int i = 0; i < p_from._size; i++) { + _data[i] = p_from._data[i]; + } + } + + MLPPMatrix(const Vector &p_from) { + _size = 0; + _data = NULL; + + resize(p_from.size()); + for (int i = 0; i < _size; i++) { + _data[i] = p_from[i]; + } + } + + MLPPMatrix(const PoolRealArray &p_from) { + _size = 0; + _data = NULL; + + resize(p_from.size()); + typename PoolRealArray::Read r = p_from.read(); + for (int i = 0; i < _size; i++) { + _data[i] = r[i]; + } + } + + _FORCE_INLINE_ ~MLPPMatrix() { + if (_data) { + reset(); + } + } + + // TODO: These are temporary + std::vector to_std_vector() const { + std::vector ret; + ret.resize(size()); + double *w = &ret[0]; + memcpy(w, _data, sizeof(double) * _size); + return ret; + } + + _FORCE_INLINE_ void set_from_std_vector(const std::vector &p_from) { + resize(p_from.size()); + for (int i = 0; i < _size; i++) { + _data[i] = p_from[i]; + } + } + + MLPPMatrix(const std::vector &p_from) { + _size = 0; + _data = NULL; + + resize(p_from.size()); + for (int i = 0; i < _size; i++) { + _data[i] = p_from[i]; + } + } protected: static void _bind_methods(); + +protected: + int _size; + double *_data; }; #endif