diff --git a/include/armadillo_bits/arma_forward.hpp b/include/armadillo_bits/arma_forward.hpp index 1bad37f4..b35d64ef 100644 --- a/include/armadillo_bits/arma_forward.hpp +++ b/include/armadillo_bits/arma_forward.hpp @@ -129,6 +129,17 @@ class spop_htrans; class spop_vectorise_row; class spop_vectorise_col; +class spop_rel_lt_pre; +class spop_rel_lt_post; +class spop_rel_gt_pre; +class spop_rel_gt_post; +class spop_rel_lteq_pre; +class spop_rel_lteq_post; +class spop_rel_gteq_pre; +class spop_rel_gteq_post; +class spop_rel_eq; +class spop_rel_noteq; + class spglue_plus; class spglue_minus; class spglue_schur; diff --git a/include/armadillo_bits/fn_accu.hpp b/include/armadillo_bits/fn_accu.hpp index 821649c1..f775a7bb 100644 --- a/include/armadillo_bits/fn_accu.hpp +++ b/include/armadillo_bits/fn_accu.hpp @@ -1111,18 +1111,15 @@ accu(const SpOp& expr) -// optimisations for sparse relational operations - - -template +template arma_warn_unused inline uword -accu(const mtSpOp& X) +accu(const mtSpOp& X, const typename arma_spop_rel_only::result* junk1 = nullptr, const typename arma_not_cx::result* junk2 = nullptr) { arma_debug_sigprint(); - - // operation: accu(scalar < spmat) + arma_ignore(junk1); + arma_ignore(junk2); typedef typename T1::elem_type eT; @@ -1132,29 +1129,70 @@ accu(const mtSpOp& X) const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); + const eT zero = eT(0); + + // shortcuts + + if( (is_same_type::yes) && (k == zero) ) { return n_zeros; } + if( (is_same_type::yes) && (k == zero) ) { return P.get_n_nonzero(); } + // take into account all implicit zeros - uword count = (k < eT(0)) ? n_zeros : 0; + + bool use_n_zeros; + + if(is_same_type::yes) { use_n_zeros = (zero == k ); } + else if(is_same_type::yes) { use_n_zeros = (zero != k ); } + else if(is_same_type::yes) { use_n_zeros = (k < zero); } + else if(is_same_type::yes) { use_n_zeros = (zero < k ); } + else if(is_same_type::yes) { use_n_zeros = (k > zero); } + else if(is_same_type::yes) { use_n_zeros = (zero > k ); } + else if(is_same_type::yes) { use_n_zeros = (k <= zero); } + else if(is_same_type::yes) { use_n_zeros = (zero <= k ); } + else if(is_same_type::yes) { use_n_zeros = (k >= zero); } + else if(is_same_type::yes) { use_n_zeros = (zero >= k ); } + else { use_n_zeros = false; } + + uword count = (use_n_zeros) ? n_zeros : 0; typename SpProxy::const_iterator_type it = P.begin(); typename SpProxy::const_iterator_type it_end = P.end(); // take into account all non-zero elements - for(; it != it_end; ++it) { count += (k < (*it)) ? uword(1) : uword(0); } + for(; it != it_end; ++it) + { + const eT val = (*it); + + bool condition; + + if(is_same_type::yes) { condition = (val == k ); } + else if(is_same_type::yes) { condition = (val != k ); } + else if(is_same_type::yes) { condition = (k < val); } + else if(is_same_type::yes) { condition = (val < k ); } + else if(is_same_type::yes) { condition = (k > val); } + else if(is_same_type::yes) { condition = (val > k ); } + else if(is_same_type::yes) { condition = (k <= val); } + else if(is_same_type::yes) { condition = (val <= k ); } + else if(is_same_type::yes) { condition = (k >= val); } + else if(is_same_type::yes) { condition = (val >= k ); } + else { condition = false; } + + count += (condition) ? uword(1) : uword(0); + } return count; } -template +template arma_warn_unused inline uword -accu(const mtSpOp& X) +accu(const mtSpOp& X, const typename arma_spop_rel_only::result* junk1 = nullptr, const typename arma_cx_only::result* junk2 = nullptr) { arma_debug_sigprint(); - - // operation: accu(scalar > spmat) + arma_ignore(junk1); + arma_ignore(junk2); typedef typename T1::elem_type eT; @@ -1164,270 +1202,39 @@ accu(const mtSpOp& X) const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); + const eT zero = eT(0); + + // shortcuts + + if( (is_same_type::yes) && (k == zero) ) { return n_zeros; } + if( (is_same_type::yes) && (k == zero) ) { return P.get_n_nonzero(); } + // take into account all implicit zeros - uword count = (k > eT(0)) ? n_zeros : 0; + + bool use_n_zeros; + + if(is_same_type::yes) { use_n_zeros = (zero == k); } + else if(is_same_type::yes) { use_n_zeros = (zero != k); } + else { use_n_zeros = false; } + + uword count = (use_n_zeros) ? n_zeros : 0; typename SpProxy::const_iterator_type it = P.begin(); typename SpProxy::const_iterator_type it_end = P.end(); // take into account all non-zero elements - for(; it != it_end; ++it) { count += (k > (*it)) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(scalar <= spmat) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); - - // take into account all implicit zeros - uword count = (k <= eT(0)) ? n_zeros : 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // take into account all non-zero elements - for(; it != it_end; ++it) { count += (k <= (*it)) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(scalar >= spmat) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); - - // take into account all implicit zeros - uword count = (k >= eT(0)) ? n_zeros : 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // take into account all non-zero elements - for(; it != it_end; ++it) { count += (k >= (*it)) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(spmat < scalar) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); - - // take into account all implicit zeros - uword count = (eT(0) < k) ? n_zeros : 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // take into account all non-zero elements - for(; it != it_end; ++it) { count += ((*it) < k) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(spmat > scalar) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); - - // take into account all implicit zeros - uword count = (eT(0) > k) ? n_zeros : 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // take into account all non-zero elements - for(; it != it_end; ++it) { count += ((*it) > k) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(spmat <= scalar) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); - - // take into account all implicit zeros - uword count = (eT(0) <= k) ? n_zeros : 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // take into account all non-zero elements - for(; it != it_end; ++it) { count += ((*it) <= k) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(spmat >= scalar) ## - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - const uword n_zeros = P.get_n_elem() - P.get_n_nonzero(); - - // take into account all implicit zeros - uword count = (eT(0) >= k) ? n_zeros : 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // take into account all non-zero elements - for(; it != it_end; ++it) { count += ((*it) >= k) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(spmat == scalar) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - // accu(spmat == 0) -> number of zeros - if(k == eT(0)) { return P.get_n_elem() - P.get_n_nonzero(); } - - uword count = 0; - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - for(; it != it_end; ++it) { count += ((*it) == k) ? uword(1) : uword(0); } - - return count; - } - - - -template -arma_warn_unused -inline -uword -accu(const mtSpOp& X) - { - arma_debug_sigprint(); - - // operation: accu(spmat != scalar) - - typedef typename T1::elem_type eT; - - const eT k = X.aux; - - const SpProxy P(X.m); - - // accu(spmat != 0) -> number of non-zeros - if(k == eT(0)) { return P.get_n_nonzero(); } - - // start with worst-case scenario: all elements are not equal to k - uword count = P.get_n_elem(); - - typename SpProxy::const_iterator_type it = P.begin(); - typename SpProxy::const_iterator_type it_end = P.end(); - - // decrease the count by the number of elements that are equal to k - for(; it != it_end; ++it) { count -= ((*it) == k) ? uword(1) : uword(0); } + for(; it != it_end; ++it) + { + const eT val = (*it); + + bool condition; + + if(is_same_type::yes) { condition = (val == k); } + else if(is_same_type::yes) { condition = (val != k); } + else { condition = false; } + + count += (condition) ? uword(1) : uword(0); + } return count; } diff --git a/include/armadillo_bits/restrictors.hpp b/include/armadillo_bits/restrictors.hpp index 019a5f41..2cb1dabc 100644 --- a/include/armadillo_bits/restrictors.hpp +++ b/include/armadillo_bits/restrictors.hpp @@ -182,6 +182,21 @@ template<> struct arma_glue_rel_only< glue_rel_or > { typedef int result; }; +template struct arma_spop_rel_only { }; + +template<> struct arma_op_rel_only< spop_rel_lt_pre > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_lt_post > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_gt_pre > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_gt_post > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_lteq_pre > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_lteq_post > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_gteq_pre > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_gteq_post > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_eq > { typedef int result; }; +template<> struct arma_op_rel_only< spop_rel_noteq > { typedef int result; }; + + + template struct arma_Mat_Col_Row_only { }; template struct arma_Mat_Col_Row_only< Mat > { typedef Mat result; };