// Copyright (C) 2012-2015 National ICT Australia (NICTA) // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------- // // Written by Conrad Sanderson - http://conradsanderson.id.au //! \addtogroup subview_each //! @{ // // // subview_each_common template inline subview_each_common::subview_each_common(const parent& in_P) : P(in_P) { arma_extra_debug_sigprint(); } template arma_inline const Mat& subview_each_common::get_mat_ref_helper(const Mat& X) const { return X; } template arma_inline const Mat& subview_each_common::get_mat_ref_helper(const subview& X) const { return X.m; } template arma_inline const Mat& subview_each_common::get_mat_ref() const { return get_mat_ref_helper(P); } template inline void subview_each_common::check_size(const Mat& A) const { if(arma_config::debug == true) { if(mode == 0) { if( (A.n_rows != P.n_rows) || (A.n_cols != 1) ) { arma_stop( incompat_size_string(A) ); } } else { if( (A.n_rows != 1) || (A.n_cols != P.n_cols) ) { arma_stop( incompat_size_string(A) ); } } } } template arma_cold inline const std::string subview_each_common::incompat_size_string(const Mat& A) const { std::stringstream tmp; if(mode == 0) { tmp << "each_col(): incompatible size; expected " << P.n_rows << "x1" << ", got " << A.n_rows << 'x' << A.n_cols; } else { tmp << "each_row(): incompatible size; expected 1x" << P.n_cols << ", got " << A.n_rows << 'x' << A.n_cols; } return tmp.str(); } // // // subview_each1 template inline subview_each1::~subview_each1() { arma_extra_debug_sigprint(); } template inline subview_each1::subview_each1(const parent& in_P) : subview_each_common::subview_each_common(in_P) { arma_extra_debug_sigprint(); } template template inline void subview_each1::operator= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const eT* A_mem = A.memptr(); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { arrayops::copy( p.colptr(i), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_set( p.colptr(i), A_mem[i], p_n_rows); } } } template template inline void subview_each1::operator+= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const eT* A_mem = A.memptr(); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_plus( p.colptr(i), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_plus( p.colptr(i), A_mem[i], p_n_rows); } } } template template inline void subview_each1::operator-= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const eT* A_mem = A.memptr(); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_minus( p.colptr(i), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_minus( p.colptr(i), A_mem[i], p_n_rows); } } } template template inline void subview_each1::operator%= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const eT* A_mem = A.memptr(); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_mul( p.colptr(i), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_mul( p.colptr(i), A_mem[i], p_n_rows); } } } template template inline void subview_each1::operator/= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const eT* A_mem = A.memptr(); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_div( p.colptr(i), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < p_n_cols; ++i) { arrayops::inplace_div( p.colptr(i), A_mem[i], p_n_rows); } } } // // // subview_each2 template inline subview_each2::~subview_each2() { arma_extra_debug_sigprint(); } template inline subview_each2::subview_each2(const parent& in_P, const Base& in_indices) : subview_each_common::subview_each_common(in_P) , base_indices(in_indices) { arma_extra_debug_sigprint(); } template inline void subview_each2::check_indices(const Mat& indices) const { if(mode == 0) { arma_debug_check( ((indices.is_vec() == false) && (indices.is_empty() == false)), "each_col(): list of indices must be a vector" ); } else { arma_debug_check( ((indices.is_vec() == false) && (indices.is_empty() == false)), "each_row(): list of indices must be a vector" ); } } template template inline void subview_each2::operator= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const unwrap_check_mixed U( base_indices.get_ref(), (*this).get_mat_ref() ); check_indices(U.M); const eT* A_mem = A.memptr(); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // each column { for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::copy( p.colptr(col), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); for(uword col=0; col < p_n_cols; ++col) { p.at(row,col) = A_mem[col]; } } } } template template inline void subview_each2::operator+= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const unwrap_check_mixed U( base_indices.get_ref(), (*this).get_mat_ref() ); check_indices(U.M); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // each column { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_plus( p.colptr(col), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); p.row(row) += A; } } } template template inline void subview_each2::operator-= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const unwrap_check_mixed U( base_indices.get_ref(), (*this).get_mat_ref() ); check_indices(U.M); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // each column { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_minus( p.colptr(col), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); p.row(row) -= A; } } } template template inline void subview_each2::operator%= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const unwrap_check_mixed U( base_indices.get_ref(), (*this).get_mat_ref() ); check_indices(U.M); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // each column { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_mul( p.colptr(col), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); p.row(row) %= A; } } } template template inline void subview_each2::operator/= (const Base& in) { arma_extra_debug_sigprint(); parent& p = access::rw(subview_each_common::P); const unwrap_check tmp( in.get_ref(), (*this).get_mat_ref() ); const Mat& A = tmp.M; subview_each_common::check_size(A); const unwrap_check_mixed U( base_indices.get_ref(), (*this).get_mat_ref() ); check_indices(U.M); const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // each column { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_div( p.colptr(col), A_mem, p_n_rows ); } } else // each row { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); p.row(row) /= A; } } } // // // subview_each1_aux template inline Mat subview_each1_aux::operator_plus ( const subview_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out(p_n_rows, p_n_cols); const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); const eT* A_mem = A.memptr(); if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] + A_mem[row]; } } } if(mode == 1) // each row { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); const eT A_val = A_mem[i]; for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] + A_val; } } } return out; } template inline Mat subview_each1_aux::operator_minus ( const subview_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out(p_n_rows, p_n_cols); const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); const eT* A_mem = A.memptr(); if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] - A_mem[row]; } } } if(mode == 1) // each row { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); const eT A_val = A_mem[i]; for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] - A_val; } } } return out; } template inline Mat subview_each1_aux::operator_minus ( const Base& X, const subview_each1& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out(p_n_rows, p_n_cols); const quasi_unwrap tmp(X.get_ref()); const Mat& A = tmp.M; Y.check_size(A); const eT* A_mem = A.memptr(); if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = A_mem[row] - p_mem[row]; } } } if(mode == 1) // each row { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); const eT A_val = A_mem[i]; for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = A_val - p_mem[row]; } } } return out; } template inline Mat subview_each1_aux::operator_schur ( const subview_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out(p_n_rows, p_n_cols); const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); const eT* A_mem = A.memptr(); if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] * A_mem[row]; } } } if(mode == 1) // each row { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); const eT A_val = A_mem[i]; for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] * A_val; } } } return out; } template inline Mat subview_each1_aux::operator_div ( const subview_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out(p_n_rows, p_n_cols); const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); const eT* A_mem = A.memptr(); if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] / A_mem[row]; } } } if(mode == 1) // each row { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); const eT A_val = A_mem[i]; for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = p_mem[row] / A_val; } } } return out; } template inline Mat subview_each1_aux::operator_div ( const Base& X, const subview_each1& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out(p_n_rows, p_n_cols); const quasi_unwrap tmp(X.get_ref()); const Mat& A = tmp.M; Y.check_size(A); const eT* A_mem = A.memptr(); if(mode == 0) // each column { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = A_mem[row] / p_mem[row]; } } } if(mode == 1) // each row { for(uword i=0; i < p_n_cols; ++i) { const eT* p_mem = p.colptr(i); eT* out_mem = out.colptr(i); const eT A_val = A_mem[i]; for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = A_val / p_mem[row]; } } } return out; } // // // subview_each2_aux template inline Mat subview_each2_aux::operator_plus ( const subview_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out = p; const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; const unwrap U(X.base_indices.get_ref()); X.check_size(A); X.check_indices(U.M); const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // process columns { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_plus( out.colptr(col), A_mem, p_n_rows ); } } if(mode == 1) // process rows { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); out.row(row) += A; } } return out; } template inline Mat subview_each2_aux::operator_minus ( const subview_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out = p; const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; const unwrap U(X.base_indices.get_ref()); X.check_size(A); X.check_indices(U.M); const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // process columns { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_minus( out.colptr(col), A_mem, p_n_rows ); } } if(mode == 1) // process rows { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); out.row(row) -= A; } } return out; } template inline Mat subview_each2_aux::operator_minus ( const Base& X, const subview_each2& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out = p; const quasi_unwrap tmp(X.get_ref()); const Mat& A = tmp.M; const unwrap U(Y.base_indices.get_ref()); Y.check_size(A); Y.check_indices(U.M); const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // process columns { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); const eT* p_mem = p.colptr(col); eT* out_mem = out.colptr(col); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = A_mem[row] - p_mem[row]; } } } if(mode == 1) // process rows { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); out.row(row) = A - p.row(row); } } return out; } template inline Mat subview_each2_aux::operator_schur ( const subview_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out = p; const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; const unwrap U(X.base_indices.get_ref()); X.check_size(A); X.check_indices(U.M); const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // process columns { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_mul( out.colptr(col), A_mem, p_n_rows ); } } if(mode == 1) // process rows { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); out.row(row) %= A; } } return out; } template inline Mat subview_each2_aux::operator_div ( const subview_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out = p; const quasi_unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; const unwrap U(X.base_indices.get_ref()); X.check_size(A); X.check_indices(U.M); const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // process columns { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); arrayops::inplace_div( out.colptr(col), A_mem, p_n_rows ); } } if(mode == 1) // process rows { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); out.row(row) /= A; } } return out; } template inline Mat subview_each2_aux::operator_div ( const Base& X, const subview_each2& Y ) { arma_extra_debug_sigprint(); typedef typename parent::elem_type eT; const parent& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; Mat out = p; const quasi_unwrap tmp(X.get_ref()); const Mat& A = tmp.M; const unwrap U(Y.base_indices.get_ref()); Y.check_size(A); Y.check_indices(U.M); const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; if(mode == 0) // process columns { const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword col = indices_mem[i]; arma_debug_check( (col >= p_n_cols), "each_col(): index out of bounds" ); const eT* p_mem = p.colptr(col); eT* out_mem = out.colptr(col); for(uword row=0; row < p_n_rows; ++row) { out_mem[row] = A_mem[row] / p_mem[row]; } } } if(mode == 1) // process rows { for(uword i=0; i < N; ++i) { const uword row = indices_mem[i]; arma_debug_check( (row >= p_n_rows), "each_row(): index out of bounds" ); out.row(row) = A / p.row(row); } } return out; } //! @}