// 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 Cube //! @{ template inline Cube::~Cube() { arma_extra_debug_sigprint_this(this); delete_mat(); if( (mem_state == 0) && (n_alloc > 0) ) { arma_extra_debug_print("Cube::destructor: releasing memory"); memory::release( access::rw(mem) ); } // try to expose buggy user code that accesses deleted objects if(arma_config::debug) { access::rw(mem) = nullptr; } arma_type_check(( is_supported_elem_type::value == false )); } template inline Cube::Cube() : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); } //! construct the cube to have user specified dimensions template inline Cube::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices) : n_rows(in_n_rows) , n_cols(in_n_cols) , n_elem_slice(in_n_rows*in_n_cols) , n_slices(in_n_slices) , n_elem(in_n_rows*in_n_cols*in_n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); if(arma_config::zero_init) { arma_extra_debug_print("Cube::constructor: zeroing memory"); arrayops::fill_zeros(memptr(), n_elem); } } template inline Cube::Cube(const SizeCube& s) : n_rows(s.n_rows) , n_cols(s.n_cols) , n_elem_slice(s.n_rows*s.n_cols) , n_slices(s.n_slices) , n_elem(s.n_rows*s.n_cols*s.n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); if(arma_config::zero_init) { arma_extra_debug_print("Cube::constructor: zeroing memory"); arrayops::fill_zeros(memptr(), n_elem); } } //! internal use only template template inline Cube::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const arma_initmode_indicator&) : n_rows(in_n_rows) , n_cols(in_n_cols) , n_elem_slice(in_n_rows*in_n_cols) , n_slices(in_n_slices) , n_elem(in_n_rows*in_n_cols*in_n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); if(do_zeros) { arma_extra_debug_print("Cube::constructor: zeroing memory"); arrayops::fill_zeros(memptr(), n_elem); } } //! internal use only template template inline Cube::Cube(const SizeCube& s, const arma_initmode_indicator&) : n_rows(s.n_rows) , n_cols(s.n_cols) , n_elem_slice(s.n_rows*s.n_cols) , n_slices(s.n_slices) , n_elem(s.n_rows*s.n_cols*s.n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); if(do_zeros) { arma_extra_debug_print("Cube::constructor: zeroing memory"); arrayops::fill_zeros(memptr(), n_elem); } } //! construct the cube to have user specified dimensions and fill with specified pattern template template inline Cube::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const fill::fill_class&) : n_rows(in_n_rows) , n_cols(in_n_cols) , n_elem_slice(in_n_rows*in_n_cols) , n_slices(in_n_slices) , n_elem(in_n_rows*in_n_cols*in_n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); if(is_same_type::yes) { (*this).zeros(); } if(is_same_type::yes) { (*this).ones(); } if(is_same_type::yes) { (*this).randu(); } if(is_same_type::yes) { (*this).randn(); } arma_static_check( (is_same_type::yes), "Cube::Cube(): unsupported fill type" ); } template template inline Cube::Cube(const SizeCube& s, const fill::fill_class&) : n_rows(s.n_rows) , n_cols(s.n_cols) , n_elem_slice(s.n_rows*s.n_cols) , n_slices(s.n_slices) , n_elem(s.n_rows*s.n_cols*s.n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); if(is_same_type::yes) { (*this).zeros(); } if(is_same_type::yes) { (*this).ones(); } if(is_same_type::yes) { (*this).randu(); } if(is_same_type::yes) { (*this).randn(); } arma_static_check( (is_same_type::yes), "Cube::Cube(): unsupported fill type" ); } //! construct the cube to have user specified dimensions and fill with specified value template inline Cube::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const fill::scalar_holder f) : n_rows(in_n_rows) , n_cols(in_n_cols) , n_elem_slice(in_n_rows*in_n_cols) , n_slices(in_n_slices) , n_elem(in_n_rows*in_n_cols*in_n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); (*this).fill(f.scalar); } template inline Cube::Cube(const SizeCube& s, const fill::scalar_holder f) : n_rows(s.n_rows) , n_cols(s.n_cols) , n_elem_slice(s.n_rows*s.n_cols) , n_slices(s.n_slices) , n_elem(s.n_rows*s.n_cols*s.n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); (*this).fill(f.scalar); } template inline Cube::Cube(Cube&& in_cube) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint(arma_str::format("this = %x in_cube = %x") % this % &in_cube); (*this).steal_mem(in_cube, true); } template inline Cube& Cube::operator=(Cube&& in_cube) { arma_extra_debug_sigprint(arma_str::format("this = %x in_cube = %x") % this % &in_cube); (*this).steal_mem(in_cube, true); return *this; } template inline void Cube::init_cold() { arma_extra_debug_sigprint( arma_str::format("n_rows = %u, n_cols = %u, n_slices = %u") % n_rows % n_cols % n_slices ); #if defined(ARMA_64BIT_WORD) const char* error_message = "Cube::init(): requested size is too large"; #else const char* error_message = "Cube::init(): requested size is too large; suggest to enable ARMA_64BIT_WORD"; #endif arma_debug_check ( ( ( (n_rows > 0x0FFF) || (n_cols > 0x0FFF) || (n_slices > 0xFF) ) ? ( (double(n_rows) * double(n_cols) * double(n_slices)) > double(ARMA_MAX_UWORD) ) : false ), error_message ); if(n_elem <= Cube_prealloc::mem_n_elem) { if(n_elem > 0) { arma_extra_debug_print("Cube::init(): using local memory"); } access::rw(mem) = (n_elem == 0) ? nullptr : mem_local; access::rw(n_alloc) = 0; } else { arma_extra_debug_print("Cube::init(): acquiring memory"); access::rw(mem) = memory::acquire(n_elem); access::rw(n_alloc) = n_elem; } create_mat(); } template inline void Cube::init_warm(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices) { arma_extra_debug_sigprint( arma_str::format("in_n_rows = %u, in_n_cols = %u, in_n_slices = %u") % in_n_rows % in_n_cols % in_n_slices ); if( (n_rows == in_n_rows) && (n_cols == in_n_cols) && (n_slices == in_n_slices) ) { return; } const uword t_mem_state = mem_state; bool err_state = false; char* err_msg = nullptr; const char* error_message_1 = "Cube::init(): size is fixed and hence cannot be changed"; arma_debug_set_error( err_state, err_msg, (t_mem_state == 3), error_message_1 ); #if defined(ARMA_64BIT_WORD) const char* error_message_2 = "Cube::init(): requested size is too large"; #else const char* error_message_2 = "Cube::init(): requested size is too large; suggest to enable ARMA_64BIT_WORD"; #endif arma_debug_set_error ( err_state, err_msg, ( ( (in_n_rows > 0x0FFF) || (in_n_cols > 0x0FFF) || (in_n_slices > 0xFF) ) ? ( (double(in_n_rows) * double(in_n_cols) * double(in_n_slices)) > double(ARMA_MAX_UWORD) ) : false ), error_message_2 ); arma_debug_check(err_state, err_msg); const uword old_n_elem = n_elem; const uword new_n_elem = in_n_rows * in_n_cols * in_n_slices; if(old_n_elem == new_n_elem) { arma_extra_debug_print("Cube::init(): reusing memory"); delete_mat(); access::rw(n_rows) = in_n_rows; access::rw(n_cols) = in_n_cols; access::rw(n_elem_slice) = in_n_rows*in_n_cols; access::rw(n_slices) = in_n_slices; create_mat(); return; } arma_debug_check( (t_mem_state == 2), "Cube::init(): mismatch between size of auxiliary memory and requested size" ); delete_mat(); if(new_n_elem <= Cube_prealloc::mem_n_elem) { if(n_alloc > 0) { arma_extra_debug_print("Cube::init(): releasing memory"); memory::release( access::rw(mem) ); } if(new_n_elem > 0) { arma_extra_debug_print("Cube::init(): using local memory"); } access::rw(mem) = (new_n_elem == 0) ? nullptr : mem_local; access::rw(n_alloc) = 0; } else // condition: new_n_elem > Cube_prealloc::mem_n_elem { if(new_n_elem > n_alloc) { if(n_alloc > 0) { arma_extra_debug_print("Cube::init(): releasing memory"); memory::release( access::rw(mem) ); // in case memory::acquire() throws an exception access::rw(mem) = nullptr; access::rw(n_rows) = 0; access::rw(n_cols) = 0; access::rw(n_elem_slice) = 0; access::rw(n_slices) = 0; access::rw(n_elem) = 0; access::rw(n_alloc) = 0; } arma_extra_debug_print("Cube::init(): acquiring memory"); access::rw(mem) = memory::acquire(new_n_elem); access::rw(n_alloc) = new_n_elem; } else // condition: new_n_elem <= n_alloc { arma_extra_debug_print("Cube::init(): reusing memory"); } } access::rw(n_rows) = in_n_rows; access::rw(n_cols) = in_n_cols; access::rw(n_elem_slice) = in_n_rows*in_n_cols; access::rw(n_slices) = in_n_slices; access::rw(n_elem) = new_n_elem; access::rw(mem_state) = 0; create_mat(); } //! for constructing a complex cube out of two non-complex cubes template template inline void Cube::init ( const BaseCube::pod_type,T1>& X, const BaseCube::pod_type,T2>& Y ) { arma_extra_debug_sigprint(); typedef typename T1::elem_type T; arma_type_check(( is_cx::no )); //!< compile-time abort if eT is not std::complex arma_type_check(( is_cx< T>::yes )); //!< compile-time abort if T is std::complex arma_type_check(( is_same_type< std::complex, eT >::no )); //!< compile-time abort if types are not compatible const ProxyCube PX(X.get_ref()); const ProxyCube PY(Y.get_ref()); arma_debug_assert_same_size(PX, PY, "Cube()"); const uword local_n_rows = PX.get_n_rows(); const uword local_n_cols = PX.get_n_cols(); const uword local_n_slices = PX.get_n_slices(); init_warm(local_n_rows, local_n_cols, local_n_slices); eT* out_mem = (*this).memptr(); const bool use_at = ( ProxyCube::use_at || ProxyCube::use_at ); if(use_at == false) { typedef typename ProxyCube::ea_type ea_type1; typedef typename ProxyCube::ea_type ea_type2; const uword N = n_elem; ea_type1 A = PX.get_ea(); ea_type2 B = PY.get_ea(); for(uword i=0; i(A[i], B[i]); } } else { for(uword uslice = 0; uslice < local_n_slices; ++uslice) for(uword ucol = 0; ucol < local_n_cols; ++ucol ) for(uword urow = 0; urow < local_n_rows; ++urow ) { *out_mem = std::complex( PX.at(urow,ucol,uslice), PY.at(urow,ucol,uslice) ); out_mem++; } } } template inline void Cube::delete_mat() { arma_extra_debug_sigprint(); if((n_slices > 0) && (mat_ptrs != nullptr)) { for(uword s=0; s < n_slices; ++s) { raw_mat_ptr_type mat_ptr = raw_mat_ptr_type(mat_ptrs[s]); // explicit cast to indicate load from std::atomic*> if(mat_ptr != nullptr) { arma_extra_debug_print( arma_str::format("Cube::delete_mat(): destroying matrix %u") % s ); delete mat_ptr; mat_ptrs[s] = nullptr; } } if( (mem_state <= 2) && (n_slices > Cube_prealloc::mat_ptrs_size) ) { arma_extra_debug_print("Cube::delete_mat(): freeing mat_ptrs array"); delete [] mat_ptrs; mat_ptrs = nullptr; } } } template inline void Cube::create_mat() { arma_extra_debug_sigprint(); if(n_slices == 0) { mat_ptrs = nullptr; return; } if(mem_state <= 2) { if(n_slices <= Cube_prealloc::mat_ptrs_size) { arma_extra_debug_print("Cube::create_mat(): using local memory for mat_ptrs array"); mat_ptrs = mat_ptrs_local; } else { arma_extra_debug_print("Cube::create_mat(): allocating mat_ptrs array"); mat_ptrs = new(std::nothrow) atomic_mat_ptr_type[n_slices]; arma_check_bad_alloc( (mat_ptrs == nullptr), "Cube::create_mat(): out of memory" ); } } for(uword s=0; s < n_slices; ++s) { mat_ptrs[s] = nullptr; } } template inline Mat* Cube::create_mat_ptr(const uword in_slice) const { arma_extra_debug_sigprint(); arma_extra_debug_print( arma_str::format("Cube::create_mat_ptr(): creating matrix %u") % in_slice ); const eT* mat_mem = (n_elem_slice > 0) ? slice_memptr(in_slice) : nullptr; Mat* mat_ptr = new(std::nothrow) Mat('j', mat_mem, n_rows, n_cols); return mat_ptr; } template inline Mat* Cube::get_mat_ptr(const uword in_slice) const { arma_extra_debug_sigprint(); raw_mat_ptr_type mat_ptr = nullptr; #if defined(ARMA_USE_OPENMP) { #pragma omp atomic read mat_ptr = mat_ptrs[in_slice]; } #elif (!defined(ARMA_DONT_USE_STD_MUTEX)) { mat_ptr = mat_ptrs[in_slice].load(); } #else { mat_ptr = mat_ptrs[in_slice]; } #endif if(mat_ptr == nullptr) { #if defined(ARMA_USE_OPENMP) { #pragma omp critical (arma_Cube_mat_ptrs) { #pragma omp atomic read mat_ptr = mat_ptrs[in_slice]; if(mat_ptr == nullptr) { mat_ptr = create_mat_ptr(in_slice); } #pragma omp atomic write mat_ptrs[in_slice] = mat_ptr; } } #elif (!defined(ARMA_DONT_USE_STD_MUTEX)) { const std::lock_guard lock(mat_mutex); mat_ptr = mat_ptrs[in_slice].load(); if(mat_ptr == nullptr) { mat_ptr = create_mat_ptr(in_slice); } mat_ptrs[in_slice].store(mat_ptr); } #else { mat_ptr = create_mat_ptr(in_slice); mat_ptrs[in_slice] = mat_ptr; } #endif arma_check_bad_alloc( (mat_ptr == nullptr), "Cube::get_mat_ptr(): out of memory" ); } return mat_ptr; } //! Set the cube to be equal to the specified scalar. //! NOTE: the size of the cube will be 1x1x1 template inline Cube& Cube::operator=(const eT val) { arma_extra_debug_sigprint(); init_warm(1,1,1); access::rw(mem[0]) = val; return *this; } //! In-place addition of a scalar to all elements of the cube template inline Cube& Cube::operator+=(const eT val) { arma_extra_debug_sigprint(); arrayops::inplace_plus( memptr(), val, n_elem ); return *this; } //! In-place subtraction of a scalar from all elements of the cube template inline Cube& Cube::operator-=(const eT val) { arma_extra_debug_sigprint(); arrayops::inplace_minus( memptr(), val, n_elem ); return *this; } //! In-place multiplication of all elements of the cube with a scalar template inline Cube& Cube::operator*=(const eT val) { arma_extra_debug_sigprint(); arrayops::inplace_mul( memptr(), val, n_elem ); return *this; } //! In-place division of all elements of the cube with a scalar template inline Cube& Cube::operator/=(const eT val) { arma_extra_debug_sigprint(); arrayops::inplace_div( memptr(), val, n_elem ); return *this; } //! construct a cube from a given cube template inline Cube::Cube(const Cube& x) : n_rows(x.n_rows) , n_cols(x.n_cols) , n_elem_slice(x.n_elem_slice) , n_slices(x.n_slices) , n_elem(x.n_elem) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint(arma_str::format("this = %x in_cube = %x") % this % &x); init_cold(); arrayops::copy( memptr(), x.mem, n_elem ); } //! construct a cube from a given cube template inline Cube& Cube::operator=(const Cube& x) { arma_extra_debug_sigprint(arma_str::format("this = %x in_cube = %x") % this % &x); if(this != &x) { init_warm(x.n_rows, x.n_cols, x.n_slices); arrayops::copy( memptr(), x.mem, n_elem ); } return *this; } //! construct a cube from a given auxiliary array of eTs. //! if copy_aux_mem is true, new memory is allocated and the array is copied. //! if copy_aux_mem is false, the auxiliary array is used directly (without allocating memory and copying). template inline Cube::Cube(eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const uword aux_n_slices, const bool copy_aux_mem, const bool strict, const bool prealloc_mat) : n_rows ( aux_n_rows ) , n_cols ( aux_n_cols ) , n_elem_slice( aux_n_rows*aux_n_cols ) , n_slices ( aux_n_slices ) , n_elem ( aux_n_rows*aux_n_cols*aux_n_slices ) , n_alloc ( 0 ) , mem_state ( copy_aux_mem ? 0 : (strict ? 2 : 1) ) , mem ( copy_aux_mem ? nullptr : aux_mem ) { arma_extra_debug_sigprint_this(this); arma_ignore(prealloc_mat); // kept only for compatibility with old user code if(copy_aux_mem) { init_cold(); arrayops::copy( memptr(), aux_mem, n_elem ); } else { create_mat(); } } //! construct a cube from a given auxiliary read-only array of eTs. //! the array is copied. template inline Cube::Cube(const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const uword aux_n_slices) : n_rows(aux_n_rows) , n_cols(aux_n_cols) , n_elem_slice(aux_n_rows*aux_n_cols) , n_slices(aux_n_slices) , n_elem(aux_n_rows*aux_n_cols*aux_n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); arrayops::copy( memptr(), aux_mem, n_elem ); } //! in-place cube addition template inline Cube& Cube::operator+=(const Cube& m) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(*this, m, "addition"); arrayops::inplace_plus( memptr(), m.memptr(), n_elem ); return *this; } //! in-place cube subtraction template inline Cube& Cube::operator-=(const Cube& m) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(*this, m, "subtraction"); arrayops::inplace_minus( memptr(), m.memptr(), n_elem ); return *this; } //! in-place element-wise cube multiplication template inline Cube& Cube::operator%=(const Cube& m) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(*this, m, "element-wise multiplication"); arrayops::inplace_mul( memptr(), m.memptr(), n_elem ); return *this; } //! in-place element-wise cube division template inline Cube& Cube::operator/=(const Cube& m) { arma_extra_debug_sigprint(); arma_debug_assert_same_size(*this, m, "element-wise division"); arrayops::inplace_div( memptr(), m.memptr(), n_elem ); return *this; } //! for constructing a complex cube out of two non-complex cubes template template inline Cube::Cube ( const BaseCube::pod_type,T1>& A, const BaseCube::pod_type,T2>& B ) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init(A,B); } //! construct a cube from a subview_cube instance (eg. construct a cube from a delayed subcube operation) template inline Cube::Cube(const subview_cube& X) : n_rows(X.n_rows) , n_cols(X.n_cols) , n_elem_slice(X.n_elem_slice) , n_slices(X.n_slices) , n_elem(X.n_elem) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); subview_cube::extract(*this, X); } //! construct a cube from a subview_cube instance (eg. construct a cube from a delayed subcube operation) template inline Cube& Cube::operator=(const subview_cube& X) { arma_extra_debug_sigprint(); const bool alias = (this == &(X.m)); if(alias == false) { init_warm(X.n_rows, X.n_cols, X.n_slices); subview_cube::extract(*this, X); } else { Cube tmp(X); steal_mem(tmp); } return *this; } //! in-place cube addition (using a subcube on the right-hand-side) template inline Cube& Cube::operator+=(const subview_cube& X) { arma_extra_debug_sigprint(); subview_cube::plus_inplace(*this, X); return *this; } //! in-place cube subtraction (using a subcube on the right-hand-side) template inline Cube& Cube::operator-=(const subview_cube& X) { arma_extra_debug_sigprint(); subview_cube::minus_inplace(*this, X); return *this; } //! in-place element-wise cube mutiplication (using a subcube on the right-hand-side) template inline Cube& Cube::operator%=(const subview_cube& X) { arma_extra_debug_sigprint(); subview_cube::schur_inplace(*this, X); return *this; } //! in-place element-wise cube division (using a subcube on the right-hand-side) template inline Cube& Cube::operator/=(const subview_cube& X) { arma_extra_debug_sigprint(); subview_cube::div_inplace(*this, X); return *this; } template template inline Cube::Cube(const subview_cube_slices& X) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); subview_cube_slices::extract(*this, X); } template template inline Cube& Cube::operator=(const subview_cube_slices& X) { arma_extra_debug_sigprint(); const bool alias = (this == &(X.m)); if(alias == false) { subview_cube_slices::extract(*this, X); } else { Cube tmp(X); steal_mem(tmp); } return *this; } template template inline Cube& Cube::operator+=(const subview_cube_slices& X) { arma_extra_debug_sigprint(); subview_cube_slices::plus_inplace(*this, X); return *this; } template template inline Cube& Cube::operator-=(const subview_cube_slices& X) { arma_extra_debug_sigprint(); subview_cube_slices::minus_inplace(*this, X); return *this; } template template inline Cube& Cube::operator%=(const subview_cube_slices& X) { arma_extra_debug_sigprint(); subview_cube_slices::schur_inplace(*this, X); return *this; } template template inline Cube& Cube::operator/=(const subview_cube_slices& X) { arma_extra_debug_sigprint(); subview_cube_slices::div_inplace(*this, X); return *this; } //! creation of subview_cube (subcube comprised of specified row) template arma_inline subview_cube Cube::row(const uword in_row) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (in_row >= n_rows), "Cube::row(): index out of bounds" ); return (*this).rows(in_row, in_row); } //! creation of subview_cube (subcube comprised of specified row) template arma_inline const subview_cube Cube::row(const uword in_row) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (in_row >= n_rows), "Cube::row(): index out of bounds" ); return (*this).rows(in_row, in_row); } //! creation of subview_cube (subcube comprised of specified column) template arma_inline subview_cube Cube::col(const uword in_col) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (in_col >= n_cols), "Cube::col(): index out of bounds" ); return (*this).cols(in_col, in_col); } //! creation of subview_cube (subcube comprised of specified column) template arma_inline const subview_cube Cube::col(const uword in_col) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (in_col >= n_cols), "Cube::col(): index out of bounds" ); return (*this).cols(in_col, in_col); } //! provide the reference to the matrix representing a single slice template inline Mat& Cube::slice(const uword in_slice) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (in_slice >= n_slices), "Cube::slice(): index out of bounds" ); return *(get_mat_ptr(in_slice)); } //! provide the reference to the matrix representing a single slice template inline const Mat& Cube::slice(const uword in_slice) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (in_slice >= n_slices), "Cube::slice(): index out of bounds" ); return *(get_mat_ptr(in_slice)); } //! creation of subview_cube (subcube comprised of specified rows) template arma_inline subview_cube Cube::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), "Cube::rows(): indices out of bounds or incorrectly used" ); const uword subcube_n_rows = in_row2 - in_row1 + 1; return subview_cube(*this, in_row1, 0, 0, subcube_n_rows, n_cols, n_slices); } //! creation of subview_cube (subcube comprised of specified rows) template arma_inline const subview_cube Cube::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), "Cube::rows(): indices out of bounds or incorrectly used" ); const uword subcube_n_rows = in_row2 - in_row1 + 1; return subview_cube(*this, in_row1, 0, 0, subcube_n_rows, n_cols, n_slices); } //! creation of subview_cube (subcube comprised of specified columns) template arma_inline subview_cube Cube::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), "Cube::cols(): indices out of bounds or incorrectly used" ); const uword subcube_n_cols = in_col2 - in_col1 + 1; return subview_cube(*this, 0, in_col1, 0, n_rows, subcube_n_cols, n_slices); } //! creation of subview_cube (subcube comprised of specified columns) template arma_inline const subview_cube Cube::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), "Cube::cols(): indices out of bounds or incorrectly used" ); const uword subcube_n_cols = in_col2 - in_col1 + 1; return subview_cube(*this, 0, in_col1, 0, n_rows, subcube_n_cols, n_slices); } //! creation of subview_cube (subcube comprised of specified slices) template arma_inline subview_cube Cube::slices(const uword in_slice1, const uword in_slice2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_slice1 > in_slice2) || (in_slice2 >= n_slices), "Cube::slices(): indices out of bounds or incorrectly used" ); const uword subcube_n_slices = in_slice2 - in_slice1 + 1; return subview_cube(*this, 0, 0, in_slice1, n_rows, n_cols, subcube_n_slices); } //! creation of subview_cube (subcube comprised of specified slices) template arma_inline const subview_cube Cube::slices(const uword in_slice1, const uword in_slice2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_slice1 > in_slice2) || (in_slice2 >= n_slices), "Cube::slices(): indices out of bounds or incorrectly used" ); const uword subcube_n_slices = in_slice2 - in_slice1 + 1; return subview_cube(*this, 0, 0, in_slice1, n_rows, n_cols, subcube_n_slices); } //! creation of subview_cube (generic subcube) template arma_inline subview_cube Cube::subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const uword in_row2, const uword in_col2, const uword in_slice2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 > in_row2) || (in_col1 > in_col2) || (in_slice1 > in_slice2) || (in_row2 >= n_rows) || (in_col2 >= n_cols) || (in_slice2 >= n_slices), "Cube::subcube(): indices out of bounds or incorrectly used" ); const uword subcube_n_rows = in_row2 - in_row1 + 1; const uword subcube_n_cols = in_col2 - in_col1 + 1; const uword subcube_n_slices = in_slice2 - in_slice1 + 1; return subview_cube(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices); } //! creation of subview_cube (generic subcube) template arma_inline const subview_cube Cube::subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const uword in_row2, const uword in_col2, const uword in_slice2) const { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_row1 > in_row2) || (in_col1 > in_col2) || (in_slice1 > in_slice2) || (in_row2 >= n_rows) || (in_col2 >= n_cols) || (in_slice2 >= n_slices), "Cube::subcube(): indices out of bounds or incorrectly used" ); const uword subcube_n_rows = in_row2 - in_row1 + 1; const uword subcube_n_cols = in_col2 - in_col1 + 1; const uword subcube_n_slices = in_slice2 - in_slice1 + 1; return subview_cube(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices); } //! creation of subview_cube (generic subcube) template inline subview_cube Cube::subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) { arma_extra_debug_sigprint(); const uword l_n_rows = n_rows; const uword l_n_cols = n_cols; const uword l_n_slices = n_slices; const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; const uword s_n_slices = s.n_slices; arma_debug_check_bounds ( ( in_row1 >= l_n_rows) || ( in_col1 >= l_n_cols) || ( in_slice1 >= l_n_slices) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols) || ((in_slice1 + s_n_slices) > l_n_slices), "Cube::subcube(): indices or size out of bounds" ); return subview_cube(*this, in_row1, in_col1, in_slice1, s_n_rows, s_n_cols, s_n_slices); } //! creation of subview_cube (generic subcube) template inline const subview_cube Cube::subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const { arma_extra_debug_sigprint(); const uword l_n_rows = n_rows; const uword l_n_cols = n_cols; const uword l_n_slices = n_slices; const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; const uword s_n_slices = s.n_slices; arma_debug_check_bounds ( ( in_row1 >= l_n_rows) || ( in_col1 >= l_n_cols) || ( in_slice1 >= l_n_slices) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols) || ((in_slice1 + s_n_slices) > l_n_slices), "Cube::subcube(): indices or size out of bounds" ); return subview_cube(*this, in_row1, in_col1, in_slice1, s_n_rows, s_n_cols, s_n_slices); } //! creation of subview_cube (generic subcube) template inline subview_cube Cube::subcube(const span& row_span, const span& col_span, const span& slice_span) { arma_extra_debug_sigprint(); const bool row_all = row_span.whole; const bool col_all = col_span.whole; const bool slice_all = slice_span.whole; const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; const uword local_n_slices = n_slices; const uword in_row1 = row_all ? 0 : row_span.a; const uword in_row2 = row_span.b; const uword subcube_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 subcube_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; const uword in_slice1 = slice_all ? 0 : slice_span.a; const uword in_slice2 = slice_span.b; const uword subcube_n_slices = slice_all ? local_n_slices : in_slice2 - in_slice1 + 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)) ) || ( slice_all ? false : ((in_slice1 > in_slice2) || (in_slice2 >= local_n_slices)) ) , "Cube::subcube(): indices out of bounds or incorrectly used" ); return subview_cube(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices); } //! creation of subview_cube (generic subcube) template inline const subview_cube Cube::subcube(const span& row_span, const span& col_span, const span& slice_span) const { arma_extra_debug_sigprint(); const bool row_all = row_span.whole; const bool col_all = col_span.whole; const bool slice_all = slice_span.whole; const uword local_n_rows = n_rows; const uword local_n_cols = n_cols; const uword local_n_slices = n_slices; const uword in_row1 = row_all ? 0 : row_span.a; const uword in_row2 = row_span.b; const uword subcube_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 subcube_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1; const uword in_slice1 = slice_all ? 0 : slice_span.a; const uword in_slice2 = slice_span.b; const uword subcube_n_slices = slice_all ? local_n_slices : in_slice2 - in_slice1 + 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)) ) || ( slice_all ? false : ((in_slice1 > in_slice2) || (in_slice2 >= local_n_slices)) ) , "Cube::subcube(): indices out of bounds or incorrectly used" ); return subview_cube(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices); } template inline subview_cube Cube::operator()(const span& row_span, const span& col_span, const span& slice_span) { arma_extra_debug_sigprint(); return (*this).subcube(row_span, col_span, slice_span); } template inline const subview_cube Cube::operator()(const span& row_span, const span& col_span, const span& slice_span) const { arma_extra_debug_sigprint(); return (*this).subcube(row_span, col_span, slice_span); } template inline subview_cube Cube::operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) { arma_extra_debug_sigprint(); return (*this).subcube(in_row1, in_col1, in_slice1, s); } template inline const subview_cube Cube::operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const { arma_extra_debug_sigprint(); return (*this).subcube(in_row1, in_col1, in_slice1, s); } template arma_inline subview_cube Cube::tube(const uword in_row1, const uword in_col1) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( ((in_row1 >= n_rows) || (in_col1 >= n_cols)), "Cube::tube(): indices out of bounds" ); return subview_cube(*this, in_row1, in_col1, 0, 1, 1, n_slices); } template arma_inline const subview_cube Cube::tube(const uword in_row1, const uword in_col1) const { arma_extra_debug_sigprint(); arma_debug_check_bounds ( ((in_row1 >= n_rows) || (in_col1 >= n_cols)), "Cube::tube(): indices out of bounds" ); return subview_cube(*this, in_row1, in_col1, 0, 1, 1, n_slices); } template arma_inline subview_cube Cube::tube(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), "Cube::tube(): indices out of bounds or incorrectly used" ); const uword subcube_n_rows = in_row2 - in_row1 + 1; const uword subcube_n_cols = in_col2 - in_col1 + 1; return subview_cube(*this, in_row1, in_col1, 0, subcube_n_rows, subcube_n_cols, n_slices); } template arma_inline const subview_cube Cube::tube(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), "Cube::tube(): indices out of bounds or incorrectly used" ); const uword subcube_n_rows = in_row2 - in_row1 + 1; const uword subcube_n_cols = in_col2 - in_col1 + 1; return subview_cube(*this, in_row1, in_col1, 0, subcube_n_rows, subcube_n_cols, n_slices); } template arma_inline subview_cube Cube::tube(const uword in_row1, const uword in_col1, const SizeMat& s) { arma_extra_debug_sigprint(); const uword l_n_rows = n_rows; const uword l_n_cols = n_cols; const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; arma_debug_check_bounds ( ((in_row1 >= l_n_rows) || (in_col1 >= l_n_cols) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols)), "Cube::tube(): indices or size out of bounds" ); return subview_cube(*this, in_row1, in_col1, 0, s_n_rows, s_n_cols, n_slices); } template arma_inline const subview_cube Cube::tube(const uword in_row1, const uword in_col1, const SizeMat& s) const { arma_extra_debug_sigprint(); const uword l_n_rows = n_rows; const uword l_n_cols = n_cols; const uword s_n_rows = s.n_rows; const uword s_n_cols = s.n_cols; arma_debug_check_bounds ( ((in_row1 >= l_n_rows) || (in_col1 >= l_n_cols) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols)), "Cube::tube(): indices or size out of bounds" ); return subview_cube(*this, in_row1, in_col1, 0, s_n_rows, s_n_cols, n_slices); } template inline subview_cube Cube::tube(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 subcube_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 subcube_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)) ) , "Cube::tube(): indices out of bounds or incorrectly used" ); return subview_cube(*this, in_row1, in_col1, 0, subcube_n_rows, subcube_n_cols, n_slices); } template inline const subview_cube Cube::tube(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 subcube_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 subcube_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)) ) , "Cube::tube(): indices out of bounds or incorrectly used" ); return subview_cube(*this, in_row1, in_col1, 0, subcube_n_rows, subcube_n_cols, n_slices); } template inline subview_cube Cube::head_slices(const uword N) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > n_slices), "Cube::head_slices(): size out of bounds" ); return subview_cube(*this, 0, 0, 0, n_rows, n_cols, N); } template inline const subview_cube Cube::head_slices(const uword N) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > n_slices), "Cube::head_slices(): size out of bounds" ); return subview_cube(*this, 0, 0, 0, n_rows, n_cols, N); } template inline subview_cube Cube::tail_slices(const uword N) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > n_slices), "Cube::tail_slices(): size out of bounds" ); const uword start_slice = n_slices - N; return subview_cube(*this, 0, 0, start_slice, n_rows, n_cols, N); } template inline const subview_cube Cube::tail_slices(const uword N) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (N > n_slices), "Cube::tail_slices(): size out of bounds" ); const uword start_slice = n_slices - N; return subview_cube(*this, 0, 0, start_slice, n_rows, n_cols, N); } template template arma_inline subview_elem1 Cube::elem(const Base& a) { arma_extra_debug_sigprint(); return subview_elem1(*this, a); } template template arma_inline const subview_elem1 Cube::elem(const Base& a) const { arma_extra_debug_sigprint(); return subview_elem1(*this, a); } template template arma_inline subview_elem1 Cube::operator()(const Base& a) { arma_extra_debug_sigprint(); return subview_elem1(*this, a); } template template arma_inline const subview_elem1 Cube::operator()(const Base& a) const { arma_extra_debug_sigprint(); return subview_elem1(*this, a); } template arma_inline subview_cube_each1 Cube::each_slice() { arma_extra_debug_sigprint(); return subview_cube_each1(*this); } template arma_inline const subview_cube_each1 Cube::each_slice() const { arma_extra_debug_sigprint(); return subview_cube_each1(*this); } template template inline subview_cube_each2 Cube::each_slice(const Base& indices) { arma_extra_debug_sigprint(); return subview_cube_each2(*this, indices); } template template inline const subview_cube_each2 Cube::each_slice(const Base& indices) const { arma_extra_debug_sigprint(); return subview_cube_each2(*this, indices); } //! apply a lambda function to each slice, where each slice is interpreted as a matrix template inline Cube& Cube::each_slice(const std::function< void(Mat&) >& F) { arma_extra_debug_sigprint(); for(uword slice_id=0; slice_id < n_slices; ++slice_id) { Mat tmp('j', slice_memptr(slice_id), n_rows, n_cols); F(tmp); } return *this; } template inline const Cube& Cube::each_slice(const std::function< void(const Mat&) >& F) const { arma_extra_debug_sigprint(); for(uword slice_id=0; slice_id < n_slices; ++slice_id) { const Mat tmp('j', slice_memptr(slice_id), n_rows, n_cols); F(tmp); } return *this; } template inline Cube& Cube::each_slice(const std::function< void(Mat&) >& F, const bool use_mp) { arma_extra_debug_sigprint(); if((use_mp == false) || (arma_config::openmp == false)) { return (*this).each_slice(F); } #if defined(ARMA_USE_OPENMP) { const uword local_n_slices = n_slices; const int n_threads = mp_thread_limit::get(); #pragma omp parallel for schedule(static) num_threads(n_threads) for(uword slice_id=0; slice_id < local_n_slices; ++slice_id) { Mat tmp('j', slice_memptr(slice_id), n_rows, n_cols); F(tmp); } } #endif return *this; } template inline const Cube& Cube::each_slice(const std::function< void(const Mat&) >& F, const bool use_mp) const { arma_extra_debug_sigprint(); if((use_mp == false) || (arma_config::openmp == false)) { return (*this).each_slice(F); } #if defined(ARMA_USE_OPENMP) { const uword local_n_slices = n_slices; const int n_threads = mp_thread_limit::get(); #pragma omp parallel for schedule(static) num_threads(n_threads) for(uword slice_id=0; slice_id < local_n_slices; ++slice_id) { Mat tmp('j', slice_memptr(slice_id), n_rows, n_cols); F(tmp); } } #endif return *this; } template template inline subview_cube_slices Cube::slices(const Base& indices) { arma_extra_debug_sigprint(); return subview_cube_slices(*this, indices); } template template inline const subview_cube_slices Cube::slices(const Base& indices) const { arma_extra_debug_sigprint(); return subview_cube_slices(*this, indices); } //! remove specified row template inline void Cube::shed_row(const uword row_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( row_num >= n_rows, "Cube::shed_row(): index out of bounds" ); shed_rows(row_num, row_num); } //! remove specified column template inline void Cube::shed_col(const uword col_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( col_num >= n_cols, "Cube::shed_col(): index out of bounds" ); shed_cols(col_num, col_num); } //! remove specified slice template inline void Cube::shed_slice(const uword slice_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( slice_num >= n_slices, "Cube::shed_slice(): index out of bounds" ); shed_slices(slice_num, slice_num); } //! remove specified rows template inline void Cube::shed_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), "Cube::shed_rows(): indices out of bounds or incorrectly used" ); const uword n_keep_front = in_row1; const uword n_keep_back = n_rows - (in_row2 + 1); Cube X(n_keep_front + n_keep_back, n_cols, n_slices, arma_nozeros_indicator()); if(n_keep_front > 0) { X.rows( 0, (n_keep_front-1) ) = rows( 0, (in_row1-1) ); } if(n_keep_back > 0) { X.rows( n_keep_front, (n_keep_front+n_keep_back-1) ) = rows( (in_row2+1), (n_rows-1) ); } steal_mem(X); } //! remove specified columns template inline void Cube::shed_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), "Cube::shed_cols(): indices out of bounds or incorrectly used" ); const uword n_keep_front = in_col1; const uword n_keep_back = n_cols - (in_col2 + 1); Cube X(n_rows, n_keep_front + n_keep_back, n_slices, arma_nozeros_indicator()); if(n_keep_front > 0) { X.cols( 0, (n_keep_front-1) ) = cols( 0, (in_col1-1) ); } if(n_keep_back > 0) { X.cols( n_keep_front, (n_keep_front+n_keep_back-1) ) = cols( (in_col2+1), (n_cols-1) ); } steal_mem(X); } //! remove specified slices template inline void Cube::shed_slices(const uword in_slice1, const uword in_slice2) { arma_extra_debug_sigprint(); arma_debug_check_bounds ( (in_slice1 > in_slice2) || (in_slice2 >= n_slices), "Cube::shed_slices(): indices out of bounds or incorrectly used" ); const uword n_keep_front = in_slice1; const uword n_keep_back = n_slices - (in_slice2 + 1); Cube X(n_rows, n_cols, n_keep_front + n_keep_back, arma_nozeros_indicator()); if(n_keep_front > 0) { X.slices( 0, (n_keep_front-1) ) = slices( 0, (in_slice1-1) ); } if(n_keep_back > 0) { X.slices( n_keep_front, (n_keep_front+n_keep_back-1) ) = slices( (in_slice2+1), (n_slices-1) ); } steal_mem(X); } //! remove specified slices template template inline void Cube::shed_slices(const Base& indices) { arma_extra_debug_sigprint(); const quasi_unwrap U(indices.get_ref()); const Mat& tmp1 = U.M; arma_debug_check( ((tmp1.is_vec() == false) && (tmp1.is_empty() == false)), "Cube::shed_slices(): list of indices must be a vector" ); if(tmp1.is_empty()) { return; } const Col tmp2(const_cast(tmp1.memptr()), tmp1.n_elem, false, false); const Col& slices_to_shed = (tmp2.is_sorted("strictascend") == false) ? Col(unique(tmp2)) : Col(const_cast(tmp2.memptr()), tmp2.n_elem, false, false); const uword* slices_to_shed_mem = slices_to_shed.memptr(); const uword N = slices_to_shed.n_elem; if(arma_config::debug) { for(uword i=0; i= n_slices), "Cube::shed_slices(): indices out of bounds" ); } } Col tmp3(n_slices, arma_nozeros_indicator()); uword* tmp3_mem = tmp3.memptr(); uword i = 0; uword count = 0; for(uword j=0; j < n_slices; ++j) { if(i < N) { if( j != slices_to_shed_mem[i] ) { tmp3_mem[count] = j; ++count; } else { ++i; } } else { tmp3_mem[count] = j; ++count; } } const Col slices_to_keep(tmp3.memptr(), count, false, false); Cube X = (*this).slices(slices_to_keep); steal_mem(X); } template inline void Cube::insert_rows(const uword row_num, const uword N, const bool set_to_zero) { arma_extra_debug_sigprint(); arma_ignore(set_to_zero); (*this).insert_rows(row_num, N); } template inline void Cube::insert_rows(const uword row_num, const uword N) { arma_extra_debug_sigprint(); const uword t_n_rows = n_rows; const uword A_n_rows = row_num; const uword B_n_rows = t_n_rows - row_num; // insertion at row_num == n_rows is in effect an append operation arma_debug_check_bounds( (row_num > t_n_rows), "Cube::insert_rows(): index out of bounds" ); if(N == 0) { return; } Cube out(t_n_rows + N, n_cols, n_slices, arma_nozeros_indicator()); if(A_n_rows > 0) { out.rows(0, A_n_rows-1) = rows(0, A_n_rows-1); } if(B_n_rows > 0) { out.rows(row_num + N, t_n_rows + N - 1) = rows(row_num, t_n_rows-1); } out.rows(row_num, row_num + N - 1).zeros(); steal_mem(out); } template inline void Cube::insert_cols(const uword col_num, const uword N, const bool set_to_zero) { arma_extra_debug_sigprint(); arma_ignore(set_to_zero); (*this).insert_cols(col_num, N); } template inline void Cube::insert_cols(const uword col_num, const uword N) { arma_extra_debug_sigprint(); const uword t_n_cols = n_cols; const uword A_n_cols = col_num; const uword B_n_cols = t_n_cols - col_num; // insertion at col_num == n_cols is in effect an append operation arma_debug_check_bounds( (col_num > t_n_cols), "Cube::insert_cols(): index out of bounds" ); if(N == 0) { return; } Cube out(n_rows, t_n_cols + N, n_slices, arma_nozeros_indicator()); if(A_n_cols > 0) { out.cols(0, A_n_cols-1) = cols(0, A_n_cols-1); } if(B_n_cols > 0) { out.cols(col_num + N, t_n_cols + N - 1) = cols(col_num, t_n_cols-1); } out.cols(col_num, col_num + N - 1).zeros(); steal_mem(out); } template inline void Cube::insert_slices(const uword slice_num, const uword N, const bool set_to_zero) { arma_extra_debug_sigprint(); arma_ignore(set_to_zero); (*this).insert_slices(slice_num, N); } template inline void Cube::insert_slices(const uword slice_num, const uword N) { arma_extra_debug_sigprint(); const uword t_n_slices = n_slices; const uword A_n_slices = slice_num; const uword B_n_slices = t_n_slices - slice_num; // insertion at slice_num == n_slices is in effect an append operation arma_debug_check_bounds( (slice_num > t_n_slices), "Cube::insert_slices(): index out of bounds" ); if(N == 0) { return; } Cube out(n_rows, n_cols, t_n_slices + N, arma_nozeros_indicator()); if(A_n_slices > 0) { out.slices(0, A_n_slices-1) = slices(0, A_n_slices-1); } if(B_n_slices > 0) { out.slices(slice_num + N, t_n_slices + N - 1) = slices(slice_num, t_n_slices-1); } //out.slices(slice_num, slice_num + N - 1).zeros(); for(uword i=slice_num; i < (slice_num + N); ++i) { arrayops::fill_zeros(out.slice_memptr(i), out.n_elem_slice); } steal_mem(out); } template template inline void Cube::insert_rows(const uword row_num, const BaseCube& X) { arma_extra_debug_sigprint(); const unwrap_cube tmp(X.get_ref()); const Cube& C = tmp.M; const uword N = C.n_rows; const uword t_n_rows = n_rows; const uword A_n_rows = row_num; const uword B_n_rows = t_n_rows - row_num; // insertion at row_num == n_rows is in effect an append operation arma_debug_check_bounds( (row_num > t_n_rows), "Cube::insert_rows(): index out of bounds" ); arma_debug_check ( ( (C.n_cols != n_cols) || (C.n_slices != n_slices) ), "Cube::insert_rows(): given object has incompatible dimensions" ); if(N == 0) { return; } Cube out(t_n_rows + N, n_cols, n_slices, arma_nozeros_indicator()); if(A_n_rows > 0) { out.rows(0, A_n_rows-1) = rows(0, A_n_rows-1); } if(B_n_rows > 0) { out.rows(row_num + N, t_n_rows + N - 1) = rows(row_num, t_n_rows - 1); } out.rows(row_num, row_num + N - 1) = C; steal_mem(out); } template template inline void Cube::insert_cols(const uword col_num, const BaseCube& X) { arma_extra_debug_sigprint(); const unwrap_cube tmp(X.get_ref()); const Cube& C = tmp.M; const uword N = C.n_cols; const uword t_n_cols = n_cols; const uword A_n_cols = col_num; const uword B_n_cols = t_n_cols - col_num; // insertion at col_num == n_cols is in effect an append operation arma_debug_check_bounds( (col_num > t_n_cols), "Cube::insert_cols(): index out of bounds" ); arma_debug_check ( ( (C.n_rows != n_rows) || (C.n_slices != n_slices) ), "Cube::insert_cols(): given object has incompatible dimensions" ); if(N == 0) { return; } Cube out(n_rows, t_n_cols + N, n_slices, arma_nozeros_indicator()); if(A_n_cols > 0) { out.cols(0, A_n_cols-1) = cols(0, A_n_cols-1); } if(B_n_cols > 0) { out.cols(col_num + N, t_n_cols + N - 1) = cols(col_num, t_n_cols - 1); } out.cols(col_num, col_num + N - 1) = C; steal_mem(out); } //! insert the given object at the specified slice position; //! the given object must have the same number of rows and columns as the cube template template inline void Cube::insert_slices(const uword slice_num, const BaseCube& X) { arma_extra_debug_sigprint(); const unwrap_cube tmp(X.get_ref()); const Cube& C = tmp.M; const uword N = C.n_slices; const uword t_n_slices = n_slices; const uword A_n_slices = slice_num; const uword B_n_slices = t_n_slices - slice_num; // insertion at slice_num == n_slices is in effect an append operation arma_debug_check_bounds( (slice_num > t_n_slices), "Cube::insert_slices(): index out of bounds" ); arma_debug_check ( ( (C.n_rows != n_rows) || (C.n_cols != n_cols) ), "Cube::insert_slices(): given object has incompatible dimensions" ); if(N == 0) { return; } Cube out(n_rows, n_cols, t_n_slices + N, arma_nozeros_indicator()); if(A_n_slices > 0) { out.slices(0, A_n_slices-1) = slices(0, A_n_slices-1); } if(B_n_slices > 0) { out.slices(slice_num + N, t_n_slices + N - 1) = slices(slice_num, t_n_slices - 1); } out.slices(slice_num, slice_num + N - 1) = C; steal_mem(out); } template template inline void Cube::insert_slices(const uword slice_num, const Base& X) { arma_extra_debug_sigprint(); const quasi_unwrap U(X.get_ref()); const Cube C(const_cast(U.M.memptr()), U.M.n_rows, U.M.n_cols, uword(1), false, true); (*this).insert_slices(slice_num, C); } //! create a cube from GenCube, ie. run the previously delayed element generation operations template template inline Cube::Cube(const GenCube& X) : n_rows(X.n_rows) , n_cols(X.n_cols) , n_elem_slice(X.n_rows*X.n_cols) , n_slices(X.n_slices) , n_elem(X.n_rows*X.n_cols*X.n_slices) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); init_cold(); X.apply(*this); } template template inline Cube& Cube::operator=(const GenCube& X) { arma_extra_debug_sigprint(); init_warm(X.n_rows, X.n_cols, X.n_slices); X.apply(*this); return *this; } template template inline Cube& Cube::operator+=(const GenCube& X) { arma_extra_debug_sigprint(); X.apply_inplace_plus(*this); return *this; } template template inline Cube& Cube::operator-=(const GenCube& X) { arma_extra_debug_sigprint(); X.apply_inplace_minus(*this); return *this; } template template inline Cube& Cube::operator%=(const GenCube& X) { arma_extra_debug_sigprint(); X.apply_inplace_schur(*this); return *this; } template template inline Cube& Cube::operator/=(const GenCube& X) { arma_extra_debug_sigprint(); X.apply_inplace_div(*this); return *this; } //! create a cube from OpCube, ie. run the previously delayed unary operations template template inline Cube::Cube(const OpCube& X) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); op_type::apply(*this, X); } //! create a cube from OpCube, ie. run the previously delayed unary operations template template inline Cube& Cube::operator=(const OpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); op_type::apply(*this, X); return *this; } //! in-place cube addition, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator+=(const OpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const Cube m(X); return (*this).operator+=(m); } //! in-place cube subtraction, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator-=(const OpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const Cube m(X); return (*this).operator-=(m); } //! in-place cube element-wise multiplication, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator%=(const OpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const Cube m(X); return (*this).operator%=(m); } //! in-place cube element-wise division, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator/=(const OpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const Cube m(X); return (*this).operator/=(m); } //! create a cube from eOpCube, ie. run the previously delayed unary operations template template inline Cube::Cube(const eOpCube& X) : n_rows(X.get_n_rows()) , n_cols(X.get_n_cols()) , n_elem_slice(X.get_n_elem_slice()) , n_slices(X.get_n_slices()) , n_elem(X.get_n_elem()) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); init_cold(); eop_type::apply(*this, X); } //! create a cube from eOpCube, ie. run the previously delayed unary operations template template inline Cube& Cube::operator=(const eOpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const bool bad_alias = ( X.P.has_subview && X.P.is_alias(*this) ); if(bad_alias) { Cube tmp(X); steal_mem(tmp); return *this; } init_warm(X.get_n_rows(), X.get_n_cols(), X.get_n_slices()); eop_type::apply(*this, X); return *this; } //! in-place cube addition, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator+=(const eOpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const bool bad_alias = ( X.P.has_subview && X.P.is_alias(*this) ); if(bad_alias) { const Cube tmp(X); return (*this).operator+=(tmp); } eop_type::apply_inplace_plus(*this, X); return *this; } //! in-place cube subtraction, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator-=(const eOpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const bool bad_alias = ( X.P.has_subview && X.P.is_alias(*this) ); if(bad_alias) { const Cube tmp(X); return (*this).operator-=(tmp); } eop_type::apply_inplace_minus(*this, X); return *this; } //! in-place cube element-wise multiplication, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator%=(const eOpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const bool bad_alias = ( X.P.has_subview && X.P.is_alias(*this) ); if(bad_alias) { const Cube tmp(X); return (*this).operator%=(tmp); } eop_type::apply_inplace_schur(*this, X); return *this; } //! in-place cube element-wise division, with the right-hand-side operand having delayed operations template template inline Cube& Cube::operator/=(const eOpCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); const bool bad_alias = ( X.P.has_subview && X.P.is_alias(*this) ); if(bad_alias) { const Cube tmp(X); return (*this).operator/=(tmp); } eop_type::apply_inplace_div(*this, X); return *this; } template template inline Cube::Cube(const mtOpCube& X) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); op_type::apply(*this, X); } template template inline Cube& Cube::operator=(const mtOpCube& X) { arma_extra_debug_sigprint(); op_type::apply(*this, X); return *this; } template template inline Cube& Cube::operator+=(const mtOpCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator+=(m); } template template inline Cube& Cube::operator-=(const mtOpCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator-=(m); } template template inline Cube& Cube::operator%=(const mtOpCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator%=(m); } template template inline Cube& Cube::operator/=(const mtOpCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator/=(m); } //! create a cube from GlueCube, ie. run the previously delayed binary operations template template inline Cube::Cube(const GlueCube& X) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); this->operator=(X); } //! create a cube from GlueCube, ie. run the previously delayed binary operations template template inline Cube& Cube::operator=(const GlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); glue_type::apply(*this, X); return *this; } //! in-place cube addition, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator+=(const GlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const Cube m(X); return (*this).operator+=(m); } //! in-place cube subtraction, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator-=(const GlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const Cube m(X); return (*this).operator-=(m); } //! in-place cube element-wise multiplication, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator%=(const GlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const Cube m(X); return (*this).operator%=(m); } //! in-place cube element-wise division, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator/=(const GlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const Cube m(X); return (*this).operator/=(m); } //! create a cube from eGlueCube, ie. run the previously delayed binary operations template template inline Cube::Cube(const eGlueCube& X) : n_rows(X.get_n_rows()) , n_cols(X.get_n_cols()) , n_elem_slice(X.get_n_elem_slice()) , n_slices(X.get_n_slices()) , n_elem(X.get_n_elem()) , n_alloc() , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); init_cold(); eglue_type::apply(*this, X); } //! create a cube from eGlueCube, ie. run the previously delayed binary operations template template inline Cube& Cube::operator=(const eGlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const bool bad_alias = ( (X.P1.has_subview && X.P1.is_alias(*this)) || (X.P2.has_subview && X.P2.is_alias(*this)) ); if(bad_alias) { Cube tmp(X); steal_mem(tmp); return *this; } init_warm(X.get_n_rows(), X.get_n_cols(), X.get_n_slices()); eglue_type::apply(*this, X); return *this; } //! in-place cube addition, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator+=(const eGlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const bool bad_alias = ( (X.P1.has_subview && X.P1.is_alias(*this)) || (X.P2.has_subview && X.P2.is_alias(*this)) ); if(bad_alias) { const Cube tmp(X); return (*this).operator+=(tmp); } eglue_type::apply_inplace_plus(*this, X); return *this; } //! in-place cube subtraction, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator-=(const eGlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const bool bad_alias = ( (X.P1.has_subview && X.P1.is_alias(*this)) || (X.P2.has_subview && X.P2.is_alias(*this)) ); if(bad_alias) { const Cube tmp(X); return (*this).operator-=(tmp); } eglue_type::apply_inplace_minus(*this, X); return *this; } //! in-place cube element-wise multiplication, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator%=(const eGlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const bool bad_alias = ( (X.P1.has_subview && X.P1.is_alias(*this)) || (X.P2.has_subview && X.P2.is_alias(*this)) ); if(bad_alias) { const Cube tmp(X); return (*this).operator%=(tmp); } eglue_type::apply_inplace_schur(*this, X); return *this; } //! in-place cube element-wise division, with the right-hand-side operands having delayed operations template template inline Cube& Cube::operator/=(const eGlueCube& X) { arma_extra_debug_sigprint(); arma_type_check(( is_same_type< eT, typename T1::elem_type >::no )); arma_type_check(( is_same_type< eT, typename T2::elem_type >::no )); const bool bad_alias = ( (X.P1.has_subview && X.P1.is_alias(*this)) || (X.P2.has_subview && X.P2.is_alias(*this)) ); if(bad_alias) { const Cube tmp(X); return (*this).operator/=(tmp); } eglue_type::apply_inplace_div(*this, X); return *this; } template template inline Cube::Cube(const mtGlueCube& X) : n_rows(0) , n_cols(0) , n_elem_slice(0) , n_slices(0) , n_elem(0) , n_alloc(0) , mem_state(0) , mem() { arma_extra_debug_sigprint_this(this); glue_type::apply(*this, X); } template template inline Cube& Cube::operator=(const mtGlueCube& X) { arma_extra_debug_sigprint(); glue_type::apply(*this, X); return *this; } template template inline Cube& Cube::operator+=(const mtGlueCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator+=(m); } template template inline Cube& Cube::operator-=(const mtGlueCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator-=(m); } template template inline Cube& Cube::operator%=(const mtGlueCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator%=(m); } template template inline Cube& Cube::operator/=(const mtGlueCube& X) { arma_extra_debug_sigprint(); const Cube m(X); return (*this).operator/=(m); } //! linear element accessor (treats the cube as a vector); no bounds check; assumes memory is aligned template arma_inline const eT& Cube::at_alt(const uword i) const { const eT* mem_aligned = mem; memory::mark_as_aligned(mem_aligned); return mem_aligned[i]; } //! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined template arma_inline eT& Cube::operator() (const uword i) { arma_debug_check_bounds( (i >= n_elem), "Cube::operator(): index out of bounds" ); return access::rw(mem[i]); } //! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined template arma_inline const eT& Cube::operator() (const uword i) const { arma_debug_check_bounds( (i >= n_elem), "Cube::operator(): index out of bounds" ); return mem[i]; } //! linear element accessor (treats the cube as a vector); no bounds check. template arma_inline eT& Cube::operator[] (const uword i) { return access::rw(mem[i]); } //! linear element accessor (treats the cube as a vector); no bounds check template arma_inline const eT& Cube::operator[] (const uword i) const { return mem[i]; } //! linear element accessor (treats the cube as a vector); no bounds check. template arma_inline eT& Cube::at(const uword i) { return access::rw(mem[i]); } //! linear element accessor (treats the cube as a vector); no bounds check template arma_inline const eT& Cube::at(const uword i) const { return mem[i]; } //! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined template arma_inline eT& Cube::operator() (const uword in_row, const uword in_col, const uword in_slice) { arma_debug_check_bounds ( (in_row >= n_rows) || (in_col >= n_cols) || (in_slice >= n_slices) , "Cube::operator(): index out of bounds" ); return access::rw(mem[in_slice*n_elem_slice + in_col*n_rows + in_row]); } //! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined template arma_inline const eT& Cube::operator() (const uword in_row, const uword in_col, const uword in_slice) const { arma_debug_check_bounds ( (in_row >= n_rows) || (in_col >= n_cols) || (in_slice >= n_slices) , "Cube::operator(): index out of bounds" ); return mem[in_slice*n_elem_slice + in_col*n_rows + in_row]; } #if defined(__cpp_multidimensional_subscript) //! element accessor; no bounds check template arma_inline eT& Cube::operator[] (const uword in_row, const uword in_col, const uword in_slice) { return access::rw( mem[in_slice*n_elem_slice + in_col*n_rows + in_row] ); } //! element accessor; no bounds check template arma_inline const eT& Cube::operator[] (const uword in_row, const uword in_col, const uword in_slice) const { return mem[in_slice*n_elem_slice + in_col*n_rows + in_row]; } #endif //! element accessor; no bounds check template arma_inline eT& Cube::at(const uword in_row, const uword in_col, const uword in_slice) { return access::rw( mem[in_slice*n_elem_slice + in_col*n_rows + in_row] ); } //! element accessor; no bounds check template arma_inline const eT& Cube::at(const uword in_row, const uword in_col, const uword in_slice) const { return mem[in_slice*n_elem_slice + in_col*n_rows + in_row]; } //! prefix ++ template arma_inline const Cube& Cube::operator++() { Cube_aux::prefix_pp(*this); return *this; } //! postfix ++ (must not return the object by reference) template arma_inline void Cube::operator++(int) { Cube_aux::postfix_pp(*this); } //! prefix -- template arma_inline const Cube& Cube::operator--() { Cube_aux::prefix_mm(*this); return *this; } //! postfix -- (must not return the object by reference) template arma_inline void Cube::operator--(int) { Cube_aux::postfix_mm(*this); } //! returns true if the cube has no elements template arma_inline bool Cube::is_empty() const { return (n_elem == 0); } template inline bool Cube::internal_is_finite() const { arma_extra_debug_sigprint(); return arrayops::is_finite(memptr(), n_elem); } template inline bool Cube::internal_has_inf() const { arma_extra_debug_sigprint(); return arrayops::has_inf(memptr(), n_elem); } template inline bool Cube::internal_has_nan() const { arma_extra_debug_sigprint(); return arrayops::has_nan(memptr(), n_elem); } template inline bool Cube::internal_has_nonfinite() const { arma_extra_debug_sigprint(); return (arrayops::is_finite(memptr(), n_elem) == false); } //! returns true if the given index is currently in range template arma_inline bool Cube::in_range(const uword i) const { return (i < n_elem); } //! returns true if the given start and end indices are currently in range template arma_inline bool Cube::in_range(const span& x) const { arma_extra_debug_sigprint(); if(x.whole) { return true; } else { const uword a = x.a; const uword b = x.b; return ( (a <= b) && (b < n_elem) ); } } //! returns true if the given location is currently in range template arma_inline bool Cube::in_range(const uword in_row, const uword in_col, const uword in_slice) const { return ( (in_row < n_rows) && (in_col < n_cols) && (in_slice < n_slices) ); } template inline bool Cube::in_range(const span& row_span, const span& col_span, const span& slice_span) const { arma_extra_debug_sigprint(); const uword in_row1 = row_span.a; const uword in_row2 = row_span.b; const uword in_col1 = col_span.a; const uword in_col2 = col_span.b; const uword in_slice1 = slice_span.a; const uword in_slice2 = slice_span.b; const bool rows_ok = row_span.whole ? true : ( (in_row1 <= in_row2) && (in_row2 < n_rows) ); const bool cols_ok = col_span.whole ? true : ( (in_col1 <= in_col2) && (in_col2 < n_cols) ); const bool slices_ok = slice_span.whole ? true : ( (in_slice1 <= in_slice2) && (in_slice2 < n_slices) ); return ( rows_ok && cols_ok && slices_ok ); } template inline bool Cube::in_range(const uword in_row, const uword in_col, const uword in_slice, const SizeCube& s) const { const uword l_n_rows = n_rows; const uword l_n_cols = n_cols; const uword l_n_slices = n_slices; if( ( in_row >= l_n_rows) || ( in_col >= l_n_cols) || ( in_slice >= l_n_slices) || ((in_row + s.n_rows) > l_n_rows) || ((in_col + s.n_cols) > l_n_cols) || ((in_slice + s.n_slices) > l_n_slices) ) { return false; } else { return true; } } //! returns a pointer to array of eTs used by the cube template arma_inline eT* Cube::memptr() { return const_cast(mem); } //! returns a pointer to array of eTs used by the cube template arma_inline const eT* Cube::memptr() const { return mem; } //! returns a pointer to array of eTs used by the specified slice in the cube template arma_inline eT* Cube::slice_memptr(const uword uslice) { return const_cast( &mem[ uslice*n_elem_slice ] ); } //! returns a pointer to array of eTs used by the specified slice in the cube template arma_inline const eT* Cube::slice_memptr(const uword uslice) const { return &mem[ uslice*n_elem_slice ]; } //! returns a pointer to array of eTs used by the specified slice in the cube template arma_inline eT* Cube::slice_colptr(const uword uslice, const uword col) { return const_cast( &mem[ uslice*n_elem_slice + col*n_rows] ); } //! returns a pointer to array of eTs used by the specified slice in the cube template arma_inline const eT* Cube::slice_colptr(const uword uslice, const uword col) const { return &mem[ uslice*n_elem_slice + col*n_rows ]; } //! change the cube to have user specified dimensions (data is not preserved) template inline Cube& Cube::set_size(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); init_warm(new_n_rows, new_n_cols, new_n_slices); return *this; } //! change the cube to have user specified dimensions (data is preserved) template inline Cube& Cube::reshape(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); op_reshape::apply_cube_inplace((*this), new_n_rows, new_n_cols, new_n_slices); return *this; } //! change the cube to have user specified dimensions (data is preserved) template inline Cube& Cube::resize(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); op_resize::apply_cube_inplace((*this), new_n_rows, new_n_cols, new_n_slices); return *this; } template inline Cube& Cube::set_size(const SizeCube& s) { arma_extra_debug_sigprint(); init_warm(s.n_rows, s.n_cols, s.n_slices); return *this; } template inline Cube& Cube::reshape(const SizeCube& s) { arma_extra_debug_sigprint(); op_reshape::apply_cube_inplace((*this), s.n_rows, s.n_cols, s.n_slices); return *this; } template inline Cube& Cube::resize(const SizeCube& s) { arma_extra_debug_sigprint(); op_resize::apply_cube_inplace((*this), s.n_rows, s.n_cols, s.n_slices); return *this; } //! change the cube (without preserving data) to have the same dimensions as the given cube template template inline Cube& Cube::copy_size(const Cube& m) { arma_extra_debug_sigprint(); init_warm(m.n_rows, m.n_cols, m.n_slices); return *this; } //! apply a functor to each element template template inline Cube& Cube::for_each(functor F) { arma_extra_debug_sigprint(); eT* data = memptr(); const uword N = n_elem; uword ii, jj; for(ii=0, jj=1; jj < N; ii+=2, jj+=2) { F(data[ii]); F(data[jj]); } if(ii < N) { F(data[ii]); } return *this; } template template inline const Cube& Cube::for_each(functor F) const { arma_extra_debug_sigprint(); const eT* data = memptr(); const uword N = n_elem; uword ii, jj; for(ii=0, jj=1; jj < N; ii+=2, jj+=2) { F(data[ii]); F(data[jj]); } if(ii < N) { F(data[ii]); } return *this; } //! transform each element in the cube using a functor template template inline Cube& Cube::transform(functor F) { arma_extra_debug_sigprint(); eT* out_mem = memptr(); const uword N = n_elem; uword ii, jj; for(ii=0, jj=1; jj < N; ii+=2, jj+=2) { eT tmp_ii = out_mem[ii]; eT tmp_jj = out_mem[jj]; tmp_ii = eT( F(tmp_ii) ); tmp_jj = eT( F(tmp_jj) ); out_mem[ii] = tmp_ii; out_mem[jj] = tmp_jj; } if(ii < N) { out_mem[ii] = eT( F(out_mem[ii]) ); } return *this; } //! imbue (fill) the cube with values provided by a functor template template inline Cube& Cube::imbue(functor F) { arma_extra_debug_sigprint(); eT* out_mem = memptr(); const uword N = n_elem; uword ii, jj; for(ii=0, jj=1; jj < N; ii+=2, jj+=2) { const eT tmp_ii = eT( F() ); const eT tmp_jj = eT( F() ); out_mem[ii] = tmp_ii; out_mem[jj] = tmp_jj; } if(ii < N) { out_mem[ii] = eT( F() ); } return *this; } template inline Cube& Cube::replace(const eT old_val, const eT new_val) { arma_extra_debug_sigprint(); arrayops::replace(memptr(), n_elem, old_val, new_val); return *this; } template inline Cube& Cube::clean(const typename get_pod_type::result threshold) { arma_extra_debug_sigprint(); arrayops::clean(memptr(), n_elem, threshold); return *this; } template inline Cube& Cube::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)), "Cube::clamp(): min_val must be less than max_val" ); } else { arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "Cube::clamp(): real(min_val) must be less than real(max_val)" ); arma_debug_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "Cube::clamp(): imag(min_val) must be less than imag(max_val)" ); } arrayops::clamp(memptr(), n_elem, min_val, max_val); return *this; } //! fill the cube with the specified value template inline Cube& Cube::fill(const eT val) { arma_extra_debug_sigprint(); arrayops::inplace_set( memptr(), val, n_elem ); return *this; } template inline Cube& Cube::zeros() { arma_extra_debug_sigprint(); arrayops::fill_zeros(memptr(), n_elem); return *this; } template inline Cube& Cube::zeros(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); set_size(new_n_rows, new_n_cols, new_n_slices); return (*this).zeros(); } template inline Cube& Cube::zeros(const SizeCube& s) { arma_extra_debug_sigprint(); return (*this).zeros(s.n_rows, s.n_cols, s.n_slices); } template inline Cube& Cube::ones() { arma_extra_debug_sigprint(); return (*this).fill(eT(1)); } template inline Cube& Cube::ones(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); set_size(new_n_rows, new_n_cols, new_n_slices); return (*this).fill(eT(1)); } template inline Cube& Cube::ones(const SizeCube& s) { arma_extra_debug_sigprint(); return (*this).ones(s.n_rows, s.n_cols, s.n_slices); } template inline Cube& Cube::randu() { arma_extra_debug_sigprint(); arma_rng::randu::fill( memptr(), n_elem ); return *this; } template inline Cube& Cube::randu(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); set_size(new_n_rows, new_n_cols, new_n_slices); return (*this).randu(); } template inline Cube& Cube::randu(const SizeCube& s) { arma_extra_debug_sigprint(); return (*this).randu(s.n_rows, s.n_cols, s.n_slices); } template inline Cube& Cube::randn() { arma_extra_debug_sigprint(); arma_rng::randn::fill( memptr(), n_elem ); return *this; } template inline Cube& Cube::randn(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices) { arma_extra_debug_sigprint(); set_size(new_n_rows, new_n_cols, new_n_slices); return (*this).randn(); } template inline Cube& Cube::randn(const SizeCube& s) { arma_extra_debug_sigprint(); return (*this).randn(s.n_rows, s.n_cols, s.n_slices); } template inline void Cube::reset() { arma_extra_debug_sigprint(); init_warm(0,0,0); } template inline void Cube::soft_reset() { arma_extra_debug_sigprint(); // don't change the size if the cube has a fixed size if(mem_state <= 1) { reset(); } else { zeros(); } } template template inline void Cube::set_real(const BaseCube::pod_type,T1>& X) { arma_extra_debug_sigprint(); Cube_aux::set_real(*this, X); } template template inline void Cube::set_imag(const BaseCube::pod_type,T1>& X) { arma_extra_debug_sigprint(); Cube_aux::set_imag(*this, X); } template inline eT Cube::min() const { arma_extra_debug_sigprint(); if(n_elem == 0) { arma_debug_check(true, "Cube::min(): object has no elements"); return Datum::nan; } return op_min::direct_min(memptr(), n_elem); } template inline eT Cube::max() const { arma_extra_debug_sigprint(); if(n_elem == 0) { arma_debug_check(true, "Cube::max(): object has no elements"); return Datum::nan; } return op_max::direct_max(memptr(), n_elem); } template inline eT Cube::min(uword& index_of_min_val) const { arma_extra_debug_sigprint(); if(n_elem == 0) { arma_debug_check(true, "Cube::min(): object has no elements"); index_of_min_val = uword(0); return Datum::nan; } return op_min::direct_min(memptr(), n_elem, index_of_min_val); } template inline eT Cube::max(uword& index_of_max_val) const { arma_extra_debug_sigprint(); if(n_elem == 0) { arma_debug_check(true, "Cube::max(): object has no elements"); index_of_max_val = uword(0); return Datum::nan; } return op_max::direct_max(memptr(), n_elem, index_of_max_val); } template inline eT Cube::min(uword& row_of_min_val, uword& col_of_min_val, uword& slice_of_min_val) const { arma_extra_debug_sigprint(); if(n_elem == 0) { arma_debug_check(true, "Cube::min(): object has no elements"); row_of_min_val = uword(0); col_of_min_val = uword(0); slice_of_min_val = uword(0); return Datum::nan; } uword i; eT val = op_min::direct_min(memptr(), n_elem, i); const uword in_slice = i / n_elem_slice; const uword offset = in_slice * n_elem_slice; const uword j = i - offset; row_of_min_val = j % n_rows; col_of_min_val = j / n_rows; slice_of_min_val = in_slice; return val; } template inline eT Cube::max(uword& row_of_max_val, uword& col_of_max_val, uword& slice_of_max_val) const { arma_extra_debug_sigprint(); if(n_elem == 0) { arma_debug_check(true, "Cube::max(): object has no elements"); row_of_max_val = uword(0); col_of_max_val = uword(0); slice_of_max_val = uword(0); return Datum::nan; } uword i; eT val = op_max::direct_max(memptr(), n_elem, i); const uword in_slice = i / n_elem_slice; const uword offset = in_slice * n_elem_slice; const uword j = i - offset; row_of_max_val = j % n_rows; col_of_max_val = j / n_rows; slice_of_max_val = in_slice; return val; } //! save the cube to a file template inline bool Cube::save(const std::string name, const file_type type) const { arma_extra_debug_sigprint(); bool save_okay = false; switch(type) { case raw_ascii: save_okay = diskio::save_raw_ascii(*this, name); break; case arma_ascii: save_okay = diskio::save_arma_ascii(*this, name); break; case raw_binary: save_okay = diskio::save_raw_binary(*this, name); break; case arma_binary: save_okay = diskio::save_arma_binary(*this, name); break; case ppm_binary: save_okay = diskio::save_ppm_binary(*this, name); break; case hdf5_binary: return (*this).save(hdf5_name(name)); break; case hdf5_binary_trans: // kept for compatibility with earlier versions of Armadillo return (*this).save(hdf5_name(name, std::string(), hdf5_opts::trans)); break; default: arma_debug_warn_level(1, "Cube::save(): unsupported file type"); save_okay = false; } if(save_okay == false) { arma_debug_warn_level(3, "Cube::save(): write failed; file: ", name); } return save_okay; } template inline bool Cube::save(const hdf5_name& spec, const file_type type) const { arma_extra_debug_sigprint(); // handling of hdf5_binary_trans kept for compatibility with earlier versions of Armadillo if( (type != hdf5_binary) && (type != hdf5_binary_trans) ) { arma_stop_runtime_error("Cube::save(): unsupported file type for hdf5_name()"); return false; } const bool do_trans = bool(spec.opts.flags & hdf5_opts::flag_trans ) || (type == hdf5_binary_trans); const bool append = bool(spec.opts.flags & hdf5_opts::flag_append ); const bool replace = bool(spec.opts.flags & hdf5_opts::flag_replace); if(append && replace) { arma_stop_runtime_error("Cube::save(): only one of 'append' or 'replace' options can be used"); return false; } bool save_okay = false; std::string err_msg; if(do_trans) { Cube tmp; op_strans_cube::apply_noalias(tmp, (*this)); save_okay = diskio::save_hdf5_binary(tmp, spec, err_msg); } else { save_okay = diskio::save_hdf5_binary(*this, spec, err_msg); } if(save_okay == false) { if(err_msg.length() > 0) { arma_debug_warn_level(3, "Cube::save(): ", err_msg, "; file: ", spec.filename); } else { arma_debug_warn_level(3, "Cube::save(): write failed; file: ", spec.filename); } } return save_okay; } //! save the cube to a stream template inline bool Cube::save(std::ostream& os, const file_type type) const { arma_extra_debug_sigprint(); bool save_okay = false; switch(type) { case raw_ascii: save_okay = diskio::save_raw_ascii(*this, os); break; case arma_ascii: save_okay = diskio::save_arma_ascii(*this, os); break; case raw_binary: save_okay = diskio::save_raw_binary(*this, os); break; case arma_binary: save_okay = diskio::save_arma_binary(*this, os); break; case ppm_binary: save_okay = diskio::save_ppm_binary(*this, os); break; default: arma_debug_warn_level(1, "Cube::save(): unsupported file type"); save_okay = false; } if(save_okay == false) { arma_debug_warn_level(3, "Cube::save(): stream write failed"); } return save_okay; } //! load a cube from a file template inline bool Cube::load(const std::string name, const file_type type) { arma_extra_debug_sigprint(); bool load_okay = false; std::string err_msg; switch(type) { case auto_detect: load_okay = diskio::load_auto_detect(*this, name, err_msg); break; case raw_ascii: load_okay = diskio::load_raw_ascii(*this, name, err_msg); break; case arma_ascii: load_okay = diskio::load_arma_ascii(*this, name, err_msg); break; case raw_binary: load_okay = diskio::load_raw_binary(*this, name, err_msg); break; case arma_binary: load_okay = diskio::load_arma_binary(*this, name, err_msg); break; case ppm_binary: load_okay = diskio::load_ppm_binary(*this, name, err_msg); break; case hdf5_binary: return (*this).load(hdf5_name(name)); break; case hdf5_binary_trans: // kept for compatibility with earlier versions of Armadillo return (*this).load(hdf5_name(name, std::string(), hdf5_opts::trans)); break; default: arma_debug_warn_level(1, "Cube::load(): unsupported file type"); load_okay = false; } if(load_okay == false) { (*this).soft_reset(); if(err_msg.length() > 0) { arma_debug_warn_level(3, "Cube::load(): ", err_msg, "; file: ", name); } else { arma_debug_warn_level(3, "Cube::load(): read failed; file: ", name); } } return load_okay; } template inline bool Cube::load(const hdf5_name& spec, const file_type type) { arma_extra_debug_sigprint(); if( (type != hdf5_binary) && (type != hdf5_binary_trans) ) { arma_stop_runtime_error("Cube::load(): unsupported file type for hdf5_name()"); return false; } bool load_okay = false; std::string err_msg; const bool do_trans = bool(spec.opts.flags & hdf5_opts::flag_trans) || (type == hdf5_binary_trans); if(do_trans) { Cube tmp; load_okay = diskio::load_hdf5_binary(tmp, spec, err_msg); if(load_okay) { op_strans_cube::apply_noalias((*this), tmp); } } else { load_okay = diskio::load_hdf5_binary(*this, spec, err_msg); } if(load_okay == false) { (*this).soft_reset(); if(err_msg.length() > 0) { arma_debug_warn_level(3, "Cube::load(): ", err_msg, "; file: ", spec.filename); } else { arma_debug_warn_level(3, "Cube::load(): read failed; file: ", spec.filename); } } return load_okay; } //! load a cube from a stream template inline bool Cube::load(std::istream& is, const file_type type) { arma_extra_debug_sigprint(); bool load_okay = false; std::string err_msg; switch(type) { case auto_detect: load_okay = diskio::load_auto_detect(*this, is, err_msg); break; case raw_ascii: load_okay = diskio::load_raw_ascii(*this, is, err_msg); break; case arma_ascii: load_okay = diskio::load_arma_ascii(*this, is, err_msg); break; case raw_binary: load_okay = diskio::load_raw_binary(*this, is, err_msg); break; case arma_binary: load_okay = diskio::load_arma_binary(*this, is, err_msg); break; case ppm_binary: load_okay = diskio::load_ppm_binary(*this, is, err_msg); break; default: arma_debug_warn_level(1, "Cube::load(): unsupported file type"); load_okay = false; } if(load_okay == false) { (*this).soft_reset(); if(err_msg.length() > 0) { arma_debug_warn_level(3, "Cube::load(): ", err_msg); } else { arma_debug_warn_level(3, "Cube::load(): stream read failed"); } } return load_okay; } template inline bool Cube::quiet_save(const std::string name, const file_type type) const { arma_extra_debug_sigprint(); return (*this).save(name, type); } template inline bool Cube::quiet_save(const hdf5_name& spec, const file_type type) const { arma_extra_debug_sigprint(); return (*this).save(spec, type); } template inline bool Cube::quiet_save(std::ostream& os, const file_type type) const { arma_extra_debug_sigprint(); return (*this).save(os, type); } template inline bool Cube::quiet_load(const std::string name, const file_type type) { arma_extra_debug_sigprint(); return (*this).load(name, type); } template inline bool Cube::quiet_load(const hdf5_name& spec, const file_type type) { arma_extra_debug_sigprint(); return (*this).load(spec, type); } template inline bool Cube::quiet_load(std::istream& is, const file_type type) { arma_extra_debug_sigprint(); return (*this).load(is, type); } template inline typename Cube::iterator Cube::begin() { arma_extra_debug_sigprint(); return memptr(); } template inline typename Cube::const_iterator Cube::begin() const { arma_extra_debug_sigprint(); return memptr(); } template inline typename Cube::const_iterator Cube::cbegin() const { arma_extra_debug_sigprint(); return memptr(); } template inline typename Cube::iterator Cube::end() { arma_extra_debug_sigprint(); return memptr() + n_elem; } template inline typename Cube::const_iterator Cube::end() const { arma_extra_debug_sigprint(); return memptr() + n_elem; } template inline typename Cube::const_iterator Cube::cend() const { arma_extra_debug_sigprint(); return memptr() + n_elem; } template inline typename Cube::slice_iterator Cube::begin_slice(const uword slice_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (slice_num >= n_slices), "begin_slice(): index out of bounds" ); return slice_memptr(slice_num); } template inline typename Cube::const_slice_iterator Cube::begin_slice(const uword slice_num) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (slice_num >= n_slices), "begin_slice(): index out of bounds" ); return slice_memptr(slice_num); } template inline typename Cube::slice_iterator Cube::end_slice(const uword slice_num) { arma_extra_debug_sigprint(); arma_debug_check_bounds( (slice_num >= n_slices), "end_slice(): index out of bounds" ); return slice_memptr(slice_num) + n_elem_slice; } template inline typename Cube::const_slice_iterator Cube::end_slice(const uword slice_num) const { arma_extra_debug_sigprint(); arma_debug_check_bounds( (slice_num >= n_slices), "end_slice(): index out of bounds" ); return slice_memptr(slice_num) + n_elem_slice; } //! resets this cube to an empty matrix template inline void Cube::clear() { reset(); } //! returns true if the cube has no elements template inline bool Cube::empty() const { return (n_elem == 0); } //! returns the number of elements in this cube template inline uword Cube::size() const { return n_elem; } template inline eT& Cube::front() { arma_debug_check( (n_elem == 0), "Cube::front(): cube is empty" ); return access::rw(mem[0]); } template inline const eT& Cube::front() const { arma_debug_check( (n_elem == 0), "Cube::front(): cube is empty" ); return mem[0]; } template inline eT& Cube::back() { arma_debug_check( (n_elem == 0), "Cube::back(): cube is empty" ); return access::rw(mem[n_elem-1]); } template inline const eT& Cube::back() const { arma_debug_check( (n_elem == 0), "Cube::back(): cube is empty" ); return mem[n_elem-1]; } template inline void Cube::swap(Cube& B) { Cube& A = (*this); arma_extra_debug_sigprint(arma_str::format("A = %x B = %x") % &A % &B); if( (A.mem_state == 0) && (B.mem_state == 0) && (A.n_elem > Cube_prealloc::mem_n_elem) && (B.n_elem > Cube_prealloc::mem_n_elem) ) { A.delete_mat(); B.delete_mat(); std::swap( access::rw(A.n_rows), access::rw(B.n_rows) ); std::swap( access::rw(A.n_cols), access::rw(B.n_cols) ); std::swap( access::rw(A.n_elem_slice), access::rw(B.n_elem_slice) ); std::swap( access::rw(A.n_slices), access::rw(B.n_slices) ); std::swap( access::rw(A.n_elem), access::rw(B.n_elem) ); std::swap( access::rw(A.mem), access::rw(B.mem) ); A.create_mat(); B.create_mat(); } else if( (A.mem_state == 0) && (B.mem_state == 0) && (A.n_elem <= Cube_prealloc::mem_n_elem) && (B.n_elem <= Cube_prealloc::mem_n_elem) ) { A.delete_mat(); B.delete_mat(); std::swap( access::rw(A.n_rows), access::rw(B.n_rows) ); std::swap( access::rw(A.n_cols), access::rw(B.n_cols) ); std::swap( access::rw(A.n_elem_slice), access::rw(B.n_elem_slice) ); std::swap( access::rw(A.n_slices), access::rw(B.n_slices) ); std::swap( access::rw(A.n_elem), access::rw(B.n_elem) ); const uword N = (std::max)(A.n_elem, B.n_elem); eT* A_mem = A.memptr(); eT* B_mem = B.memptr(); for(uword i=0; i C = A; A.steal_mem(B); B.steal_mem(C); } else { Cube C = B; B.steal_mem(A); A.steal_mem(C); } } } //! try to steal the memory from a given cube; //! if memory can't be stolen, copy the given cube template inline void Cube::steal_mem(Cube& x) { arma_extra_debug_sigprint(); (*this).steal_mem(x, false); } template inline void Cube::steal_mem(Cube& x, const bool is_move) { arma_extra_debug_sigprint(); if(this == &x) { return; } if( (mem_state <= 1) && ( (x.n_alloc > Cube_prealloc::mem_n_elem) || (x.mem_state == 1) || (is_move && (x.mem_state == 2)) ) ) { arma_extra_debug_print("Cube::steal_mem(): stealing memory"); reset(); const uword x_n_slices = x.n_slices; access::rw(n_rows) = x.n_rows; access::rw(n_cols) = x.n_cols; access::rw(n_elem_slice) = x.n_elem_slice; access::rw(n_slices) = x_n_slices; access::rw(n_elem) = x.n_elem; access::rw(n_alloc) = x.n_alloc; access::rw(mem_state) = x.mem_state; access::rw(mem) = x.mem; if(x_n_slices > Cube_prealloc::mat_ptrs_size) { arma_extra_debug_print("Cube::steal_mem(): stealing mat_ptrs array"); mat_ptrs = x.mat_ptrs; x.mat_ptrs = nullptr; } else { arma_extra_debug_print("Cube::steal_mem(): copying mat_ptrs array"); mat_ptrs = mat_ptrs_local; for(uword i=0; i < x_n_slices; ++i) { mat_ptrs[i] = raw_mat_ptr_type(x.mat_ptrs[i]); // cast required by std::atomic x.mat_ptrs[i] = nullptr; } } access::rw(x.n_rows) = 0; access::rw(x.n_cols) = 0; access::rw(x.n_elem_slice) = 0; access::rw(x.n_slices) = 0; access::rw(x.n_elem) = 0; access::rw(x.n_alloc) = 0; access::rw(x.mem_state) = 0; access::rw(x.mem) = nullptr; } else { arma_extra_debug_print("Cube::steal_mem(): copying memory"); (*this).operator=(x); if( (is_move) && (x.mem_state == 0) && (x.n_alloc <= Cube_prealloc::mem_n_elem) ) { x.reset(); } } } // // Cube::fixed template template arma_inline void Cube::fixed::mem_setup() { arma_extra_debug_sigprint(); if(fixed_n_elem > 0) { access::rw(Cube::n_rows) = fixed_n_rows; access::rw(Cube::n_cols) = fixed_n_cols; access::rw(Cube::n_elem_slice) = fixed_n_rows * fixed_n_cols; access::rw(Cube::n_slices) = fixed_n_slices; access::rw(Cube::n_elem) = fixed_n_elem; access::rw(Cube::n_alloc) = 0; access::rw(Cube::mem_state) = 3; access::rw(Cube::mem) = (fixed_n_elem > Cube_prealloc::mem_n_elem) ? mem_local_extra : mem_local; Cube::mat_ptrs = (fixed_n_slices > Cube_prealloc::mat_ptrs_size) ? mat_ptrs_local_extra : mat_ptrs_local; create_mat(); } else { access::rw(Cube::n_rows) = 0; access::rw(Cube::n_cols) = 0; access::rw(Cube::n_elem_slice) = 0; access::rw(Cube::n_slices) = 0; access::rw(Cube::n_elem) = 0; access::rw(Cube::n_alloc) = 0; access::rw(Cube::mem_state) = 3; access::rw(Cube::mem) = nullptr; Cube::mat_ptrs = nullptr; } } template template inline Cube::fixed::fixed() { arma_extra_debug_sigprint_this(this); mem_setup(); if(arma_config::zero_init) { arma_extra_debug_print("Cube::fixed::constructor: zeroing memory"); eT* mem_use = (use_extra) ? &(mem_local_extra[0]) : &(mem_local[0]); arrayops::fill_zeros(mem_use, fixed_n_elem); } } template template inline Cube::fixed::fixed(const fixed& X) { arma_extra_debug_sigprint_this(this); mem_setup(); eT* dest = (use_extra) ? mem_local_extra : mem_local; const eT* src = (use_extra) ? X.mem_local_extra : X.mem_local; arrayops::copy( dest, src, fixed_n_elem ); } template template inline Cube::fixed::fixed(const fill::scalar_holder f) { arma_extra_debug_sigprint_this(this); mem_setup(); (*this).fill(f.scalar); } template template template inline Cube::fixed::fixed(const fill::fill_class&) { arma_extra_debug_sigprint_this(this); mem_setup(); if(is_same_type::yes) { (*this).zeros(); } if(is_same_type::yes) { (*this).ones(); } if(is_same_type::yes) { (*this).randu(); } if(is_same_type::yes) { (*this).randn(); } arma_static_check( (is_same_type::yes), "Cube::fixed::fixed(): unsupported fill type" ); } template template template inline Cube::fixed::fixed(const BaseCube& A) { arma_extra_debug_sigprint_this(this); mem_setup(); Cube::operator=(A.get_ref()); } template template template inline Cube::fixed::fixed(const BaseCube& A, const BaseCube& B) { arma_extra_debug_sigprint_this(this); mem_setup(); Cube::init(A,B); } template template inline Cube& Cube::fixed::operator=(const fixed& X) { arma_extra_debug_sigprint(); eT* dest = (use_extra) ? mem_local_extra : mem_local; const eT* src = (use_extra) ? X.mem_local_extra : X.mem_local; arrayops::copy( dest, src, fixed_n_elem ); return *this; } template template arma_inline eT& Cube::fixed::operator[] (const uword i) { return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline const eT& Cube::fixed::operator[] (const uword i) const { return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline eT& Cube::fixed::at(const uword i) { return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline const eT& Cube::fixed::at(const uword i) const { return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline eT& Cube::fixed::operator() (const uword i) { arma_debug_check_bounds( (i >= fixed_n_elem), "Cube::operator(): index out of bounds" ); return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline const eT& Cube::fixed::operator() (const uword i) const { arma_debug_check_bounds( (i >= fixed_n_elem), "Cube::operator(): index out of bounds" ); return (use_extra) ? mem_local_extra[i] : mem_local[i]; } #if defined(__cpp_multidimensional_subscript) template template arma_inline eT& Cube::fixed::operator[] (const uword in_row, const uword in_col, const uword in_slice) { const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row; return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline const eT& Cube::fixed::operator[] (const uword in_row, const uword in_col, const uword in_slice) const { const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row; return (use_extra) ? mem_local_extra[i] : mem_local[i]; } #endif template template arma_inline eT& Cube::fixed::at(const uword in_row, const uword in_col, const uword in_slice) { const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row; return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline const eT& Cube::fixed::at(const uword in_row, const uword in_col, const uword in_slice) const { const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row; return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline eT& Cube::fixed::operator() (const uword in_row, const uword in_col, const uword in_slice) { arma_debug_check_bounds ( (in_row >= fixed_n_rows ) || (in_col >= fixed_n_cols ) || (in_slice >= fixed_n_slices) , "operator(): index out of bounds" ); const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row; return (use_extra) ? mem_local_extra[i] : mem_local[i]; } template template arma_inline const eT& Cube::fixed::operator() (const uword in_row, const uword in_col, const uword in_slice) const { arma_debug_check_bounds ( (in_row >= fixed_n_rows ) || (in_col >= fixed_n_cols ) || (in_slice >= fixed_n_slices) , "Cube::operator(): index out of bounds" ); const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row; return (use_extra) ? mem_local_extra[i] : mem_local[i]; } // // Cube_aux //! prefix ++ template arma_inline void Cube_aux::prefix_pp(Cube& x) { eT* memptr = x.memptr(); const uword n_elem = x.n_elem; uword i,j; for(i=0, j=1; j arma_inline void Cube_aux::prefix_pp(Cube< std::complex >& x) { x += T(1); } //! postfix ++ template arma_inline void Cube_aux::postfix_pp(Cube& x) { eT* memptr = x.memptr(); const uword n_elem = x.n_elem; uword i,j; for(i=0, j=1; j arma_inline void Cube_aux::postfix_pp(Cube< std::complex >& x) { x += T(1); } //! prefix -- template arma_inline void Cube_aux::prefix_mm(Cube& x) { eT* memptr = x.memptr(); const uword n_elem = x.n_elem; uword i,j; for(i=0, j=1; j arma_inline void Cube_aux::prefix_mm(Cube< std::complex >& x) { x -= T(1); } //! postfix -- template arma_inline void Cube_aux::postfix_mm(Cube& x) { eT* memptr = x.memptr(); const uword n_elem = x.n_elem; uword i,j; for(i=0, j=1; j arma_inline void Cube_aux::postfix_mm(Cube< std::complex >& x) { x -= T(1); } template inline void Cube_aux::set_real(Cube& out, const BaseCube& X) { arma_extra_debug_sigprint(); const unwrap_cube tmp(X.get_ref()); const Cube& A = tmp.M; arma_debug_assert_same_size( out, A, "Cube::set_real()" ); out = A; } template inline void Cube_aux::set_imag(Cube&, const BaseCube&) { arma_extra_debug_sigprint(); } template inline void Cube_aux::set_real(Cube< std::complex >& out, const BaseCube& X) { arma_extra_debug_sigprint(); typedef typename std::complex eT; const ProxyCube P(X.get_ref()); const uword local_n_rows = P.get_n_rows(); const uword local_n_cols = P.get_n_cols(); const uword local_n_slices = P.get_n_slices(); arma_debug_assert_same_size ( out.n_rows, out.n_cols, out.n_slices, local_n_rows, local_n_cols, local_n_slices, "Cube::set_real()" ); eT* out_mem = out.memptr(); if(ProxyCube::use_at == false) { typedef typename ProxyCube::ea_type ea_type; ea_type A = P.get_ea(); const uword N = out.n_elem; for(uword i=0; i inline void Cube_aux::set_imag(Cube< std::complex >& out, const BaseCube& X) { arma_extra_debug_sigprint(); typedef typename std::complex eT; const ProxyCube P(X.get_ref()); const uword local_n_rows = P.get_n_rows(); const uword local_n_cols = P.get_n_cols(); const uword local_n_slices = P.get_n_slices(); arma_debug_assert_same_size ( out.n_rows, out.n_cols, out.n_slices, local_n_rows, local_n_cols, local_n_slices, "Cube::set_imag()" ); eT* out_mem = out.memptr(); if(ProxyCube::use_at == false) { typedef typename ProxyCube::ea_type ea_type; ea_type A = P.get_ea(); const uword N = out.n_elem; for(uword i=0; i