1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup Cube
20 //! @{
21 
22 
23 
24 struct Cube_prealloc
25   {
26   static constexpr uword mat_ptrs_size = 4;
27   static constexpr uword mem_n_elem    = 64;
28   };
29 
30 
31 
32 //! Dense cube class
33 
34 template<typename eT>
35 class Cube : public BaseCube< eT, Cube<eT> >
36   {
37   public:
38 
39   typedef eT                                elem_type; //!< the type of elements stored in the cube
40   typedef typename get_pod_type<eT>::result  pod_type; //!< if eT is std::complex<T>, pod_type is T; otherwise pod_type is eT
41 
42   const uword  n_rows;       //!< number of rows     in each slice (read-only)
43   const uword  n_cols;       //!< number of columns  in each slice (read-only)
44   const uword  n_elem_slice; //!< number of elements in each slice (read-only)
45   const uword  n_slices;     //!< number of slices   in the cube   (read-only)
46   const uword  n_elem;       //!< number of elements in the cube   (read-only)
47   const uword  n_alloc;      //!< number of allocated elements     (read-only); NOTE: n_alloc can be 0, even if n_elem > 0
48   const uword  mem_state;
49 
50   // mem_state = 0: normal cube which manages its own memory
51   // mem_state = 1: use auxiliary memory until a size change
52   // mem_state = 2: use auxiliary memory and don't allow the number of elements to be changed
53   // mem_state = 3: fixed size (eg. via template based size specification)
54 
55   arma_aligned const eT* const mem;  //!< pointer to the memory used for storing elements (memory is read-only)
56 
57 
58   protected:
59 
60   arma_aligned const Mat<eT>** const mat_ptrs;
61 
62   arma_align_mem Mat<eT>* mat_ptrs_local[ Cube_prealloc::mat_ptrs_size ];
63   arma_align_mem eT            mem_local[ Cube_prealloc::mem_n_elem    ];  // local storage, for small cubes
64 
65 
66   public:
67 
68   inline ~Cube();
69   inline  Cube();
70 
71   inline explicit Cube(const uword in_rows, const uword in_cols, const uword in_slices);
72   inline explicit Cube(const SizeCube& s);
73 
74   template<bool do_zeros> inline explicit Cube(const uword in_rows, const uword in_cols, const uword in_slices, const arma_initmode_indicator<do_zeros>&);
75   template<bool do_zeros> inline explicit Cube(const SizeCube& s,                                               const arma_initmode_indicator<do_zeros>&);
76 
77   template<typename fill_type> inline Cube(const uword in_rows, const uword in_cols, const uword in_slices, const fill::fill_class<fill_type>& f);
78   template<typename fill_type> inline Cube(const SizeCube& s,                                               const fill::fill_class<fill_type>& f);
79 
80   inline Cube(const uword in_rows, const uword in_cols, const uword in_slices, const fill::scalar_holder<eT> f);
81   inline Cube(const SizeCube& s,                                               const fill::scalar_holder<eT> f);
82 
83   inline            Cube(Cube&& m);
84   inline Cube& operator=(Cube&& m);
85 
86   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);
87   inline Cube(const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const uword aux_n_slices);
88 
89   inline Cube& operator= (const eT val);
90   inline Cube& operator+=(const eT val);
91   inline Cube& operator-=(const eT val);
92   inline Cube& operator*=(const eT val);
93   inline Cube& operator/=(const eT val);
94 
95   inline             Cube(const Cube& m);
96   inline Cube& operator= (const Cube& m);
97   inline Cube& operator+=(const Cube& m);
98   inline Cube& operator-=(const Cube& m);
99   inline Cube& operator%=(const Cube& m);
100   inline Cube& operator/=(const Cube& m);
101 
102   template<typename T1, typename T2>
103   inline explicit Cube(const BaseCube<pod_type,T1>& A, const BaseCube<pod_type,T2>& B);
104 
105   inline             Cube(const subview_cube<eT>& X);
106   inline Cube& operator= (const subview_cube<eT>& X);
107   inline Cube& operator+=(const subview_cube<eT>& X);
108   inline Cube& operator-=(const subview_cube<eT>& X);
109   inline Cube& operator%=(const subview_cube<eT>& X);
110   inline Cube& operator/=(const subview_cube<eT>& X);
111 
112   template<typename T1> inline             Cube(const subview_cube_slices<eT,T1>& X);
113   template<typename T1> inline Cube& operator= (const subview_cube_slices<eT,T1>& X);
114   template<typename T1> inline Cube& operator+=(const subview_cube_slices<eT,T1>& X);
115   template<typename T1> inline Cube& operator-=(const subview_cube_slices<eT,T1>& X);
116   template<typename T1> inline Cube& operator%=(const subview_cube_slices<eT,T1>& X);
117   template<typename T1> inline Cube& operator/=(const subview_cube_slices<eT,T1>& X);
118 
119   arma_inline       subview_cube<eT> row(const uword in_row);
120   arma_inline const subview_cube<eT> row(const uword in_row) const;
121 
122   arma_inline       subview_cube<eT> col(const uword in_col);
123   arma_inline const subview_cube<eT> col(const uword in_col) const;
124 
125   inline       Mat<eT>& slice(const uword in_slice);
126   inline const Mat<eT>& slice(const uword in_slice) const;
127 
128   arma_inline       subview_cube<eT> rows(const uword in_row1, const uword in_row2);
129   arma_inline const subview_cube<eT> rows(const uword in_row1, const uword in_row2) const;
130 
131   arma_inline       subview_cube<eT> cols(const uword in_col1, const uword in_col2);
132   arma_inline const subview_cube<eT> cols(const uword in_col1, const uword in_col2) const;
133 
134   arma_inline       subview_cube<eT> slices(const uword in_slice1, const uword in_slice2);
135   arma_inline const subview_cube<eT> slices(const uword in_slice1, const uword in_slice2) const;
136 
137   arma_inline       subview_cube<eT> 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);
138   arma_inline const subview_cube<eT> 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;
139 
140   inline            subview_cube<eT> subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s);
141   inline      const subview_cube<eT> subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const;
142 
143   inline            subview_cube<eT> subcube(const span& row_span, const span& col_span, const span& slice_span);
144   inline      const subview_cube<eT> subcube(const span& row_span, const span& col_span, const span& slice_span) const;
145 
146   inline            subview_cube<eT> operator()(const span& row_span, const span& col_span, const span& slice_span);
147   inline      const subview_cube<eT> operator()(const span& row_span, const span& col_span, const span& slice_span) const;
148 
149   inline            subview_cube<eT> operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s);
150   inline      const subview_cube<eT> operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const;
151 
152   arma_inline       subview_cube<eT> tube(const uword in_row1, const uword in_col1);
153   arma_inline const subview_cube<eT> tube(const uword in_row1, const uword in_col1) const;
154 
155   arma_inline       subview_cube<eT> tube(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2);
156   arma_inline const subview_cube<eT> tube(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const;
157 
158   arma_inline       subview_cube<eT> tube(const uword in_row1, const uword in_col1, const SizeMat& s);
159   arma_inline const subview_cube<eT> tube(const uword in_row1, const uword in_col1, const SizeMat& s) const;
160 
161   inline            subview_cube<eT> tube(const span& row_span, const span& col_span);
162   inline      const subview_cube<eT> tube(const span& row_span, const span& col_span) const;
163 
164   inline            subview_cube<eT> head_slices(const uword N);
165   inline      const subview_cube<eT> head_slices(const uword N) const;
166 
167   inline            subview_cube<eT> tail_slices(const uword N);
168   inline      const subview_cube<eT> tail_slices(const uword N) const;
169 
170   template<typename T1> arma_inline       subview_elem1<eT,T1> elem(const Base<uword,T1>& a);
171   template<typename T1> arma_inline const subview_elem1<eT,T1> elem(const Base<uword,T1>& a) const;
172 
173   template<typename T1> arma_inline       subview_elem1<eT,T1> operator()(const Base<uword,T1>& a);
174   template<typename T1> arma_inline const subview_elem1<eT,T1> operator()(const Base<uword,T1>& a) const;
175 
176 
177   arma_inline       subview_cube_each1<eT> each_slice();
178   arma_inline const subview_cube_each1<eT> each_slice() const;
179 
180   template<typename T1> inline       subview_cube_each2<eT, T1> each_slice(const Base<uword, T1>& indices);
181   template<typename T1> inline const subview_cube_each2<eT, T1> each_slice(const Base<uword, T1>& indices) const;
182 
183   inline const Cube& each_slice(const std::function< void(      Mat<eT>&) >& F);
184   inline const Cube& each_slice(const std::function< void(const Mat<eT>&) >& F) const;
185 
186   inline const Cube& each_slice(const std::function< void(      Mat<eT>&) >& F, const bool use_mp);
187   inline const Cube& each_slice(const std::function< void(const Mat<eT>&) >& F, const bool use_mp) const;
188 
189 
190   template<typename T1> arma_inline       subview_cube_slices<eT,T1> slices(const Base<uword,T1>& indices);
191   template<typename T1> arma_inline const subview_cube_slices<eT,T1> slices(const Base<uword,T1>& indices) const;
192 
193 
194   inline void shed_row(const uword row_num);
195   inline void shed_col(const uword col_num);
196   inline void shed_slice(const uword slice_num);
197 
198   inline void shed_rows(const uword in_row1, const uword in_row2);
199   inline void shed_cols(const uword in_col1, const uword in_col2);
200   inline void shed_slices(const uword in_slice1, const uword in_slice2);
201 
202   template<typename T1> inline void shed_slices(const Base<uword, T1>& indices);
203 
204   inline void insert_rows(const uword row_num, const uword N, const bool set_to_zero = true);
205   inline void insert_cols(const uword row_num, const uword N, const bool set_to_zero = true);
206   inline void insert_slices(const uword slice_num, const uword N, const bool set_to_zero = true);
207 
208   template<typename T1> inline void insert_rows(const uword row_num, const BaseCube<eT,T1>& X);
209   template<typename T1> inline void insert_cols(const uword col_num, const BaseCube<eT,T1>& X);
210   template<typename T1> inline void insert_slices(const uword slice_num, const BaseCube<eT,T1>& X);
211 
212 
213   template<typename gen_type> inline             Cube(const GenCube<eT, gen_type>& X);
214   template<typename gen_type> inline Cube& operator= (const GenCube<eT, gen_type>& X);
215   template<typename gen_type> inline Cube& operator+=(const GenCube<eT, gen_type>& X);
216   template<typename gen_type> inline Cube& operator-=(const GenCube<eT, gen_type>& X);
217   template<typename gen_type> inline Cube& operator%=(const GenCube<eT, gen_type>& X);
218   template<typename gen_type> inline Cube& operator/=(const GenCube<eT, gen_type>& X);
219 
220   template<typename T1, typename op_type> inline             Cube(const OpCube<T1, op_type>& X);
221   template<typename T1, typename op_type> inline Cube& operator= (const OpCube<T1, op_type>& X);
222   template<typename T1, typename op_type> inline Cube& operator+=(const OpCube<T1, op_type>& X);
223   template<typename T1, typename op_type> inline Cube& operator-=(const OpCube<T1, op_type>& X);
224   template<typename T1, typename op_type> inline Cube& operator%=(const OpCube<T1, op_type>& X);
225   template<typename T1, typename op_type> inline Cube& operator/=(const OpCube<T1, op_type>& X);
226 
227   template<typename T1, typename eop_type> inline             Cube(const eOpCube<T1, eop_type>& X);
228   template<typename T1, typename eop_type> inline Cube& operator= (const eOpCube<T1, eop_type>& X);
229   template<typename T1, typename eop_type> inline Cube& operator+=(const eOpCube<T1, eop_type>& X);
230   template<typename T1, typename eop_type> inline Cube& operator-=(const eOpCube<T1, eop_type>& X);
231   template<typename T1, typename eop_type> inline Cube& operator%=(const eOpCube<T1, eop_type>& X);
232   template<typename T1, typename eop_type> inline Cube& operator/=(const eOpCube<T1, eop_type>& X);
233 
234   template<typename T1, typename op_type> inline             Cube(const mtOpCube<eT, T1, op_type>& X);
235   template<typename T1, typename op_type> inline Cube& operator= (const mtOpCube<eT, T1, op_type>& X);
236   template<typename T1, typename op_type> inline Cube& operator+=(const mtOpCube<eT, T1, op_type>& X);
237   template<typename T1, typename op_type> inline Cube& operator-=(const mtOpCube<eT, T1, op_type>& X);
238   template<typename T1, typename op_type> inline Cube& operator%=(const mtOpCube<eT, T1, op_type>& X);
239   template<typename T1, typename op_type> inline Cube& operator/=(const mtOpCube<eT, T1, op_type>& X);
240 
241   template<typename T1, typename T2, typename glue_type> inline             Cube(const GlueCube<T1, T2, glue_type>& X);
242   template<typename T1, typename T2, typename glue_type> inline Cube& operator= (const GlueCube<T1, T2, glue_type>& X);
243   template<typename T1, typename T2, typename glue_type> inline Cube& operator+=(const GlueCube<T1, T2, glue_type>& X);
244   template<typename T1, typename T2, typename glue_type> inline Cube& operator-=(const GlueCube<T1, T2, glue_type>& X);
245   template<typename T1, typename T2, typename glue_type> inline Cube& operator%=(const GlueCube<T1, T2, glue_type>& X);
246   template<typename T1, typename T2, typename glue_type> inline Cube& operator/=(const GlueCube<T1, T2, glue_type>& X);
247 
248   template<typename T1, typename T2, typename eglue_type> inline             Cube(const eGlueCube<T1, T2, eglue_type>& X);
249   template<typename T1, typename T2, typename eglue_type> inline Cube& operator= (const eGlueCube<T1, T2, eglue_type>& X);
250   template<typename T1, typename T2, typename eglue_type> inline Cube& operator+=(const eGlueCube<T1, T2, eglue_type>& X);
251   template<typename T1, typename T2, typename eglue_type> inline Cube& operator-=(const eGlueCube<T1, T2, eglue_type>& X);
252   template<typename T1, typename T2, typename eglue_type> inline Cube& operator%=(const eGlueCube<T1, T2, eglue_type>& X);
253   template<typename T1, typename T2, typename eglue_type> inline Cube& operator/=(const eGlueCube<T1, T2, eglue_type>& X);
254 
255   template<typename T1, typename T2, typename glue_type> inline             Cube(const mtGlueCube<eT, T1, T2, glue_type>& X);
256   template<typename T1, typename T2, typename glue_type> inline Cube& operator= (const mtGlueCube<eT, T1, T2, glue_type>& X);
257   template<typename T1, typename T2, typename glue_type> inline Cube& operator+=(const mtGlueCube<eT, T1, T2, glue_type>& X);
258   template<typename T1, typename T2, typename glue_type> inline Cube& operator-=(const mtGlueCube<eT, T1, T2, glue_type>& X);
259   template<typename T1, typename T2, typename glue_type> inline Cube& operator%=(const mtGlueCube<eT, T1, T2, glue_type>& X);
260   template<typename T1, typename T2, typename glue_type> inline Cube& operator/=(const mtGlueCube<eT, T1, T2, glue_type>& X);
261 
262 
263   arma_inline arma_warn_unused const eT& at_alt     (const uword i) const;
264 
265   arma_inline arma_warn_unused       eT& operator[] (const uword i);
266   arma_inline arma_warn_unused const eT& operator[] (const uword i) const;
267 
268   arma_inline arma_warn_unused       eT& at(const uword i);
269   arma_inline arma_warn_unused const eT& at(const uword i) const;
270 
271   arma_inline arma_warn_unused       eT& operator() (const uword i);
272   arma_inline arma_warn_unused const eT& operator() (const uword i) const;
273 
274   arma_inline arma_warn_unused       eT& at         (const uword in_row, const uword in_col, const uword in_slice);
275   arma_inline arma_warn_unused const eT& at         (const uword in_row, const uword in_col, const uword in_slice) const;
276 
277   arma_inline arma_warn_unused       eT& operator() (const uword in_row, const uword in_col, const uword in_slice);
278   arma_inline arma_warn_unused const eT& operator() (const uword in_row, const uword in_col, const uword in_slice) const;
279 
280   arma_inline const Cube& operator++();
281   arma_inline void        operator++(int);
282 
283   arma_inline const Cube& operator--();
284   arma_inline void        operator--(int);
285 
286        inline arma_warn_unused bool is_finite() const;
287   arma_inline arma_warn_unused bool is_empty()  const;
288 
289   inline arma_warn_unused bool has_inf() const;
290   inline arma_warn_unused bool has_nan() const;
291 
292   arma_inline arma_warn_unused bool in_range(const uword i) const;
293   arma_inline arma_warn_unused bool in_range(const span& x) const;
294 
295   arma_inline arma_warn_unused bool in_range(const uword   in_row, const uword   in_col, const uword   in_slice) const;
296        inline arma_warn_unused bool in_range(const span& row_span, const span& col_span, const span& slice_span) const;
297 
298        inline arma_warn_unused bool in_range(const uword   in_row, const uword   in_col, const uword   in_slice, const SizeCube& s) const;
299 
300   arma_inline arma_warn_unused       eT* memptr();
301   arma_inline arma_warn_unused const eT* memptr() const;
302 
303   arma_inline arma_warn_unused       eT* slice_memptr(const uword slice);
304   arma_inline arma_warn_unused const eT* slice_memptr(const uword slice) const;
305 
306   arma_inline arma_warn_unused       eT* slice_colptr(const uword in_slice, const uword in_col);
307   arma_inline arma_warn_unused const eT* slice_colptr(const uword in_slice, const uword in_col) const;
308 
309   inline void set_size(const uword in_rows, const uword in_cols, const uword in_slices);
310   inline void set_size(const SizeCube& s);
311 
312   inline void reshape(const uword in_rows, const uword in_cols, const uword in_slices);
313   inline void reshape(const SizeCube& s);
314 
315   inline void resize(const uword in_rows, const uword in_cols, const uword in_slices);
316   inline void resize(const SizeCube& s);
317 
318 
319   template<typename eT2> inline void copy_size(const Cube<eT2>& m);
320 
321   template<typename functor> inline const Cube&  for_each(functor F);
322   template<typename functor> inline const Cube&  for_each(functor F) const;
323 
324   template<typename functor> inline const Cube& transform(functor F);
325   template<typename functor> inline const Cube&     imbue(functor F);
326 
327   inline const Cube& replace(const eT old_val, const eT new_val);
328 
329   inline const Cube& clean(const pod_type threshold);
330 
331   inline const Cube& clamp(const eT min_val, const eT max_val);
332 
333   inline const Cube& fill(const eT val);
334 
335   inline const Cube& zeros();
336   inline const Cube& zeros(const uword in_rows, const uword in_cols, const uword in_slices);
337   inline const Cube& zeros(const SizeCube& s);
338 
339   inline const Cube& ones();
340   inline const Cube& ones(const uword in_rows, const uword in_cols, const uword in_slices);
341   inline const Cube& ones(const SizeCube& s);
342 
343   inline const Cube& randu();
344   inline const Cube& randu(const uword in_rows, const uword in_cols, const uword in_slices);
345   inline const Cube& randu(const SizeCube& s);
346 
347   inline const Cube& randn();
348   inline const Cube& randn(const uword in_rows, const uword in_cols, const uword in_slices);
349   inline const Cube& randn(const SizeCube& s);
350 
351   inline void      reset();
352   inline void soft_reset();
353 
354 
355   template<typename T1> inline void set_real(const BaseCube<pod_type,T1>& X);
356   template<typename T1> inline void set_imag(const BaseCube<pod_type,T1>& X);
357 
358 
359   inline arma_warn_unused eT min() const;
360   inline arma_warn_unused eT max() const;
361 
362   inline eT min(uword& index_of_min_val) const;
363   inline eT max(uword& index_of_max_val) const;
364 
365   inline eT min(uword& row_of_min_val, uword& col_of_min_val, uword& slice_of_min_val) const;
366   inline eT max(uword& row_of_max_val, uword& col_of_max_val, uword& slice_of_max_val) const;
367 
368 
369   inline arma_cold bool save(const std::string   name, const file_type type = arma_binary) const;
370   inline arma_cold bool save(const hdf5_name&    spec, const file_type type = hdf5_binary) const;
371   inline arma_cold bool save(      std::ostream& os,   const file_type type = arma_binary) const;
372 
373   inline arma_cold bool load(const std::string   name, const file_type type = auto_detect);
374   inline arma_cold bool load(const hdf5_name&    spec, const file_type type = hdf5_binary);
375   inline arma_cold bool load(      std::istream& is,   const file_type type = auto_detect);
376 
377   inline arma_cold bool quiet_save(const std::string   name, const file_type type = arma_binary) const;
378   inline arma_cold bool quiet_save(const hdf5_name&    spec, const file_type type = hdf5_binary) const;
379   inline arma_cold bool quiet_save(      std::ostream& os,   const file_type type = arma_binary) const;
380 
381   inline arma_cold bool quiet_load(const std::string   name, const file_type type = auto_detect);
382   inline arma_cold bool quiet_load(const hdf5_name&    spec, const file_type type = hdf5_binary);
383   inline arma_cold bool quiet_load(      std::istream& is,   const file_type type = auto_detect);
384 
385 
386   // iterators
387 
388   typedef       eT*       iterator;
389   typedef const eT* const_iterator;
390 
391   typedef       eT*       slice_iterator;
392   typedef const eT* const_slice_iterator;
393 
394   inline       iterator  begin();
395   inline const_iterator  begin() const;
396   inline const_iterator cbegin() const;
397 
398   inline       iterator  end();
399   inline const_iterator  end() const;
400   inline const_iterator cend() const;
401 
402   inline       slice_iterator begin_slice(const uword slice_num);
403   inline const_slice_iterator begin_slice(const uword slice_num) const;
404 
405   inline       slice_iterator end_slice(const uword slice_num);
406   inline const_slice_iterator end_slice(const uword slice_num)   const;
407 
408   inline void  clear();
409   inline bool  empty() const;
410   inline uword size()  const;
411 
412   inline arma_warn_unused       eT& front();
413   inline arma_warn_unused const eT& front() const;
414 
415   inline arma_warn_unused       eT& back();
416   inline arma_warn_unused const eT& back() const;
417 
418   inline void swap(Cube& B);
419 
420   inline void steal_mem(Cube& X);  //!< don't use this unless you're writing code internal to Armadillo
421 
422   template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices> class fixed;
423 
424 
425   protected:
426 
427   inline void init_cold();
428   inline void init_warm(const uword in_rows, const uword in_cols, const uword in_slices);
429 
430   template<typename T1, typename T2>
431   inline void init(const BaseCube<pod_type,T1>& A, const BaseCube<pod_type,T2>& B);
432 
433   inline void delete_mat();
434   inline void create_mat();
435 
436   friend class glue_join;
437   friend class op_reshape;
438   friend class op_resize;
439   friend class subview_cube<eT>;
440 
441 
442   public:
443 
444   #ifdef ARMA_EXTRA_CUBE_PROTO
445     #include ARMA_INCFILE_WRAP(ARMA_EXTRA_CUBE_PROTO)
446   #endif
447   };
448 
449 
450 
451 template<typename eT>
452 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
453 class Cube<eT>::fixed : public Cube<eT>
454   {
455   private:
456 
457   static constexpr uword fixed_n_elem       = fixed_n_rows * fixed_n_cols * fixed_n_slices;
458   static constexpr uword fixed_n_elem_slice = fixed_n_rows * fixed_n_cols;
459 
460   static constexpr bool use_extra = (fixed_n_elem > Cube_prealloc::mem_n_elem);
461 
462   arma_aligned   Mat<eT>* mat_ptrs_local_extra[ (fixed_n_slices > Cube_prealloc::mat_ptrs_size) ? fixed_n_slices : 1 ];
463   arma_align_mem eT       mem_local_extra     [ use_extra                                       ? fixed_n_elem   : 1 ];
464 
465   arma_inline void mem_setup();
466 
467 
468   public:
469 
470   inline fixed();
471   inline fixed(const fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>& X);
472 
473                                      inline fixed(const fill::scalar_holder<eT> f);
474   template<typename fill_type>       inline fixed(const fill::fill_class<fill_type>& f);
475   template<typename T1>              inline fixed(const BaseCube<eT,T1>& A);
476   template<typename T1, typename T2> inline fixed(const BaseCube<pod_type,T1>& A, const BaseCube<pod_type,T2>& B);
477 
478   using Cube<eT>::operator=;
479   using Cube<eT>::operator();
480 
481   inline Cube& operator=(const fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>& X);
482 
483 
484   arma_inline arma_warn_unused       eT& operator[] (const uword i);
485   arma_inline arma_warn_unused const eT& operator[] (const uword i) const;
486 
487   arma_inline arma_warn_unused       eT& at         (const uword i);
488   arma_inline arma_warn_unused const eT& at         (const uword i) const;
489 
490   arma_inline arma_warn_unused       eT& operator() (const uword i);
491   arma_inline arma_warn_unused const eT& operator() (const uword i) const;
492 
493   arma_inline arma_warn_unused       eT& at         (const uword in_row, const uword in_col, const uword in_slice);
494   arma_inline arma_warn_unused const eT& at         (const uword in_row, const uword in_col, const uword in_slice) const;
495 
496   arma_inline arma_warn_unused       eT& operator() (const uword in_row, const uword in_col, const uword in_slice);
497   arma_inline arma_warn_unused const eT& operator() (const uword in_row, const uword in_col, const uword in_slice) const;
498   };
499 
500 
501 
502 class Cube_aux
503   {
504   public:
505 
506   template<typename eT> arma_inline static void prefix_pp(Cube<eT>& x);
507   template<typename T>  arma_inline static void prefix_pp(Cube< std::complex<T> >& x);
508 
509   template<typename eT> arma_inline static void postfix_pp(Cube<eT>& x);
510   template<typename T>  arma_inline static void postfix_pp(Cube< std::complex<T> >& x);
511 
512   template<typename eT> arma_inline static void prefix_mm(Cube<eT>& x);
513   template<typename T>  arma_inline static void prefix_mm(Cube< std::complex<T> >& x);
514 
515   template<typename eT> arma_inline static void postfix_mm(Cube<eT>& x);
516   template<typename T>  arma_inline static void postfix_mm(Cube< std::complex<T> >& x);
517 
518   template<typename eT, typename T1> inline static void set_real(Cube<eT>&                out, const BaseCube<eT,T1>& X);
519   template<typename eT, typename T1> inline static void set_imag(Cube<eT>&                out, const BaseCube<eT,T1>& X);
520 
521   template<typename T,  typename T1> inline static void set_real(Cube< std::complex<T> >& out, const BaseCube< T,T1>& X);
522   template<typename T,  typename T1> inline static void set_imag(Cube< std::complex<T> >& out, const BaseCube< T,T1>& X);
523   };
524 
525 
526 
527 //! @}
528