diff --git a/mlpp/lin_alg/mlpp_matrix.cpp b/mlpp/lin_alg/mlpp_matrix.cpp index ce90b9e..b0e929c 100644 --- a/mlpp/lin_alg/mlpp_matrix.cpp +++ b/mlpp/lin_alg/mlpp_matrix.cpp @@ -246,18 +246,53 @@ void MLPPMatrix::multb(const Ref &A, const Ref &B) { } } -Ref MLPPMatrix::hadamard_productnm(const Ref &A, const Ref &B) { - ERR_FAIL_COND_V(!A.is_valid() || !B.is_valid(), Ref()); - Size2i a_size = A->size(); - ERR_FAIL_COND_V(a_size != B->size(), Ref()); +void MLPPMatrix::hadamard_product(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(); + + for (int i = 0; i < _size.y; i++) { + for (int j = 0; j < _size.x; j++) { + int ind_i_j = calculate_index(i, j); + c_ptr[ind_i_j] = c_ptr[ind_i_j] * b_ptr[ind_i_j]; + } + } +} +Ref MLPPMatrix::hadamard_productn(const Ref &B) const { + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + ERR_FAIL_COND_V(_size != B->size(), Ref()); Ref C; C.instance(); - C->resize(a_size); + 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 < _size.y; i++) { + for (int j = 0; j < _size.x; j++) { + int ind_i_j = calculate_index(i, j); + c_ptr[ind_i_j] = a_ptr[ind_i_j] * b_ptr[ind_i_j]; + } + } + + return C; +} +void MLPPMatrix::hadamard_productb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size2i a_size = A->size(); + ERR_FAIL_COND(a_size != B->size()); + + if (a_size != _size) { + resize(a_size); + } const real_t *a_ptr = A->ptr(); const real_t *b_ptr = B->ptr(); - real_t *c_ptr = C->ptrw(); + real_t *c_ptr = ptrw(); for (int i = 0; i < a_size.y; i++) { for (int j = 0; j < a_size.x; j++) { @@ -265,10 +300,9 @@ Ref MLPPMatrix::hadamard_productnm(const Ref &A, const R c_ptr[ind_i_j] = a_ptr[ind_i_j] * b_ptr[ind_i_j]; } } - - return C; } -Ref MLPPMatrix::kronecker_productnm(const Ref &A, const Ref &B) { + +void MLPPMatrix::kronecker_product(const Ref &B) { // [1,1,1,1] [1,2,3,4,5] // [1,1,1,1] [1,2,3,4,5] // [1,2,3,4,5] @@ -283,14 +317,102 @@ Ref MLPPMatrix::kronecker_productnm(const Ref &A, const // Resulting matrix: A.size() * B.size() // A[0].size() * B[0].size() - ERR_FAIL_COND_V(!A.is_valid() || !B.is_valid(), Ref()); - Size2i a_size = A->size(); + ERR_FAIL_COND(!B.is_valid()); + Size2i a_size = size(); + Size2i b_size = B->size(); + + Ref A = duplicate(); + + resize(Size2i(b_size.x * a_size.x, b_size.y * a_size.y)); + + const real_t *a_ptr = A->ptr(); + + Ref row_tmp; + row_tmp.instance(); + row_tmp->resize(b_size.x); + + for (int i = 0; i < _size.y; ++i) { + for (int j = 0; j < b_size.y; ++j) { + B->get_row_into_mlpp_vector(j, row_tmp); + + Vector> row; + for (int k = 0; k < _size.x; ++k) { + row.push_back(row_tmp->scalar_multiplyn(a_ptr[A->calculate_index(i, k)])); + } + + Ref flattened_row = row_tmp->flatten_vectorsn(row); + + set_row_mlpp_vector(i * b_size.y + j, flattened_row); + } + } +} +Ref MLPPMatrix::kronecker_productn(const Ref &B) const { + // [1,1,1,1] [1,2,3,4,5] + // [1,1,1,1] [1,2,3,4,5] + // [1,2,3,4,5] + + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + + // Resulting matrix: A.size() * B.size() + // A[0].size() * B[0].size() + + ERR_FAIL_COND_V(!B.is_valid(), Ref()); + Size2i a_size = size(); Size2i b_size = B->size(); Ref C; C.instance(); C->resize(Size2i(b_size.x * a_size.x, b_size.y * a_size.y)); + const real_t *a_ptr = ptr(); + + Ref row_tmp; + row_tmp.instance(); + row_tmp->resize(b_size.x); + + for (int i = 0; i < a_size.y; ++i) { + for (int j = 0; j < b_size.y; ++j) { + B->get_row_into_mlpp_vector(j, row_tmp); + + Vector> row; + for (int k = 0; k < a_size.x; ++k) { + row.push_back(row_tmp->scalar_multiplyn(a_ptr[calculate_index(i, k)])); + } + + Ref flattened_row = row_tmp->flatten_vectorsn(row); + + C->set_row_mlpp_vector(i * b_size.y + j, flattened_row); + } + } + + return C; +} +void MLPPMatrix::kronecker_productb(const Ref &A, const Ref &B) { + // [1,1,1,1] [1,2,3,4,5] + // [1,1,1,1] [1,2,3,4,5] + // [1,2,3,4,5] + + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + // [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] + + // Resulting matrix: A.size() * B.size() + // A[0].size() * B[0].size() + + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); + Size2i a_size = A->size(); + Size2i b_size = B->size(); + + resize(Size2i(b_size.x * a_size.x, b_size.y * a_size.y)); + const real_t *a_ptr = A->ptr(); Ref row_tmp; @@ -308,24 +430,58 @@ Ref MLPPMatrix::kronecker_productnm(const Ref &A, const Ref flattened_row = row_tmp->flatten_vectorsn(row); - C->set_row_mlpp_vector(i * b_size.y + j, flattened_row); + set_row_mlpp_vector(i * b_size.y + j, flattened_row); + } + } +} + +void MLPPMatrix::element_wise_division(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(); + + for (int i = 0; i < _size.y; i++) { + for (int j = 0; j < _size.x; j++) { + int ind_i_j = calculate_index(i, j); + c_ptr[ind_i_j] /= b_ptr[ind_i_j]; + } + } +} +Ref MLPPMatrix::element_wise_divisionn(const Ref &B) const { + 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(); + + for (int i = 0; i < _size.y; i++) { + for (int j = 0; j < _size.x; j++) { + int ind_i_j = calculate_index(i, j); + c_ptr[ind_i_j] = a_ptr[ind_i_j] / b_ptr[ind_i_j]; } } return C; } -Ref MLPPMatrix::element_wise_divisionnvnm(const Ref &A, const Ref &B) { - ERR_FAIL_COND_V(!A.is_valid() || !B.is_valid(), Ref()); +void MLPPMatrix::element_wise_divisionb(const Ref &A, const Ref &B) { + ERR_FAIL_COND(!A.is_valid() || !B.is_valid()); Size2i a_size = A->size(); - ERR_FAIL_COND_V(a_size != B->size(), Ref()); + ERR_FAIL_COND(a_size != B->size()); - Ref C; - C.instance(); - C->resize(a_size); + if (a_size != _size) { + resize(a_size); + } const real_t *a_ptr = A->ptr(); const real_t *b_ptr = B->ptr(); - real_t *c_ptr = C->ptrw(); + real_t *c_ptr = ptrw(); for (int i = 0; i < a_size.y; i++) { for (int j = 0; j < a_size.x; j++) { @@ -333,8 +489,6 @@ Ref MLPPMatrix::element_wise_divisionnvnm(const Ref &A, c_ptr[ind_i_j] = a_ptr[ind_i_j] / b_ptr[ind_i_j]; } } - - return C; } Ref MLPPMatrix::transposenm(const Ref &A) { diff --git a/mlpp/lin_alg/mlpp_matrix.h b/mlpp/lin_alg/mlpp_matrix.h index 1854532..1f5013a 100644 --- a/mlpp/lin_alg/mlpp_matrix.h +++ b/mlpp/lin_alg/mlpp_matrix.h @@ -601,9 +601,17 @@ public: Ref multn(const Ref &B) const; void multb(const Ref &A, const Ref &B); - Ref hadamard_productnm(const Ref &A, const Ref &B); - Ref kronecker_productnm(const Ref &A, const Ref &B); - Ref element_wise_divisionnvnm(const Ref &A, const Ref &B); + void hadamard_product(const Ref &B); + Ref hadamard_productn(const Ref &B) const; + void hadamard_productb(const Ref &A, const Ref &B); + + void kronecker_product(const Ref &B); + Ref kronecker_productn(const Ref &B) const; + void kronecker_productb(const Ref &A, const Ref &B); + + 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); Ref transposenm(const Ref &A); Ref scalar_multiplynm(real_t scalar, const Ref &A);