#ifndef MLPP_TENSOR3_H #define MLPP_TENSOR3_H /*************************************************************************/ /* mlpp_tensor3.h */ /*************************************************************************/ /* This file is part of: */ /* PMLPP Machine Learning Library */ /* https://github.com/Relintai/pmlpp */ /*************************************************************************/ /* Copyright (c) 2023-present Péter Magyar. */ /* Copyright (c) 2022-2023 Marc Melikyan */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #ifdef USING_SFW #include "sfw.h" #else #include "core/math/math_defs.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/math/vector2i.h" #include "core/os/memory.h" #include "core/object/resource.h" #endif #include "mlpp_matrix.h" #include "mlpp_vector.h" class Image; class MLPPTensor3 : public Resource { GDCLASS(MLPPTensor3, Resource); public: Array get_data(); void set_data(const Array &p_from); _FORCE_INLINE_ real_t *ptrw() { return _data; } _FORCE_INLINE_ const real_t *ptr() const { return _data; } void z_slice_add(const Vector &p_row); void z_slice_add_pool_vector(const PoolRealArray &p_row); void z_slice_add_mlpp_vector(const Ref &p_row); void z_slice_add_mlpp_matrix(const Ref &p_matrix); void z_slice_remove(int p_index); // Removes the item copying the last value into the position of the one to // remove. It's generally faster than `remove`. void z_slice_remove_unordered(int p_index); void z_slice_swap(int p_index_1, int p_index_2); _FORCE_INLINE_ void clear() { resize(Size3i()); } _FORCE_INLINE_ void reset() { if (_data) { memfree(_data); _data = NULL; _size = Size3i(); } } _FORCE_INLINE_ bool empty() const { return _size == Size3i(); } _FORCE_INLINE_ int z_slice_data_size() const { return _size.x * _size.y; } _FORCE_INLINE_ Size2i z_slice_size() const { return Size2i(_size.x, _size.y); } _FORCE_INLINE_ int data_size() const { return _size.x * _size.y * _size.z; } _FORCE_INLINE_ Size3i size() const { return _size; } void resize(const Size3i &p_size); void shape_set(const Size3i &p_size); _FORCE_INLINE_ int calculate_index(int p_index_z, int p_index_y, int p_index_x) const { return p_index_y * _size.x + p_index_x + _size.x * _size.y * p_index_z; } _FORCE_INLINE_ int calculate_z_slice_index(int p_index_z) const { return _size.x * _size.y * p_index_z; } _FORCE_INLINE_ const real_t &operator[](int p_index) const { CRASH_BAD_INDEX(p_index, data_size()); return _data[p_index]; } _FORCE_INLINE_ real_t &operator[](int p_index) { CRASH_BAD_INDEX(p_index, data_size()); return _data[p_index]; } _FORCE_INLINE_ real_t element_get_index(int p_index) const { ERR_FAIL_INDEX_V(p_index, data_size(), 0); return _data[p_index]; } _FORCE_INLINE_ void element_set_index(int p_index, real_t p_val) { ERR_FAIL_INDEX(p_index, data_size()); _data[p_index] = p_val; } _FORCE_INLINE_ real_t element_get(int p_index_z, int p_index_y, int p_index_x) const { ERR_FAIL_INDEX_V(p_index_x, _size.x, 0); ERR_FAIL_INDEX_V(p_index_y, _size.y, 0); ERR_FAIL_INDEX_V(p_index_z, _size.z, 0); return _data[p_index_y * _size.x + p_index_x + _size.x * _size.y * p_index_z]; } _FORCE_INLINE_ void element_set(int p_index_z, int p_index_y, int p_index_x, real_t p_val) { ERR_FAIL_INDEX(p_index_x, _size.x); ERR_FAIL_INDEX(p_index_y, _size.y); ERR_FAIL_INDEX(p_index_z, _size.z); _data[p_index_y * _size.x + p_index_x + _size.x * _size.y * p_index_z] = p_val; } Vector row_get_vector(int p_index_z, int p_index_y) const; PoolRealArray row_get_pool_vector(int p_index_z, int p_index_y) const; Ref row_get_mlpp_vector(int p_index_z, int p_index_y) const; void row_get_into_mlpp_vector(int p_index_z, int p_index_y, Ref target) const; void row_set_vector(int p_index_z, int p_index_y, const Vector &p_row); void row_set_pool_vector(int p_index_z, int p_index_y, const PoolRealArray &p_row); void row_set_mlpp_vector(int p_index_z, int p_index_y, const Ref &p_row); Vector z_slice_get_vector(int p_index_z) const; PoolRealArray z_slice_get_pool_vector(int p_index_z) const; Ref z_slice_get_mlpp_vector(int p_index_z) const; void z_slice_get_into_mlpp_vector(int p_index_z, Ref target) const; Ref z_slice_get_mlpp_matrix(int p_index_z) const; void z_slice_get_into_mlpp_matrix(int p_index_z, Ref target) const; void z_slice_set_vector(int p_index_z, const Vector &p_row); void z_slice_set_pool_vector(int p_index_z, const PoolRealArray &p_row); void z_slice_set_mlpp_vector(int p_index_z, const Ref &p_row); void z_slice_set_mlpp_matrix(int p_index_z, const Ref &p_mat); // TODO resize() need to be reworked for add and remove to work, in any other // direction than z void x_slice_add(const Ref &p_matrix); void // x_slice_remove(int p_index); void x_slice_get_into(int p_index_x, Ref target) const; Ref x_slice_get(int p_index_x) const; void x_slice_set(int p_index_x, const Ref &p_mat); // void y_slice_add(const Ref &p_matrix); // void y_slice_remove(int p_index); void y_slice_get_into(int p_index_y, Ref target) const; Ref y_slice_get(int p_index_y) const; void y_slice_set(int p_index_y, const Ref &p_mat); public: // Image api enum ImageChannelFlags { IMAGE_CHANNEL_FLAG_R = 1 << 0, IMAGE_CHANNEL_FLAG_G = 1 << 1, IMAGE_CHANNEL_FLAG_B = 1 << 2, IMAGE_CHANNEL_FLAG_A = 1 << 3, IMAGE_CHANNEL_FLAG_NONE = 0, IMAGE_CHANNEL_FLAG_RG = IMAGE_CHANNEL_FLAG_R | IMAGE_CHANNEL_FLAG_G, IMAGE_CHANNEL_FLAG_RGB = IMAGE_CHANNEL_FLAG_R | IMAGE_CHANNEL_FLAG_G | IMAGE_CHANNEL_FLAG_B, IMAGE_CHANNEL_FLAG_GB = IMAGE_CHANNEL_FLAG_G | IMAGE_CHANNEL_FLAG_B, IMAGE_CHANNEL_FLAG_GBA = IMAGE_CHANNEL_FLAG_G | IMAGE_CHANNEL_FLAG_B | IMAGE_CHANNEL_FLAG_A, IMAGE_CHANNEL_FLAG_BA = IMAGE_CHANNEL_FLAG_B | IMAGE_CHANNEL_FLAG_A, IMAGE_CHANNEL_FLAG_RGBA = IMAGE_CHANNEL_FLAG_R | IMAGE_CHANNEL_FLAG_G | IMAGE_CHANNEL_FLAG_B | IMAGE_CHANNEL_FLAG_A, }; void z_slices_add_image(const Ref &p_img, const int p_channels = IMAGE_CHANNEL_FLAG_RGBA); Ref z_slice_get_image(const int p_index_z) const; Ref z_slices_get_image(const int p_index_r = -1, const int p_index_g = -1, const int p_index_b = -1, const int p_index_a = -1) const; void z_slice_get_into_image( Ref p_target, const int p_index_z, const int p_target_channels = IMAGE_CHANNEL_FLAG_RGB) const; void z_slices_get_into_image(Ref p_target, const int p_index_r = -1, const int p_index_g = -1, const int p_index_b = -1, const int p_index_a = -1) const; void z_slice_set_image(const Ref &p_img, const int p_index_z, const int p_image_channel_flag = IMAGE_CHANNEL_FLAG_R); void z_slices_set_image(const Ref &p_img, const int p_index_r = -1, const int p_index_g = -1, const int p_index_b = -1, const int p_index_a = -1); void set_from_image(const Ref &p_img, const int p_channels = IMAGE_CHANNEL_FLAG_RGBA); // void x_slices_add_image(const Ref &p_img, const int p_channels = // IMAGE_CHANNEL_FLAG_RGBA); Ref x_slice_get_image(const int p_index_x) const; void x_slice_get_into_image( Ref p_target, const int p_index_x, const int p_target_channels = IMAGE_CHANNEL_FLAG_RGB) const; void x_slice_set_image(const Ref &p_img, const int p_index_x, const int p_image_channel_flag = IMAGE_CHANNEL_FLAG_R); // void y_slices_add_image(const Ref &p_img, const int p_channels = // IMAGE_CHANNEL_FLAG_RGBA); Ref y_slice_get_image(const int p_index_y) const; void y_slice_get_into_image( Ref p_target, const int p_index_y, const int p_target_channels = IMAGE_CHANNEL_FLAG_RGB) const; void y_slice_set_image(const Ref &p_img, const int p_index_y, const int p_image_channel_flag = IMAGE_CHANNEL_FLAG_R); public: // math api void add(const Ref &B); Ref addn(const Ref &B) const; void addb(const Ref &A, const Ref &B); void sub(const Ref &B); Ref subn(const Ref &B) const; void subb(const Ref &A, const Ref &B); void division_element_wise(const Ref &B); Ref division_element_wisen(const Ref &B) const; void division_element_wiseb(const Ref &A, const Ref &B); void sqrt(); Ref sqrtn() const; void sqrtb(const Ref &A); void exponentiate(real_t p); Ref exponentiaten(real_t p) const; void exponentiateb(const Ref &A, real_t p); void scalar_multiply(const real_t scalar); Ref scalar_multiplyn(const real_t scalar) const; void scalar_multiplyb(const real_t scalar, const Ref &A); void scalar_add(const real_t scalar); Ref scalar_addn(const real_t scalar) const; void scalar_addb(const real_t scalar, const Ref &A); void hadamard_product(const Ref &B); Ref hadamard_productn(const Ref &B) const; void hadamard_productb(const Ref &A, const Ref &B); void max(const Ref &B); Ref maxn(const Ref &B) const; void maxb(const Ref &A, const Ref &B); void abs(); Ref absn() const; void absb(const Ref &A); Ref flatten() const; void flatteno(Ref out) const; // real_t norm_2(std::vector>> A); Ref tensor_vec_mult(const Ref &b); // std::vector>> // vector_wise_tensor_product(std::vector>> A, // std::vector> B); public: void fill(real_t p_val); Vector to_flat_vector() const; PoolRealArray to_flat_pool_vector() const; Vector to_flat_byte_array() const; Ref duplicate_fast() const; void set_from_mlpp_tensor3(const Ref &p_from); void set_from_mlpp_tensor3r(const MLPPTensor3 &p_from); void set_from_mlpp_matrix(const Ref &p_from); void set_from_mlpp_matrixr(const MLPPMatrix &p_from); void set_from_mlpp_vectors(const Vector> &p_from); void set_from_mlpp_matricess(const Vector> &p_from); void set_from_mlpp_vectors_array(const Array &p_from); void set_from_mlpp_matrices_array(const Array &p_from); bool is_equal_approx(const Ref &p_with, real_t tolerance = static_cast(CMP_EPSILON)) const; String to_string(); MLPPTensor3(); MLPPTensor3(const MLPPMatrix &p_from); MLPPTensor3(const Array &p_from); ~MLPPTensor3(); // TODO: These are temporary std::vector to_flat_std_vector() const; void set_from_std_vectors( const std::vector>> &p_from); std::vector>> to_std_vector(); MLPPTensor3(const std::vector>> &p_from); protected: static void _bind_methods(); protected: Size3i _size; real_t *_data; }; VARIANT_ENUM_CAST(MLPPTensor3::ImageChannelFlags); #endif