summaryrefslogtreecommitdiffstats
path: root/src/armadillo/include/armadillo_bits/Cube_bones.hpp
blob: 5cf364aafc0fcfe6f37b02a887d84a53e448ad5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
// 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<typename eT>
class Cube : public BaseCube< eT, Cube<eT> >
  {
  public:
  
  typedef eT                                elem_type; //!< the type of elements stored in the cube
  typedef typename get_pod_type<eT>::result  pod_type; //!< if eT is std::complex<T>, 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<eT>;
  
  #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<mat_type*>;
  #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<bool do_zeros> inline explicit Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const arma_initmode_indicator<do_zeros>&);
  template<bool do_zeros> inline explicit Cube(const SizeCube& s,                                                     const arma_initmode_indicator<do_zeros>&);
  
  template<typename fill_type> inline Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices, const fill::fill_class<fill_type>& f);
  template<typename fill_type> inline Cube(const SizeCube& s,                                                     const fill::fill_class<fill_type>& f);
  
  inline Cube(const uword in_rows, const uword in_cols, const uword in_slices, const fill::scalar_holder<eT> f);
  inline Cube(const SizeCube& s,                                               const fill::scalar_holder<eT> 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<typename T1, typename T2>
  inline explicit Cube(const BaseCube<pod_type,T1>& A, const BaseCube<pod_type,T2>& B);
  
  inline             Cube(const subview_cube<eT>& X);
  inline Cube& operator= (const subview_cube<eT>& X);
  inline Cube& operator+=(const subview_cube<eT>& X);
  inline Cube& operator-=(const subview_cube<eT>& X);
  inline Cube& operator%=(const subview_cube<eT>& X);
  inline Cube& operator/=(const subview_cube<eT>& X);

  template<typename T1> inline             Cube(const subview_cube_slices<eT,T1>& X);
  template<typename T1> inline Cube& operator= (const subview_cube_slices<eT,T1>& X);
  template<typename T1> inline Cube& operator+=(const subview_cube_slices<eT,T1>& X);
  template<typename T1> inline Cube& operator-=(const subview_cube_slices<eT,T1>& X);
  template<typename T1> inline Cube& operator%=(const subview_cube_slices<eT,T1>& X);
  template<typename T1> inline Cube& operator/=(const subview_cube_slices<eT,T1>& X);

  arma_inline       subview_cube<eT> row(const uword in_row);
  arma_inline const subview_cube<eT> row(const uword in_row) const;
  
  arma_inline       subview_cube<eT> col(const uword in_col);
  arma_inline const subview_cube<eT> col(const uword in_col) const;
  
  inline       Mat<eT>& slice(const uword in_slice);
  inline const Mat<eT>& slice(const uword in_slice) const;
  
  arma_inline       subview_cube<eT> rows(const uword in_row1, const uword in_row2);
  arma_inline const subview_cube<eT> rows(const uword in_row1, const uword in_row2) const;
  
  arma_inline       subview_cube<eT> cols(const uword in_col1, const uword in_col2);
  arma_inline const subview_cube<eT> cols(const uword in_col1, const uword in_col2) const;

  arma_inline       subview_cube<eT> slices(const uword in_slice1, const uword in_slice2);
  arma_inline const subview_cube<eT> slices(const uword in_slice1, const uword in_slice2) const;
  
  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);
  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;
  
  inline            subview_cube<eT> subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s);
  inline      const subview_cube<eT> subcube(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const;
  
  inline            subview_cube<eT> subcube(const span& row_span, const span& col_span, const span& slice_span);
  inline      const subview_cube<eT> subcube(const span& row_span, const span& col_span, const span& slice_span) const;
  
  inline            subview_cube<eT> operator()(const span& row_span, const span& col_span, const span& slice_span);
  inline      const subview_cube<eT> operator()(const span& row_span, const span& col_span, const span& slice_span) const;
  
  inline            subview_cube<eT> operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s);
  inline      const subview_cube<eT> operator()(const uword in_row1, const uword in_col1, const uword in_slice1, const SizeCube& s) const;
  
  arma_inline       subview_cube<eT> tube(const uword in_row1, const uword in_col1);
  arma_inline const subview_cube<eT> tube(const uword in_row1, const uword in_col1) const;
  
  arma_inline       subview_cube<eT> tube(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2);
  arma_inline const subview_cube<eT> tube(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const;
  
  arma_inline       subview_cube<eT> tube(const uword in_row1, const uword in_col1, const SizeMat& s);
  arma_inline const subview_cube<eT> tube(const uword in_row1, const uword in_col1, const SizeMat& s) const;
  
  inline            subview_cube<eT> tube(const span& row_span, const span& col_span);
  inline      const subview_cube<eT> tube(const span& row_span, const span& col_span) const;
  
  inline            subview_cube<eT> head_slices(const uword N);
  inline      const subview_cube<eT> head_slices(const uword N) const;
  
  inline            subview_cube<eT> tail_slices(const uword N);
  inline      const subview_cube<eT> tail_slices(const uword N) const;
  
  template<typename T1> arma_inline       subview_elem1<eT,T1> elem(const Base<uword,T1>& a);
  template<typename T1> arma_inline const subview_elem1<eT,T1> elem(const Base<uword,T1>& a) const;
  
  template<typename T1> arma_inline       subview_elem1<eT,T1> operator()(const Base<uword,T1>& a);
  template<typename T1> arma_inline const subview_elem1<eT,T1> operator()(const Base<uword,T1>& a) const;
  
  
  arma_inline       subview_cube_each1<eT> each_slice();
  arma_inline const subview_cube_each1<eT> each_slice() const;
  
  template<typename T1> inline       subview_cube_each2<eT, T1> each_slice(const Base<uword, T1>& indices);
  template<typename T1> inline const subview_cube_each2<eT, T1> each_slice(const Base<uword, T1>& indices) const;
  
  inline       Cube& each_slice(const std::function< void(      Mat<eT>&) >& F);
  inline const Cube& each_slice(const std::function< void(const Mat<eT>&) >& F) const;
  
  inline       Cube& each_slice(const std::function< void(      Mat<eT>&) >& F, const bool use_mp);
  inline const Cube& each_slice(const std::function< void(const Mat<eT>&) >& F, const bool use_mp) const;
  
  
  template<typename T1> arma_inline       subview_cube_slices<eT,T1> slices(const Base<uword,T1>& indices);
  template<typename T1> arma_inline const subview_cube_slices<eT,T1> slices(const Base<uword,T1>& 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<typename T1> inline void shed_slices(const Base<uword, T1>& 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<typename T1> inline void insert_rows(const uword row_num, const BaseCube<eT,T1>& X);
  template<typename T1> inline void insert_cols(const uword col_num, const BaseCube<eT,T1>& X);
  template<typename T1> inline void insert_slices(const uword slice_num, const BaseCube<eT,T1>& X);
  template<typename T1> inline void insert_slices(const uword slice_num, const     Base<eT,T1>& X);
  
  
  template<typename gen_type> inline             Cube(const GenCube<eT, gen_type>& X);
  template<typename gen_type> inline Cube& operator= (const GenCube<eT, gen_type>& X);
  template<typename gen_type> inline Cube& operator+=(const GenCube<eT, gen_type>& X);
  template<typename gen_type> inline Cube& operator-=(const GenCube<eT, gen_type>& X);
  template<typename gen_type> inline Cube& operator%=(const GenCube<eT, gen_type>& X);
  template<typename gen_type> inline Cube& operator/=(const GenCube<eT, gen_type>& X);
  
  template<typename T1, typename op_type> inline             Cube(const OpCube<T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator= (const OpCube<T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator+=(const OpCube<T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator-=(const OpCube<T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator%=(const OpCube<T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator/=(const OpCube<T1, op_type>& X);
  
  template<typename T1, typename eop_type> inline             Cube(const eOpCube<T1, eop_type>& X);
  template<typename T1, typename eop_type> inline Cube& operator= (const eOpCube<T1, eop_type>& X);
  template<typename T1, typename eop_type> inline Cube& operator+=(const eOpCube<T1, eop_type>& X);
  template<typename T1, typename eop_type> inline Cube& operator-=(const eOpCube<T1, eop_type>& X);
  template<typename T1, typename eop_type> inline Cube& operator%=(const eOpCube<T1, eop_type>& X);
  template<typename T1, typename eop_type> inline Cube& operator/=(const eOpCube<T1, eop_type>& X);
  
  template<typename T1, typename op_type> inline             Cube(const mtOpCube<eT, T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator= (const mtOpCube<eT, T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator+=(const mtOpCube<eT, T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator-=(const mtOpCube<eT, T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator%=(const mtOpCube<eT, T1, op_type>& X);
  template<typename T1, typename op_type> inline Cube& operator/=(const mtOpCube<eT, T1, op_type>& X);
  
  template<typename T1, typename T2, typename glue_type> inline             Cube(const GlueCube<T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator= (const GlueCube<T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator+=(const GlueCube<T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator-=(const GlueCube<T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator%=(const GlueCube<T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator/=(const GlueCube<T1, T2, glue_type>& X);
  
  template<typename T1, typename T2, typename eglue_type> inline             Cube(const eGlueCube<T1, T2, eglue_type>& X);
  template<typename T1, typename T2, typename eglue_type> inline Cube& operator= (const eGlueCube<T1, T2, eglue_type>& X);
  template<typename T1, typename T2, typename eglue_type> inline Cube& operator+=(const eGlueCube<T1, T2, eglue_type>& X);
  template<typename T1, typename T2, typename eglue_type> inline Cube& operator-=(const eGlueCube<T1, T2, eglue_type>& X);
  template<typename T1, typename T2, typename eglue_type> inline Cube& operator%=(const eGlueCube<T1, T2, eglue_type>& X);
  template<typename T1, typename T2, typename eglue_type> inline Cube& operator/=(const eGlueCube<T1, T2, eglue_type>& X);
  
  template<typename T1, typename T2, typename glue_type> inline             Cube(const mtGlueCube<eT, T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator= (const mtGlueCube<eT, T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator+=(const mtGlueCube<eT, T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator-=(const mtGlueCube<eT, T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator%=(const mtGlueCube<eT, T1, T2, glue_type>& X);
  template<typename T1, typename T2, typename glue_type> inline Cube& operator/=(const mtGlueCube<eT, T1, T2, glue_type>& 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<typename eT2> inline Cube& copy_size(const Cube<eT2>& m);
  
  template<typename functor> inline       Cube&  for_each(functor F);
  template<typename functor> inline const Cube&  for_each(functor F) const;
  
  template<typename functor> inline       Cube& transform(functor F);
  template<typename functor> 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<typename T1> inline void set_real(const BaseCube<pod_type,T1>& X);
  template<typename T1> inline void set_imag(const BaseCube<pod_type,T1>& 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<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices> 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<typename T1, typename T2>
  inline void init(const BaseCube<pod_type,T1>& A, const BaseCube<pod_type,T2>& B);
  
  inline void delete_mat();
  inline void create_mat();
  
  inline Mat<eT>* create_mat_ptr(const uword in_slice) const;
  inline Mat<eT>*    get_mat_ptr(const uword in_slice) const;
  
  friend class glue_join;
  friend class op_reshape;
  friend class op_resize;
  friend class subview_cube<eT>;
  
  
  public:
  
  #if defined(ARMA_EXTRA_CUBE_PROTO)
    #include ARMA_INCFILE_WRAP(ARMA_EXTRA_CUBE_PROTO)
  #endif
  };



template<typename eT>
template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
class Cube<eT>::fixed : public Cube<eT>
  {
  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<fixed_n_rows, fixed_n_cols, fixed_n_slices>& X);
  
                                     inline fixed(const fill::scalar_holder<eT> f);
  template<typename fill_type>       inline fixed(const fill::fill_class<fill_type>& f);
  template<typename T1>              inline fixed(const BaseCube<eT,T1>& A);
  template<typename T1, typename T2> inline fixed(const BaseCube<pod_type,T1>& A, const BaseCube<pod_type,T2>& B);
  
  using Cube<eT>::operator=;
  using Cube<eT>::operator();
  
  inline Cube& operator=(const fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>& 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<typename eT> arma_inline static void prefix_pp(Cube<eT>& x);
  template<typename T>  arma_inline static void prefix_pp(Cube< std::complex<T> >& x);
  
  template<typename eT> arma_inline static void postfix_pp(Cube<eT>& x);
  template<typename T>  arma_inline static void postfix_pp(Cube< std::complex<T> >& x);
  
  template<typename eT> arma_inline static void prefix_mm(Cube<eT>& x);
  template<typename T>  arma_inline static void prefix_mm(Cube< std::complex<T> >& x);
  
  template<typename eT> arma_inline static void postfix_mm(Cube<eT>& x);
  template<typename T>  arma_inline static void postfix_mm(Cube< std::complex<T> >& x);
  
  template<typename eT, typename T1> inline static void set_real(Cube<eT>&                out, const BaseCube<eT,T1>& X);
  template<typename eT, typename T1> inline static void set_imag(Cube<eT>&                out, const BaseCube<eT,T1>& X);
  
  template<typename T,  typename T1> inline static void set_real(Cube< std::complex<T> >& out, const BaseCube< T,T1>& X);
  template<typename T,  typename T1> inline static void set_imag(Cube< std::complex<T> >& out, const BaseCube< T,T1>& X);
  };



//! @}