// SPDX-License-Identifier: Apache-2.0 // // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au) // Copyright 2008-2016 National ICT Australia (NICTA) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ------------------------------------------------------------------------ //! \addtogroup SpSubview_col_list //! @{ template inline SpSubview_col_list::~SpSubview_col_list() { arma_debug_sigprint(); } template arma_inline SpSubview_col_list::SpSubview_col_list ( const SpMat& in_m, const Base& in_ci ) : m (in_m ) , U_ci(in_ci.get_ref()) { arma_debug_sigprint(); const umat& ci = U_ci.M; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; arma_conform_check ( ( (ci.is_vec() == false) && (ci.is_empty() == false) ), "SpMat::cols(): given object must be a vector" ); for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; arma_conform_check_bounds( (i >= in_m.n_cols), "SpMat::cols(): index out of bounds" ); } } //! apply a functor to each element template template inline void SpSubview_col_list::for_each(functor F) { arma_debug_sigprint(); SpMat tmp(*this); tmp.for_each(F); (*this).operator=(tmp); } template template inline void SpSubview_col_list::for_each(functor F) const { arma_debug_sigprint(); const SpMat tmp(*this); tmp.for_each(F); } //! transform each element using a functor template template inline void SpSubview_col_list::transform(functor F) { arma_debug_sigprint(); SpMat tmp(*this); tmp.transform(F); (*this).operator=(tmp); } template inline void SpSubview_col_list::replace(const eT old_val, const eT new_val) { arma_debug_sigprint(); SpMat tmp(*this); tmp.replace(old_val, new_val); (*this).operator=(tmp); } template inline void SpSubview_col_list::clean(const typename get_pod_type::result threshold) { arma_debug_sigprint(); SpMat tmp(*this); tmp.clean(threshold); (*this).operator=(tmp); } template inline void SpSubview_col_list::fill(const eT val) { arma_debug_sigprint(); Mat tmp(m.n_rows, U_ci.M.n_elem, arma_nozeros_indicator()); tmp.fill(val); (*this).operator=(tmp); } template inline void SpSubview_col_list::zeros() { arma_debug_sigprint(); SpMat& m_local = const_cast< SpMat& >(m); const umat& ci = U_ci.M; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; m_local.sync_csc(); m_local.invalidate_cache(); for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; const uword col_n_nonzero = m_local.col_ptrs[i+1] - m_local.col_ptrs[i]; uword offset = m_local.col_ptrs[i]; for(uword j=0; j < col_n_nonzero; ++j) { access::rw(m_local.values[offset]) = eT(0); ++offset; } } m_local.remove_zeros(); } template inline void SpSubview_col_list::ones() { arma_debug_sigprint(); const Mat tmp(m.n_rows, U_ci.M.n_elem, fill::ones); (*this).operator=(tmp); } template inline void SpSubview_col_list::operator+= (const eT val) { arma_debug_sigprint(); const SpMat tmp1(*this); Mat tmp2(tmp1.n_rows, tmp1.n_cols, arma_nozeros_indicator()); tmp2.fill(val); const Mat tmp3 = tmp1 + tmp2; (*this).operator=(tmp3); } template inline void SpSubview_col_list::operator-= (const eT val) { arma_debug_sigprint(); const SpMat tmp1(*this); Mat tmp2(tmp1.n_rows, tmp1.n_cols, arma_nozeros_indicator()); tmp2.fill(val); const Mat tmp3 = tmp1 - tmp2; (*this).operator=(tmp3); } template inline void SpSubview_col_list::operator*= (const eT val) { arma_debug_sigprint(); SpMat& m_local = const_cast< SpMat& >(m); const umat& ci = U_ci.M; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; m_local.sync_csc(); m_local.invalidate_cache(); bool has_zero = false; for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; const uword col_n_nonzero = m_local.col_ptrs[i+1] - m_local.col_ptrs[i]; uword offset = m_local.col_ptrs[i]; for(uword j=0; j < col_n_nonzero; ++j) { eT& m_local_val = access::rw(m_local.values[offset]); m_local_val *= val; if(m_local_val == eT(0)) { has_zero = true; } ++offset; } } if(has_zero) { m_local.remove_zeros(); } } template inline void SpSubview_col_list::operator/= (const eT val) { arma_debug_sigprint(); const SpMat tmp1(*this); Mat tmp2(tmp1.n_rows, tmp1.n_cols, arma_nozeros_indicator()); tmp2.fill(val); const SpMat tmp3 = tmp1 / tmp2; (*this).operator=(tmp3); } template template inline void SpSubview_col_list::operator= (const Base& x) { arma_debug_sigprint(); const quasi_unwrap U(x.get_ref()); const Mat& X = U.M; SpMat& m_local = const_cast< SpMat& >(m); const umat& ci = U_ci.M; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; arma_conform_assert_same_size( m_local.n_rows, ci_n_elem, X.n_rows, X.n_cols, "SpMat::cols()" ); const uword X_n_elem = X.n_elem; const eT* X_mem = X.memptr(); uword X_n_nonzero = 0; for(uword i=0; i < X_n_elem; ++i) { X_n_nonzero += (X_mem[i] != eT(0)) ? uword(1) : uword(0); } SpMat Y(arma_reserve_indicator(), X.n_rows, m_local.n_cols, X_n_nonzero); uword count = 0; for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; for(uword row=0; row < X.n_rows; ++row) { const eT X_val = (*X_mem); ++X_mem; if(X_val != eT(0)) { access::rw(Y.row_indices[count]) = row; access::rw(Y.values [count]) = X_val; ++count; ++access::rw(Y.col_ptrs[i + 1]); } } } // fix the column pointers for(uword i = 0; i < Y.n_cols; ++i) { access::rw(Y.col_ptrs[i+1]) += Y.col_ptrs[i]; } (*this).zeros(); SpMat tmp = m_local + Y; m_local.steal_mem(tmp); } template template inline void SpSubview_col_list::operator+= (const Base& x) { arma_debug_sigprint(); const Mat tmp = SpMat(*this) + x.get_ref(); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator-= (const Base& x) { arma_debug_sigprint(); const Mat tmp = SpMat(*this) - x.get_ref(); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator%= (const Base& x) { arma_debug_sigprint(); const SpMat tmp = SpMat(*this) % x.get_ref(); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator/= (const Base& x) { arma_debug_sigprint(); const SpMat tmp = SpMat(*this) / x.get_ref(); (*this).operator=(tmp); } template inline void SpSubview_col_list::operator= (const SpSubview_col_list& x) { arma_debug_sigprint(); const SpMat tmp(x); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator= (const SpSubview_col_list& x) { arma_debug_sigprint(); const SpMat tmp(x); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator= (const SpBase& x) { arma_debug_sigprint(); const unwrap_spmat U(x.get_ref()); const SpMat& X = U.M; if(U.is_alias(m)) { const SpMat tmp(X); (*this).operator=(tmp); return; } SpMat& m_local = const_cast< SpMat& >(m); const umat& ci = U_ci.M; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; arma_conform_assert_same_size( m_local.n_rows, ci_n_elem, X.n_rows, X.n_cols, "SpMat::cols()" ); SpMat Y(arma_reserve_indicator(), X.n_rows, m_local.n_cols, X.n_nonzero); uword count = 0; for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; typename SpMat::const_col_iterator X_col_it = X.begin_col(ci_count); typename SpMat::const_col_iterator X_col_it_end = X.end_col(ci_count); while(X_col_it != X_col_it_end) { access::rw(Y.row_indices[count]) = X_col_it.row(); access::rw(Y.values [count]) = (*X_col_it); ++count; ++access::rw(Y.col_ptrs[i + 1]); ++X_col_it; } } // fix the column pointers for(uword i = 0; i < Y.n_cols; ++i) { access::rw(Y.col_ptrs[i+1]) += Y.col_ptrs[i]; } (*this).zeros(); SpMat tmp = m_local + Y; m_local.steal_mem(tmp); } template template inline void SpSubview_col_list::operator+= (const SpBase& x) { arma_debug_sigprint(); const SpMat tmp = SpMat(*this) + x.get_ref(); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator-= (const SpBase& x) { arma_debug_sigprint(); const SpMat tmp = SpMat(*this) - x.get_ref(); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator%= (const SpBase& x) { arma_debug_sigprint(); const SpMat tmp = SpMat(*this) % x.get_ref(); (*this).operator=(tmp); } template template inline void SpSubview_col_list::operator/= (const SpBase& x) { arma_debug_sigprint(); SpMat tmp(*this); tmp /= x.get_ref(); (*this).operator=(tmp); } // // template inline void SpSubview_col_list::extract(SpMat& out, const SpSubview_col_list& in) { arma_debug_sigprint(); // NOTE: aliasing is handled by SpMat::operator=(const SpSubview_col_list& in) const umat& ci = in.U_ci.M; const uword* ci_mem = ci.memptr(); const uword ci_n_elem = ci.n_elem; const SpMat& in_m = in.m; in_m.sync_csc(); uword total_n_nonzero = 0; for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; const uword col_n_nonzero = in_m.col_ptrs[i+1] - in_m.col_ptrs[i]; total_n_nonzero += col_n_nonzero; } out.reserve(in.m.n_rows, ci_n_elem, total_n_nonzero); uword out_n_nonzero = 0; uword out_col_count = 0; for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count) { const uword i = ci_mem[ci_count]; const uword col_n_nonzero = in_m.col_ptrs[i+1] - in_m.col_ptrs[i]; uword offset = in_m.col_ptrs[i]; for(uword j=0; j < col_n_nonzero; ++j) { const eT val = in_m.values [ offset ]; const uword row = in_m.row_indices[ offset ]; ++offset; access::rw(out.values [out_n_nonzero]) = val; access::rw(out.row_indices[out_n_nonzero]) = row; access::rw(out.col_ptrs[out_col_count+1])++; ++out_n_nonzero; } ++out_col_count; } // fix the column pointers for(uword i = 0; i < out.n_cols; ++i) { access::rw(out.col_ptrs[i+1]) += out.col_ptrs[i]; } } template inline void SpSubview_col_list::plus_inplace(SpMat& out, const SpSubview_col_list& in) { arma_debug_sigprint(); const SpMat tmp(in); out += tmp; } template inline void SpSubview_col_list::minus_inplace(SpMat& out, const SpSubview_col_list& in) { arma_debug_sigprint(); const SpMat tmp(in); out -= tmp; } template inline void SpSubview_col_list::schur_inplace(SpMat& out, const SpSubview_col_list& in) { arma_debug_sigprint(); const SpMat tmp(in); out %= tmp; } template inline void SpSubview_col_list::div_inplace(SpMat& out, const SpSubview_col_list& in) { arma_debug_sigprint(); const SpMat tmp(in); out /= tmp; } //! @}