// 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 subview //! @{ template inline subview::~subview() { arma_extra_debug_sigprint_this(this); } template inline subview::subview(const Mat& in_m, const uword in_row1, const uword in_col1, const uword in_n_rows, const uword in_n_cols) : m (in_m ) , aux_row1(in_row1 ) , aux_col1(in_col1 ) , n_rows (in_n_rows) , n_cols (in_n_cols) , n_elem (in_n_rows*in_n_cols) { arma_extra_debug_sigprint_this(this); } template inline subview::subview(const subview& in) : m (in.m ) , aux_row1(in.aux_row1) , aux_col1(in.aux_col1) , n_rows (in.n_rows ) , n_cols (in.n_cols ) , n_elem (in.n_elem ) { arma_extra_debug_sigprint(arma_str::format("this = %x in = %x") % this % &in); } template inline subview::subview(subview&& in) : m (in.m ) , aux_row1(in.aux_row1) , aux_col1(in.aux_col1) , n_rows (in.n_rows ) , n_cols (in.n_cols ) , n_elem (in.n_elem ) { arma_extra_debug_sigprint(arma_str::format("this = %x in = %x") % this % &in); // for paranoia access::rw(in.aux_row1) = 0; access::rw(in.aux_col1) = 0; access::rw(in.n_rows ) = 0; access::rw(in.n_cols ) = 0; access::rw(in.n_elem ) = 0; } template template inline void subview::inplace_op(const eT val) { arma_extra_debug_sigprint(); subview& s = *this; const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; if(s_n_rows == 1) { Mat& A = const_cast< Mat& >(s.m); const uword A_n_rows = A.n_rows; eT* Aptr = &(A.at(s.aux_row1,s.aux_col1)); uword jj; for(jj=1; jj < s_n_cols; jj+=2) { if(is_same_type::yes) { (*Aptr) += val; Aptr += A_n_rows; (*Aptr) += val; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) -= val; Aptr += A_n_rows; (*Aptr) -= val; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) *= val; Aptr += A_n_rows; (*Aptr) *= val; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) /= val; Aptr += A_n_rows; (*Aptr) /= val; Aptr += A_n_rows; } } if((jj-1) < s_n_cols) { if(is_same_type::yes) { (*Aptr) += val; } if(is_same_type::yes) { (*Aptr) -= val; } if(is_same_type::yes) { (*Aptr) *= val; } if(is_same_type::yes) { (*Aptr) /= val; } } } else { for(uword ucol=0; ucol < s_n_cols; ++ucol) { if(is_same_type::yes) { arrayops::inplace_plus ( colptr(ucol), val, s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_minus( colptr(ucol), val, s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_mul ( colptr(ucol), val, s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_div ( colptr(ucol), val, s_n_rows ); } } } } template template inline void subview::inplace_op(const Base& in, const char* identifier) { arma_extra_debug_sigprint(); const Proxy P(in.get_ref()); subview& s = *this; const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; arma_debug_assert_same_size(s, P, identifier); const bool use_mp = arma_config::openmp && Proxy::use_mp && mp_gate::eval(s.n_elem); const bool has_overlap = P.has_overlap(s); if(has_overlap) { arma_extra_debug_print("aliasing or overlap detected"); } if( (is_Mat::stored_type>::value) || (use_mp) || (has_overlap) ) { const unwrap_check::stored_type> tmp(P.Q, has_overlap); const Mat& B = tmp.M; if(s_n_rows == 1) { Mat& A = const_cast< Mat& >(m); const uword A_n_rows = A.n_rows; eT* Aptr = &(A.at(aux_row1,aux_col1)); const eT* Bptr = B.memptr(); uword jj; for(jj=1; jj < s_n_cols; jj+=2) { const eT tmp1 = (*Bptr); Bptr++; const eT tmp2 = (*Bptr); Bptr++; if(is_same_type::yes) { (*Aptr) = tmp1; Aptr += A_n_rows; (*Aptr) = tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) += tmp1; Aptr += A_n_rows; (*Aptr) += tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) -= tmp1; Aptr += A_n_rows; (*Aptr) -= tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) *= tmp1; Aptr += A_n_rows; (*Aptr) *= tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) /= tmp1; Aptr += A_n_rows; (*Aptr) /= tmp2; Aptr += A_n_rows; } } if((jj-1) < s_n_cols) { if(is_same_type::yes) { (*Aptr) = (*Bptr); } if(is_same_type::yes) { (*Aptr) += (*Bptr); } if(is_same_type::yes) { (*Aptr) -= (*Bptr); } if(is_same_type::yes) { (*Aptr) *= (*Bptr); } if(is_same_type::yes) { (*Aptr) /= (*Bptr); } } } else // not a row vector { if((s.aux_row1 == 0) && (s_n_rows == s.m.n_rows)) { if(is_same_type::yes) { arrayops::copy ( s.colptr(0), B.memptr(), s.n_elem ); } if(is_same_type::yes) { arrayops::inplace_plus ( s.colptr(0), B.memptr(), s.n_elem ); } if(is_same_type::yes) { arrayops::inplace_minus( s.colptr(0), B.memptr(), s.n_elem ); } if(is_same_type::yes) { arrayops::inplace_mul ( s.colptr(0), B.memptr(), s.n_elem ); } if(is_same_type::yes) { arrayops::inplace_div ( s.colptr(0), B.memptr(), s.n_elem ); } } else { for(uword ucol=0; ucol < s_n_cols; ++ucol) { if(is_same_type::yes) { arrayops::copy ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_plus ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_minus( s.colptr(ucol), B.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_mul ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_div ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); } } } } } else // use the Proxy { if(s_n_rows == 1) { Mat& A = const_cast< Mat& >(m); const uword A_n_rows = A.n_rows; eT* Aptr = &(A.at(aux_row1,aux_col1)); uword jj; for(jj=1; jj < s_n_cols; jj+=2) { const uword ii = (jj-1); const eT tmp1 = (Proxy::use_at) ? P.at(0,ii) : P[ii]; const eT tmp2 = (Proxy::use_at) ? P.at(0,jj) : P[jj]; if(is_same_type::yes) { (*Aptr) = tmp1; Aptr += A_n_rows; (*Aptr) = tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) += tmp1; Aptr += A_n_rows; (*Aptr) += tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) -= tmp1; Aptr += A_n_rows; (*Aptr) -= tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) *= tmp1; Aptr += A_n_rows; (*Aptr) *= tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) /= tmp1; Aptr += A_n_rows; (*Aptr) /= tmp2; Aptr += A_n_rows; } } const uword ii = (jj-1); if(ii < s_n_cols) { if(is_same_type::yes) { (*Aptr) = (Proxy::use_at) ? P.at(0,ii) : P[ii]; } if(is_same_type::yes) { (*Aptr) += (Proxy::use_at) ? P.at(0,ii) : P[ii]; } if(is_same_type::yes) { (*Aptr) -= (Proxy::use_at) ? P.at(0,ii) : P[ii]; } if(is_same_type::yes) { (*Aptr) *= (Proxy::use_at) ? P.at(0,ii) : P[ii]; } if(is_same_type::yes) { (*Aptr) /= (Proxy::use_at) ? P.at(0,ii) : P[ii]; } } } else // not a row vector { if(Proxy::use_at) { for(uword ucol=0; ucol < s_n_cols; ++ucol) { eT* s_col_data = s.colptr(ucol); uword jj; for(jj=1; jj < s_n_rows; jj+=2) { const uword ii = (jj-1); const eT tmp1 = P.at(ii,ucol); const eT tmp2 = P.at(jj,ucol); if(is_same_type::yes) { (*s_col_data) = tmp1; s_col_data++; (*s_col_data) = tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) += tmp1; s_col_data++; (*s_col_data) += tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) -= tmp1; s_col_data++; (*s_col_data) -= tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) *= tmp1; s_col_data++; (*s_col_data) *= tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) /= tmp1; s_col_data++; (*s_col_data) /= tmp2; s_col_data++; } } const uword ii = (jj-1); if(ii < s_n_rows) { if(is_same_type::yes) { (*s_col_data) = P.at(ii,ucol); } if(is_same_type::yes) { (*s_col_data) += P.at(ii,ucol); } if(is_same_type::yes) { (*s_col_data) -= P.at(ii,ucol); } if(is_same_type::yes) { (*s_col_data) *= P.at(ii,ucol); } if(is_same_type::yes) { (*s_col_data) /= P.at(ii,ucol); } } } } else { typename Proxy::ea_type Pea = P.get_ea(); uword count = 0; for(uword ucol=0; ucol < s_n_cols; ++ucol) { eT* s_col_data = s.colptr(ucol); uword jj; for(jj=1; jj < s_n_rows; jj+=2) { const eT tmp1 = Pea[count]; count++; const eT tmp2 = Pea[count]; count++; if(is_same_type::yes) { (*s_col_data) = tmp1; s_col_data++; (*s_col_data) = tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) += tmp1; s_col_data++; (*s_col_data) += tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) -= tmp1; s_col_data++; (*s_col_data) -= tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) *= tmp1; s_col_data++; (*s_col_data) *= tmp2; s_col_data++; } if(is_same_type::yes) { (*s_col_data) /= tmp1; s_col_data++; (*s_col_data) /= tmp2; s_col_data++; } } if((jj-1) < s_n_rows) { if(is_same_type::yes) { (*s_col_data) = Pea[count]; count++; } if(is_same_type::yes) { (*s_col_data) += Pea[count]; count++; } if(is_same_type::yes) { (*s_col_data) -= Pea[count]; count++; } if(is_same_type::yes) { (*s_col_data) *= Pea[count]; count++; } if(is_same_type::yes) { (*s_col_data) /= Pea[count]; count++; } } } } } } } template template inline void subview::inplace_op(const subview& x, const char* identifier) { arma_extra_debug_sigprint(); if(check_overlap(x)) { const Mat tmp(x); if(is_same_type::yes) { (*this).operator= (tmp); } if(is_same_type::yes) { (*this).operator+=(tmp); } if(is_same_type::yes) { (*this).operator-=(tmp); } if(is_same_type::yes) { (*this).operator%=(tmp); } if(is_same_type::yes) { (*this).operator/=(tmp); } return; } subview& s = *this; arma_debug_assert_same_size(s, x, identifier); const uword s_n_cols = s.n_cols; const uword s_n_rows = s.n_rows; if(s_n_rows == 1) { Mat& A = const_cast< Mat& >(s.m); const Mat& B = x.m; const uword A_n_rows = A.n_rows; const uword B_n_rows = B.n_rows; eT* Aptr = &(A.at(s.aux_row1,s.aux_col1)); const eT* Bptr = &(B.at(x.aux_row1,x.aux_col1)); uword jj; for(jj=1; jj < s_n_cols; jj+=2) { const eT tmp1 = (*Bptr); Bptr += B_n_rows; const eT tmp2 = (*Bptr); Bptr += B_n_rows; if(is_same_type::yes) { (*Aptr) = tmp1; Aptr += A_n_rows; (*Aptr) = tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) += tmp1; Aptr += A_n_rows; (*Aptr) += tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) -= tmp1; Aptr += A_n_rows; (*Aptr) -= tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) *= tmp1; Aptr += A_n_rows; (*Aptr) *= tmp2; Aptr += A_n_rows; } if(is_same_type::yes) { (*Aptr) /= tmp1; Aptr += A_n_rows; (*Aptr) /= tmp2; Aptr += A_n_rows; } } if((jj-1) < s_n_cols) { if(is_same_type::yes) { (*Aptr) = (*Bptr); } if(is_same_type::yes) { (*Aptr) += (*Bptr); } if(is_same_type::yes) { (*Aptr) -= (*Bptr); } if(is_same_type::yes) { (*Aptr) *= (*Bptr); } if(is_same_type::yes) { (*Aptr) /= (*Bptr); } } } else { for(uword ucol=0; ucol < s_n_cols; ++ucol) { if(is_same_type::yes) { arrayops::copy ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_plus ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_minus( s.colptr(ucol), x.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_mul ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); } if(is_same_type::yes) { arrayops::inplace_div ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); } } } } template inline void subview::operator= (const eT val) { arma_extra_debug_sigprint(); if(n_elem != 1) { arma_debug_assert_same_size(n_rows, n_cols, 1, 1, "copy into submatrix"); } Mat& X = const_cast< Mat& >(m); X.at(aux_row1, aux_col1) = val; } template inline void subview::operator+= (const eT val) { arma_extra_debug_sigprint(); inplace_op(val); } template inline void subview::operator-= (const eT val) { arma_extra_debug_sigprint(); inplace_op(val); } template inline void subview::operator*= (const eT val) { arma_extra_debug_sigprint(); inplace_op(val); } template inline void subview::operator/= (const eT val) { arma_extra_debug_sigprint(); inplace_op(val); } template inline void subview::operator= (const subview& x) { arma_extra_debug_sigprint(); inplace_op(x, "copy into submatrix"); } template inline void subview::operator+= (const subview& x) { arma_extra_debug_sigprint(); inplace_op(x, "addition"); } template inline void subview::operator-= (const subview& x) { arma_extra_debug_sigprint(); inplace_op(x, "subtraction"); } template inline void subview::operator%= (const subview& x) { arma_extra_debug_sigprint(); inplace_op(x, "element-wise multiplication"); } template inline void subview::operator/= (const subview& x) { arma_extra_debug_sigprint(); inplace_op(x, "element-wise division"); } template template inline void subview::operator= (const Base& in) { arma_extra_debug_sigprint(); inplace_op(in, "copy into submatrix"); } template template inline void subview::operator+= (const Base& in) { arma_extra_debug_sigprint(); inplace_op(in, "addition"); } template template inline void subview::operator-= (const Base& in) { arma_extra_debug_sigprint(); inplace_op(in, "subtraction"); } template template inline void subview::operator%= (const Base& in) { arma_extra_debug_sigprint(); inplace_op(in, "element-wise multiplication"); } template template inline void subview::operator/= (const Base& in) { arma_extra_debug_sigprint(); inplace_op(in, "element-wise division"); } template template inline void subview::operator=(const SpBase& x) { arma_extra_debug_sigprint(); const SpProxy p(x.get_ref()); arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "copy into submatrix"); // Clear the subview. zeros(); // Iterate through the sparse subview and set the nonzero values appropriately. typename SpProxy::const_iterator_type cit = p.begin(); typename SpProxy::const_iterator_type cit_end = p.end(); while(cit != cit_end) { at(cit.row(), cit.col()) = *cit; ++cit; } } template template inline void subview::operator+=(const SpBase& x) { arma_extra_debug_sigprint(); const SpProxy p(x.get_ref()); arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "addition"); // Iterate through the sparse subview and add its values. typename SpProxy::const_iterator_type cit = p.begin(); typename SpProxy::const_iterator_type cit_end = p.end(); while(cit != cit_end) { at(cit.row(), cit.col()) += *cit; ++cit; } } template template inline void subview::operator-=(const SpBase& x) { arma_extra_debug_sigprint(); const SpProxy p(x.get_ref()); arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "subtraction"); // Iterate through the sparse subview and subtract its values. typename SpProxy::const_iterator_type cit = p.begin(); typename SpProxy::const_iterator_type cit_end = p.end(); while(cit != cit_end) { at(cit.row(), cit.col()) -= *cit; ++cit; } } template template inline void subview::operator%=(const SpBase& x) { arma_extra_debug_sigprint(); const uword s_n_rows = (*this).n_rows; const uword s_n_cols = (*this).n_cols; const SpProxy p(x.get_ref()); arma_debug_assert_same_size(s_n_rows, s_n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise multiplication"); if(n_elem == 0) { return; } if(p.get_n_nonzero() == 0) { (*this).zeros(); return; } // Iterate over nonzero values. // Any zero values in the sparse expression will result in a zero in our subview. typename SpProxy::const_iterator_type cit = p.begin(); typename SpProxy::const_iterator_type cit_end = p.end(); uword r = 0; uword c = 0; while(cit != cit_end) { const uword cit_row = cit.row(); const uword cit_col = cit.col(); while( ((r == cit_row) && (c == cit_col)) == false ) { at(r,c) = eT(0); r++; if(r >= s_n_rows) { r = 0; c++; } } at(r, c) *= (*cit); ++cit; r++; if(r >= s_n_rows) { r = 0; c++; } } } template template inline void subview::operator/=(const SpBase& x) { arma_extra_debug_sigprint(); const SpProxy p(x.get_ref()); arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise division"); // This is probably going to fill your subview with a bunch of NaNs, // so I'm not going to bother to implement it fast. // You can have slow NaNs. They're fine too. for(uword c = 0; c < n_cols; ++c) for(uword r = 0; r < n_rows; ++r) { at(r, c) /= p.at(r, c); } } template template inline typename enable_if2< is_same_type::value, void>::result subview::operator= (const Gen& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(n_rows, n_cols, in.n_rows, in.n_cols, "copy into submatrix"); in.apply(*this); } template inline void subview::operator=(const std::initializer_list& list) { arma_extra_debug_sigprint(); arma_debug_check( (is_vec() == false), "copy into submatrix: size mismatch" ); const uword N = uword(list.size()); if(n_rows == 1) { arma_debug_assert_same_size(1, n_cols, 1, N, "copy into submatrix"); auto it = list.begin(); for(uword ii=0; ii < N; ++ii) { (*this).at(0,ii) = (*it); ++it; } } else if(n_cols == 1) { arma_debug_assert_same_size(n_rows, 1, N, 1, "copy into submatrix"); arrayops::copy( (*this).colptr(0), list.begin(), N ); } } template inline void subview::operator=(const std::initializer_list< std::initializer_list >& list) { arma_extra_debug_sigprint(); const Mat tmp(list); (*this).operator=(tmp); } //! apply a functor to each element template template inline void subview::for_each(functor F) { arma_extra_debug_sigprint(); Mat& X = const_cast< Mat& >(m); if(n_rows == 1) { const uword urow = aux_row1; const uword start_col = aux_col1; const uword end_col_plus1 = start_col + n_cols; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) { F( X.at(urow, ucol) ); } } else { const uword start_col = aux_col1; const uword start_row = aux_row1; const uword end_col_plus1 = start_col + n_cols; const uword end_row_plus1 = start_row + n_rows; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) for(uword urow = start_row; urow < end_row_plus1; ++urow) { F( X.at(urow, ucol) ); } } } template template inline void subview::for_each(functor F) const { arma_extra_debug_sigprint(); const Mat& X = m; if(n_rows == 1) { const uword urow = aux_row1; const uword start_col = aux_col1; const uword end_col_plus1 = start_col + n_cols; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) { F( X.at(urow, ucol) ); } } else { const uword start_col = aux_col1; const uword start_row = aux_row1; const uword end_col_plus1 = start_col + n_cols; const uword end_row_plus1 = start_row + n_rows; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) for(uword urow = start_row; urow < end_row_plus1; ++urow) { F( X.at(urow, ucol) ); } } } //! transform each element in the subview using a functor template template inline void subview::transform(functor F) { arma_extra_debug_sigprint(); Mat& X = const_cast< Mat& >(m); if(n_rows == 1) { const uword urow = aux_row1; const uword start_col = aux_col1; const uword end_col_plus1 = start_col + n_cols; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) { X.at(urow, ucol) = eT( F( X.at(urow, ucol) ) ); } } else { const uword start_col = aux_col1; const uword start_row = aux_row1; const uword end_col_plus1 = start_col + n_cols; const uword end_row_plus1 = start_row + n_rows; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) for(uword urow = start_row; urow < end_row_plus1; ++urow) { X.at(urow, ucol) = eT( F( X.at(urow, ucol) ) ); } } } //! imbue (fill) the subview with values provided by a functor template template inline void subview::imbue(functor F) { arma_extra_debug_sigprint(); Mat& X = const_cast< Mat& >(m); if(n_rows == 1) { const uword urow = aux_row1; const uword start_col = aux_col1; const uword end_col_plus1 = start_col + n_cols; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) { X.at(urow, ucol) = eT( F() ); } } else { const uword start_col = aux_col1; const uword start_row = aux_row1; const uword end_col_plus1 = start_col + n_cols; const uword end_row_plus1 = start_row + n_rows; for(uword ucol = start_col; ucol < end_col_plus1; ++ucol) for(uword urow = start_row; urow < end_row_plus1; ++urow) { X.at(urow, ucol) = eT( F() ); } } } template inline void subview::replace(const eT old_val, const eT new_val) { arma_extra_debug_sigprint(); subview& s = *this; const uword s_n_cols = s.n_cols; const uword s_n_rows = s.n_rows; if(s_n_rows == 1) { Mat& A = const_cast< Mat& >(s.m); const uword A_n_rows = A.n_rows; eT* Aptr = &(A.at(s.aux_row1,s.aux_col1)); if(arma_isnan(old_val)) { for(uword ucol=0; ucol < s_n_cols; ++ucol) { (*Aptr) = (arma_isnan(*Aptr)) ? new_val : (*Aptr); Aptr += A_n_rows; } } else { for(uword ucol=0; ucol < s_n_cols; ++ucol) { (*Aptr) = ((*Aptr) == old_val) ? new_val : (*Aptr); Aptr += A_n_rows; } } } else { for(uword ucol=0; ucol < s_n_cols; ++ucol) { arrayops::replace(s.colptr(ucol), s_n_rows, old_val, new_val); } } } template inline void subview::clean(const typename get_pod_type::result threshold) { arma_extra_debug_sigprint(); subview& s = *this; const uword s_n_cols = s.n_cols; const uword s_n_rows = s.n_rows; for(uword ucol=0; ucol < s_n_cols; ++ucol) { arrayops::clean( s.colptr(ucol), s_n_rows, threshold ); } } template inline void subview::clamp(const eT min_val, const eT max_val) { arma_extra_debug_sigprint(); if(is_cx::no) { arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview::clamp(): min_val must be less than max_val" ); } else { arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview::clamp(): real(min_val) must be less than real(max_val)" ); arma_debug_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "subview::clamp(): imag(min_val) must be less than imag(max_val)" ); } subview& s = *this; const uword s_n_cols = s.n_cols; const uword s_n_rows = s.n_rows; for(uword ucol=0; ucol < s_n_cols; ++ucol) { arrayops::clamp( s.colptr(ucol), s_n_rows, min_val, max_val ); } } template inline void subview::fill(const eT val) { arma_extra_debug_sigprint(); subview& s = *this; const uword s_n_cols = s.n_cols; const uword s_n_rows = s.n_rows; if(s_n_rows == 1) { Mat& A = const_cast< Mat& >(s.m); const uword A_n_rows = A.n_rows; eT* Aptr = &(A.at(s.aux_row1,s.aux_col1)); uword jj; for(jj=1; jj < s_n_cols; jj+=2) { (*Aptr) = val; Aptr += A_n_rows; (*Aptr) = val; Aptr += A_n_rows; } if((jj-1) < s_n_cols) { (*Aptr) = val; } } else { if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) ) { arrayops::inplace_set( s.colptr(0), val, s.n_elem ); } else { for(uword ucol=0; ucol < s_n_cols; ++ucol) { arrayops::inplace_set( s.colptr(ucol), val, s_n_rows ); } } } } template inline void subview::zeros() { arma_extra_debug_sigprint(); (*this).fill(eT(0)); } template inline void subview::ones() { arma_extra_debug_sigprint(); (*this).fill(eT(1)); } template inline void subview::eye() { arma_extra_debug_sigprint(); (*this).zeros(); const uword N = (std::min)(n_rows, n_cols); for(uword ii=0; ii < N; ++ii) { at(ii,ii) = eT(1); } } template inline void subview::randu() { arma_extra_debug_sigprint(); subview& s = (*this); const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; if(s_n_rows == 1) { podarray tmp(s_n_cols); eT* tmp_mem = tmp.memptr(); arma_rng::randu::fill( tmp_mem, s_n_cols ); for(uword ii=0; ii < s_n_cols; ++ii) { at(0,ii) = tmp_mem[ii]; } } else { if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) ) { arma_rng::randu::fill( s.colptr(0), s.n_elem ); } else { for(uword ii=0; ii < s_n_cols; ++ii) { arma_rng::randu::fill( s.colptr(ii), s_n_rows ); } } } } template inline void subview::randn() { arma_extra_debug_sigprint(); subview& s = (*this); const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; if(s_n_rows == 1) { podarray tmp(s_n_cols); eT* tmp_mem = tmp.memptr(); arma_rng::randn::fill( tmp_mem, s_n_cols ); for(uword ii=0; ii < s_n_cols; ++ii) { at(0,ii) = tmp_mem[ii]; } } else { if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) ) { arma_rng::randn::fill( s.colptr(0), s.n_elem ); } else { for(uword ii=0; ii < s_n_cols; ++ii) { arma_rng::randn::fill( s.colptr(ii), s_n_rows ); } } } } template inline eT subview::at_alt(const uword ii) const { return operator[](ii); } template inline eT& subview::operator[](const uword ii) { const uword in_col = ii / n_rows; const uword in_row = ii % n_rows; const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return access::rw( (const_cast< Mat& >(m)).mem[index] ); } template inline eT subview::operator[](const uword ii) const { const uword in_col = ii / n_rows; const uword in_row = ii % n_rows; const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return m.mem[index]; } template inline eT& subview::operator()(const uword ii) { arma_debug_check_bounds( (ii >= n_elem), "subview::operator(): index out of bounds" ); const uword in_col = ii / n_rows; const uword in_row = ii % n_rows; const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return access::rw( (const_cast< Mat& >(m)).mem[index] ); } template inline eT subview::operator()(const uword ii) const { arma_debug_check_bounds( (ii >= n_elem), "subview::operator(): index out of bounds" ); const uword in_col = ii / n_rows; const uword in_row = ii % n_rows; const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return m.mem[index]; } template inline eT& subview::operator()(const uword in_row, const uword in_col) { arma_debug_check_bounds( ((in_row >= n_rows) || (in_col >= n_cols)), "subview::operator(): index out of bounds" ); const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return access::rw( (const_cast< Mat& >(m)).mem[index] ); } template inline eT subview::operator()(const uword in_row, const uword in_col) const { arma_debug_check_bounds( ((in_row >= n_rows) || (in_col >= n_cols)), "subview::operator(): index out of bounds" ); const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return m.mem[index]; } template inline eT& subview::at(const uword in_row, const uword in_col) { const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return access::rw( (const_cast< Mat& >(m)).mem[index] ); } template inline eT subview::at(const uword in_row, const uword in_col) const { const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return m.mem[index]; } template inline eT& subview::front() { const uword index = aux_col1*m.n_rows + aux_row1; return access::rw( (const_cast< Mat& >(m)).mem[index] ); } template inline eT subview::front() const { const uword index = aux_col1*m.n_rows + aux_row1; return m.mem[index]; } template inline eT& subview::back() { const uword in_row = n_rows - 1; const uword in_col = n_cols - 1; const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return access::rw( (const_cast< Mat& >(m)).mem[index] ); } template inline eT subview::back() const { const uword in_row = n_rows - 1; const uword in_col = n_cols - 1; const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row; return m.mem[index]; } template arma_inline eT* subview::colptr(const uword in_col) { return & access::rw((const_cast< Mat& >(m)).mem[ (in_col + aux_col1)*m.n_rows + aux_row1 ]); } template arma_inline const eT* subview::colptr(const uword in_col) const { return & m.mem[ (in_col + aux_col1)*m.n_rows + aux_row1 ]; } template template inline bool subview::check_overlap(const subview& x) const { if(is_same_type::value == false) { return false; } const subview& s = (*this); if(void_ptr(&(s.m)) != void_ptr(&(x.m))) { return false; } if( (s.n_elem == 0) || (x.n_elem == 0) ) { return false; } const uword s_row_start = s.aux_row1; const uword s_row_end_p1 = s_row_start + s.n_rows; const uword s_col_start = s.aux_col1; const uword s_col_end_p1 = s_col_start + s.n_cols; const uword x_row_start = x.aux_row1; const uword x_row_end_p1 = x_row_start + x.n_rows; const uword x_col_start = x.aux_col1; const uword x_col_end_p1 = x_col_start + x.n_cols; const bool outside_rows = ( (x_row_start >= s_row_end_p1) || (s_row_start >= x_row_end_p1) ); const bool outside_cols = ( (x_col_start >= s_col_end_p1) || (s_col_start >= x_col_end_p1) ); return ( (outside_rows == false) && (outside_cols == false) ); } template inline bool subview::is_vec() const { return ( (n_rows == 1) || (n_cols == 1) ); } template inline bool subview::is_finite() const { arma_extra_debug_sigprint(); if(arma_config::fast_math_warn) { arma_debug_warn_level(1, "is_finite(): detection of non-finite values is not reliable in fast math mode"); } const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; for(uword ii=0; ii inline bool subview::is_zero(const typename get_pod_type::result tol) const { arma_extra_debug_sigprint(); const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; for(uword ii=0; ii inline bool subview::has_inf() const { arma_extra_debug_sigprint(); if(arma_config::fast_math_warn) { arma_debug_warn_level(1, "has_inf(): detection of non-finite values is not reliable in fast math mode"); } const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; for(uword ii=0; ii inline bool subview::has_nan() const { arma_extra_debug_sigprint(); if(arma_config::fast_math_warn) { arma_debug_warn_level(1, "has_nan(): detection of non-finite values is not reliable in fast math mode"); } const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; for(uword ii=0; ii inline bool subview::has_nonfinite() const { arma_extra_debug_sigprint(); if(arma_config::fast_math_warn) { arma_debug_warn_level(1, "has_nonfinite(): detection of non-finite values is not reliable in fast math mode"); } const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; for(uword ii=0; ii inline void subview::extract(Mat& out, const subview& in) { arma_extra_debug_sigprint(); // NOTE: we're assuming that the matrix has already been set to the correct size and there is no aliasing; // size setting and alias checking is done by either the Mat contructor or operator=() const uword n_rows = in.n_rows; // number of rows in the subview const uword n_cols = in.n_cols; // number of columns in the subview arma_extra_debug_print(arma_str::format("out.n_rows = %u out.n_cols = %u in.m.n_rows = %u in.m.n_cols = %u") % out.n_rows % out.n_cols % in.m.n_rows % in.m.n_cols ); if(in.is_vec()) { if(n_cols == 1) // a column vector { arma_extra_debug_print("subview::extract(): copying col (going across rows)"); // in.colptr(0) the first column of the subview, taking into account any row offset arrayops::copy( out.memptr(), in.colptr(0), n_rows ); } else if(n_rows == 1) // a row vector { arma_extra_debug_print("subview::extract(): copying row (going across columns)"); eT* out_mem = out.memptr(); const uword X_n_rows = in.m.n_rows; const eT* Xptr = &(in.m.at(in.aux_row1,in.aux_col1)); uword j; for(j=1; j < n_cols; j+=2) { const eT tmp1 = (*Xptr); Xptr += X_n_rows; const eT tmp2 = (*Xptr); Xptr += X_n_rows; (*out_mem) = tmp1; out_mem++; (*out_mem) = tmp2; out_mem++; } if((j-1) < n_cols) { (*out_mem) = (*Xptr); } } } else // general submatrix { arma_extra_debug_print("subview::extract(): general submatrix"); if( (in.aux_row1 == 0) && (n_rows == in.m.n_rows) ) { arrayops::copy( out.memptr(), in.colptr(0), in.n_elem ); } else { for(uword col=0; col < n_cols; ++col) { arrayops::copy( out.colptr(col), in.colptr(col), n_rows ); } } } } //! X += Y.submat(...) template inline void subview::plus_inplace(Mat& out, const subview& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(out, in, "addition"); const uword n_rows = in.n_rows; const uword n_cols = in.n_cols; if(n_rows == 1) { eT* out_mem = out.memptr(); const Mat& X = in.m; const uword row = in.aux_row1; const uword start_col = in.aux_col1; uword i,j; for(i=0, j=1; j < n_cols; i+=2, j+=2) { const eT tmp1 = X.at(row, start_col+i); const eT tmp2 = X.at(row, start_col+j); out_mem[i] += tmp1; out_mem[j] += tmp2; } if(i < n_cols) { out_mem[i] += X.at(row, start_col+i); } } else { for(uword col=0; col < n_cols; ++col) { arrayops::inplace_plus(out.colptr(col), in.colptr(col), n_rows); } } } //! X -= Y.submat(...) template inline void subview::minus_inplace(Mat& out, const subview& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(out, in, "subtraction"); const uword n_rows = in.n_rows; const uword n_cols = in.n_cols; if(n_rows == 1) { eT* out_mem = out.memptr(); const Mat& X = in.m; const uword row = in.aux_row1; const uword start_col = in.aux_col1; uword i,j; for(i=0, j=1; j < n_cols; i+=2, j+=2) { const eT tmp1 = X.at(row, start_col+i); const eT tmp2 = X.at(row, start_col+j); out_mem[i] -= tmp1; out_mem[j] -= tmp2; } if(i < n_cols) { out_mem[i] -= X.at(row, start_col+i); } } else { for(uword col=0; col < n_cols; ++col) { arrayops::inplace_minus(out.colptr(col), in.colptr(col), n_rows); } } } //! X %= Y.submat(...) template inline void subview::schur_inplace(Mat& out, const subview& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(out, in, "element-wise multiplication"); const uword n_rows = in.n_rows; const uword n_cols = in.n_cols; if(n_rows == 1) { eT* out_mem = out.memptr(); const Mat& X = in.m; const uword row = in.aux_row1; const uword start_col = in.aux_col1; uword i,j; for(i=0, j=1; j < n_cols; i+=2, j+=2) { const eT tmp1 = X.at(row, start_col+i); const eT tmp2 = X.at(row, start_col+j); out_mem[i] *= tmp1; out_mem[j] *= tmp2; } if(i < n_cols) { out_mem[i] *= X.at(row, start_col+i); } } else { for(uword col=0; col < n_cols; ++col) { arrayops::inplace_mul(out.colptr(col), in.colptr(col), n_rows); } } } //! X /= Y.submat(...) template inline void subview::div_inplace(Mat& out, const subview& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(out, in, "element-wise division"); const uword n_rows = in.n_rows; const uword n_cols = in.n_cols; if(n_rows == 1) { eT* out_mem = out.memptr(); const Mat& X = in.m; const uword row = in.aux_row1; const uword start_col = in.aux_col1; uword i,j; for(i=0, j=1; j < n_cols; i+=2, j+=2) { const eT tmp1 = X.at(row, start_col+i); const eT tmp2 = X.at(row, start_col+j); out_mem[i] /= tmp1; out_mem[j] /= tmp2; } if(i < n_cols) { out_mem[i] /= X.at(row, start_col+i); } } else { for(uword col=0; col < n_cols; ++col) { arrayops::inplace_div(out.colptr(col), in.colptr(col), n_rows); } } } //! creation of subview (row vector) template inline subview_row subview::row(const uword row_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( row_num >= n_rows, "subview::row(): out of bounds" ); const uword base_row = aux_row1 + row_num; return subview_row(m, base_row, aux_col1, n_cols); } //! creation of subview (row vector) template inline const subview_row subview::row(const uword row_num) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( row_num >= n_rows, "subview::row(): out of bounds" ); const uword base_row = aux_row1 + row_num; return subview_row(m, base_row, aux_col1, n_cols); } template inline subview_row subview::operator()(const uword row_num, const span& col_span) { arma_extra_debug_sigprint(); const bool col_all = col_span.whole; const uword local_n_cols = n_cols; const uword in_col1 = col_all ? 0 : col_span.a; const uword in_col2 = col_span.b; const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; const uword base_col1 = aux_col1 + in_col1; const uword base_row = aux_row1 + row_num; arma_debug_check_bounds ( (row_num >= n_rows) || ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) , "subview::operator(): indices out of bounds or incorrectly used" ); return subview_row(m, base_row, base_col1, submat_n_cols); } template inline const subview_row subview::operator()(const uword row_num, const span& col_span) const { arma_extra_debug_sigprint(); const bool col_all = col_span.whole; const uword local_n_cols = n_cols; const uword in_col1 = col_all ? 0 : col_span.a; const uword in_col2 = col_span.b; const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; const uword base_col1 = aux_col1 + in_col1; const uword base_row = aux_row1 + row_num; arma_debug_check_bounds ( (row_num >= n_rows) || ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) , "subview::operator(): indices out of bounds or incorrectly used" ); return subview_row(m, base_row, base_col1, submat_n_cols); } //! creation of subview (column vector) template inline subview_col subview::col(const uword col_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( col_num >= n_cols, "subview::col(): out of bounds" ); const uword base_col = aux_col1 + col_num; return subview_col(m, base_col, aux_row1, n_rows); } //! creation of subview (column vector) template inline const subview_col subview::col(const uword col_num) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( col_num >= n_cols, "subview::col(): out of bounds" ); const uword base_col = aux_col1 + col_num; return subview_col(m, base_col, aux_row1, n_rows); } template inline subview_col subview::operator()(const span& row_span, const uword col_num) { arma_extra_debug_sigprint(); const bool row_all = row_span.whole; const uword local_n_rows = n_rows; const uword in_row1 = row_all ? 0 : row_span.a; const uword in_row2 = row_span.b; const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; const uword base_row1 = aux_row1 + in_row1; const uword base_col = aux_col1 + col_num; arma_debug_check_bounds ( (col_num >= n_cols) || ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) , "subview::operator(): indices out of bounds or incorrectly used" ); return subview_col(m, base_col, base_row1, submat_n_rows); } template inline const subview_col subview::operator()(const span& row_span, const uword col_num) const { arma_extra_debug_sigprint(); const bool row_all = row_span.whole; const uword local_n_rows = n_rows; const uword in_row1 = row_all ? 0 : row_span.a; const uword in_row2 = row_span.b; const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; const uword base_row1 = aux_row1 + in_row1; const uword base_col = aux_col1 + col_num; arma_debug_check_bounds ( (col_num >= n_cols) || ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) , "subview::operator(): indices out of bounds or incorrectly used" ); return subview_col(m, base_col, base_row1, submat_n_rows); } //! create a Col object which uses memory from an existing matrix object. //! this approach is currently not alias safe //! and does not take into account that the parent matrix object could be deleted. //! if deleted memory is accessed by the created Col object, //! it will cause memory corruption and/or a crash template inline Col subview::unsafe_col(const uword col_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( col_num >= n_cols, "subview::unsafe_col(): out of bounds" ); return Col(colptr(col_num), n_rows, false, true); } //! create a Col object which uses memory from an existing matrix object. //! this approach is currently not alias safe //! and does not take into account that the parent matrix object could be deleted. //! if deleted memory is accessed by the created Col object, //! it will cause memory corruption and/or a crash template inline const Col subview::unsafe_col(const uword col_num) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( col_num >= n_cols, "subview::unsafe_col(): out of bounds" ); return Col(const_cast(colptr(col_num)), n_rows, false, true); } //! creation of subview (submatrix comprised of specified row vectors) template inline subview subview::rows(const uword in_row1, const uword in_row2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 > in_row2) || (in_row2 >= n_rows), "subview::rows(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword base_row1 = aux_row1 + in_row1; return subview(m, base_row1, aux_col1, subview_n_rows, n_cols ); } //! creation of subview (submatrix comprised of specified row vectors) template inline const subview subview::rows(const uword in_row1, const uword in_row2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 > in_row2) || (in_row2 >= n_rows), "subview::rows(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword base_row1 = aux_row1 + in_row1; return subview(m, base_row1, aux_col1, subview_n_rows, n_cols ); } //! creation of subview (submatrix comprised of specified column vectors) template inline subview subview::cols(const uword in_col1, const uword in_col2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_col1 > in_col2) || (in_col2 >= n_cols), "subview::cols(): indices out of bounds or incorrectly used" ); const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_col1 = aux_col1 + in_col1; return subview(m, aux_row1, base_col1, n_rows, subview_n_cols); } //! creation of subview (submatrix comprised of specified column vectors) template inline const subview subview::cols(const uword in_col1, const uword in_col2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_col1 > in_col2) || (in_col2 >= n_cols), "subview::cols(): indices out of bounds or incorrectly used" ); const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_col1 = aux_col1 + in_col1; return subview(m, aux_row1, base_col1, n_rows, subview_n_cols); } //! creation of subview (submatrix) template inline subview subview::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols), "subview::submat(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_row1 = aux_row1 + in_row1; const uword base_col1 = aux_col1 + in_col1; return subview(m, base_row1, base_col1, subview_n_rows, subview_n_cols); } //! creation of subview (generic submatrix) template inline const subview subview::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols), "subview::submat(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_row1 = aux_row1 + in_row1; const uword base_col1 = aux_col1 + in_col1; return subview(m, base_row1, base_col1, subview_n_rows, subview_n_cols); } //! creation of subview (submatrix) template inline subview subview::submat(const span& row_span, const span& col_span) { arma_extra_debug_sigprint(); const bool row_all = row_span.whole; const bool col_all = col_span.whole; const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; const uword in_row1 = row_all ? 0 : row_span.a; const uword in_row2 = row_span.b; const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; const uword in_col1 = col_all ? 0 : col_span.a; const uword in_col2 = col_span.b; const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; arma_debug_check_bounds ( ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) || ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) , "subview::submat(): indices out of bounds or incorrectly used" ); const uword base_row1 = aux_row1 + in_row1; const uword base_col1 = aux_col1 + in_col1; return subview(m, base_row1, base_col1, submat_n_rows, submat_n_cols); } //! creation of subview (generic submatrix) template inline const subview subview::submat(const span& row_span, const span& col_span) const { arma_extra_debug_sigprint(); const bool row_all = row_span.whole; const bool col_all = col_span.whole; const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; const uword in_row1 = row_all ? 0 : row_span.a; const uword in_row2 = row_span.b; const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1; const uword in_col1 = col_all ? 0 : col_span.a; const uword in_col2 = col_span.b; const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; arma_debug_check_bounds ( ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) ) || ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) ) , "subview::submat(): indices out of bounds or incorrectly used" ); const uword base_row1 = aux_row1 + in_row1; const uword base_col1 = aux_col1 + in_col1; return subview(m, base_row1, base_col1, submat_n_rows, submat_n_cols); } template inline subview subview::operator()(const span& row_span, const span& col_span) { arma_extra_debug_sigprint(); return (*this).submat(row_span, col_span); } template inline const subview subview::operator()(const span& row_span, const span& col_span) const { arma_extra_debug_sigprint(); return (*this).submat(row_span, col_span); } template inline subview_each1< subview, 0 > subview::each_col() { arma_extra_debug_sigprint(); return subview_each1< subview, 0 >(*this); } template inline subview_each1< subview, 1 > subview::each_row() { arma_extra_debug_sigprint(); return subview_each1< subview, 1 >(*this); } template template inline subview_each2< subview, 0, T1 > subview::each_col(const Base& indices) { arma_extra_debug_sigprint(); return subview_each2< subview, 0, T1 >(*this, indices); } template template inline subview_each2< subview, 1, T1 > subview::each_row(const Base& indices) { arma_extra_debug_sigprint(); return subview_each2< subview, 1, T1 >(*this, indices); } //! apply a lambda function to each column, where each column is interpreted as a column vector template inline void subview::each_col(const std::function< void(Col&) >& F) { arma_extra_debug_sigprint(); for(uword ii=0; ii < n_cols; ++ii) { Col tmp(colptr(ii), n_rows, false, true); F(tmp); } } template inline void subview::each_col(const std::function< void(const Col&) >& F) const { arma_extra_debug_sigprint(); for(uword ii=0; ii < n_cols; ++ii) { const Col tmp(colptr(ii), n_rows, false, true); F(tmp); } } //! apply a lambda function to each row, where each row is interpreted as a row vector template inline void subview::each_row(const std::function< void(Row&) >& F) { arma_extra_debug_sigprint(); podarray array1(n_cols); podarray array2(n_cols); Row tmp1( array1.memptr(), n_cols, false, true ); Row tmp2( array2.memptr(), n_cols, false, true ); eT* tmp1_mem = tmp1.memptr(); eT* tmp2_mem = tmp2.memptr(); uword ii, jj; for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2) { for(uword col_id = 0; col_id < n_cols; ++col_id) { const eT* col_mem = colptr(col_id); tmp1_mem[col_id] = col_mem[ii]; tmp2_mem[col_id] = col_mem[jj]; } F(tmp1); F(tmp2); for(uword col_id = 0; col_id < n_cols; ++col_id) { eT* col_mem = colptr(col_id); col_mem[ii] = tmp1_mem[col_id]; col_mem[jj] = tmp2_mem[col_id]; } } if(ii < n_rows) { tmp1 = (*this).row(ii); F(tmp1); (*this).row(ii) = tmp1; } } template inline void subview::each_row(const std::function< void(const Row&) >& F) const { arma_extra_debug_sigprint(); podarray array1(n_cols); podarray array2(n_cols); Row tmp1( array1.memptr(), n_cols, false, true ); Row tmp2( array2.memptr(), n_cols, false, true ); eT* tmp1_mem = tmp1.memptr(); eT* tmp2_mem = tmp2.memptr(); uword ii, jj; for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2) { for(uword col_id = 0; col_id < n_cols; ++col_id) { const eT* col_mem = colptr(col_id); tmp1_mem[col_id] = col_mem[ii]; tmp2_mem[col_id] = col_mem[jj]; } F(tmp1); F(tmp2); } if(ii < n_rows) { tmp1 = (*this).row(ii); F(tmp1); } } //! creation of diagview (diagonal) template inline diagview subview::diag(const sword in_id) { arma_extra_debug_sigprint(); const uword row_offset = (in_id < 0) ? uword(-in_id) : 0; const uword col_offset = (in_id > 0) ? uword( in_id) : 0; arma_debug_check_bounds ( ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)), "subview::diag(): requested diagonal out of bounds" ); const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset); const uword base_row_offset = aux_row1 + row_offset; const uword base_col_offset = aux_col1 + col_offset; return diagview(m, base_row_offset, base_col_offset, len); } //! creation of diagview (diagonal) template inline const diagview subview::diag(const sword in_id) const { arma_extra_debug_sigprint(); const uword row_offset = uword( (in_id < 0) ? -in_id : 0 ); const uword col_offset = uword( (in_id > 0) ? in_id : 0 ); arma_debug_check_bounds ( ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)), "subview::diag(): requested diagonal out of bounds" ); const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset); const uword base_row_offset = aux_row1 + row_offset; const uword base_col_offset = aux_col1 + col_offset; return diagview(m, base_row_offset, base_col_offset, len); } template inline void subview::swap_rows(const uword in_row1, const uword in_row2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 >= n_rows) || (in_row2 >= n_rows), "subview::swap_rows(): out of bounds" ); eT* mem = (const_cast< Mat& >(m)).memptr(); if(n_elem > 0) { const uword m_n_rows = m.n_rows; for(uword ucol=0; ucol < n_cols; ++ucol) { const uword offset = (aux_col1 + ucol) * m_n_rows; const uword pos1 = aux_row1 + in_row1 + offset; const uword pos2 = aux_row1 + in_row2 + offset; std::swap( access::rw(mem[pos1]), access::rw(mem[pos2]) ); } } } template inline void subview::swap_cols(const uword in_col1, const uword in_col2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_col1 >= n_cols) || (in_col2 >= n_cols), "subview::swap_cols(): out of bounds" ); if(n_elem > 0) { eT* ptr1 = colptr(in_col1); eT* ptr2 = colptr(in_col2); for(uword urow=0; urow < n_rows; ++urow) { std::swap( ptr1[urow], ptr2[urow] ); } } } template inline typename subview::iterator subview::begin() { return iterator(*this, aux_row1, aux_col1); } template inline typename subview::const_iterator subview::begin() const { return const_iterator(*this, aux_row1, aux_col1); } template inline typename subview::const_iterator subview::cbegin() const { return const_iterator(*this, aux_row1, aux_col1); } template inline typename subview::iterator subview::end() { return iterator(*this, aux_row1, aux_col1 + n_cols); } template inline typename subview::const_iterator subview::end() const { return const_iterator(*this, aux_row1, aux_col1 + n_cols); } template inline typename subview::const_iterator subview::cend() const { return const_iterator(*this, aux_row1, aux_col1 + n_cols); } // // // template inline subview::iterator::iterator() : M (nullptr) , current_ptr(nullptr) , current_row(0 ) , current_col(0 ) , aux_row1 (0 ) , aux_row2_p1(0 ) { arma_extra_debug_sigprint(); // Technically this iterator is invalid (it does not point to a valid element) } template inline subview::iterator::iterator(const iterator& X) : M (X.M ) , current_ptr(X.current_ptr) , current_row(X.current_row) , current_col(X.current_col) , aux_row1 (X.aux_row1 ) , aux_row2_p1(X.aux_row2_p1) { arma_extra_debug_sigprint(); } template inline subview::iterator::iterator(subview& in_sv, const uword in_row, const uword in_col) : M (&(const_cast< Mat& >(in_sv.m))) , current_ptr(&(M->at(in_row,in_col)) ) , current_row(in_row ) , current_col(in_col ) , aux_row1 (in_sv.aux_row1 ) , aux_row2_p1(in_sv.aux_row1 + in_sv.n_rows ) { arma_extra_debug_sigprint(); } template inline eT& subview::iterator::operator*() { return (*current_ptr); } template inline typename subview::iterator& subview::iterator::operator++() { current_row++; if(current_row == aux_row2_p1) { current_row = aux_row1; current_col++; current_ptr = &( (*M).at(current_row,current_col) ); } else { current_ptr++; } return *this; } template inline typename subview::iterator subview::iterator::operator++(int) { typename subview::iterator temp(*this); ++(*this); return temp; } template inline bool subview::iterator::operator==(const iterator& rhs) const { return (current_ptr == rhs.current_ptr); } template inline bool subview::iterator::operator!=(const iterator& rhs) const { return (current_ptr != rhs.current_ptr); } template inline bool subview::iterator::operator==(const const_iterator& rhs) const { return (current_ptr == rhs.current_ptr); } template inline bool subview::iterator::operator!=(const const_iterator& rhs) const { return (current_ptr != rhs.current_ptr); } // // // template inline subview::const_iterator::const_iterator() : M (nullptr) , current_ptr(nullptr) , current_row(0 ) , current_col(0 ) , aux_row1 (0 ) , aux_row2_p1(0 ) { arma_extra_debug_sigprint(); // Technically this iterator is invalid (it does not point to a valid element) } template inline subview::const_iterator::const_iterator(const iterator& X) : M (X.M ) , current_ptr(X.current_ptr) , current_row(X.current_row) , current_col(X.current_col) , aux_row1 (X.aux_row1 ) , aux_row2_p1(X.aux_row2_p1) { arma_extra_debug_sigprint(); } template inline subview::const_iterator::const_iterator(const const_iterator& X) : M (X.M ) , current_ptr(X.current_ptr) , current_row(X.current_row) , current_col(X.current_col) , aux_row1 (X.aux_row1 ) , aux_row2_p1(X.aux_row2_p1) { arma_extra_debug_sigprint(); } template inline subview::const_iterator::const_iterator(const subview& in_sv, const uword in_row, const uword in_col) : M (&(in_sv.m) ) , current_ptr(&(M->at(in_row,in_col)) ) , current_row(in_row ) , current_col(in_col ) , aux_row1 (in_sv.aux_row1 ) , aux_row2_p1(in_sv.aux_row1 + in_sv.n_rows) { arma_extra_debug_sigprint(); } template inline const eT& subview::const_iterator::operator*() { return (*current_ptr); } template inline typename subview::const_iterator& subview::const_iterator::operator++() { current_row++; if(current_row == aux_row2_p1) { current_row = aux_row1; current_col++; current_ptr = &( (*M).at(current_row,current_col) ); } else { current_ptr++; } return *this; } template inline typename subview::const_iterator subview::const_iterator::operator++(int) { typename subview::const_iterator temp(*this); ++(*this); return temp; } template inline bool subview::const_iterator::operator==(const iterator& rhs) const { return (current_ptr == rhs.current_ptr); } template inline bool subview::const_iterator::operator!=(const iterator& rhs) const { return (current_ptr != rhs.current_ptr); } template inline bool subview::const_iterator::operator==(const const_iterator& rhs) const { return (current_ptr == rhs.current_ptr); } template inline bool subview::const_iterator::operator!=(const const_iterator& rhs) const { return (current_ptr != rhs.current_ptr); } // // // template inline subview::row_iterator::row_iterator() : M (nullptr) , current_row(0 ) , current_col(0 ) , aux_col1 (0 ) , aux_col2_p1(0 ) { arma_extra_debug_sigprint(); // Technically this iterator is invalid (it does not point to a valid element) } template inline subview::row_iterator::row_iterator(const row_iterator& X) : M (X.M ) , current_row(X.current_row) , current_col(X.current_col) , aux_col1 (X.aux_col1 ) , aux_col2_p1(X.aux_col2_p1) { arma_extra_debug_sigprint(); } template inline subview::row_iterator::row_iterator(subview& in_sv, const uword in_row, const uword in_col) : M (&(const_cast< Mat& >(in_sv.m))) , current_row(in_row ) , current_col(in_col ) , aux_col1 (in_sv.aux_col1 ) , aux_col2_p1(in_sv.aux_col1 + in_sv.n_cols ) { arma_extra_debug_sigprint(); } template inline eT& subview::row_iterator::operator*() { return M->at(current_row,current_col); } template inline typename subview::row_iterator& subview::row_iterator::operator++() { current_col++; if(current_col == aux_col2_p1) { current_col = aux_col1; current_row++; } return *this; } template inline typename subview::row_iterator subview::row_iterator::operator++(int) { typename subview::row_iterator temp(*this); ++(*this); return temp; } template inline bool subview::row_iterator::operator==(const row_iterator& rhs) const { return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) ); } template inline bool subview::row_iterator::operator!=(const row_iterator& rhs) const { return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) ); } template inline bool subview::row_iterator::operator==(const const_row_iterator& rhs) const { return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) ); } template inline bool subview::row_iterator::operator!=(const const_row_iterator& rhs) const { return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) ); } // // // template inline subview::const_row_iterator::const_row_iterator() : M (nullptr) , current_row(0 ) , current_col(0 ) , aux_col1 (0 ) , aux_col2_p1(0 ) { arma_extra_debug_sigprint(); // Technically this iterator is invalid (it does not point to a valid element) } template inline subview::const_row_iterator::const_row_iterator(const row_iterator& X) : M (X.M ) , current_row(X.current_row) , current_col(X.current_col) , aux_col1 (X.aux_col1 ) , aux_col2_p1(X.aux_col2_p1) { arma_extra_debug_sigprint(); } template inline subview::const_row_iterator::const_row_iterator(const const_row_iterator& X) : M (X.M ) , current_row(X.current_row) , current_col(X.current_col) , aux_col1 (X.aux_col1 ) , aux_col2_p1(X.aux_col2_p1) { arma_extra_debug_sigprint(); } template inline subview::const_row_iterator::const_row_iterator(const subview& in_sv, const uword in_row, const uword in_col) : M (&(in_sv.m) ) , current_row(in_row ) , current_col(in_col ) , aux_col1 (in_sv.aux_col1 ) , aux_col2_p1(in_sv.aux_col1 + in_sv.n_cols) { arma_extra_debug_sigprint(); } template inline const eT& subview::const_row_iterator::operator*() const { return M->at(current_row,current_col); } template inline typename subview::const_row_iterator& subview::const_row_iterator::operator++() { current_col++; if(current_col == aux_col2_p1) { current_col = aux_col1; current_row++; } return *this; } template inline typename subview::const_row_iterator subview::const_row_iterator::operator++(int) { typename subview::const_row_iterator temp(*this); ++(*this); return temp; } template inline bool subview::const_row_iterator::operator==(const row_iterator& rhs) const { return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) ); } template inline bool subview::const_row_iterator::operator!=(const row_iterator& rhs) const { return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) ); } template inline bool subview::const_row_iterator::operator==(const const_row_iterator& rhs) const { return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) ); } template inline bool subview::const_row_iterator::operator!=(const const_row_iterator& rhs) const { return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) ); } // // // template inline subview_col::subview_col(const Mat& in_m, const uword in_col) : subview(in_m, 0, in_col, in_m.n_rows, 1) , colmem(subview::colptr(0)) { arma_extra_debug_sigprint(); } template inline subview_col::subview_col(const Mat& in_m, const uword in_col, const uword in_row1, const uword in_n_rows) : subview(in_m, in_row1, in_col, in_n_rows, 1) , colmem(subview::colptr(0)) { arma_extra_debug_sigprint(); } template inline subview_col::subview_col(const subview_col& in) : subview(in) // interprets 'subview_col' as 'subview' , colmem(in.colmem) { arma_extra_debug_sigprint(); } template inline subview_col::subview_col(subview_col&& in) : subview(std::move(in)) // interprets 'subview_col' as 'subview' , colmem(in.colmem) { arma_extra_debug_sigprint(); access::rw(in.colmem) = nullptr; } template inline void subview_col::operator=(const subview& X) { arma_extra_debug_sigprint(); subview::operator=(X); } template inline void subview_col::operator=(const subview_col& X) { arma_extra_debug_sigprint(); subview::operator=(X); // interprets 'subview_col' as 'subview' } template inline void subview_col::operator=(const std::initializer_list& list) { arma_extra_debug_sigprint(); const uword N = uword(list.size()); arma_debug_assert_same_size(subview::n_rows, subview::n_cols, N, 1, "copy into submatrix"); arrayops::copy( access::rwp(colmem), list.begin(), N ); } template inline void subview_col::operator=(const eT val) { arma_extra_debug_sigprint(); if(subview::n_elem != 1) { arma_debug_assert_same_size(subview::n_rows, subview::n_cols, 1, 1, "copy into submatrix"); } access::rw( colmem[0] ) = val; } template template inline void subview_col::operator=(const Base& X) { arma_extra_debug_sigprint(); subview::operator=(X); } template template inline void subview_col::operator=(const SpBase& X) { arma_extra_debug_sigprint(); subview::operator=(X.get_ref()); } template template inline typename enable_if2< is_same_type::value, void>::result subview_col::operator= (const Gen& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(subview::n_rows, uword(1), in.n_rows, (in.is_col ? uword(1) : in.n_cols), "copy into submatrix"); in.apply(*this); } template arma_inline const Op,op_htrans> subview_col::t() const { return Op,op_htrans>(*this); } template arma_inline const Op,op_htrans> subview_col::ht() const { return Op,op_htrans>(*this); } template arma_inline const Op,op_strans> subview_col::st() const { return Op,op_strans>(*this); } template arma_inline const Op,op_strans> subview_col::as_row() const { return Op,op_strans>(*this); } template inline void subview_col::fill(const eT val) { arma_extra_debug_sigprint(); arrayops::inplace_set( access::rwp(colmem), val, subview::n_rows ); } template inline void subview_col::zeros() { arma_extra_debug_sigprint(); arrayops::fill_zeros( access::rwp(colmem), subview::n_rows ); } template inline void subview_col::ones() { arma_extra_debug_sigprint(); arrayops::inplace_set( access::rwp(colmem), eT(1), subview::n_rows ); } template arma_inline eT subview_col::at_alt(const uword ii) const { const eT* colmem_aligned = colmem; memory::mark_as_aligned(colmem_aligned); return colmem_aligned[ii]; } template arma_inline eT& subview_col::operator[](const uword ii) { return access::rw( colmem[ii] ); } template arma_inline eT subview_col::operator[](const uword ii) const { return colmem[ii]; } template inline eT& subview_col::operator()(const uword ii) { arma_debug_check_bounds( (ii >= subview::n_elem), "subview::operator(): index out of bounds" ); return access::rw( colmem[ii] ); } template inline eT subview_col::operator()(const uword ii) const { arma_debug_check_bounds( (ii >= subview::n_elem), "subview::operator(): index out of bounds" ); return colmem[ii]; } template inline eT& subview_col::operator()(const uword in_row, const uword in_col) { arma_debug_check_bounds( ((in_row >= subview::n_rows) || (in_col > 0)), "subview::operator(): index out of bounds" ); return access::rw( colmem[in_row] ); } template inline eT subview_col::operator()(const uword in_row, const uword in_col) const { arma_debug_check_bounds( ((in_row >= subview::n_rows) || (in_col > 0)), "subview::operator(): index out of bounds" ); return colmem[in_row]; } template inline eT& subview_col::at(const uword in_row, const uword) { return access::rw( colmem[in_row] ); } template inline eT subview_col::at(const uword in_row, const uword) const { return colmem[in_row]; } template arma_inline eT* subview_col::colptr(const uword) { return const_cast(colmem); } template arma_inline const eT* subview_col::colptr(const uword) const { return colmem; } template inline subview_col subview_col::rows(const uword in_row1, const uword in_row2) { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview::n_rows) ), "subview_col::rows(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword base_row1 = this->aux_row1 + in_row1; return subview_col(this->m, this->aux_col1, base_row1, subview_n_rows); } template inline const subview_col subview_col::rows(const uword in_row1, const uword in_row2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview::n_rows) ), "subview_col::rows(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword base_row1 = this->aux_row1 + in_row1; return subview_col(this->m, this->aux_col1, base_row1, subview_n_rows); } template inline subview_col subview_col::subvec(const uword in_row1, const uword in_row2) { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview::n_rows) ), "subview_col::subvec(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword base_row1 = this->aux_row1 + in_row1; return subview_col(this->m, this->aux_col1, base_row1, subview_n_rows); } template inline const subview_col subview_col::subvec(const uword in_row1, const uword in_row2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview::n_rows) ), "subview_col::subvec(): indices out of bounds or incorrectly used" ); const uword subview_n_rows = in_row2 - in_row1 + 1; const uword base_row1 = this->aux_row1 + in_row1; return subview_col(this->m, this->aux_col1, base_row1, subview_n_rows); } template inline subview_col subview_col::subvec(const uword start_row, const SizeMat& s) { arma_extra_debug_sigprint(); arma_debug_check( (s.n_cols != 1), "subview_col::subvec(): given size does not specify a column vector" ); arma_debug_check_bounds( ( (start_row >= subview::n_rows) || ((start_row + s.n_rows) > subview::n_rows) ), "subview_col::subvec(): size out of bounds" ); const uword base_row1 = this->aux_row1 + start_row; return subview_col(this->m, this->aux_col1, base_row1, s.n_rows); } template inline const subview_col subview_col::subvec(const uword start_row, const SizeMat& s) const { arma_extra_debug_sigprint(); arma_debug_check( (s.n_cols != 1), "subview_col::subvec(): given size does not specify a column vector" ); arma_debug_check_bounds( ( (start_row >= subview::n_rows) || ((start_row + s.n_rows) > subview::n_rows) ), "subview_col::subvec(): size out of bounds" ); const uword base_row1 = this->aux_row1 + start_row; return subview_col(this->m, this->aux_col1, base_row1, s.n_rows); } template inline subview_col subview_col::head(const uword N) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_rows), "subview_col::head(): size out of bounds" ); return subview_col(this->m, this->aux_col1, this->aux_row1, N); } template inline const subview_col subview_col::head(const uword N) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_rows), "subview_col::head(): size out of bounds" ); return subview_col(this->m, this->aux_col1, this->aux_row1, N); } template inline subview_col subview_col::tail(const uword N) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_rows), "subview_col::tail(): size out of bounds" ); const uword start_row = subview::aux_row1 + subview::n_rows - N; return subview_col(this->m, this->aux_col1, start_row, N); } template inline const subview_col subview_col::tail(const uword N) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_rows), "subview_col::tail(): size out of bounds" ); const uword start_row = subview::aux_row1 + subview::n_rows - N; return subview_col(this->m, this->aux_col1, start_row, N); } template inline eT subview_col::min() const { arma_extra_debug_sigprint(); if(subview::n_elem == 0) { arma_debug_check(true, "min(): object has no elements"); return Datum::nan; } return op_min::direct_min(colmem, subview::n_elem); } template inline eT subview_col::max() const { arma_extra_debug_sigprint(); if(subview::n_elem == 0) { arma_debug_check(true, "max(): object has no elements"); return Datum::nan; } return op_max::direct_max(colmem, subview::n_elem); } template inline eT subview_col::min(uword& index_of_min_val) const { arma_extra_debug_sigprint(); if(subview::n_elem == 0) { arma_debug_check(true, "min(): object has no elements"); index_of_min_val = uword(0); return Datum::nan; } else { return op_min::direct_min(colmem, subview::n_elem, index_of_min_val); } } template inline eT subview_col::max(uword& index_of_max_val) const { arma_extra_debug_sigprint(); if(subview::n_elem == 0) { arma_debug_check(true, "max(): object has no elements"); index_of_max_val = uword(0); return Datum::nan; } else { return op_max::direct_max(colmem, subview::n_elem, index_of_max_val); } } template inline uword subview_col::index_min() const { arma_extra_debug_sigprint(); uword index = 0; if(subview::n_elem == 0) { arma_debug_check(true, "index_min(): object has no elements"); } else { op_min::direct_min(colmem, subview::n_elem, index); } return index; } template inline uword subview_col::index_max() const { arma_extra_debug_sigprint(); uword index = 0; if(subview::n_elem == 0) { arma_debug_check(true, "index_max(): object has no elements"); } else { op_max::direct_max(colmem, subview::n_elem, index); } return index; } // // // template inline subview_cols::subview_cols(const Mat& in_m, const uword in_col1, const uword in_n_cols) : subview(in_m, 0, in_col1, in_m.n_rows, in_n_cols) { arma_extra_debug_sigprint(); } template inline subview_cols::subview_cols(const subview_cols& in) : subview(in) // interprets 'subview_cols' as 'subview' { arma_extra_debug_sigprint(); } template inline subview_cols::subview_cols(subview_cols&& in) : subview(std::move(in)) // interprets 'subview_cols' as 'subview' { arma_extra_debug_sigprint(); } template inline void subview_cols::operator=(const subview& X) { arma_extra_debug_sigprint(); subview::operator=(X); } template inline void subview_cols::operator=(const subview_cols& X) { arma_extra_debug_sigprint(); subview::operator=(X); // interprets 'subview_cols' as 'subview' } template inline void subview_cols::operator=(const std::initializer_list& list) { arma_extra_debug_sigprint(); subview::operator=(list); } template inline void subview_cols::operator=(const std::initializer_list< std::initializer_list >& list) { arma_extra_debug_sigprint(); subview::operator=(list); } template inline void subview_cols::operator=(const eT val) { arma_extra_debug_sigprint(); subview::operator=(val); } template template inline void subview_cols::operator=(const Base& X) { arma_extra_debug_sigprint(); subview::operator=(X.get_ref()); } template template inline void subview_cols::operator=(const SpBase& X) { arma_extra_debug_sigprint(); subview::operator=(X.get_ref()); } template template inline typename enable_if2< is_same_type::value, void>::result subview_cols::operator= (const Gen& in) { arma_extra_debug_sigprint(); subview::operator=(in); } template arma_inline const Op,op_htrans> subview_cols::t() const { return Op,op_htrans>(*this); } template arma_inline const Op,op_htrans> subview_cols::ht() const { return Op,op_htrans>(*this); } template arma_inline const Op,op_strans> subview_cols::st() const { return Op,op_strans>(*this); } template arma_inline const Op,op_vectorise_col> subview_cols::as_col() const { return Op,op_vectorise_col>(*this); } template inline eT subview_cols::at_alt(const uword ii) const { return operator[](ii); } template inline eT& subview_cols::operator[](const uword ii) { const uword index = subview::aux_col1 * subview::m.n_rows + ii; return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_cols::operator[](const uword ii) const { const uword index = subview::aux_col1 * subview::m.n_rows + ii; return subview::m.mem[index]; } template inline eT& subview_cols::operator()(const uword ii) { arma_debug_check_bounds( (ii >= subview::n_elem), "subview::operator(): index out of bounds" ); const uword index = subview::aux_col1 * subview::m.n_rows + ii; return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_cols::operator()(const uword ii) const { arma_debug_check_bounds( (ii >= subview::n_elem), "subview::operator(): index out of bounds" ); const uword index = subview::aux_col1 * subview::m.n_rows + ii; return subview::m.mem[index]; } template inline eT& subview_cols::operator()(const uword in_row, const uword in_col) { arma_debug_check_bounds( ((in_row >= subview::n_rows) || (in_col >= subview::n_cols)), "subview::operator(): index out of bounds" ); const uword index = (in_col + subview::aux_col1) * subview::m.n_rows + in_row; return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_cols::operator()(const uword in_row, const uword in_col) const { arma_debug_check_bounds( ((in_row >= subview::n_rows) || (in_col >= subview::n_cols)), "subview::operator(): index out of bounds" ); const uword index = (in_col + subview::aux_col1) * subview::m.n_rows + in_row; return subview::m.mem[index]; } template inline eT& subview_cols::at(const uword in_row, const uword in_col) { const uword index = (in_col + subview::aux_col1) * subview::m.n_rows + in_row; return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_cols::at(const uword in_row, const uword in_col) const { const uword index = (in_col + subview::aux_col1) * subview::m.n_rows + in_row; return subview::m.mem[index]; } template arma_inline eT* subview_cols::colptr(const uword in_col) { return & access::rw((const_cast< Mat& >(subview::m)).mem[ (in_col + subview::aux_col1) * subview::m.n_rows ]); } template arma_inline const eT* subview_cols::colptr(const uword in_col) const { return & subview::m.mem[ (in_col + subview::aux_col1) * subview::m.n_rows ]; } // // // template inline subview_row::subview_row(const Mat& in_m, const uword in_row) : subview(in_m, in_row, 0, 1, in_m.n_cols) { arma_extra_debug_sigprint(); } template inline subview_row::subview_row(const Mat& in_m, const uword in_row, const uword in_col1, const uword in_n_cols) : subview(in_m, in_row, in_col1, 1, in_n_cols) { arma_extra_debug_sigprint(); } template inline subview_row::subview_row(const subview_row& in) : subview(in) // interprets 'subview_row' as 'subview' { arma_extra_debug_sigprint(); } template inline subview_row::subview_row(subview_row&& in) : subview(std::move(in)) // interprets 'subview_row' as 'subview' { arma_extra_debug_sigprint(); } template inline void subview_row::operator=(const subview& X) { arma_extra_debug_sigprint(); subview::operator=(X); } template inline void subview_row::operator=(const subview_row& X) { arma_extra_debug_sigprint(); subview::operator=(X); // interprets 'subview_row' as 'subview' } template inline void subview_row::operator=(const eT val) { arma_extra_debug_sigprint(); subview::operator=(val); // interprets 'subview_row' as 'subview' } template inline void subview_row::operator=(const std::initializer_list& list) { arma_extra_debug_sigprint(); const uword N = uword(list.size()); arma_debug_assert_same_size(subview::n_rows, subview::n_cols, 1, N, "copy into submatrix"); auto it = list.begin(); for(uword ii=0; ii < N; ++ii) { (*this).operator[](ii) = (*it); ++it; } } template template inline void subview_row::operator=(const Base& X) { arma_extra_debug_sigprint(); subview::operator=(X); } template template inline void subview_row::operator=(const SpBase& X) { arma_extra_debug_sigprint(); subview::operator=(X.get_ref()); } template template inline typename enable_if2< is_same_type::value, void>::result subview_row::operator= (const Gen& in) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(uword(1), subview::n_cols, (in.is_row ? uword(1) : in.n_rows), in.n_cols, "copy into submatrix"); in.apply(*this); } template arma_inline const Op,op_htrans> subview_row::t() const { return Op,op_htrans>(*this); } template arma_inline const Op,op_htrans> subview_row::ht() const { return Op,op_htrans>(*this); } template arma_inline const Op,op_strans> subview_row::st() const { return Op,op_strans>(*this); } template arma_inline const Op,op_strans> subview_row::as_col() const { return Op,op_strans>(*this); } template inline eT subview_row::at_alt(const uword ii) const { const uword index = (ii + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return subview::m.mem[index]; } template inline eT& subview_row::operator[](const uword ii) { const uword index = (ii + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_row::operator[](const uword ii) const { const uword index = (ii + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return subview::m.mem[index]; } template inline eT& subview_row::operator()(const uword ii) { arma_debug_check_bounds( (ii >= subview::n_elem), "subview::operator(): index out of bounds" ); const uword index = (ii + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_row::operator()(const uword ii) const { arma_debug_check_bounds( (ii >= subview::n_elem), "subview::operator(): index out of bounds" ); const uword index = (ii + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return subview::m.mem[index]; } template inline eT& subview_row::operator()(const uword in_row, const uword in_col) { arma_debug_check_bounds( ((in_row > 0) || (in_col >= subview::n_cols)), "subview::operator(): index out of bounds" ); const uword index = (in_col + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_row::operator()(const uword in_row, const uword in_col) const { arma_debug_check_bounds( ((in_row > 0) || (in_col >= subview::n_cols)), "subview::operator(): index out of bounds" ); const uword index = (in_col + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return subview::m.mem[index]; } template inline eT& subview_row::at(const uword, const uword in_col) { const uword index = (in_col + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return access::rw( (const_cast< Mat& >(subview::m)).mem[index] ); } template inline eT subview_row::at(const uword, const uword in_col) const { const uword index = (in_col + (subview::aux_col1))*(subview::m).n_rows + (subview::aux_row1); return subview::m.mem[index]; } template inline subview_row subview_row::cols(const uword in_col1, const uword in_col2) { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview::n_cols) ), "subview_row::cols(): indices out of bounds or incorrectly used" ); const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_col1 = this->aux_col1 + in_col1; return subview_row(this->m, this->aux_row1, base_col1, subview_n_cols); } template inline const subview_row subview_row::cols(const uword in_col1, const uword in_col2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview::n_cols) ), "subview_row::cols(): indices out of bounds or incorrectly used" ); const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_col1 = this->aux_col1 + in_col1; return subview_row(this->m, this->aux_row1, base_col1, subview_n_cols); } template inline subview_row subview_row::subvec(const uword in_col1, const uword in_col2) { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview::n_cols) ), "subview_row::subvec(): indices out of bounds or incorrectly used" ); const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_col1 = this->aux_col1 + in_col1; return subview_row(this->m, this->aux_row1, base_col1, subview_n_cols); } template inline const subview_row subview_row::subvec(const uword in_col1, const uword in_col2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview::n_cols) ), "subview_row::subvec(): indices out of bounds or incorrectly used" ); const uword subview_n_cols = in_col2 - in_col1 + 1; const uword base_col1 = this->aux_col1 + in_col1; return subview_row(this->m, this->aux_row1, base_col1, subview_n_cols); } template inline subview_row subview_row::subvec(const uword start_col, const SizeMat& s) { arma_extra_debug_sigprint(); arma_debug_check( (s.n_rows != 1), "subview_row::subvec(): given size does not specify a row vector" ); arma_debug_check_bounds( ( (start_col >= subview::n_cols) || ((start_col + s.n_cols) > subview::n_cols) ), "subview_row::subvec(): size out of bounds" ); const uword base_col1 = this->aux_col1 + start_col; return subview_row(this->m, this->aux_row1, base_col1, s.n_cols); } template inline const subview_row subview_row::subvec(const uword start_col, const SizeMat& s) const { arma_extra_debug_sigprint(); arma_debug_check( (s.n_rows != 1), "subview_row::subvec(): given size does not specify a row vector" ); arma_debug_check_bounds( ( (start_col >= subview::n_cols) || ((start_col + s.n_cols) > subview::n_cols) ), "subview_row::subvec(): size out of bounds" ); const uword base_col1 = this->aux_col1 + start_col; return subview_row(this->m, this->aux_row1, base_col1, s.n_cols); } template inline subview_row subview_row::head(const uword N) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_cols), "subview_row::head(): size out of bounds" ); return subview_row(this->m, this->aux_row1, this->aux_col1, N); } template inline const subview_row subview_row::head(const uword N) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_cols), "subview_row::head(): size out of bounds" ); return subview_row(this->m, this->aux_row1, this->aux_col1, N); } template inline subview_row subview_row::tail(const uword N) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_cols), "subview_row::tail(): size out of bounds" ); const uword start_col = subview::aux_col1 + subview::n_cols - N; return subview_row(this->m, this->aux_row1, start_col, N); } template inline const subview_row subview_row::tail(const uword N) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > subview::n_cols), "subview_row::tail(): size out of bounds" ); const uword start_col = subview::aux_col1 + subview::n_cols - N; return subview_row(this->m, this->aux_row1, start_col, N); } template inline uword subview_row::index_min() const { const Proxy< subview_row > P(*this); uword index = 0; if(P.get_n_elem() == 0) { arma_debug_check(true, "index_min(): object has no elements"); } else { op_min::min_with_index(P, index); } return index; } template inline uword subview_row::index_max() const { const Proxy< subview_row > P(*this); uword index = 0; if(P.get_n_elem() == 0) { arma_debug_check(true, "index_max(): object has no elements"); } else { op_max::max_with_index(P, index); } return index; } template inline typename subview::row_iterator subview_row::begin() { return typename subview::row_iterator(*this, subview::aux_row1, subview::aux_col1); } template inline typename subview::const_row_iterator subview_row::begin() const { return typename subview::const_row_iterator(*this, subview::aux_row1, subview::aux_col1); } template inline typename subview::const_row_iterator subview_row::cbegin() const { return typename subview::const_row_iterator(*this, subview::aux_row1, subview::aux_col1); } template inline typename subview::row_iterator subview_row::end() { return typename subview::row_iterator(*this, subview::aux_row1 + subview::n_rows, subview::aux_col1); } template inline typename subview::const_row_iterator subview_row::end() const { return typename subview::const_row_iterator(*this, subview::aux_row1 + subview::n_rows, subview::aux_col1); } template inline typename subview::const_row_iterator subview_row::cend() const { return typename subview::const_row_iterator(*this, subview::aux_row1 + subview::n_rows, subview::aux_col1); } // // // template inline subview_row_strans::subview_row_strans(const subview_row& in_sv_row) : sv_row(in_sv_row ) , n_rows(in_sv_row.n_cols) , n_elem(in_sv_row.n_elem) { arma_extra_debug_sigprint(); } template inline void subview_row_strans::extract(Mat& out) const { arma_extra_debug_sigprint(); // NOTE: this function assumes that matrix 'out' has already been set to the correct size const Mat& X = sv_row.m; eT* out_mem = out.memptr(); const uword row = sv_row.aux_row1; const uword start_col = sv_row.aux_col1; const uword sv_row_n_cols = sv_row.n_cols; uword ii,jj; for(ii=0, jj=1; jj < sv_row_n_cols; ii+=2, jj+=2) { const eT tmp1 = X.at(row, start_col+ii); const eT tmp2 = X.at(row, start_col+jj); out_mem[ii] = tmp1; out_mem[jj] = tmp2; } if(ii < sv_row_n_cols) { out_mem[ii] = X.at(row, start_col+ii); } } template inline eT subview_row_strans::at_alt(const uword ii) const { return sv_row[ii]; } template inline eT subview_row_strans::operator[](const uword ii) const { return sv_row[ii]; } template inline eT subview_row_strans::operator()(const uword ii) const { return sv_row(ii); } template inline eT subview_row_strans::operator()(const uword in_row, const uword in_col) const { return sv_row(in_col, in_row); // deliberately swapped } template inline eT subview_row_strans::at(const uword in_row, const uword) const { return sv_row.at(0, in_row); // deliberately swapped } // // // template inline subview_row_htrans::subview_row_htrans(const subview_row& in_sv_row) : sv_row(in_sv_row ) , n_rows(in_sv_row.n_cols) , n_elem(in_sv_row.n_elem) { arma_extra_debug_sigprint(); } template inline void subview_row_htrans::extract(Mat& out) const { arma_extra_debug_sigprint(); // NOTE: this function assumes that matrix 'out' has already been set to the correct size const Mat& X = sv_row.m; eT* out_mem = out.memptr(); const uword row = sv_row.aux_row1; const uword start_col = sv_row.aux_col1; const uword sv_row_n_cols = sv_row.n_cols; for(uword ii=0; ii < sv_row_n_cols; ++ii) { out_mem[ii] = access::alt_conj( X.at(row, start_col+ii) ); } } template inline eT subview_row_htrans::at_alt(const uword ii) const { return access::alt_conj( sv_row[ii] ); } template inline eT subview_row_htrans::operator[](const uword ii) const { return access::alt_conj( sv_row[ii] ); } template inline eT subview_row_htrans::operator()(const uword ii) const { return access::alt_conj( sv_row(ii) ); } template inline eT subview_row_htrans::operator()(const uword in_row, const uword in_col) const { return access::alt_conj( sv_row(in_col, in_row) ); // deliberately swapped } template inline eT subview_row_htrans::at(const uword in_row, const uword) const { return access::alt_conj( sv_row.at(0, in_row) ); // deliberately swapped } //! @}