// 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_cube_each //! @{ // // // subview_cube_each_common template inline subview_cube_each_common::subview_cube_each_common(const Cube& in_p) : P(in_p) { arma_extra_debug_sigprint(); } template template inline void subview_cube_each_common::check_size(const Mat& A) const { if(arma_config::debug) { if( (A.n_rows != P.n_rows) || (A.n_cols != P.n_cols) ) { arma_stop_logic_error( incompat_size_string(A) ); } } } template template inline const std::string subview_cube_each_common::incompat_size_string(const Mat& A) const { std::ostringstream tmp; tmp << "each_slice(): incompatible size; expected " << P.n_rows << 'x' << P.n_cols << ", got " << A.n_rows << 'x' << A.n_cols; return tmp.str(); } // // // subview_cube_each1 template inline subview_cube_each1::~subview_cube_each1() { arma_extra_debug_sigprint(); } template inline subview_cube_each1::subview_cube_each1(const Cube& in_p) : subview_cube_each_common::subview_cube_each_common(in_p) { arma_extra_debug_sigprint(); } template template inline void subview_cube_each1::operator= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const eT* A_mem = A.memptr(); for(uword i=0; i < p_n_slices; ++i) { arrayops::copy( p.slice_memptr(i), A_mem, p_n_elem_slice ); } } template template inline void subview_cube_each1::operator+= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const eT* A_mem = A.memptr(); for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_plus( p.slice_memptr(i), A_mem, p_n_elem_slice ); } } template template inline void subview_cube_each1::operator-= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const eT* A_mem = A.memptr(); for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_minus( p.slice_memptr(i), A_mem, p_n_elem_slice ); } } template template inline void subview_cube_each1::operator%= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const eT* A_mem = A.memptr(); for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_mul( p.slice_memptr(i), A_mem, p_n_elem_slice ); } } template template inline void subview_cube_each1::operator/= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const eT* A_mem = A.memptr(); for(uword i=0; i < p_n_slices; ++i) { arrayops::inplace_div( p.slice_memptr(i), A_mem, p_n_elem_slice ); } } template template inline void subview_cube_each1::operator*= (const Base& in) { arma_extra_debug_sigprint(); Cube& C = access::rw(subview_cube_each_common::P); C = C.each_slice() * in.get_ref(); } // // // subview_cube_each2 template inline subview_cube_each2::~subview_cube_each2() { arma_extra_debug_sigprint(); } template inline subview_cube_each2::subview_cube_each2(const Cube& in_p, const Base& in_indices) : subview_cube_each_common::subview_cube_each_common(in_p) , base_indices(in_indices) { arma_extra_debug_sigprint(); } template inline void subview_cube_each2::check_indices(const Mat& indices) const { arma_debug_check( ((indices.is_vec() == false) && (indices.is_empty() == false)), "each_slice(): list of indices must be a vector" ); } template template inline void subview_cube_each2::operator= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const unwrap U( base_indices.get_ref() ); check_indices(U.M); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::copy(p.slice_memptr(slice), A_mem, p_n_elem_slice); } } template template inline void subview_cube_each2::operator+= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const unwrap U( base_indices.get_ref() ); check_indices(U.M); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_plus(p.slice_memptr(slice), A_mem, p_n_elem_slice); } } template template inline void subview_cube_each2::operator-= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const unwrap U( base_indices.get_ref() ); check_indices(U.M); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_minus(p.slice_memptr(slice), A_mem, p_n_elem_slice); } } template template inline void subview_cube_each2::operator%= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const unwrap U( base_indices.get_ref() ); check_indices(U.M); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_mul(p.slice_memptr(slice), A_mem, p_n_elem_slice); } } template template inline void subview_cube_each2::operator/= (const Base& in) { arma_extra_debug_sigprint(); Cube& p = access::rw(subview_cube_each_common::P); const unwrap tmp( in.get_ref() ); const Mat& A = tmp.M; subview_cube_each_common::check_size(A); const unwrap U( base_indices.get_ref() ); check_indices(U.M); const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; const uword* indices_mem = U.M.memptr(); const uword N = U.M.n_elem; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_div(p.slice_memptr(slice), A_mem, p_n_elem_slice); } } // // // subview_cube_each1_aux template inline Cube subview_cube_each1_aux::operator_plus ( const subview_cube_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator()); const unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); for(uword i=0; i < p_n_slices; ++i) { Mat out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true); out_slice = p_slice + A; } return out; } template inline Cube subview_cube_each1_aux::operator_minus ( const subview_cube_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator()); const unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); for(uword i=0; i < p_n_slices; ++i) { Mat out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true); out_slice = p_slice - A; } return out; } template inline Cube subview_cube_each1_aux::operator_minus ( const Base& X, const subview_cube_each1& Y ) { arma_extra_debug_sigprint(); const Cube& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator()); const unwrap tmp(X.get_ref()); const Mat& A = tmp.M; Y.check_size(A); for(uword i=0; i < p_n_slices; ++i) { Mat out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true); out_slice = A - p_slice; } return out; } template inline Cube subview_cube_each1_aux::operator_schur ( const subview_cube_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator()); const unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); for(uword i=0; i < p_n_slices; ++i) { Mat out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true); out_slice = p_slice % A; } return out; } template inline Cube subview_cube_each1_aux::operator_div ( const subview_cube_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator()); const unwrap tmp(Y.get_ref()); const Mat& A = tmp.M; X.check_size(A); for(uword i=0; i < p_n_slices; ++i) { Mat out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true); out_slice = p_slice / A; } return out; } template inline Cube subview_cube_each1_aux::operator_div ( const Base& X, const subview_cube_each1& Y ) { arma_extra_debug_sigprint(); const Cube& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator()); const unwrap tmp(X.get_ref()); const Mat& A = tmp.M; Y.check_size(A); for(uword i=0; i < p_n_slices; ++i) { Mat out_slice( out.slice_memptr(i), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true); out_slice = A / p_slice; } return out; } template inline Cube subview_cube_each1_aux::operator_times ( const subview_cube_each1& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& C = X.P; const unwrap tmp(Y.get_ref()); const Mat& M = tmp.M; Cube out(C.n_rows, M.n_cols, C.n_slices, arma_nozeros_indicator()); for(uword i=0; i < C.n_slices; ++i) { Mat out_slice( out.slice_memptr(i), C.n_rows, M.n_cols, false, true); const Mat C_slice(const_cast(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true); out_slice = C_slice * M; } return out; } template inline Cube subview_cube_each1_aux::operator_times ( const Base& X, const subview_cube_each1& Y ) { arma_extra_debug_sigprint(); const unwrap tmp(X.get_ref()); const Mat& M = tmp.M; const Cube& C = Y.P; Cube out(M.n_rows, C.n_cols, C.n_slices, arma_nozeros_indicator()); for(uword i=0; i < C.n_slices; ++i) { Mat out_slice( out.slice_memptr(i), M.n_rows, C.n_cols, false, true); const Mat C_slice(const_cast(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true); out_slice = M * C_slice; } return out; } // // // subview_cube_each2_aux template inline Cube subview_cube_each2_aux::operator_plus ( const subview_cube_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; Cube out = p; const 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; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_plus(out.slice_memptr(slice), A_mem, p_n_elem_slice); } return out; } template inline Cube subview_cube_each2_aux::operator_minus ( const subview_cube_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; Cube out = p; const 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; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_minus(out.slice_memptr(slice), A_mem, p_n_elem_slice); } return out; } template inline Cube subview_cube_each2_aux::operator_minus ( const Base& X, const subview_cube_each2& Y ) { arma_extra_debug_sigprint(); const Cube& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out = p; const 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; for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); Mat out_slice( out.slice_memptr(slice), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(slice)), p_n_rows, p_n_cols, false, true); out_slice = A - p_slice; } return out; } template inline Cube subview_cube_each2_aux::operator_schur ( const subview_cube_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; Cube out = p; const 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; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_mul(out.slice_memptr(slice), A_mem, p_n_elem_slice); } return out; } template inline Cube subview_cube_each2_aux::operator_div ( const subview_cube_each2& X, const Base& Y ) { arma_extra_debug_sigprint(); const Cube& p = X.P; const uword p_n_slices = p.n_slices; const uword p_n_elem_slice = p.n_elem_slice; Cube out = p; const 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; const eT* A_mem = A.memptr(); for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); arrayops::inplace_div(out.slice_memptr(slice), A_mem, p_n_elem_slice); } return out; } template inline Cube subview_cube_each2_aux::operator_div ( const Base& X, const subview_cube_each2& Y ) { arma_extra_debug_sigprint(); const Cube& p = Y.P; const uword p_n_rows = p.n_rows; const uword p_n_cols = p.n_cols; const uword p_n_slices = p.n_slices; Cube out = p; const 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; for(uword i=0; i < N; ++i) { const uword slice = indices_mem[i]; arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" ); Mat out_slice( out.slice_memptr(slice), p_n_rows, p_n_cols, false, true); const Mat p_slice(const_cast(p.slice_memptr(slice)), p_n_rows, p_n_cols, false, true); out_slice = A / p_slice; } return out; } //! @}