// 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 //! @{ struct Cube_prealloc { static constexpr uword mat_ptrs_size = 4; static constexpr uword mem_n_elem = 64; }; //! Dense cube class template class Cube : public BaseCube< eT, Cube > { public: typedef eT elem_type; //!< the type of elements stored in the cube typedef typename get_pod_type::result pod_type; //!< if eT is std::complex, pod_type is T; otherwise pod_type is eT const uword n_rows; //!< number of rows in each slice (read-only) const uword n_cols; //!< number of columns in each slice (read-only) const uword n_elem_slice; //!< number of elements in each slice (read-only) const uword n_slices; //!< number of slices in the cube (read-only) const uword n_elem; //!< number of elements in the cube (read-only) const uword n_alloc; //!< number of allocated elements (read-only); NOTE: n_alloc can be 0, even if n_elem > 0 const uword mem_state; // mem_state = 0: normal cube which manages its own memory // mem_state = 1: use auxiliary memory until a size change // mem_state = 2: use auxiliary memory and don't allow the number of elements to be changed // mem_state = 3: fixed size (eg. via template based size specification) arma_aligned const eT* const mem; //!< pointer to the memory used for storing elements (memory is read-only) protected: using mat_type = Mat; #if defined(ARMA_USE_OPENMP) using raw_mat_ptr_type = mat_type*; using atomic_mat_ptr_type = mat_type*; #elif (!defined(ARMA_DONT_USE_STD_MUTEX)) using raw_mat_ptr_type = mat_type*; using atomic_mat_ptr_type = std::atomic; #else using raw_mat_ptr_type = mat_type*; using atomic_mat_ptr_type = mat_type*; #endif atomic_mat_ptr_type* mat_ptrs = nullptr; #if (!defined(ARMA_DONT_USE_STD_MUTEX)) mutable std::mutex mat_mutex; // required for slice() #endif arma_aligned atomic_mat_ptr_type mat_ptrs_local[ Cube_prealloc::mat_ptrs_size ]; arma_align_mem eT mem_local[ Cube_prealloc::mem_n_elem ]; // local storage, for small cubes public: inline ~Cube(); inline Cube(); inline explicit Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices); inline explicit Cube(const SizeCube& s); template inline explicit Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const arma_initmode_indicator&); template inline explicit Cube(const SizeCube& s, const arma_initmode_indicator&); template inline Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const fill::fill_class& f); template inline Cube(const SizeCube& s, const fill::fill_class& f); inline Cube(const uword in_rows, const uword in_cols, const uword in_slices, const fill::scalar_holder f); inline Cube(const SizeCube& s, const fill::scalar_holder f); inline Cube(Cube&& m); inline Cube& operator=(Cube&& m); inline Cube( eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const uword aux_n_slices, const bool copy_aux_mem = true, const bool strict = false, const bool prealloc_mat = false); inline Cube(const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const uword aux_n_slices); inline Cube& operator= (const eT val); inline Cube& operator+=(const eT val); inline Cube& operator-=(const eT val); inline Cube& operator*=(const eT val); inline Cube& operator/=(const eT val); inline Cube(const Cube& m); inline Cube& operator= (const Cube& m); inline Cube& operator+=(const Cube& m); inline Cube& operator-=(const Cube& m); inline Cube& operator%=(const Cube& m); inline Cube& operator/=(const Cube& m); template inline explicit Cube(const BaseCube& A, const BaseCube& B); inline Cube(const subview_cube& X); inline Cube& operator= (const subview_cube& X); inline Cube& operator+=(const subview_cube& X); inline Cube& operator-=(const subview_cube& X); inline Cube& operator%=(const subview_cube& X); inline Cube& operator/=(const subview_cube& X); template inline Cube(const subview_cube_slices& X); template inline Cube& operator= (const subview_cube_slices& X); template inline Cube& operator+=(const subview_cube_slices& X); template inline Cube& operator-=(const subview_cube_slices& X); template inline Cube& operator%=(const subview_cube_slices& X); template inline Cube& operator/=(const subview_cube_slices& X); arma_inline subview_cube row(const uword in_row); arma_inline const subview_cube row(const uword in_row) const; arma_inline subview_cube col(const uword in_col); arma_inline const subview_cube col(const uword in_col) const; inline Mat& slice(const uword in_slice); inline const Mat& slice(const uword in_slice) const; arma_inline subview_cube rows(const uword in_row1, const uword in_row2); arma_inline const subview_cube rows(const uword in_row1, const uword in_row2) const; arma_inline subview_cube cols(const uword in_col1, const uword in_col2); arma_inline const subview_cube cols(const uword in_col1, const uword in_col2) const; arma_inline subview_cube slices(const uword in_slice1, const uword in_slice2); arma_inline const subview_cube slices(const uword in_slice1, const uword in_slice2) const; arma_inline subview_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_inline const subview_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; inline subview_cube subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s); inline const subview_cube subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const; inline subview_cube subcube(const span& row_span, const span& col_span, const span& slice_span); inline const subview_cube subcube(const span& row_span, const span& col_span, const span& slice_span) const; inline subview_cube operator()(const span& row_span, const span& col_span, const span& slice_span); inline const subview_cube operator()(const span& row_span, const span& col_span, const span& slice_span) const; inline subview_cube operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s); inline const subview_cube operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const; arma_inline subview_cube tube(const uword in_row1, const uword in_col1); arma_inline const subview_cube tube(const uword in_row1, const uword in_col1) const; arma_inline subview_cube tube(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2); arma_inline const subview_cube tube(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const; arma_inline subview_cube tube(const uword in_row1, const uword in_col1, const SizeMat& s); arma_inline const subview_cube tube(const uword in_row1, const uword in_col1, const SizeMat& s) const; inline subview_cube tube(const span& row_span, const span& col_span); inline const subview_cube tube(const span& row_span, const span& col_span) const; inline subview_cube head_slices(const uword N); inline const subview_cube head_slices(const uword N) const; inline subview_cube tail_slices(const uword N); inline const subview_cube tail_slices(const uword N) const; template arma_inline subview_elem1 elem(const Base& a); template arma_inline const subview_elem1 elem(const Base& a) const; template arma_inline subview_elem1 operator()(const Base& a); template arma_inline const subview_elem1 operator()(const Base& a) const; arma_inline subview_cube_each1 each_slice(); arma_inline const subview_cube_each1 each_slice() const; template inline subview_cube_each2 each_slice(const Base& indices); template inline const subview_cube_each2 each_slice(const Base& indices) const; inline Cube& each_slice(const std::function< void( Mat&) >& F); inline const Cube& each_slice(const std::function< void(const Mat&) >& F) const; inline Cube& each_slice(const std::function< void( Mat&) >& F, const bool use_mp); inline const Cube& each_slice(const std::function< void(const Mat&) >& F, const bool use_mp) const; template arma_inline subview_cube_slices slices(const Base& indices); template arma_inline const subview_cube_slices slices(const Base& indices) const; inline void shed_row(const uword row_num); inline void shed_col(const uword col_num); inline void shed_slice(const uword slice_num); inline void shed_rows(const uword in_row1, const uword in_row2); inline void shed_cols(const uword in_col1, const uword in_col2); inline void shed_slices(const uword in_slice1, const uword in_slice2); template inline void shed_slices(const Base& indices); arma_deprecated inline void insert_rows(const uword row_num, const uword N, const bool set_to_zero); arma_deprecated inline void insert_cols(const uword row_num, const uword N, const bool set_to_zero); arma_deprecated inline void insert_slices(const uword slice_num, const uword N, const bool set_to_zero); inline void insert_rows(const uword row_num, const uword N); inline void insert_cols(const uword row_num, const uword N); inline void insert_slices(const uword slice_num, const uword N); template inline void insert_rows(const uword row_num, const BaseCube& X); template inline void insert_cols(const uword col_num, const BaseCube& X); template inline void insert_slices(const uword slice_num, const BaseCube& X); template inline void insert_slices(const uword slice_num, const Base& X); template inline Cube(const GenCube& X); template inline Cube& operator= (const GenCube& X); template inline Cube& operator+=(const GenCube& X); template inline Cube& operator-=(const GenCube& X); template inline Cube& operator%=(const GenCube& X); template inline Cube& operator/=(const GenCube& X); template inline Cube(const OpCube& X); template inline Cube& operator= (const OpCube& X); template inline Cube& operator+=(const OpCube& X); template inline Cube& operator-=(const OpCube& X); template inline Cube& operator%=(const OpCube& X); template inline Cube& operator/=(const OpCube& X); template inline Cube(const eOpCube& X); template inline Cube& operator= (const eOpCube& X); template inline Cube& operator+=(const eOpCube& X); template inline Cube& operator-=(const eOpCube& X); template inline Cube& operator%=(const eOpCube& X); template inline Cube& operator/=(const eOpCube& X); template inline Cube(const mtOpCube& X); template inline Cube& operator= (const mtOpCube& X); template inline Cube& operator+=(const mtOpCube& X); template inline Cube& operator-=(const mtOpCube& X); template inline Cube& operator%=(const mtOpCube& X); template inline Cube& operator/=(const mtOpCube& X); template inline Cube(const GlueCube& X); template inline Cube& operator= (const GlueCube& X); template inline Cube& operator+=(const GlueCube& X); template inline Cube& operator-=(const GlueCube& X); template inline Cube& operator%=(const GlueCube& X); template inline Cube& operator/=(const GlueCube& X); template inline Cube(const eGlueCube& X); template inline Cube& operator= (const eGlueCube& X); template inline Cube& operator+=(const eGlueCube& X); template inline Cube& operator-=(const eGlueCube& X); template inline Cube& operator%=(const eGlueCube& X); template inline Cube& operator/=(const eGlueCube& X); template inline Cube(const mtGlueCube& X); template inline Cube& operator= (const mtGlueCube& X); template inline Cube& operator+=(const mtGlueCube& X); template inline Cube& operator-=(const mtGlueCube& X); template inline Cube& operator%=(const mtGlueCube& X); template inline Cube& operator/=(const mtGlueCube& X); arma_warn_unused arma_inline const eT& at_alt (const uword i) const; arma_warn_unused arma_inline eT& operator[] (const uword i); arma_warn_unused arma_inline const eT& operator[] (const uword i) const; arma_warn_unused arma_inline eT& at(const uword i); arma_warn_unused arma_inline const eT& at(const uword i) const; arma_warn_unused arma_inline eT& operator() (const uword i); arma_warn_unused arma_inline const eT& operator() (const uword i) const; #if defined(__cpp_multidimensional_subscript) arma_warn_unused arma_inline eT& operator[] (const uword in_row, const uword in_col, const uword in_slice); arma_warn_unused arma_inline const eT& operator[] (const uword in_row, const uword in_col, const uword in_slice) const; #endif arma_warn_unused arma_inline eT& at (const uword in_row, const uword in_col, const uword in_slice); arma_warn_unused arma_inline const eT& at (const uword in_row, const uword in_col, const uword in_slice) const; arma_warn_unused arma_inline eT& operator() (const uword in_row, const uword in_col, const uword in_slice); arma_warn_unused arma_inline const eT& operator() (const uword in_row, const uword in_col, const uword in_slice) const; arma_inline const Cube& operator++(); arma_inline void operator++(int); arma_inline const Cube& operator--(); arma_inline void operator--(int); arma_warn_unused arma_inline bool is_empty() const; arma_warn_unused inline bool internal_is_finite() const; arma_warn_unused inline bool internal_has_inf() const; arma_warn_unused inline bool internal_has_nan() const; arma_warn_unused inline bool internal_has_nonfinite() const; arma_warn_unused arma_inline bool in_range(const uword i) const; arma_warn_unused arma_inline bool in_range(const span& x) const; arma_warn_unused arma_inline bool in_range(const uword in_row, const uword in_col, const uword in_slice) const; arma_warn_unused inline bool in_range(const span& row_span, const span& col_span, const span& slice_span) const; arma_warn_unused inline bool in_range(const uword in_row, const uword in_col, const uword in_slice, const SizeCube& s) const; arma_warn_unused arma_inline eT* memptr(); arma_warn_unused arma_inline const eT* memptr() const; arma_warn_unused arma_inline eT* slice_memptr(const uword slice); arma_warn_unused arma_inline const eT* slice_memptr(const uword slice) const; arma_warn_unused arma_inline eT* slice_colptr(const uword in_slice, const uword in_col); arma_warn_unused arma_inline const eT* slice_colptr(const uword in_slice, const uword in_col) const; inline Cube& set_size(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& set_size(const SizeCube& s); inline Cube& reshape(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& reshape(const SizeCube& s); inline Cube& resize(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& resize(const SizeCube& s); template inline Cube& copy_size(const Cube& m); template inline Cube& for_each(functor F); template inline const Cube& for_each(functor F) const; template inline Cube& transform(functor F); template inline Cube& imbue(functor F); inline Cube& replace(const eT old_val, const eT new_val); inline Cube& clean(const pod_type threshold); inline Cube& clamp(const eT min_val, const eT max_val); inline Cube& fill(const eT val); inline Cube& zeros(); inline Cube& zeros(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& zeros(const SizeCube& s); inline Cube& ones(); inline Cube& ones(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& ones(const SizeCube& s); inline Cube& randu(); inline Cube& randu(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& randu(const SizeCube& s); inline Cube& randn(); inline Cube& randn(const uword new_n_rows, const uword new_n_cols, const uword new_n_slices); inline Cube& randn(const SizeCube& s); inline void reset(); inline void soft_reset(); template inline void set_real(const BaseCube& X); template inline void set_imag(const BaseCube& X); arma_warn_unused inline eT min() const; arma_warn_unused inline eT max() const; inline eT min(uword& index_of_min_val) const; inline eT max(uword& index_of_max_val) const; inline eT min(uword& row_of_min_val, uword& col_of_min_val, uword& slice_of_min_val) const; inline eT max(uword& row_of_max_val, uword& col_of_max_val, uword& slice_of_max_val) const; arma_cold inline bool save(const std::string name, const file_type type = arma_binary) const; arma_cold inline bool save(const hdf5_name& spec, const file_type type = hdf5_binary) const; arma_cold inline bool save( std::ostream& os, const file_type type = arma_binary) const; arma_cold inline bool load(const std::string name, const file_type type = auto_detect); arma_cold inline bool load(const hdf5_name& spec, const file_type type = hdf5_binary); arma_cold inline bool load( std::istream& is, const file_type type = auto_detect); arma_deprecated inline bool quiet_save(const std::string name, const file_type type = arma_binary) const; arma_deprecated inline bool quiet_save(const hdf5_name& spec, const file_type type = hdf5_binary) const; arma_deprecated inline bool quiet_save( std::ostream& os, const file_type type = arma_binary) const; arma_deprecated inline bool quiet_load(const std::string name, const file_type type = auto_detect); arma_deprecated inline bool quiet_load(const hdf5_name& spec, const file_type type = hdf5_binary); arma_deprecated inline bool quiet_load( std::istream& is, const file_type type = auto_detect); // iterators typedef eT* iterator; typedef const eT* const_iterator; typedef eT* slice_iterator; typedef const eT* const_slice_iterator; inline iterator begin(); inline const_iterator begin() const; inline const_iterator cbegin() const; inline iterator end(); inline const_iterator end() const; inline const_iterator cend() const; inline slice_iterator begin_slice(const uword slice_num); inline const_slice_iterator begin_slice(const uword slice_num) const; inline slice_iterator end_slice(const uword slice_num); inline const_slice_iterator end_slice(const uword slice_num) const; inline void clear(); inline bool empty() const; inline uword size() const; arma_warn_unused inline eT& front(); arma_warn_unused inline const eT& front() const; arma_warn_unused inline eT& back(); arma_warn_unused inline const eT& back() const; inline void swap(Cube& B); inline void steal_mem(Cube& X); //!< don't use this unless you're writing code internal to Armadillo inline void steal_mem(Cube& X, const bool is_move); //!< don't use this unless you're writing code internal to Armadillo template class fixed; protected: inline void init_cold(); inline void init_warm(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices); template inline void init(const BaseCube& A, const BaseCube& B); inline void delete_mat(); inline void create_mat(); inline Mat* create_mat_ptr(const uword in_slice) const; inline Mat* get_mat_ptr(const uword in_slice) const; friend class glue_join; friend class op_reshape; friend class op_resize; friend class subview_cube; public: #if defined(ARMA_EXTRA_CUBE_PROTO) #include ARMA_INCFILE_WRAP(ARMA_EXTRA_CUBE_PROTO) #endif }; template template class Cube::fixed : public Cube { private: static constexpr uword fixed_n_elem = fixed_n_rows * fixed_n_cols * fixed_n_slices; static constexpr uword fixed_n_elem_slice = fixed_n_rows * fixed_n_cols; static constexpr bool use_extra = (fixed_n_elem > Cube_prealloc::mem_n_elem); arma_aligned atomic_mat_ptr_type mat_ptrs_local_extra[ (fixed_n_slices > Cube_prealloc::mat_ptrs_size) ? fixed_n_slices : 1 ]; arma_align_mem eT mem_local_extra[ use_extra ? fixed_n_elem : 1 ]; arma_inline void mem_setup(); public: inline fixed(); inline fixed(const fixed& X); inline fixed(const fill::scalar_holder f); template inline fixed(const fill::fill_class& f); template inline fixed(const BaseCube& A); template inline fixed(const BaseCube& A, const BaseCube& B); using Cube::operator=; using Cube::operator(); inline Cube& operator=(const fixed& X); arma_warn_unused arma_inline eT& operator[] (const uword i); arma_warn_unused arma_inline const eT& operator[] (const uword i) const; arma_warn_unused arma_inline eT& at (const uword i); arma_warn_unused arma_inline const eT& at (const uword i) const; arma_warn_unused arma_inline eT& operator() (const uword i); arma_warn_unused arma_inline const eT& operator() (const uword i) const; #if defined(__cpp_multidimensional_subscript) arma_warn_unused arma_inline eT& operator[] (const uword in_row, const uword in_col, const uword in_slice); arma_warn_unused arma_inline const eT& operator[] (const uword in_row, const uword in_col, const uword in_slice) const; #endif arma_warn_unused arma_inline eT& at (const uword in_row, const uword in_col, const uword in_slice); arma_warn_unused arma_inline const eT& at (const uword in_row, const uword in_col, const uword in_slice) const; arma_warn_unused arma_inline eT& operator() (const uword in_row, const uword in_col, const uword in_slice); arma_warn_unused arma_inline const eT& operator() (const uword in_row, const uword in_col, const uword in_slice) const; }; class Cube_aux { public: template arma_inline static void prefix_pp(Cube& x); template arma_inline static void prefix_pp(Cube< std::complex >& x); template arma_inline static void postfix_pp(Cube& x); template arma_inline static void postfix_pp(Cube< std::complex >& x); template arma_inline static void prefix_mm(Cube& x); template arma_inline static void prefix_mm(Cube< std::complex >& x); template arma_inline static void postfix_mm(Cube& x); template arma_inline static void postfix_mm(Cube< std::complex >& x); template inline static void set_real(Cube& out, const BaseCube& X); template inline static void set_imag(Cube& out, const BaseCube& X); template inline static void set_real(Cube< std::complex >& out, const BaseCube< T,T1>& X); template inline static void set_imag(Cube< std::complex >& out, const BaseCube< T,T1>& X); }; //! @}