From 17b2f55f2d15290e2ad881f5ee20f8d661be3902 Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 25 Apr 2023 14:06:12 +0200 Subject: [PATCH] MLPPTensor math api rework. --- mlpp/lin_alg/mlpp_tensor3.cpp | 610 +++++++++++++++++++++++++++------- mlpp/lin_alg/mlpp_tensor3.h | 50 ++- 2 files changed, 531 insertions(+), 129 deletions(-) diff --git a/mlpp/lin_alg/mlpp_tensor3.cpp b/mlpp/lin_alg/mlpp_tensor3.cpp index 9c496ce..4f443fd 100644 --- a/mlpp/lin_alg/mlpp_tensor3.cpp +++ b/mlpp/lin_alg/mlpp_tensor3.cpp @@ -424,55 +424,516 @@ void MLPPTensor3::set_from_image(const Ref &p_img, const int p_channels) img->unlock(); } -/* -Vector> MLPPTensor3::additionnvt(const Vector> &A, const Vector> &B) { - Vector> res; - res.resize(A.size()); +void MLPPTensor3::add(const Ref &B) { + ERR_FAIL_COND(!B.is_valid()); + ERR_FAIL_COND(_size != B->size()); - for (int i = 0; i < res.size(); i++) { - res.write[i] = additionnm(A[i], B[i]); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + c_ptr[i] += b_ptr[i]; + } +} +Ref MLPPTensor3::addn(const Ref &B) { + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + ERR_FAIL_COND_V(_size != B->size(), Ref()); + + Ref C; + C.instance(); + C->resize(_size); + + const real_t *a_ptr = ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = C->ptrw(); + + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + c_ptr[i] = a_ptr[i] + b_ptr[i]; + } + + return C; +} +void MLPPTensor3::addb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size3i a_size = A->size(); + ERR_FAIL_COND(a_size != B->size()); + + if (_size != a_size) { + resize(a_size); + } + + const real_t *a_ptr = A->ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + int data_size = A->data_size(); + + for (int i = 0; i < data_size; ++i) { + c_ptr[i] = a_ptr[i] + b_ptr[i]; + } +} + +void MLPPTensor3::sub(const Ref &B) { + ERR_FAIL_COND(!B.is_valid()); + ERR_FAIL_COND(_size != B->size()); + + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + c_ptr[i] -= b_ptr[i]; + } +} +Ref MLPPTensor3::subn(const Ref &B) { + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + ERR_FAIL_COND_V(_size != B->size(), Ref()); + + Ref C; + C.instance(); + C->resize(_size); + + const real_t *a_ptr = ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = C->ptrw(); + + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + c_ptr[i] = a_ptr[i] - b_ptr[i]; + } + + return C; +} +void MLPPTensor3::subb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size3i a_size = A->size(); + ERR_FAIL_COND(a_size != B->size()); + + if (_size != a_size) { + resize(a_size); + } + + const real_t *a_ptr = A->ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + int data_size = A->data_size(); + + for (int i = 0; i < data_size; ++i) { + c_ptr[i] = a_ptr[i] - b_ptr[i]; + } +} + +void MLPPTensor3::element_wise_division(const Ref &B) { + ERR_FAIL_COND(!B.is_valid()); + ERR_FAIL_COND(_size != B->size()); + + int ds = data_size(); + + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + for (int i = 0; i < ds; i++) { + c_ptr[i] /= b_ptr[i]; + } +} +Ref MLPPTensor3::element_wise_divisionn(const Ref &B) const { + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + ERR_FAIL_COND_V(_size != B->size(), Ref()); + + int ds = data_size(); + + Ref C; + C.instance(); + C->resize(_size); + + const real_t *a_ptr = ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = C->ptrw(); + + for (int i = 0; i < ds; i++) { + c_ptr[i] = a_ptr[i] / b_ptr[i]; + } + + return C; +} +void MLPPTensor3::element_wise_divisionb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size3i a_size = A->size(); + ERR_FAIL_COND(a_size != B->size()); + + if (a_size != _size) { + resize(a_size); + } + + int ds = data_size(); + + const real_t *a_ptr = A->ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + for (int i = 0; i < ds; i++) { + c_ptr[i] = a_ptr[i] / b_ptr[i]; + } +} + +void MLPPTensor3::sqrt() { + int ds = data_size(); + + real_t *out_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = Math::sqrt(out_ptr[i]); + } +} +Ref MLPPTensor3::sqrtn() const { + Ref out; + out.instance(); + out->resize(size()); + + int ds = data_size(); + + const real_t *a_ptr = ptr(); + real_t *out_ptr = out->ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = Math::sqrt(a_ptr[i]); + } + + return out; +} +void MLPPTensor3::sqrtb(const Ref &A) { + ERR_FAIL_COND(!A.is_valid()); + + Size3i a_size = A->size(); + + if (a_size != size()) { + resize(a_size); + } + + int ds = data_size(); + + const real_t *a_ptr = A->ptr(); + real_t *out_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = Math::sqrt(a_ptr[i]); + } +} + +void MLPPTensor3::exponentiate(real_t p) { + int ds = data_size(); + + real_t *out_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = Math::pow(out_ptr[i], p); + } +} +Ref MLPPTensor3::exponentiaten(real_t p) const { + Ref out; + out.instance(); + out->resize(size()); + + int ds = data_size(); + + const real_t *a_ptr = ptr(); + real_t *out_ptr = out->ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = Math::pow(a_ptr[i], p); + } + + return out; +} +void MLPPTensor3::exponentiateb(const Ref &A, real_t p) { + ERR_FAIL_COND(!A.is_valid()); + + Size3i a_size = A->size(); + + if (a_size != size()) { + resize(a_size); + } + + int ds = data_size(); + + const real_t *a_ptr = A->ptr(); + real_t *out_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = Math::pow(a_ptr[i], p); + } +} + +void MLPPTensor3::scalar_multiply(const real_t scalar) { + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + _data[i] *= scalar; + } +} +Ref MLPPTensor3::scalar_multiplyn(const real_t scalar) const { + Ref AN = duplicate(); + int ds = AN->data_size(); + real_t *an_ptr = AN->ptrw(); + + for (int i = 0; i < ds; ++i) { + an_ptr[i] *= scalar; + } + + return AN; +} +void MLPPTensor3::scalar_multiplyb(const real_t scalar, const Ref &A) { + ERR_FAIL_COND(!A.is_valid()); + + if (A->size() != _size) { + resize(A->size()); + } + + int ds = data_size(); + real_t *an_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + _data[i] = an_ptr[i] * scalar; + } +} + +void MLPPTensor3::scalar_add(const real_t scalar) { + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + _data[i] += scalar; + } +} +Ref MLPPTensor3::scalar_addn(const real_t scalar) const { + Ref AN = duplicate(); + int ds = AN->data_size(); + real_t *an_ptr = AN->ptrw(); + + for (int i = 0; i < ds; ++i) { + an_ptr[i] += scalar; + } + + return AN; +} +void MLPPTensor3::scalar_addb(const real_t scalar, const Ref &A) { + ERR_FAIL_COND(!A.is_valid()); + + if (A->size() != _size) { + resize(A->size()); + } + + int ds = data_size(); + real_t *an_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + _data[i] = an_ptr[i] + scalar; + } +} + +void MLPPTensor3::hadamard_product(const Ref &B) { + ERR_FAIL_COND(!B.is_valid()); + ERR_FAIL_COND(_size != B->size()); + + int ds = data_size(); + + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + for (int i = 0; i < ds; i++) { + c_ptr[i] = c_ptr[i] * b_ptr[i]; + } +} +Ref MLPPTensor3::hadamard_productn(const Ref &B) const { + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + ERR_FAIL_COND_V(_size != B->size(), Ref()); + + int ds = data_size(); + + Ref C; + C.instance(); + C->resize(_size); + + const real_t *a_ptr = ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = C->ptrw(); + + for (int i = 0; i < ds; i++) { + c_ptr[i] = a_ptr[i] * b_ptr[i]; + } + + return C; +} +void MLPPTensor3::hadamard_productb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size3i a_size = A->size(); + ERR_FAIL_COND(a_size != B->size()); + + if (a_size != _size) { + resize(a_size); + } + + int ds = data_size(); + + const real_t *a_ptr = A->ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + for (int i = 0; i < ds; i++) { + c_ptr[i] = a_ptr[i] * b_ptr[i]; + } +} + +void MLPPTensor3::max(const Ref &B) { + ERR_FAIL_COND(!B.is_valid()); + ERR_FAIL_COND(_size != B->size()); + + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + c_ptr[i] = MAX(c_ptr[i], b_ptr[i]); + } +} +Ref MLPPTensor3::maxn(const Ref &B) { + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + ERR_FAIL_COND_V(_size != B->size(), Ref()); + + Ref C; + C.instance(); + C->resize(_size); + + const real_t *a_ptr = ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = C->ptrw(); + + int ds = data_size(); + + for (int i = 0; i < ds; ++i) { + c_ptr[i] = MAX(a_ptr[i], b_ptr[i]); + } + + return C; +} +void MLPPTensor3::maxb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size3i a_size = A->size(); + ERR_FAIL_COND(a_size != B->size()); + + if (_size != a_size) { + resize(a_size); + } + + const real_t *a_ptr = A->ptr(); + const real_t *b_ptr = B->ptr(); + real_t *c_ptr = ptrw(); + + int data_size = A->data_size(); + + for (int i = 0; i < data_size; ++i) { + c_ptr[i] = MAX(a_ptr[i], b_ptr[i]); + } +} + +void MLPPTensor3::abs() { + int ds = data_size(); + + real_t *out_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = ABS(out_ptr[i]); + } +} +Ref MLPPTensor3::absn() const { + Ref out; + out.instance(); + out->resize(size()); + + int ds = data_size(); + + const real_t *a_ptr = ptr(); + real_t *out_ptr = out->ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = ABS(a_ptr[i]); + } + + return out; +} +void MLPPTensor3::absb(const Ref &A) { + ERR_FAIL_COND(!A.is_valid()); + + Size3i a_size = A->size(); + + if (a_size != size()) { + resize(a_size); + } + + int ds = data_size(); + + const real_t *a_ptr = A->ptr(); + real_t *out_ptr = ptrw(); + + for (int i = 0; i < ds; ++i) { + out_ptr[i] = ABS(a_ptr[i]); + } +} + +Ref MLPPTensor3::flatten() const { + int ds = data_size(); + + Ref res; + res.instance(); + res->resize(ds); + + real_t *res_ptr = res->ptrw(); + const real_t *a_ptr = ptr(); + + for (int i = 0; i < ds; ++i) { + res_ptr[i] = a_ptr[i]; } return res; } -*/ -/* -Vector> MLPPTensor3::element_wise_divisionnvnvt(const Vector> &A, const Vector> &B) { - Vector> res; - res.resize(A.size()); +void MLPPTensor3::flatteno(Ref out) const { + ERR_FAIL_COND(!out.is_valid()); - for (int i = 0; i < A.size(); i++) { - res.write[i] = element_wise_divisionnvnm(A[i], B[i]); + int ds = data_size(); + + if (unlikely(out->size() != ds)) { + out->resize(ds); } - return res; -} -*/ -/* -Vector> MLPPTensor3::sqrtnvt(const Vector> &A) { - Vector> res; - res.resize(A.size()); + real_t *res_ptr = out->ptrw(); + const real_t *a_ptr = ptr(); - for (int i = 0; i < A.size(); i++) { - res.write[i] = sqrtnm(A[i]); + for (int i = 0; i < ds; ++i) { + res_ptr[i] = a_ptr[i]; } - - return res; } -*/ + /* -Vector> MLPPTensor3::exponentiatenvt(const Vector> &A, real_t p) { - Vector> res; - res.resize(A.size()); - - for (int i = 0; i < A.size(); i++) { - res.write[i] = exponentiatenm(A[i], p); +real_t MLPPTensor3::norm_2(std::vector>> A) { + real_t sum = 0; + for (uint32_t i = 0; i < A.size(); i++) { + for (uint32_t j = 0; j < A[i].size(); j++) { + for (uint32_t k = 0; k < A[i][j].size(); k++) { + sum += A[i][j][k] * A[i][j][k]; + } + } } - - return res; + return Math::sqrt(sum); } - */ + /* std::vector> MLPPTensor3::tensor_vec_mult(std::vector>> A, std::vector b) { std::vector> C; @@ -489,87 +950,6 @@ std::vector> MLPPTensor3::tensor_vec_mult(std::vector MLPPTensor3::flatten(std::vector>> A) { - std::vector c; - for (uint32_t i = 0; i < A.size(); i++) { - std::vector flattenedVec = flatten(A[i]); - c.insert(c.end(), flattenedVec.begin(), flattenedVec.end()); - } - return c; -} -*/ - -/* -Vector> MLPPTensor3::scalar_multiplynvt(real_t scalar, Vector> A) { - for (int i = 0; i < A.size(); i++) { - A.write[i] = scalar_multiplynm(scalar, A[i]); - } - return A; -} -Vector> MLPPTensor3::scalar_addnvt(real_t scalar, Vector> A) { - for (int i = 0; i < A.size(); i++) { - A.write[i] = scalar_addnm(scalar, A[i]); - } - return A; -} - -Vector> MLPPTensor3::resizenvt(const Vector> &A, const Vector> &B) { - Vector> res; - res.resize(B.size()); - - for (int i = 0; i < res.size(); i++) { - Ref m; - m.instance(); - m->resize(B[i]->size()); - - res.write[i] = m; - } - - return res; -} -*/ - -//std::vector>> hadamard_product(std::vector>> A, std::vector>> B); - -/* -Vector> MLPPTensor3::maxnvt(const Vector> &A, const Vector> &B) { - Vector> res; - res.resize(A.size()); - - for (int i = 0; i < A.size(); i++) { - res.write[i] = maxnm(A[i], B[i]); - } - - return res; -} - -Vector> MLPPTensor3::absnvt(const Vector> &A) { - Vector> res; - res.resize(A.size()); - - for (int i = 0; i < A.size(); i++) { - res.write[i] = absnm(A[i]); - } - - return A; -} -*/ - -/* -real_t MLPPTensor3::norm_2(std::vector>> A) { - real_t sum = 0; - for (uint32_t i = 0; i < A.size(); i++) { - for (uint32_t j = 0; j < A[i].size(); j++) { - for (uint32_t k = 0; k < A[i][j].size(); k++) { - sum += A[i][j][k] * A[i][j][k]; - } - } - } - return Math::sqrt(sum); -} -*/ - /* // Bad implementation. Change this later. std::vector>> MLPPTensor3::vector_wise_tensor_product(std::vector>> A, std::vector> B) { diff --git a/mlpp/lin_alg/mlpp_tensor3.h b/mlpp/lin_alg/mlpp_tensor3.h index ba73fd0..6fa894e 100644 --- a/mlpp/lin_alg/mlpp_tensor3.h +++ b/mlpp/lin_alg/mlpp_tensor3.h @@ -30,7 +30,7 @@ public: } // TODO: Need to double check whether it's right to call the z axis feature map (probably not) - // TODO: Add helper methods for the other axes aswell (probably shouldn't have as extensive of a coverage as z), + // TODO: Add helper methods for the other axes aswell (probably shouldn't have as extensive of a coverage as z), // Only MLPPMatrix: get, add, set. // TODO: Add Image get, set helper methods to MLPPMatrix -> so the other axis helper methods can use them. // TODO: _FORCE_INLINE_ less big methods (Also do this in MLPPVEctor and MLPPMatrix) @@ -657,30 +657,52 @@ public: public: //math api - //Vector> additionnvt(const Vector> &A, const Vector> &B); + void add(const Ref &B); + Ref addn(const Ref &B); + void addb(const Ref &A, const Ref &B); - //Vector> element_wise_divisionnvnvt(const Vector> &A, const Vector> &B); + void sub(const Ref &B); + Ref subn(const Ref &B); + void subb(const Ref &A, const Ref &B); - //Vector> sqrtnvt(const Vector> &A); - - //Vector> exponentiatenvt(const Vector> &A, real_t p); + void element_wise_division(const Ref &B); + Ref element_wise_divisionn(const Ref &B) const; + void element_wise_divisionb(const Ref &A, const Ref &B); - //std::vector> tensor_vec_mult(std::vector>> A, std::vector b); + void sqrt(); + Ref sqrtn() const; + void sqrtb(const Ref &A); - //std::vector flatten(std::vector>> A); + void exponentiate(real_t p); + Ref exponentiaten(real_t p) const; + void exponentiateb(const Ref &A, real_t p); - //Vector> scalar_multiplynvt(real_t scalar, Vector> A); - //Vector> scalar_addnvt(real_t scalar, Vector> A); + 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); - //Vector> resizenvt(const Vector> &A, const Vector> &B); + 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); - //std::vector>> hadamard_product(std::vector>> A, std::vector>> B); + void hadamard_product(const Ref &B); + Ref hadamard_productn(const Ref &B) const; + void hadamard_productb(const Ref &A, const Ref &B); - //Vector> maxnvt(const Vector> &A, const Vector> &B); - //Vector> absnvt(const Vector> &A); + void max(const Ref &B); + Ref maxn(const Ref &B); + 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); + //std::vector> tensor_vec_mult(std::vector>> A, std::vector b); //std::vector>> vector_wise_tensor_product(std::vector>> A, std::vector> B); public: