From 449e6f682fc3d5ccebcaef1ab7040a531826dce8 Mon Sep 17 00:00:00 2001 From: conrad Date: Tue, 10 Mar 2026 11:51:20 +1000 Subject: [PATCH] speedups for blank sparse matrices --- include/armadillo_bits/SpMat_meat.hpp | 202 ++++++++++++++++---------- 1 file changed, 125 insertions(+), 77 deletions(-) diff --git a/include/armadillo_bits/SpMat_meat.hpp b/include/armadillo_bits/SpMat_meat.hpp index 266f6d95..c17fed4d 100644 --- a/include/armadillo_bits/SpMat_meat.hpp +++ b/include/armadillo_bits/SpMat_meat.hpp @@ -688,15 +688,22 @@ SpMat::operator=(const SpMat& x) template inline SpMat& -SpMat::operator+=(const SpMat& x) +SpMat::operator+=(const SpMat& X) { arma_debug_sigprint(); sync_csc(); - SpMat out = (*this) + x; - - steal_mem(out); + if(X.n_nonzero == 0) + { + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition"); + } + else + { + SpMat tmp = (*this) + X; + + steal_mem(tmp); + } return *this; } @@ -706,15 +713,22 @@ SpMat::operator+=(const SpMat& x) template inline SpMat& -SpMat::operator-=(const SpMat& x) +SpMat::operator-=(const SpMat& X) { arma_debug_sigprint(); sync_csc(); - SpMat out = (*this) - x; - - steal_mem(out); + if(X.n_nonzero == 0) + { + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtraction"); + } + else + { + SpMat tmp = (*this) - X; + + steal_mem(tmp); + } return *this; } @@ -724,15 +738,15 @@ SpMat::operator-=(const SpMat& x) template inline SpMat& -SpMat::operator*=(const SpMat& y) +SpMat::operator*=(const SpMat& X) { arma_debug_sigprint(); sync_csc(); - SpMat z = (*this) * y; + SpMat tmp = (*this) * X; - steal_mem(z); + steal_mem(tmp); return *this; } @@ -743,15 +757,24 @@ SpMat::operator*=(const SpMat& y) template inline SpMat& -SpMat::operator%=(const SpMat& y) +SpMat::operator%=(const SpMat& X) { arma_debug_sigprint(); sync_csc(); - SpMat z = (*this) % y; - - steal_mem(z); + if(X.n_nonzero == 0) + { + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "element-wise multiplication"); + + (*this).zeros(); + } + else + { + SpMat tmp = (*this) % X; + + steal_mem(tmp); + } return *this; } @@ -1338,9 +1361,16 @@ SpMat::operator+=(const SpSubview& X) sync_csc(); - SpMat tmp = (*this) + X; - - steal_mem(tmp); + if(X.n_nonzero == 0) + { + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition"); + } + else + { + SpMat tmp = (*this) + X; + + steal_mem(tmp); + } return *this; } @@ -1356,64 +1386,82 @@ SpMat::operator-=(const SpSubview& X) sync_csc(); - SpMat tmp = (*this) - X; - - steal_mem(tmp); - - return *this; - } - - - -template -inline -SpMat& -SpMat::operator*=(const SpSubview& y) - { - arma_debug_sigprint(); - - sync_csc(); - - SpMat z = (*this) * y; - - steal_mem(z); - - return *this; - } - - - -template -inline -SpMat& -SpMat::operator%=(const SpSubview& x) - { - arma_debug_sigprint(); - - sync_csc(); - - SpMat tmp = (*this) % x; - - steal_mem(tmp); - - return *this; - } - - - -template -inline -SpMat& -SpMat::operator/=(const SpSubview& x) - { - arma_debug_sigprint(); - - arma_conform_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division"); - - // There is no pretty way to do this. - for(uword elem = 0; elem < n_elem; elem++) + if(X.n_nonzero == 0) { - at(elem) /= x(elem); + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtraction"); + } + else + { + SpMat tmp = (*this) - X; + + steal_mem(tmp); + } + + return *this; + } + + + +template +inline +SpMat& +SpMat::operator*=(const SpSubview& X) + { + arma_debug_sigprint(); + + sync_csc(); + + SpMat tmp = (*this) * X; + + steal_mem(tmp); + + return *this; + } + + + +template +inline +SpMat& +SpMat::operator%=(const SpSubview& X) + { + arma_debug_sigprint(); + + sync_csc(); + + if(X.n_nonzero == 0) + { + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "element-wise multiplication"); + + (*this).zeros(); + } + else + { + SpMat tmp = (*this) % X; + + steal_mem(tmp); + } + + return *this; + } + + + +template +inline +SpMat& +SpMat::operator/=(const SpSubview& X) + { + arma_debug_sigprint(); + + // NOTE: use of this function is not advised; it is implemented only for completeness + + arma_conform_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "element-wise division"); + + for(uword c = 0; c < n_cols; ++c) + for(uword r = 0; r < n_rows; ++r) + { + at(r, c) /= X.at(r, c); } return *this; @@ -1507,9 +1555,9 @@ SpMat::operator*=(const SpSubview_col_list& X) sync_csc(); - SpMat z = (*this) * X; + SpMat tmp = (*this) * X; - steal_mem(z); + steal_mem(tmp); return *this; }