comparison armadillo-3.900.4/include/armadillo_bits/Cube_meat.hpp @ 49:1ec0e2823891

Switch to using subrepo copies of qm-dsp, nnls-chroma, vamp-plugin-sdk; update Armadillo version; assume build without external BLAS/LAPACK
author Chris Cannam
date Thu, 13 Jun 2013 10:25:24 +0100
parents
children
comparison
equal deleted inserted replaced
48:69251e11a913 49:1ec0e2823891
1 // Copyright (C) 2008-2013 NICTA (www.nicta.com.au)
2 // Copyright (C) 2008-2013 Conrad Sanderson
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8
9 //! \addtogroup Cube
10 //! @{
11
12
13 template<typename eT>
14 inline
15 Cube<eT>::~Cube()
16 {
17 arma_extra_debug_sigprint_this(this);
18
19 delete_mat();
20
21 if(mem_state == 0)
22 {
23 if(n_elem > Cube_prealloc::mem_n_elem)
24 {
25 memory::release( access::rw(mem) );
26 }
27 }
28
29 if(arma_config::debug == true)
30 {
31 // try to expose buggy user code that accesses deleted objects
32 access::rw(mat_ptrs) = 0;
33 access::rw(mem) = 0;
34 }
35
36 arma_type_check(( is_supported_elem_type<eT>::value == false ));
37 }
38
39
40
41 template<typename eT>
42 inline
43 Cube<eT>::Cube()
44 : n_rows(0)
45 , n_cols(0)
46 , n_elem_slice(0)
47 , n_slices(0)
48 , n_elem(0)
49 , mem_state(0)
50 , mat_ptrs()
51 , mem()
52 {
53 arma_extra_debug_sigprint_this(this);
54 }
55
56
57
58 //! construct the cube to have user specified dimensions
59 template<typename eT>
60 inline
61 Cube<eT>::Cube(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices)
62 : n_rows(in_n_rows)
63 , n_cols(in_n_cols)
64 , n_elem_slice(in_n_rows*in_n_cols)
65 , n_slices(in_n_slices)
66 , n_elem(in_n_rows*in_n_cols*in_n_slices)
67 , mem_state(0)
68 , mat_ptrs()
69 , mem()
70 {
71 arma_extra_debug_sigprint_this(this);
72
73 init_cold();
74 }
75
76
77
78 template<typename eT>
79 inline
80 void
81 Cube<eT>::init_cold()
82 {
83 arma_extra_debug_sigprint( arma_boost::format("n_rows = %d, n_cols = %d, n_slices = %d") % n_rows % n_cols % n_slices );
84
85 arma_debug_check
86 (
87 (
88 ( (n_rows > 0x0FFF) || (n_cols > 0x0FFF) || (n_slices > 0xFF) )
89 ? ( (float(n_rows) * float(n_cols) * float(n_slices)) > float(ARMA_MAX_UWORD) )
90 : false
91 ),
92 "Cube::init(): requested size is too large"
93 );
94
95 if(n_elem <= Cube_prealloc::mem_n_elem)
96 {
97 access::rw(mem) = mem_local;
98 }
99 else
100 {
101 arma_extra_debug_print("Cube::init(): allocating memory");
102
103 access::rw(mem) = memory::acquire<eT>(n_elem);
104
105 arma_check_bad_alloc( (mem == 0), "Cube::init(): out of memory" );
106 }
107
108
109 if(n_elem == 0)
110 {
111 access::rw(n_rows) = 0;
112 access::rw(n_cols) = 0;
113 access::rw(n_elem_slice) = 0;
114 access::rw(n_slices) = 0;
115 }
116 else
117 {
118 create_mat();
119 }
120 }
121
122
123
124 //! internal cube construction; if the requested size is small enough, memory from the stack is used.
125 //! otherwise memory is allocated via 'new'
126 template<typename eT>
127 inline
128 void
129 Cube<eT>::init_warm(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices)
130 {
131 arma_extra_debug_sigprint( arma_boost::format("in_n_rows = %d, in_n_cols = %d, in_n_slices = %d") % in_n_rows % in_n_cols % in_n_slices );
132
133 if( (n_rows == in_n_rows) && (n_cols == in_n_cols) && (n_slices == in_n_slices) )
134 {
135 return;
136 }
137
138 const uword t_mem_state = mem_state;
139
140 bool err_state = false;
141 char* err_msg = 0;
142
143 arma_debug_set_error
144 (
145 err_state,
146 err_msg,
147 (t_mem_state == 3),
148 "Cube::init(): size is fixed and hence cannot be changed"
149 );
150
151 arma_debug_set_error
152 (
153 err_state,
154 err_msg,
155 (
156 ( (in_n_rows > 0x0FFF) || (in_n_cols > 0x0FFF) || (in_n_slices > 0xFF) )
157 ? ( (float(in_n_rows) * float(in_n_cols) * float(in_n_slices)) > float(ARMA_MAX_UWORD) )
158 : false
159 ),
160 "Cube::init(): requested size is too large"
161 );
162
163 arma_debug_check(err_state, err_msg);
164
165 const uword old_n_elem = n_elem;
166 const uword new_n_elem = in_n_rows * in_n_cols * in_n_slices;
167
168 if(old_n_elem == new_n_elem)
169 {
170 delete_mat();
171
172 if(new_n_elem > 0)
173 {
174 access::rw(n_rows) = in_n_rows;
175 access::rw(n_cols) = in_n_cols;
176 access::rw(n_elem_slice) = in_n_rows*in_n_cols;
177 access::rw(n_slices) = in_n_slices;
178
179 create_mat();
180 }
181 }
182 else
183 {
184 arma_debug_check( (t_mem_state == 2), "Cube::init(): requested size is not compatible with the size of auxiliary memory" );
185
186 delete_mat();
187
188 if(t_mem_state == 0)
189 {
190 if(n_elem > Cube_prealloc::mem_n_elem )
191 {
192 arma_extra_debug_print("Cube::init(): freeing memory");
193
194 memory::release( access::rw(mem) );
195 }
196 }
197
198 access::rw(mem_state) = 0;
199
200 if(new_n_elem <= Cube_prealloc::mem_n_elem)
201 {
202 access::rw(mem) = mem_local;
203 }
204 else
205 {
206 arma_extra_debug_print("Cube::init(): allocating memory");
207
208 access::rw(mem) = memory::acquire<eT>(new_n_elem);
209
210 arma_check_bad_alloc( (mem == 0), "Cube::init(): out of memory" );
211 }
212
213 if(new_n_elem > 0)
214 {
215 access::rw(n_rows) = in_n_rows;
216 access::rw(n_cols) = in_n_cols;
217 access::rw(n_elem_slice) = in_n_rows*in_n_cols;
218 access::rw(n_slices) = in_n_slices;
219 access::rw(n_elem) = new_n_elem;
220
221 create_mat();
222 }
223 }
224
225
226 if(new_n_elem == 0)
227 {
228 access::rw(n_rows) = 0;
229 access::rw(n_cols) = 0;
230 access::rw(n_elem_slice) = 0;
231 access::rw(n_slices) = 0;
232 access::rw(n_elem) = 0;
233 }
234 }
235
236
237
238 //! for constructing a complex cube out of two non-complex cubes
239 template<typename eT>
240 template<typename T1, typename T2>
241 inline
242 void
243 Cube<eT>::init
244 (
245 const BaseCube<typename Cube<eT>::pod_type,T1>& X,
246 const BaseCube<typename Cube<eT>::pod_type,T2>& Y
247 )
248 {
249 arma_extra_debug_sigprint();
250
251 typedef typename T1::elem_type T;
252
253 arma_type_check(( is_complex<eT>::value == false )); //!< compile-time abort if eT isn't std::complex
254 arma_type_check(( is_complex< T>::value == true )); //!< compile-time abort if T is std::complex
255
256 arma_type_check(( is_same_type< std::complex<T>, eT >::value == false )); //!< compile-time abort if types are not compatible
257
258 const ProxyCube<T1> PX(X.get_ref());
259 const ProxyCube<T2> PY(Y.get_ref());
260
261 arma_debug_assert_same_size(PX, PY, "Cube()");
262
263 const uword local_n_rows = PX.get_n_rows();
264 const uword local_n_cols = PX.get_n_cols();
265 const uword local_n_slices = PX.get_n_slices();
266
267 init_warm(local_n_rows, local_n_cols, local_n_slices);
268
269 eT* out_mem = (*this).memptr();
270
271 const bool prefer_at_accessor = ( ProxyCube<T1>::prefer_at_accessor || ProxyCube<T2>::prefer_at_accessor );
272
273 if(prefer_at_accessor == false)
274 {
275 typedef typename ProxyCube<T1>::ea_type ea_type1;
276 typedef typename ProxyCube<T2>::ea_type ea_type2;
277
278 const uword N = n_elem;
279
280 ea_type1 A = PX.get_ea();
281 ea_type2 B = PY.get_ea();
282
283 for(uword i=0; i<N; ++i)
284 {
285 out_mem[i] = std::complex<T>(A[i], B[i]);
286 }
287 }
288 else
289 {
290 for(uword uslice = 0; uslice < local_n_slices; ++uslice)
291 for(uword ucol = 0; ucol < local_n_cols; ++ucol )
292 for(uword urow = 0; urow < local_n_rows; ++urow )
293 {
294 *out_mem = std::complex<T>( PX.at(urow,ucol,uslice), PY.at(urow,ucol,uslice) );
295 out_mem++;
296 }
297 }
298 }
299
300
301
302 template<typename eT>
303 inline
304 void
305 Cube<eT>::delete_mat()
306 {
307 arma_extra_debug_sigprint();
308
309 for(uword uslice = 0; uslice < n_slices; ++uslice)
310 {
311 delete access::rw(mat_ptrs[uslice]);
312 }
313
314 if(mem_state <= 2)
315 {
316 if(n_slices > Cube_prealloc::mat_ptrs_size)
317 {
318 delete [] mat_ptrs;
319 }
320 }
321 }
322
323
324
325 template<typename eT>
326 inline
327 void
328 Cube<eT>::create_mat()
329 {
330 arma_extra_debug_sigprint();
331
332 if(mem_state <= 2)
333 {
334 if(n_slices <= Cube_prealloc::mat_ptrs_size)
335 {
336 access::rw(mat_ptrs) = const_cast< const Mat<eT>** >(mat_ptrs_local);
337 }
338 else
339 {
340 access::rw(mat_ptrs) = new(std::nothrow) const Mat<eT>*[n_slices];
341
342 arma_check_bad_alloc( (mat_ptrs == 0), "Cube::create_mat(): out of memory" );
343 }
344 }
345
346 for(uword uslice = 0; uslice < n_slices; ++uslice)
347 {
348 mat_ptrs[uslice] = new Mat<eT>('j', slice_memptr(uslice), n_rows, n_cols);
349 }
350 }
351
352
353
354 //! Set the cube to be equal to the specified scalar.
355 //! NOTE: the size of the cube will be 1x1x1
356 template<typename eT>
357 arma_inline
358 const Cube<eT>&
359 Cube<eT>::operator=(const eT val)
360 {
361 arma_extra_debug_sigprint();
362
363 init_warm(1,1,1);
364 access::rw(mem[0]) = val;
365 return *this;
366 }
367
368
369
370 //! In-place addition of a scalar to all elements of the cube
371 template<typename eT>
372 arma_inline
373 const Cube<eT>&
374 Cube<eT>::operator+=(const eT val)
375 {
376 arma_extra_debug_sigprint();
377
378 arrayops::inplace_plus( memptr(), val, n_elem );
379
380 return *this;
381 }
382
383
384
385 //! In-place subtraction of a scalar from all elements of the cube
386 template<typename eT>
387 arma_inline
388 const Cube<eT>&
389 Cube<eT>::operator-=(const eT val)
390 {
391 arma_extra_debug_sigprint();
392
393 arrayops::inplace_minus( memptr(), val, n_elem );
394
395 return *this;
396 }
397
398
399
400 //! In-place multiplication of all elements of the cube with a scalar
401 template<typename eT>
402 arma_inline
403 const Cube<eT>&
404 Cube<eT>::operator*=(const eT val)
405 {
406 arma_extra_debug_sigprint();
407
408 arrayops::inplace_mul( memptr(), val, n_elem );
409
410 return *this;
411 }
412
413
414
415 //! In-place division of all elements of the cube with a scalar
416 template<typename eT>
417 arma_inline
418 const Cube<eT>&
419 Cube<eT>::operator/=(const eT val)
420 {
421 arma_extra_debug_sigprint();
422
423 arrayops::inplace_div( memptr(), val, n_elem );
424
425 return *this;
426 }
427
428
429
430 //! construct a cube from a given cube
431 template<typename eT>
432 inline
433 Cube<eT>::Cube(const Cube<eT>& x)
434 : n_rows(x.n_rows)
435 , n_cols(x.n_cols)
436 , n_elem_slice(x.n_elem_slice)
437 , n_slices(x.n_slices)
438 , n_elem(x.n_elem)
439 , mem_state(0)
440 , mat_ptrs()
441 , mem()
442 {
443 arma_extra_debug_sigprint_this(this);
444 arma_extra_debug_sigprint(arma_boost::format("this = %x in_cube = %x") % this % &x);
445
446 init_cold();
447
448 arrayops::copy( memptr(), x.mem, n_elem );
449 }
450
451
452
453 //! construct a cube from a given cube
454 template<typename eT>
455 inline
456 const Cube<eT>&
457 Cube<eT>::operator=(const Cube<eT>& x)
458 {
459 arma_extra_debug_sigprint(arma_boost::format("this = %x in_cube = %x") % this % &x);
460
461 if(this != &x)
462 {
463 init_warm(x.n_rows, x.n_cols, x.n_slices);
464
465 arrayops::copy( memptr(), x.mem, n_elem );
466 }
467
468 return *this;
469 }
470
471
472
473 //! construct a cube from a given auxiliary array of eTs.
474 //! if copy_aux_mem is true, new memory is allocated and the array is copied.
475 //! if copy_aux_mem is false, the auxiliary array is used directly (without allocating memory and copying).
476 //! note that in the latter case
477 //! the default is to copy the array.
478
479 template<typename eT>
480 inline
481 Cube<eT>::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)
482 : n_rows ( aux_n_rows )
483 , n_cols ( aux_n_cols )
484 , n_elem_slice( aux_n_rows*aux_n_cols )
485 , n_slices ( aux_n_slices )
486 , n_elem ( aux_n_rows*aux_n_cols*aux_n_slices )
487 , mem_state ( copy_aux_mem ? 0 : (strict ? 2 : 1) )
488 , mat_ptrs ( 0 )
489 , mem ( copy_aux_mem ? 0 : aux_mem )
490 {
491 arma_extra_debug_sigprint_this(this);
492
493 if(copy_aux_mem == true)
494 {
495 init_cold();
496
497 arrayops::copy( memptr(), aux_mem, n_elem );
498 }
499 else
500 {
501 create_mat();
502 }
503 }
504
505
506
507 //! construct a cube from a given auxiliary read-only array of eTs.
508 //! the array is copied.
509 template<typename eT>
510 inline
511 Cube<eT>::Cube(const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const uword aux_n_slices)
512 : n_rows(aux_n_rows)
513 , n_cols(aux_n_cols)
514 , n_elem_slice(aux_n_rows*aux_n_cols)
515 , n_slices(aux_n_slices)
516 , n_elem(aux_n_rows*aux_n_cols*aux_n_slices)
517 , mem_state(0)
518 , mat_ptrs()
519 , mem()
520 {
521 arma_extra_debug_sigprint_this(this);
522
523 init_cold();
524
525 arrayops::copy( memptr(), aux_mem, n_elem );
526 }
527
528
529
530 //! in-place cube addition
531 template<typename eT>
532 inline
533 const Cube<eT>&
534 Cube<eT>::operator+=(const Cube<eT>& m)
535 {
536 arma_extra_debug_sigprint();
537
538 arma_debug_assert_same_size(*this, m, "addition");
539
540 arrayops::inplace_plus( memptr(), m.memptr(), n_elem );
541
542 return *this;
543 }
544
545
546
547 //! in-place cube subtraction
548 template<typename eT>
549 inline
550 const Cube<eT>&
551 Cube<eT>::operator-=(const Cube<eT>& m)
552 {
553 arma_extra_debug_sigprint();
554
555 arma_debug_assert_same_size(*this, m, "subtraction");
556
557 arrayops::inplace_minus( memptr(), m.memptr(), n_elem );
558
559 return *this;
560 }
561
562
563
564 //! in-place element-wise cube multiplication
565 template<typename eT>
566 inline
567 const Cube<eT>&
568 Cube<eT>::operator%=(const Cube<eT>& m)
569 {
570 arma_extra_debug_sigprint();
571
572 arma_debug_assert_same_size(*this, m, "element-wise multiplication");
573
574 arrayops::inplace_mul( memptr(), m.memptr(), n_elem );
575
576 return *this;
577 }
578
579
580
581 //! in-place element-wise cube division
582 template<typename eT>
583 inline
584 const Cube<eT>&
585 Cube<eT>::operator/=(const Cube<eT>& m)
586 {
587 arma_extra_debug_sigprint();
588
589 arma_debug_assert_same_size(*this, m, "element-wise division");
590
591 arrayops::inplace_div( memptr(), m.memptr(), n_elem );
592
593 return *this;
594 }
595
596
597
598 //! for constructing a complex cube out of two non-complex cubes
599 template<typename eT>
600 template<typename T1, typename T2>
601 inline
602 Cube<eT>::Cube
603 (
604 const BaseCube<typename Cube<eT>::pod_type,T1>& A,
605 const BaseCube<typename Cube<eT>::pod_type,T2>& B
606 )
607 : n_rows(0)
608 , n_cols(0)
609 , n_elem_slice(0)
610 , n_slices(0)
611 , n_elem(0)
612 , mem_state(0)
613 , mat_ptrs()
614 , mem()
615 {
616 arma_extra_debug_sigprint_this(this);
617
618 init(A,B);
619 }
620
621
622
623 //! construct a cube from a subview_cube instance (e.g. construct a cube from a delayed subcube operation)
624 template<typename eT>
625 inline
626 Cube<eT>::Cube(const subview_cube<eT>& X)
627 : n_rows(X.n_rows)
628 , n_cols(X.n_cols)
629 , n_elem_slice(X.n_elem_slice)
630 , n_slices(X.n_slices)
631 , n_elem(X.n_elem)
632 , mem_state(0)
633 , mat_ptrs()
634 , mem()
635 {
636 arma_extra_debug_sigprint_this(this);
637
638 init_cold();
639
640 subview_cube<eT>::extract(*this, X);
641 }
642
643
644
645 //! construct a cube from a subview_cube instance (e.g. construct a cube from a delayed subcube operation)
646 template<typename eT>
647 inline
648 const Cube<eT>&
649 Cube<eT>::operator=(const subview_cube<eT>& X)
650 {
651 arma_extra_debug_sigprint();
652
653 const bool alias = (this == &(X.m));
654
655 if(alias == false)
656 {
657 init_warm(X.n_rows, X.n_cols, X.n_slices);
658
659 subview_cube<eT>::extract(*this, X);
660 }
661 else
662 {
663 Cube<eT> tmp(X);
664
665 steal_mem(tmp);
666 }
667
668 return *this;
669 }
670
671
672
673 //! in-place cube addition (using a subcube on the right-hand-side)
674 template<typename eT>
675 inline
676 const Cube<eT>&
677 Cube<eT>::operator+=(const subview_cube<eT>& X)
678 {
679 arma_extra_debug_sigprint();
680
681 subview_cube<eT>::plus_inplace(*this, X);
682
683 return *this;
684 }
685
686
687
688 //! in-place cube subtraction (using a subcube on the right-hand-side)
689 template<typename eT>
690 inline
691 const Cube<eT>&
692 Cube<eT>::operator-=(const subview_cube<eT>& X)
693 {
694 arma_extra_debug_sigprint();
695
696 subview_cube<eT>::minus_inplace(*this, X);
697
698 return *this;
699 }
700
701
702
703 //! in-place element-wise cube mutiplication (using a subcube on the right-hand-side)
704 template<typename eT>
705 inline
706 const Cube<eT>&
707 Cube<eT>::operator%=(const subview_cube<eT>& X)
708 {
709 arma_extra_debug_sigprint();
710
711 subview_cube<eT>::schur_inplace(*this, X);
712
713 return *this;
714 }
715
716
717
718 //! in-place element-wise cube division (using a subcube on the right-hand-side)
719 template<typename eT>
720 inline
721 const Cube<eT>&
722 Cube<eT>::operator/=(const subview_cube<eT>& X)
723 {
724 arma_extra_debug_sigprint();
725
726 subview_cube<eT>::div_inplace(*this, X);
727
728 return *this;
729 }
730
731
732
733 //! provide the reference to the matrix representing a single slice
734 template<typename eT>
735 arma_inline
736 Mat<eT>&
737 Cube<eT>::slice(const uword in_slice)
738 {
739 arma_extra_debug_sigprint();
740
741 arma_debug_check
742 (
743 (in_slice >= n_slices),
744 "Cube::slice(): index out of bounds"
745 );
746
747 return const_cast< Mat<eT>& >( *(mat_ptrs[in_slice]) );
748 }
749
750
751
752 //! provide the reference to the matrix representing a single slice
753 template<typename eT>
754 arma_inline
755 const Mat<eT>&
756 Cube<eT>::slice(const uword in_slice) const
757 {
758 arma_extra_debug_sigprint();
759
760 arma_debug_check
761 (
762 (in_slice >= n_slices),
763 "Cube::slice(): index out of bounds"
764 );
765
766 return *(mat_ptrs[in_slice]);
767 }
768
769
770
771 //! creation of subview_cube (subcube comprised of specified slices)
772 template<typename eT>
773 arma_inline
774 subview_cube<eT>
775 Cube<eT>::slices(const uword in_slice1, const uword in_slice2)
776 {
777 arma_extra_debug_sigprint();
778
779 arma_debug_check
780 (
781 (in_slice1 > in_slice2) || (in_slice2 >= n_slices),
782 "Cube::slices(): indices out of bounds or incorrectly used"
783 );
784
785 const uword subcube_n_slices = in_slice2 - in_slice1 + 1;
786
787 return subview_cube<eT>(*this, 0, 0, in_slice1, n_rows, n_cols, subcube_n_slices);
788 }
789
790
791
792 //! creation of subview_cube (subcube comprised of specified slices)
793 template<typename eT>
794 arma_inline
795 const subview_cube<eT>
796 Cube<eT>::slices(const uword in_slice1, const uword in_slice2) const
797 {
798 arma_extra_debug_sigprint();
799
800 arma_debug_check
801 (
802 (in_slice1 > in_slice2) || (in_slice2 >= n_slices),
803 "Cube::rows(): indices out of bounds or incorrectly used"
804 );
805
806 const uword subcube_n_slices = in_slice2 - in_slice1 + 1;
807
808 return subview_cube<eT>(*this, 0, 0, in_slice1, n_rows, n_cols, subcube_n_slices);
809 }
810
811
812
813 //! creation of subview_cube (generic subcube)
814 template<typename eT>
815 arma_inline
816 subview_cube<eT>
817 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)
818 {
819 arma_extra_debug_sigprint();
820
821 arma_debug_check
822 (
823 (in_row1 > in_row2) || (in_col1 > in_col2) || (in_slice1 > in_slice2) ||
824 (in_row2 >= n_rows) || (in_col2 >= n_cols) || (in_slice2 >= n_slices),
825 "Cube::subcube(): indices out of bounds or incorrectly used"
826 );
827
828 const uword subcube_n_rows = in_row2 - in_row1 + 1;
829 const uword subcube_n_cols = in_col2 - in_col1 + 1;
830 const uword subcube_n_slices = in_slice2 - in_slice1 + 1;
831
832 return subview_cube<eT>(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices);
833 }
834
835
836
837 //! creation of subview_cube (generic subcube)
838 template<typename eT>
839 arma_inline
840 const subview_cube<eT>
841 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
842 {
843 arma_extra_debug_sigprint();
844
845 arma_debug_check
846 (
847 (in_row1 > in_row2) || (in_col1 > in_col2) || (in_slice1 > in_slice2) ||
848 (in_row2 >= n_rows) || (in_col2 >= n_cols) || (in_slice2 >= n_slices),
849 "Cube::subcube(): indices out of bounds or incorrectly used"
850 );
851
852 const uword subcube_n_rows = in_row2 - in_row1 + 1;
853 const uword subcube_n_cols = in_col2 - in_col1 + 1;
854 const uword subcube_n_slices = in_slice2 - in_slice1 + 1;
855
856 return subview_cube<eT>(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices);
857 }
858
859
860
861 //! creation of subview_cube (generic subcube)
862 template<typename eT>
863 inline
864 subview_cube<eT>
865 Cube<eT>::subcube(const span& row_span, const span& col_span, const span& slice_span)
866 {
867 arma_extra_debug_sigprint();
868
869 const bool row_all = row_span.whole;
870 const bool col_all = col_span.whole;
871 const bool slice_all = slice_span.whole;
872
873 const uword local_n_rows = n_rows;
874 const uword local_n_cols = n_cols;
875 const uword local_n_slices = n_slices;
876
877 const uword in_row1 = row_all ? 0 : row_span.a;
878 const uword in_row2 = row_span.b;
879 const uword subcube_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
880
881 const uword in_col1 = col_all ? 0 : col_span.a;
882 const uword in_col2 = col_span.b;
883 const uword subcube_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
884
885 const uword in_slice1 = slice_all ? 0 : slice_span.a;
886 const uword in_slice2 = slice_span.b;
887 const uword subcube_n_slices = slice_all ? local_n_slices : in_slice2 - in_slice1 + 1;
888
889 arma_debug_check
890 (
891 ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
892 ||
893 ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
894 ||
895 ( slice_all ? false : ((in_slice1 > in_slice2) || (in_slice2 >= local_n_slices)) )
896 ,
897 "Cube::subcube(): indices out of bounds or incorrectly used"
898 );
899
900 return subview_cube<eT>(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices);
901 }
902
903
904
905 //! creation of subview_cube (generic subcube)
906 template<typename eT>
907 inline
908 const subview_cube<eT>
909 Cube<eT>::subcube(const span& row_span, const span& col_span, const span& slice_span) const
910 {
911 arma_extra_debug_sigprint();
912
913 const bool row_all = row_span.whole;
914 const bool col_all = col_span.whole;
915 const bool slice_all = slice_span.whole;
916
917 const uword local_n_rows = n_rows;
918 const uword local_n_cols = n_cols;
919 const uword local_n_slices = n_slices;
920
921 const uword in_row1 = row_all ? 0 : row_span.a;
922 const uword in_row2 = row_span.b;
923 const uword subcube_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
924
925 const uword in_col1 = col_all ? 0 : col_span.a;
926 const uword in_col2 = col_span.b;
927 const uword subcube_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
928
929 const uword in_slice1 = slice_all ? 0 : slice_span.a;
930 const uword in_slice2 = slice_span.b;
931 const uword subcube_n_slices = slice_all ? local_n_slices : in_slice2 - in_slice1 + 1;
932
933 arma_debug_check
934 (
935 ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
936 ||
937 ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
938 ||
939 ( slice_all ? false : ((in_slice1 > in_slice2) || (in_slice2 >= local_n_slices)) )
940 ,
941 "Cube::subcube(): indices out of bounds or incorrectly used"
942 );
943
944 return subview_cube<eT>(*this, in_row1, in_col1, in_slice1, subcube_n_rows, subcube_n_cols, subcube_n_slices);
945 }
946
947
948
949 template<typename eT>
950 inline
951 subview_cube<eT>
952 Cube<eT>::operator()(const span& row_span, const span& col_span, const span& slice_span)
953 {
954 arma_extra_debug_sigprint();
955
956 return (*this).subcube(row_span, col_span, slice_span);
957 }
958
959
960
961 template<typename eT>
962 inline
963 const subview_cube<eT>
964 Cube<eT>::operator()(const span& row_span, const span& col_span, const span& slice_span) const
965 {
966 arma_extra_debug_sigprint();
967
968 return (*this).subcube(row_span, col_span, slice_span);
969 }
970
971
972
973 //! remove specified slice
974 template<typename eT>
975 inline
976 void
977 Cube<eT>::shed_slice(const uword slice_num)
978 {
979 arma_extra_debug_sigprint();
980
981 arma_debug_check( slice_num >= n_slices, "Cube::shed_slice(): index out of bounds");
982
983 shed_slices(slice_num, slice_num);
984 }
985
986
987
988 //! remove specified slices
989 template<typename eT>
990 inline
991 void
992 Cube<eT>::shed_slices(const uword in_slice1, const uword in_slice2)
993 {
994 arma_extra_debug_sigprint();
995
996 arma_debug_check
997 (
998 (in_slice1 > in_slice2) || (in_slice2 >= n_slices),
999 "Cube::shed_slices(): indices out of bounds or incorrectly used"
1000 );
1001
1002 const uword n_keep_front = in_slice1;
1003 const uword n_keep_back = n_slices - (in_slice2 + 1);
1004
1005 Cube<eT> X(n_rows, n_cols, n_keep_front + n_keep_back);
1006
1007 if(n_keep_front > 0)
1008 {
1009 X.slices( 0, (n_keep_front-1) ) = slices( 0, (in_slice1-1) );
1010 }
1011
1012 if(n_keep_back > 0)
1013 {
1014 X.slices( n_keep_front, (n_keep_front+n_keep_back-1) ) = slices( (in_slice2+1), (n_slices-1) );
1015 }
1016
1017 steal_mem(X);
1018 }
1019
1020
1021
1022 //! insert N slices at the specified slice position,
1023 //! optionally setting the elements of the inserted slices to zero
1024 template<typename eT>
1025 inline
1026 void
1027 Cube<eT>::insert_slices(const uword slice_num, const uword N, const bool set_to_zero)
1028 {
1029 arma_extra_debug_sigprint();
1030
1031 const uword t_n_slices = n_slices;
1032
1033 const uword A_n_slices = slice_num;
1034 const uword B_n_slices = t_n_slices - slice_num;
1035
1036 // insertion at slice_num == n_slices is in effect an append operation
1037 arma_debug_check( (slice_num > t_n_slices), "Cube::insert_slices(): index out of bounds");
1038
1039 if(N > 0)
1040 {
1041 Cube<eT> out(n_rows, n_cols, t_n_slices + N);
1042
1043 if(A_n_slices > 0)
1044 {
1045 out.slices(0, A_n_slices-1) = slices(0, A_n_slices-1);
1046 }
1047
1048 if(B_n_slices > 0)
1049 {
1050 out.slices(slice_num + N, t_n_slices + N - 1) = slices(slice_num, t_n_slices-1);
1051 }
1052
1053 if(set_to_zero == true)
1054 {
1055 //out.slices(slice_num, slice_num + N - 1).zeros();
1056
1057 for(uword i=slice_num; i < (slice_num + N); ++i)
1058 {
1059 out.slice(i).zeros();
1060 }
1061 }
1062
1063 steal_mem(out);
1064 }
1065 }
1066
1067
1068
1069 //! insert the given object at the specified slice position;
1070 //! the given object must have the same number of rows and columns as the cube
1071 template<typename eT>
1072 template<typename T1>
1073 inline
1074 void
1075 Cube<eT>::insert_slices(const uword slice_num, const BaseCube<eT,T1>& X)
1076 {
1077 arma_extra_debug_sigprint();
1078
1079 const unwrap_cube<T1> tmp(X.get_ref());
1080 const Cube<eT>& C = tmp.M;
1081
1082 const uword N = C.n_slices;
1083
1084 const uword t_n_slices = n_slices;
1085
1086 const uword A_n_slices = slice_num;
1087 const uword B_n_slices = t_n_slices - slice_num;
1088
1089 // insertion at slice_num == n_slices is in effect an append operation
1090 arma_debug_check( (slice_num > t_n_slices), "Cube::insert_slices(): index out of bounds");
1091
1092 arma_debug_check
1093 (
1094 ( (C.n_rows != n_rows) || (C.n_cols != n_cols) ),
1095 "Cube::insert_slices(): given object has incompatible dimensions"
1096 );
1097
1098 if(N > 0)
1099 {
1100 Cube<eT> out(n_rows, n_cols, t_n_slices + N);
1101
1102 if(A_n_slices > 0)
1103 {
1104 out.slices(0, A_n_slices-1) = slices(0, A_n_slices-1);
1105 }
1106
1107 if(B_n_slices > 0)
1108 {
1109 out.slices(slice_num + N, t_n_slices + N - 1) = slices(slice_num, t_n_slices - 1);
1110 }
1111
1112 out.slices(slice_num, slice_num + N - 1) = C;
1113
1114 steal_mem(out);
1115 }
1116 }
1117
1118
1119
1120 //! create a cube from OpCube, i.e. run the previously delayed unary operations
1121 template<typename eT>
1122 template<typename gen_type>
1123 inline
1124 Cube<eT>::Cube(const GenCube<eT, gen_type>& X)
1125 : n_rows(X.n_rows)
1126 , n_cols(X.n_cols)
1127 , n_elem_slice(X.n_rows*X.n_cols)
1128 , n_slices(X.n_slices)
1129 , n_elem(X.n_rows*X.n_cols*X.n_slices)
1130 , mem_state(0)
1131 , mat_ptrs()
1132 , mem()
1133 {
1134 arma_extra_debug_sigprint_this(this);
1135
1136 init_cold();
1137
1138 X.apply(*this);
1139 }
1140
1141
1142
1143 template<typename eT>
1144 template<typename gen_type>
1145 inline
1146 const Cube<eT>&
1147 Cube<eT>::operator=(const GenCube<eT, gen_type>& X)
1148 {
1149 arma_extra_debug_sigprint();
1150
1151 init_warm(X.n_rows, X.n_cols, X.n_slices);
1152
1153 X.apply(*this);
1154
1155 return *this;
1156 }
1157
1158
1159
1160 template<typename eT>
1161 template<typename gen_type>
1162 inline
1163 const Cube<eT>&
1164 Cube<eT>::operator+=(const GenCube<eT, gen_type>& X)
1165 {
1166 arma_extra_debug_sigprint();
1167
1168 X.apply_inplace_plus(*this);
1169
1170 return *this;
1171 }
1172
1173
1174
1175 template<typename eT>
1176 template<typename gen_type>
1177 inline
1178 const Cube<eT>&
1179 Cube<eT>::operator-=(const GenCube<eT, gen_type>& X)
1180 {
1181 arma_extra_debug_sigprint();
1182
1183 X.apply_inplace_minus(*this);
1184
1185 return *this;
1186 }
1187
1188
1189
1190 template<typename eT>
1191 template<typename gen_type>
1192 inline
1193 const Cube<eT>&
1194 Cube<eT>::operator%=(const GenCube<eT, gen_type>& X)
1195 {
1196 arma_extra_debug_sigprint();
1197
1198 X.apply_inplace_schur(*this);
1199
1200 return *this;
1201 }
1202
1203
1204
1205 template<typename eT>
1206 template<typename gen_type>
1207 inline
1208 const Cube<eT>&
1209 Cube<eT>::operator/=(const GenCube<eT, gen_type>& X)
1210 {
1211 arma_extra_debug_sigprint();
1212
1213 X.apply_inplace_div(*this);
1214
1215 return *this;
1216 }
1217
1218
1219
1220 //! create a cube from OpCube, i.e. run the previously delayed unary operations
1221 template<typename eT>
1222 template<typename T1, typename op_type>
1223 inline
1224 Cube<eT>::Cube(const OpCube<T1, op_type>& X)
1225 : n_rows(0)
1226 , n_cols(0)
1227 , n_elem_slice(0)
1228 , n_slices(0)
1229 , n_elem(0)
1230 , mem_state(0)
1231 , mat_ptrs()
1232 , mem()
1233 {
1234 arma_extra_debug_sigprint_this(this);
1235
1236 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1237
1238 op_type::apply(*this, X);
1239 }
1240
1241
1242
1243 //! create a cube from OpCube, i.e. run the previously delayed unary operations
1244 template<typename eT>
1245 template<typename T1, typename op_type>
1246 inline
1247 const Cube<eT>&
1248 Cube<eT>::operator=(const OpCube<T1, op_type>& X)
1249 {
1250 arma_extra_debug_sigprint();
1251
1252 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1253
1254 op_type::apply(*this, X);
1255
1256 return *this;
1257 }
1258
1259
1260
1261 //! in-place cube addition, with the right-hand-side operand having delayed operations
1262 template<typename eT>
1263 template<typename T1, typename op_type>
1264 inline
1265 const Cube<eT>&
1266 Cube<eT>::operator+=(const OpCube<T1, op_type>& X)
1267 {
1268 arma_extra_debug_sigprint();
1269
1270 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1271
1272 const Cube<eT> m(X);
1273
1274 return (*this).operator+=(m);
1275 }
1276
1277
1278
1279 //! in-place cube subtraction, with the right-hand-side operand having delayed operations
1280 template<typename eT>
1281 template<typename T1, typename op_type>
1282 inline
1283 const Cube<eT>&
1284 Cube<eT>::operator-=(const OpCube<T1, op_type>& X)
1285 {
1286 arma_extra_debug_sigprint();
1287
1288 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1289
1290 const Cube<eT> m(X);
1291
1292 return (*this).operator-=(m);
1293 }
1294
1295
1296
1297 //! in-place cube element-wise multiplication, with the right-hand-side operand having delayed operations
1298 template<typename eT>
1299 template<typename T1, typename op_type>
1300 inline
1301 const Cube<eT>&
1302 Cube<eT>::operator%=(const OpCube<T1, op_type>& X)
1303 {
1304 arma_extra_debug_sigprint();
1305
1306 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1307
1308 const Cube<eT> m(X);
1309
1310 return (*this).operator%=(m);
1311 }
1312
1313
1314
1315 //! in-place cube element-wise division, with the right-hand-side operand having delayed operations
1316 template<typename eT>
1317 template<typename T1, typename op_type>
1318 inline
1319 const Cube<eT>&
1320 Cube<eT>::operator/=(const OpCube<T1, op_type>& X)
1321 {
1322 arma_extra_debug_sigprint();
1323
1324 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1325
1326 const Cube<eT> m(X);
1327
1328 return (*this).operator/=(m);
1329 }
1330
1331
1332
1333 //! create a cube from eOpCube, i.e. run the previously delayed unary operations
1334 template<typename eT>
1335 template<typename T1, typename eop_type>
1336 inline
1337 Cube<eT>::Cube(const eOpCube<T1, eop_type>& X)
1338 : n_rows(X.get_n_rows())
1339 , n_cols(X.get_n_cols())
1340 , n_elem_slice(X.get_n_elem_slice())
1341 , n_slices(X.get_n_slices())
1342 , n_elem(X.get_n_elem())
1343 , mem_state(0)
1344 , mat_ptrs()
1345 , mem()
1346 {
1347 arma_extra_debug_sigprint_this(this);
1348
1349 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1350
1351 init_cold();
1352
1353 eop_type::apply(*this, X);
1354 }
1355
1356
1357
1358 //! create a cube from eOpCube, i.e. run the previously delayed unary operations
1359 template<typename eT>
1360 template<typename T1, typename eop_type>
1361 inline
1362 const Cube<eT>&
1363 Cube<eT>::operator=(const eOpCube<T1, eop_type>& X)
1364 {
1365 arma_extra_debug_sigprint();
1366
1367 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1368
1369 const bool bad_alias = ( X.P.has_subview && X.P.is_alias(*this) );
1370
1371 if(bad_alias == false)
1372 {
1373 init_warm(X.get_n_rows(), X.get_n_cols(), X.get_n_slices());
1374
1375 eop_type::apply(*this, X);
1376 }
1377 else
1378 {
1379 Cube<eT> tmp(X);
1380
1381 steal_mem(tmp);
1382 }
1383
1384 return *this;
1385 }
1386
1387
1388
1389 //! in-place cube addition, with the right-hand-side operand having delayed operations
1390 template<typename eT>
1391 template<typename T1, typename eop_type>
1392 inline
1393 const Cube<eT>&
1394 Cube<eT>::operator+=(const eOpCube<T1, eop_type>& X)
1395 {
1396 arma_extra_debug_sigprint();
1397
1398 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1399
1400 eop_type::apply_inplace_plus(*this, X);
1401
1402 return *this;
1403 }
1404
1405
1406
1407 //! in-place cube subtraction, with the right-hand-side operand having delayed operations
1408 template<typename eT>
1409 template<typename T1, typename eop_type>
1410 inline
1411 const Cube<eT>&
1412 Cube<eT>::operator-=(const eOpCube<T1, eop_type>& X)
1413 {
1414 arma_extra_debug_sigprint();
1415
1416 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1417
1418 eop_type::apply_inplace_minus(*this, X);
1419
1420 return *this;
1421 }
1422
1423
1424
1425 //! in-place cube element-wise multiplication, with the right-hand-side operand having delayed operations
1426 template<typename eT>
1427 template<typename T1, typename eop_type>
1428 inline
1429 const Cube<eT>&
1430 Cube<eT>::operator%=(const eOpCube<T1, eop_type>& X)
1431 {
1432 arma_extra_debug_sigprint();
1433
1434 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1435
1436 eop_type::apply_inplace_schur(*this, X);
1437
1438 return *this;
1439 }
1440
1441
1442
1443 //! in-place cube element-wise division, with the right-hand-side operand having delayed operations
1444 template<typename eT>
1445 template<typename T1, typename eop_type>
1446 inline
1447 const Cube<eT>&
1448 Cube<eT>::operator/=(const eOpCube<T1, eop_type>& X)
1449 {
1450 arma_extra_debug_sigprint();
1451
1452 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1453
1454 eop_type::apply_inplace_div(*this, X);
1455
1456 return *this;
1457 }
1458
1459
1460
1461 //! EXPERIMENTAL
1462 template<typename eT>
1463 template<typename T1, typename op_type>
1464 inline
1465 Cube<eT>::Cube(const mtOpCube<eT, T1, op_type>& X)
1466 : n_rows(0)
1467 , n_cols(0)
1468 , n_elem_slice(0)
1469 , n_slices(0)
1470 , n_elem(0)
1471 , mem_state(0)
1472 , mat_ptrs()
1473 , mem()
1474 {
1475 arma_extra_debug_sigprint_this(this);
1476
1477 op_type::apply(*this, X);
1478 }
1479
1480
1481
1482 //! EXPERIMENTAL
1483 template<typename eT>
1484 template<typename T1, typename op_type>
1485 inline
1486 const Cube<eT>&
1487 Cube<eT>::operator=(const mtOpCube<eT, T1, op_type>& X)
1488 {
1489 arma_extra_debug_sigprint();
1490
1491 op_type::apply(*this, X);
1492
1493 return *this;
1494 }
1495
1496
1497
1498 //! EXPERIMENTAL
1499 template<typename eT>
1500 template<typename T1, typename op_type>
1501 inline
1502 const Cube<eT>&
1503 Cube<eT>::operator+=(const mtOpCube<eT, T1, op_type>& X)
1504 {
1505 arma_extra_debug_sigprint();
1506
1507 const Cube<eT> m(X);
1508
1509 return (*this).operator+=(m);
1510 }
1511
1512
1513
1514 //! EXPERIMENTAL
1515 template<typename eT>
1516 template<typename T1, typename op_type>
1517 inline
1518 const Cube<eT>&
1519 Cube<eT>::operator-=(const mtOpCube<eT, T1, op_type>& X)
1520 {
1521 arma_extra_debug_sigprint();
1522
1523 const Cube<eT> m(X);
1524
1525 return (*this).operator-=(m);
1526 }
1527
1528
1529
1530 //! EXPERIMENTAL
1531 template<typename eT>
1532 template<typename T1, typename op_type>
1533 inline
1534 const Cube<eT>&
1535 Cube<eT>::operator%=(const mtOpCube<eT, T1, op_type>& X)
1536 {
1537 arma_extra_debug_sigprint();
1538
1539 const Cube<eT> m(X);
1540
1541 return (*this).operator%=(m);
1542 }
1543
1544
1545
1546 //! EXPERIMENTAL
1547 template<typename eT>
1548 template<typename T1, typename op_type>
1549 inline
1550 const Cube<eT>&
1551 Cube<eT>::operator/=(const mtOpCube<eT, T1, op_type>& X)
1552 {
1553 arma_extra_debug_sigprint();
1554
1555 const Cube<eT> m(X);
1556
1557 return (*this).operator/=(m);
1558 }
1559
1560
1561
1562 //! create a cube from Glue, i.e. run the previously delayed binary operations
1563 template<typename eT>
1564 template<typename T1, typename T2, typename glue_type>
1565 inline
1566 Cube<eT>::Cube(const GlueCube<T1, T2, glue_type>& X)
1567 : n_rows(0)
1568 , n_cols(0)
1569 , n_elem_slice(0)
1570 , n_slices(0)
1571 , n_elem(0)
1572 , mem_state(0)
1573 , mat_ptrs()
1574 , mem()
1575 {
1576 arma_extra_debug_sigprint_this(this);
1577 this->operator=(X);
1578 }
1579
1580
1581
1582 //! create a cube from Glue, i.e. run the previously delayed binary operations
1583 template<typename eT>
1584 template<typename T1, typename T2, typename glue_type>
1585 inline
1586 const Cube<eT>&
1587 Cube<eT>::operator=(const GlueCube<T1, T2, glue_type>& X)
1588 {
1589 arma_extra_debug_sigprint();
1590
1591 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1592 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1593
1594 glue_type::apply(*this, X);
1595
1596 return *this;
1597 }
1598
1599
1600 //! in-place cube addition, with the right-hand-side operands having delayed operations
1601 template<typename eT>
1602 template<typename T1, typename T2, typename glue_type>
1603 inline
1604 const Cube<eT>&
1605 Cube<eT>::operator+=(const GlueCube<T1, T2, glue_type>& X)
1606 {
1607 arma_extra_debug_sigprint();
1608
1609 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1610 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1611
1612 const Cube<eT> m(X);
1613
1614 return (*this).operator+=(m);
1615 }
1616
1617
1618
1619 //! in-place cube subtraction, with the right-hand-side operands having delayed operations
1620 template<typename eT>
1621 template<typename T1, typename T2, typename glue_type>
1622 inline
1623 const Cube<eT>&
1624 Cube<eT>::operator-=(const GlueCube<T1, T2, glue_type>& X)
1625 {
1626 arma_extra_debug_sigprint();
1627
1628 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1629 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1630
1631 const Cube<eT> m(X);
1632
1633 return (*this).operator-=(m);
1634 }
1635
1636
1637
1638 //! in-place cube element-wise multiplication, with the right-hand-side operands having delayed operations
1639 template<typename eT>
1640 template<typename T1, typename T2, typename glue_type>
1641 inline
1642 const Cube<eT>&
1643 Cube<eT>::operator%=(const GlueCube<T1, T2, glue_type>& X)
1644 {
1645 arma_extra_debug_sigprint();
1646
1647 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1648 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1649
1650 const Cube<eT> m(X);
1651
1652 return (*this).operator%=(m);
1653 }
1654
1655
1656
1657 //! in-place cube element-wise division, with the right-hand-side operands having delayed operations
1658 template<typename eT>
1659 template<typename T1, typename T2, typename glue_type>
1660 inline
1661 const Cube<eT>&
1662 Cube<eT>::operator/=(const GlueCube<T1, T2, glue_type>& X)
1663 {
1664 arma_extra_debug_sigprint();
1665
1666 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1667 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1668
1669 const Cube<eT> m(X);
1670
1671 return (*this).operator/=(m);
1672 }
1673
1674
1675
1676 //! create a cube from eGlue, i.e. run the previously delayed binary operations
1677 template<typename eT>
1678 template<typename T1, typename T2, typename eglue_type>
1679 inline
1680 Cube<eT>::Cube(const eGlueCube<T1, T2, eglue_type>& X)
1681 : n_rows(X.get_n_rows())
1682 , n_cols(X.get_n_cols())
1683 , n_elem_slice(X.get_n_elem_slice())
1684 , n_slices(X.get_n_slices())
1685 , n_elem(X.get_n_elem())
1686 , mem_state(0)
1687 , mat_ptrs()
1688 , mem()
1689 {
1690 arma_extra_debug_sigprint_this(this);
1691
1692 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1693 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1694
1695 init_cold();
1696
1697 eglue_type::apply(*this, X);
1698 }
1699
1700
1701
1702 //! create a cube from Glue, i.e. run the previously delayed binary operations
1703 template<typename eT>
1704 template<typename T1, typename T2, typename eglue_type>
1705 inline
1706 const Cube<eT>&
1707 Cube<eT>::operator=(const eGlueCube<T1, T2, eglue_type>& X)
1708 {
1709 arma_extra_debug_sigprint();
1710
1711 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1712 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1713
1714 const bool bad_alias = ( (X.P1.has_subview && X.P1.is_alias(*this)) || (X.P2.has_subview && X.P2.is_alias(*this)) );
1715
1716 if(bad_alias == false)
1717 {
1718 init_warm(X.get_n_rows(), X.get_n_cols(), X.get_n_slices());
1719
1720 eglue_type::apply(*this, X);
1721 }
1722 else
1723 {
1724 Cube<eT> tmp(X);
1725
1726 steal_mem(tmp);
1727 }
1728
1729 return *this;
1730 }
1731
1732
1733
1734 //! in-place cube addition, with the right-hand-side operands having delayed operations
1735 template<typename eT>
1736 template<typename T1, typename T2, typename eglue_type>
1737 inline
1738 const Cube<eT>&
1739 Cube<eT>::operator+=(const eGlueCube<T1, T2, eglue_type>& X)
1740 {
1741 arma_extra_debug_sigprint();
1742
1743 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1744 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1745
1746 eglue_type::apply_inplace_plus(*this, X);
1747
1748 return *this;
1749 }
1750
1751
1752
1753 //! in-place cube subtraction, with the right-hand-side operands having delayed operations
1754 template<typename eT>
1755 template<typename T1, typename T2, typename eglue_type>
1756 inline
1757 const Cube<eT>&
1758 Cube<eT>::operator-=(const eGlueCube<T1, T2, eglue_type>& X)
1759 {
1760 arma_extra_debug_sigprint();
1761
1762 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1763 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1764
1765 eglue_type::apply_inplace_minus(*this, X);
1766
1767 return *this;
1768 }
1769
1770
1771
1772 //! in-place cube element-wise multiplication, with the right-hand-side operands having delayed operations
1773 template<typename eT>
1774 template<typename T1, typename T2, typename eglue_type>
1775 inline
1776 const Cube<eT>&
1777 Cube<eT>::operator%=(const eGlueCube<T1, T2, eglue_type>& X)
1778 {
1779 arma_extra_debug_sigprint();
1780
1781 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1782 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1783
1784 eglue_type::apply_inplace_schur(*this, X);
1785
1786 return *this;
1787 }
1788
1789
1790
1791 //! in-place cube element-wise division, with the right-hand-side operands having delayed operations
1792 template<typename eT>
1793 template<typename T1, typename T2, typename eglue_type>
1794 inline
1795 const Cube<eT>&
1796 Cube<eT>::operator/=(const eGlueCube<T1, T2, eglue_type>& X)
1797 {
1798 arma_extra_debug_sigprint();
1799
1800 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
1801 arma_type_check(( is_same_type< eT, typename T2::elem_type >::value == false ));
1802
1803 eglue_type::apply_inplace_div(*this, X);
1804
1805 return *this;
1806 }
1807
1808
1809
1810 //! EXPERIMENTAL
1811 template<typename eT>
1812 template<typename T1, typename T2, typename glue_type>
1813 inline
1814 Cube<eT>::Cube(const mtGlueCube<eT, T1, T2, glue_type>& X)
1815 : n_rows(0)
1816 , n_cols(0)
1817 , n_elem_slice(0)
1818 , n_slices(0)
1819 , n_elem(0)
1820 , mem_state(0)
1821 , mat_ptrs()
1822 , mem()
1823 {
1824 arma_extra_debug_sigprint_this(this);
1825
1826 glue_type::apply(*this, X);
1827 }
1828
1829
1830
1831 //! EXPERIMENTAL
1832 template<typename eT>
1833 template<typename T1, typename T2, typename glue_type>
1834 inline
1835 const Cube<eT>&
1836 Cube<eT>::operator=(const mtGlueCube<eT, T1, T2, glue_type>& X)
1837 {
1838 arma_extra_debug_sigprint();
1839
1840 glue_type::apply(*this, X);
1841
1842 return *this;
1843 }
1844
1845
1846
1847 //! EXPERIMENTAL
1848 template<typename eT>
1849 template<typename T1, typename T2, typename glue_type>
1850 inline
1851 const Cube<eT>&
1852 Cube<eT>::operator+=(const mtGlueCube<eT, T1, T2, glue_type>& X)
1853 {
1854 arma_extra_debug_sigprint();
1855
1856 const Cube<eT> m(X);
1857
1858 return (*this).operator+=(m);
1859 }
1860
1861
1862
1863 //! EXPERIMENTAL
1864 template<typename eT>
1865 template<typename T1, typename T2, typename glue_type>
1866 inline
1867 const Cube<eT>&
1868 Cube<eT>::operator-=(const mtGlueCube<eT, T1, T2, glue_type>& X)
1869 {
1870 arma_extra_debug_sigprint();
1871
1872 const Cube<eT> m(X);
1873
1874 return (*this).operator-=(m);
1875 }
1876
1877
1878
1879 //! EXPERIMENTAL
1880 template<typename eT>
1881 template<typename T1, typename T2, typename glue_type>
1882 inline
1883 const Cube<eT>&
1884 Cube<eT>::operator%=(const mtGlueCube<eT, T1, T2, glue_type>& X)
1885 {
1886 arma_extra_debug_sigprint();
1887
1888 const Cube<eT> m(X);
1889
1890 return (*this).operator%=(m);
1891 }
1892
1893
1894
1895 //! EXPERIMENTAL
1896 template<typename eT>
1897 template<typename T1, typename T2, typename glue_type>
1898 inline
1899 const Cube<eT>&
1900 Cube<eT>::operator/=(const mtGlueCube<eT, T1, T2, glue_type>& X)
1901 {
1902 arma_extra_debug_sigprint();
1903
1904 const Cube<eT> m(X);
1905
1906 return (*this).operator/=(m);
1907 }
1908
1909
1910
1911 //! linear element accessor (treats the cube as a vector); no bounds check; assumes memory is aligned
1912 template<typename eT>
1913 arma_inline
1914 arma_warn_unused
1915 const eT&
1916 Cube<eT>::at_alt(const uword i) const
1917 {
1918 const eT* mem_aligned = mem;
1919 memory::mark_as_aligned(mem_aligned);
1920
1921 return mem_aligned[i];
1922 }
1923
1924
1925
1926 //! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
1927 template<typename eT>
1928 arma_inline
1929 arma_warn_unused
1930 eT&
1931 Cube<eT>::operator() (const uword i)
1932 {
1933 arma_debug_check( (i >= n_elem), "Cube::operator(): index out of bounds");
1934 return access::rw(mem[i]);
1935 }
1936
1937
1938
1939 //! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
1940 template<typename eT>
1941 arma_inline
1942 arma_warn_unused
1943 const eT&
1944 Cube<eT>::operator() (const uword i) const
1945 {
1946 arma_debug_check( (i >= n_elem), "Cube::operator(): index out of bounds");
1947 return mem[i];
1948 }
1949
1950
1951 //! linear element accessor (treats the cube as a vector); no bounds check.
1952 template<typename eT>
1953 arma_inline
1954 arma_warn_unused
1955 eT&
1956 Cube<eT>::operator[] (const uword i)
1957 {
1958 return access::rw(mem[i]);
1959 }
1960
1961
1962
1963 //! linear element accessor (treats the cube as a vector); no bounds check
1964 template<typename eT>
1965 arma_inline
1966 arma_warn_unused
1967 const eT&
1968 Cube<eT>::operator[] (const uword i) const
1969 {
1970 return mem[i];
1971 }
1972
1973
1974
1975 //! linear element accessor (treats the cube as a vector); no bounds check.
1976 template<typename eT>
1977 arma_inline
1978 arma_warn_unused
1979 eT&
1980 Cube<eT>::at(const uword i)
1981 {
1982 return access::rw(mem[i]);
1983 }
1984
1985
1986
1987 //! linear element accessor (treats the cube as a vector); no bounds check
1988 template<typename eT>
1989 arma_inline
1990 arma_warn_unused
1991 const eT&
1992 Cube<eT>::at(const uword i) const
1993 {
1994 return mem[i];
1995 }
1996
1997
1998
1999 //! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
2000 template<typename eT>
2001 arma_inline
2002 arma_warn_unused
2003 eT&
2004 Cube<eT>::operator() (const uword in_row, const uword in_col, const uword in_slice)
2005 {
2006 arma_debug_check
2007 (
2008 (in_row >= n_rows) ||
2009 (in_col >= n_cols) ||
2010 (in_slice >= n_slices)
2011 ,
2012 "Cube::operator(): index out of bounds"
2013 );
2014
2015 return access::rw(mem[in_slice*n_elem_slice + in_col*n_rows + in_row]);
2016 }
2017
2018
2019
2020 //! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
2021 template<typename eT>
2022 arma_inline
2023 arma_warn_unused
2024 const eT&
2025 Cube<eT>::operator() (const uword in_row, const uword in_col, const uword in_slice) const
2026 {
2027 arma_debug_check
2028 (
2029 (in_row >= n_rows) ||
2030 (in_col >= n_cols) ||
2031 (in_slice >= n_slices)
2032 ,
2033 "Cube::operator(): index out of bounds"
2034 );
2035
2036 return mem[in_slice*n_elem_slice + in_col*n_rows + in_row];
2037 }
2038
2039
2040
2041 //! element accessor; no bounds check
2042 template<typename eT>
2043 arma_inline
2044 arma_warn_unused
2045 eT&
2046 Cube<eT>::at(const uword in_row, const uword in_col, const uword in_slice)
2047 {
2048 return access::rw( mem[in_slice*n_elem_slice + in_col*n_rows + in_row] );
2049 }
2050
2051
2052
2053 //! element accessor; no bounds check
2054 template<typename eT>
2055 arma_inline
2056 arma_warn_unused
2057 const eT&
2058 Cube<eT>::at(const uword in_row, const uword in_col, const uword in_slice) const
2059 {
2060 return mem[in_slice*n_elem_slice + in_col*n_rows + in_row];
2061 }
2062
2063
2064
2065 //! prefix ++
2066 template<typename eT>
2067 arma_inline
2068 const Cube<eT>&
2069 Cube<eT>::operator++()
2070 {
2071 Cube_aux::prefix_pp(*this);
2072 return *this;
2073 }
2074
2075
2076
2077 //! postfix ++ (must not return the object by reference)
2078 template<typename eT>
2079 arma_inline
2080 void
2081 Cube<eT>::operator++(int)
2082 {
2083 Cube_aux::postfix_pp(*this);
2084 }
2085
2086
2087
2088 //! prefix --
2089 template<typename eT>
2090 arma_inline
2091 const Cube<eT>&
2092 Cube<eT>::operator--()
2093 {
2094 Cube_aux::prefix_mm(*this);
2095 return *this;
2096 }
2097
2098
2099
2100 //! postfix -- (must not return the object by reference)
2101 template<typename eT>
2102 arma_inline
2103 void
2104 Cube<eT>::operator--(int)
2105 {
2106 Cube_aux::postfix_mm(*this);
2107 }
2108
2109
2110
2111 //! returns true if all of the elements are finite
2112 template<typename eT>
2113 arma_inline
2114 arma_warn_unused
2115 bool
2116 Cube<eT>::is_finite() const
2117 {
2118 return arrayops::is_finite( memptr(), n_elem );
2119 }
2120
2121
2122
2123 //! returns true if the cube has no elements
2124 template<typename eT>
2125 arma_inline
2126 arma_warn_unused
2127 bool
2128 Cube<eT>::is_empty() const
2129 {
2130 return (n_elem == 0);
2131 }
2132
2133
2134
2135 //! returns true if the given index is currently in range
2136 template<typename eT>
2137 arma_inline
2138 arma_warn_unused
2139 bool
2140 Cube<eT>::in_range(const uword i) const
2141 {
2142 return (i < n_elem);
2143 }
2144
2145
2146
2147 //! returns true if the given start and end indices are currently in range
2148 template<typename eT>
2149 arma_inline
2150 arma_warn_unused
2151 bool
2152 Cube<eT>::in_range(const span& x) const
2153 {
2154 arma_extra_debug_sigprint();
2155
2156 if(x.whole == true)
2157 {
2158 return true;
2159 }
2160 else
2161 {
2162 const uword a = x.a;
2163 const uword b = x.b;
2164
2165 return ( (a <= b) && (b < n_elem) );
2166 }
2167 }
2168
2169
2170
2171 //! returns true if the given location is currently in range
2172 template<typename eT>
2173 arma_inline
2174 arma_warn_unused
2175 bool
2176 Cube<eT>::in_range(const uword in_row, const uword in_col, const uword in_slice) const
2177 {
2178 return ( (in_row < n_rows) && (in_col < n_cols) && (in_slice < n_slices) );
2179 }
2180
2181
2182
2183 template<typename eT>
2184 inline
2185 arma_warn_unused
2186 bool
2187 Cube<eT>::in_range(const span& row_span, const span& col_span, const span& slice_span) const
2188 {
2189 arma_extra_debug_sigprint();
2190
2191 const uword in_row1 = row_span.a;
2192 const uword in_row2 = row_span.b;
2193
2194 const uword in_col1 = col_span.a;
2195 const uword in_col2 = col_span.b;
2196
2197 const uword in_slice1 = slice_span.a;
2198 const uword in_slice2 = slice_span.b;
2199
2200
2201 const bool rows_ok = row_span.whole ? true : ( (in_row1 <= in_row2) && (in_row2 < n_rows) );
2202 const bool cols_ok = col_span.whole ? true : ( (in_col1 <= in_col2) && (in_col2 < n_cols) );
2203 const bool slices_ok = slice_span.whole ? true : ( (in_slice1 <= in_slice2) && (in_slice2 < n_slices) );
2204
2205
2206 return ( (rows_ok == true) && (cols_ok == true) && (slices_ok == true) );
2207 }
2208
2209
2210
2211 //! returns a pointer to array of eTs used by the cube
2212 template<typename eT>
2213 arma_inline
2214 arma_warn_unused
2215 eT*
2216 Cube<eT>::memptr()
2217 {
2218 return const_cast<eT*>(mem);
2219 }
2220
2221
2222
2223 //! returns a pointer to array of eTs used by the cube
2224 template<typename eT>
2225 arma_inline
2226 arma_warn_unused
2227 const eT*
2228 Cube<eT>::memptr() const
2229 {
2230 return mem;
2231 }
2232
2233
2234
2235 //! returns a pointer to array of eTs used by the specified slice in the cube
2236 template<typename eT>
2237 arma_inline
2238 arma_warn_unused
2239 eT*
2240 Cube<eT>::slice_memptr(const uword uslice)
2241 {
2242 return const_cast<eT*>( &mem[ uslice*n_elem_slice ] );
2243 }
2244
2245
2246
2247 //! returns a pointer to array of eTs used by the specified slice in the cube
2248 template<typename eT>
2249 arma_inline
2250 arma_warn_unused
2251 const eT*
2252 Cube<eT>::slice_memptr(const uword uslice) const
2253 {
2254 return &mem[ uslice*n_elem_slice ];
2255 }
2256
2257
2258
2259 //! returns a pointer to array of eTs used by the specified slice in the cube
2260 template<typename eT>
2261 arma_inline
2262 arma_warn_unused
2263 eT*
2264 Cube<eT>::slice_colptr(const uword uslice, const uword col)
2265 {
2266 return const_cast<eT*>( &mem[ uslice*n_elem_slice + col*n_rows] );
2267 }
2268
2269
2270
2271 //! returns a pointer to array of eTs used by the specified slice in the cube
2272 template<typename eT>
2273 arma_inline
2274 arma_warn_unused
2275 const eT*
2276 Cube<eT>::slice_colptr(const uword uslice, const uword col) const
2277 {
2278 return &mem[ uslice*n_elem_slice + col*n_rows ];
2279 }
2280
2281
2282
2283 //! print contents of the cube (to the cout stream),
2284 //! optionally preceding with a user specified line of text.
2285 //! the precision and cell width are modified.
2286 //! on return, the stream's state are restored to their original values.
2287 template<typename eT>
2288 inline
2289 void
2290 Cube<eT>::impl_print(const std::string& extra_text) const
2291 {
2292 arma_extra_debug_sigprint();
2293
2294 if(extra_text.length() != 0)
2295 {
2296 ARMA_DEFAULT_OSTREAM << extra_text << '\n';
2297 }
2298
2299 arma_ostream::print(ARMA_DEFAULT_OSTREAM, *this, true);
2300 }
2301
2302
2303 //! print contents of the cube to a user specified stream,
2304 //! optionally preceding with a user specified line of text.
2305 //! the precision and cell width are modified.
2306 //! on return, the stream's state are restored to their original values.
2307 template<typename eT>
2308 inline
2309 void
2310 Cube<eT>::impl_print(std::ostream& user_stream, const std::string& extra_text) const
2311 {
2312 arma_extra_debug_sigprint();
2313
2314 if(extra_text.length() != 0)
2315 {
2316 user_stream << extra_text << '\n';
2317 }
2318
2319 arma_ostream::print(user_stream, *this, true);
2320 }
2321
2322
2323
2324 //! print contents of the cube (to the cout stream),
2325 //! optionally preceding with a user specified line of text.
2326 //! the stream's state are used as is and are not modified
2327 //! (i.e. the precision and cell width are not modified).
2328 template<typename eT>
2329 inline
2330 void
2331 Cube<eT>::impl_raw_print(const std::string& extra_text) const
2332 {
2333 arma_extra_debug_sigprint();
2334
2335 if(extra_text.length() != 0)
2336 {
2337 ARMA_DEFAULT_OSTREAM << extra_text << '\n';
2338 }
2339
2340 arma_ostream::print(ARMA_DEFAULT_OSTREAM, *this, false);
2341 }
2342
2343
2344
2345 //! print contents of the cube to a user specified stream,
2346 //! optionally preceding with a user specified line of text.
2347 //! the stream's state are used as is and are not modified.
2348 //! (i.e. the precision and cell width are not modified).
2349 template<typename eT>
2350 inline
2351 void
2352 Cube<eT>::impl_raw_print(std::ostream& user_stream, const std::string& extra_text) const
2353 {
2354 arma_extra_debug_sigprint();
2355
2356 if(extra_text.length() != 0)
2357 {
2358 user_stream << extra_text << '\n';
2359 }
2360
2361 arma_ostream::print(user_stream, *this, false);
2362 }
2363
2364
2365
2366 //! change the cube to have user specified dimensions (data is not preserved)
2367 template<typename eT>
2368 inline
2369 void
2370 Cube<eT>::set_size(const uword in_n_rows, const uword in_n_cols, const uword in_n_slices)
2371 {
2372 arma_extra_debug_sigprint();
2373
2374 init_warm(in_n_rows, in_n_cols, in_n_slices);
2375 }
2376
2377
2378
2379 //! change the cube to have user specified dimensions (data is preserved)
2380 template<typename eT>
2381 inline
2382 void
2383 Cube<eT>::reshape(const uword in_rows, const uword in_cols, const uword in_slices, const uword dim)
2384 {
2385 arma_extra_debug_sigprint();
2386
2387 *this = arma::reshape(*this, in_rows, in_cols, in_slices, dim);
2388 }
2389
2390
2391
2392 //! change the cube to have user specified dimensions (data is preserved)
2393 template<typename eT>
2394 inline
2395 void
2396 Cube<eT>::resize(const uword in_rows, const uword in_cols, const uword in_slices)
2397 {
2398 arma_extra_debug_sigprint();
2399
2400 *this = arma::resize(*this, in_rows, in_cols, in_slices);
2401 }
2402
2403
2404
2405 //! change the cube (without preserving data) to have the same dimensions as the given cube
2406 template<typename eT>
2407 template<typename eT2>
2408 inline
2409 void
2410 Cube<eT>::copy_size(const Cube<eT2>& m)
2411 {
2412 arma_extra_debug_sigprint();
2413
2414 init_warm(m.n_rows, m.n_cols, m.n_slices);
2415 }
2416
2417
2418
2419 //! transform each element in the cube using a functor
2420 template<typename eT>
2421 template<typename functor>
2422 inline
2423 const Cube<eT>&
2424 Cube<eT>::transform(functor F)
2425 {
2426 arma_extra_debug_sigprint();
2427
2428 eT* out_mem = memptr();
2429
2430 const uword N = n_elem;
2431
2432 uword ii, jj;
2433
2434 for(ii=0, jj=1; jj < N; ii+=2, jj+=2)
2435 {
2436 eT tmp_ii = out_mem[ii];
2437 eT tmp_jj = out_mem[jj];
2438
2439 tmp_ii = eT( F(tmp_ii) );
2440 tmp_jj = eT( F(tmp_jj) );
2441
2442 out_mem[ii] = tmp_ii;
2443 out_mem[jj] = tmp_jj;
2444 }
2445
2446 if(ii < N)
2447 {
2448 out_mem[ii] = eT( F(out_mem[ii]) );
2449 }
2450
2451 return *this;
2452 }
2453
2454
2455
2456 //! imbue (fill) the cube with values provided by a functor
2457 template<typename eT>
2458 template<typename functor>
2459 inline
2460 const Cube<eT>&
2461 Cube<eT>::imbue(functor F)
2462 {
2463 arma_extra_debug_sigprint();
2464
2465 eT* out_mem = memptr();
2466
2467 const uword N = n_elem;
2468
2469 uword ii, jj;
2470
2471 for(ii=0, jj=1; jj < N; ii+=2, jj+=2)
2472 {
2473 const eT tmp_ii = eT( F() );
2474 const eT tmp_jj = eT( F() );
2475
2476 out_mem[ii] = tmp_ii;
2477 out_mem[jj] = tmp_jj;
2478 }
2479
2480 if(ii < N)
2481 {
2482 out_mem[ii] = eT( F() );
2483 }
2484
2485 return *this;
2486 }
2487
2488
2489
2490 //! fill the cube with the specified value
2491 template<typename eT>
2492 inline
2493 const Cube<eT>&
2494 Cube<eT>::fill(const eT val)
2495 {
2496 arma_extra_debug_sigprint();
2497
2498 arrayops::inplace_set( memptr(), val, n_elem );
2499
2500 return *this;
2501 }
2502
2503
2504
2505 template<typename eT>
2506 inline
2507 const Cube<eT>&
2508 Cube<eT>::zeros()
2509 {
2510 arma_extra_debug_sigprint();
2511
2512 return (*this).fill(eT(0));
2513 }
2514
2515
2516
2517 template<typename eT>
2518 inline
2519 const Cube<eT>&
2520 Cube<eT>::zeros(const uword in_rows, const uword in_cols, const uword in_slices)
2521 {
2522 arma_extra_debug_sigprint();
2523
2524 set_size(in_rows, in_cols, in_slices);
2525
2526 return (*this).fill(eT(0));
2527 }
2528
2529
2530
2531 template<typename eT>
2532 inline
2533 const Cube<eT>&
2534 Cube<eT>::ones()
2535 {
2536 arma_extra_debug_sigprint();
2537
2538 return (*this).fill(eT(1));
2539 }
2540
2541
2542
2543 template<typename eT>
2544 inline
2545 const Cube<eT>&
2546 Cube<eT>::ones(const uword in_rows, const uword in_cols, const uword in_slices)
2547 {
2548 arma_extra_debug_sigprint();
2549
2550 set_size(in_rows, in_cols, in_slices);
2551
2552 return (*this).fill(eT(1));
2553 }
2554
2555
2556
2557 template<typename eT>
2558 inline
2559 const Cube<eT>&
2560 Cube<eT>::randu()
2561 {
2562 arma_extra_debug_sigprint();
2563
2564 eop_aux_randu<eT>::fill( memptr(), n_elem );
2565
2566 return *this;
2567 }
2568
2569
2570
2571 template<typename eT>
2572 inline
2573 const Cube<eT>&
2574 Cube<eT>::randu(const uword in_rows, const uword in_cols, const uword in_slices)
2575 {
2576 arma_extra_debug_sigprint();
2577
2578 set_size(in_rows, in_cols, in_slices);
2579
2580 return (*this).randu();
2581 }
2582
2583
2584
2585 template<typename eT>
2586 inline
2587 const Cube<eT>&
2588 Cube<eT>::randn()
2589 {
2590 arma_extra_debug_sigprint();
2591
2592 eop_aux_randn<eT>::fill( memptr(), n_elem );
2593
2594 return *this;
2595 }
2596
2597
2598
2599 template<typename eT>
2600 inline
2601 const Cube<eT>&
2602 Cube<eT>::randn(const uword in_rows, const uword in_cols, const uword in_slices)
2603 {
2604 arma_extra_debug_sigprint();
2605
2606 set_size(in_rows, in_cols, in_slices);
2607
2608 return (*this).randn();
2609 }
2610
2611
2612
2613 template<typename eT>
2614 inline
2615 void
2616 Cube<eT>::reset()
2617 {
2618 arma_extra_debug_sigprint();
2619
2620 init_warm(0,0,0);
2621 }
2622
2623
2624
2625 template<typename eT>
2626 template<typename T1>
2627 inline
2628 void
2629 Cube<eT>::set_real(const BaseCube<typename Cube<eT>::pod_type,T1>& X)
2630 {
2631 arma_extra_debug_sigprint();
2632
2633 Cube_aux::set_real(*this, X);
2634 }
2635
2636
2637
2638 template<typename eT>
2639 template<typename T1>
2640 inline
2641 void
2642 Cube<eT>::set_imag(const BaseCube<typename Cube<eT>::pod_type,T1>& X)
2643 {
2644 arma_extra_debug_sigprint();
2645
2646 Cube_aux::set_imag(*this, X);
2647 }
2648
2649
2650
2651 template<typename eT>
2652 inline
2653 arma_warn_unused
2654 eT
2655 Cube<eT>::min() const
2656 {
2657 arma_extra_debug_sigprint();
2658
2659 arma_debug_check( (n_elem == 0), "min(): object has no elements" );
2660
2661 return op_min::direct_min(memptr(), n_elem);
2662 }
2663
2664
2665
2666 template<typename eT>
2667 inline
2668 arma_warn_unused
2669 eT
2670 Cube<eT>::max() const
2671 {
2672 arma_extra_debug_sigprint();
2673
2674 arma_debug_check( (n_elem == 0), "max(): object has no elements" );
2675
2676 return op_max::direct_max(memptr(), n_elem);
2677 }
2678
2679
2680
2681 template<typename eT>
2682 inline
2683 eT
2684 Cube<eT>::min(uword& index_of_min_val) const
2685 {
2686 arma_extra_debug_sigprint();
2687
2688 arma_debug_check( (n_elem == 0), "min(): object has no elements" );
2689
2690 return op_min::direct_min(memptr(), n_elem, index_of_min_val);
2691 }
2692
2693
2694
2695 template<typename eT>
2696 inline
2697 eT
2698 Cube<eT>::max(uword& index_of_max_val) const
2699 {
2700 arma_extra_debug_sigprint();
2701
2702 arma_debug_check( (n_elem == 0), "max(): object has no elements" );
2703
2704 return op_max::direct_max(memptr(), n_elem, index_of_max_val);
2705 }
2706
2707
2708
2709 template<typename eT>
2710 inline
2711 eT
2712 Cube<eT>::min(uword& row_of_min_val, uword& col_of_min_val, uword& slice_of_min_val) const
2713 {
2714 arma_extra_debug_sigprint();
2715
2716 arma_debug_check( (n_elem == 0), "min(): object has no elements" );
2717
2718 uword i;
2719
2720 eT val = op_min::direct_min(memptr(), n_elem, i);
2721
2722 const uword in_slice = i / n_elem_slice;
2723 const uword offset = in_slice * n_elem_slice;
2724 const uword j = i - offset;
2725
2726 row_of_min_val = j % n_rows;
2727 col_of_min_val = j / n_rows;
2728 slice_of_min_val = in_slice;
2729
2730 return val;
2731 }
2732
2733
2734
2735 template<typename eT>
2736 inline
2737 eT
2738 Cube<eT>::max(uword& row_of_max_val, uword& col_of_max_val, uword& slice_of_max_val) const
2739 {
2740 arma_extra_debug_sigprint();
2741
2742 arma_debug_check( (n_elem == 0), "max(): object has no elements" );
2743
2744 uword i;
2745
2746 eT val = op_max::direct_max(memptr(), n_elem, i);
2747
2748 const uword in_slice = i / n_elem_slice;
2749 const uword offset = in_slice * n_elem_slice;
2750 const uword j = i - offset;
2751
2752 row_of_max_val = j % n_rows;
2753 col_of_max_val = j / n_rows;
2754 slice_of_max_val = in_slice;
2755
2756 return val;
2757 }
2758
2759
2760
2761 //! save the cube to a file
2762 template<typename eT>
2763 inline
2764 bool
2765 Cube<eT>::save(const std::string name, const file_type type, const bool print_status) const
2766 {
2767 arma_extra_debug_sigprint();
2768
2769 bool save_okay;
2770
2771 switch(type)
2772 {
2773 case raw_ascii:
2774 save_okay = diskio::save_raw_ascii(*this, name);
2775 break;
2776
2777 case arma_ascii:
2778 save_okay = diskio::save_arma_ascii(*this, name);
2779 break;
2780
2781 case raw_binary:
2782 save_okay = diskio::save_raw_binary(*this, name);
2783 break;
2784
2785 case arma_binary:
2786 save_okay = diskio::save_arma_binary(*this, name);
2787 break;
2788
2789 case ppm_binary:
2790 save_okay = diskio::save_ppm_binary(*this, name);
2791 break;
2792
2793 case hdf5_binary:
2794 save_okay = diskio::save_hdf5_binary(*this, name);
2795 break;
2796
2797 default:
2798 arma_warn(print_status, "Cube::save(): unsupported file type");
2799 save_okay = false;
2800 }
2801
2802 arma_warn( (print_status && (save_okay == false)), "Cube::save(): couldn't write to ", name);
2803
2804 return save_okay;
2805 }
2806
2807
2808
2809 //! save the cube to a stream
2810 template<typename eT>
2811 inline
2812 bool
2813 Cube<eT>::save(std::ostream& os, const file_type type, const bool print_status) const
2814 {
2815 arma_extra_debug_sigprint();
2816
2817 bool save_okay;
2818
2819 switch(type)
2820 {
2821 case raw_ascii:
2822 save_okay = diskio::save_raw_ascii(*this, os);
2823 break;
2824
2825 case arma_ascii:
2826 save_okay = diskio::save_arma_ascii(*this, os);
2827 break;
2828
2829 case raw_binary:
2830 save_okay = diskio::save_raw_binary(*this, os);
2831 break;
2832
2833 case arma_binary:
2834 save_okay = diskio::save_arma_binary(*this, os);
2835 break;
2836
2837 case ppm_binary:
2838 save_okay = diskio::save_ppm_binary(*this, os);
2839 break;
2840
2841 default:
2842 arma_warn(print_status, "Cube::save(): unsupported file type");
2843 save_okay = false;
2844 }
2845
2846 arma_warn( (print_status && (save_okay == false)), "Cube::save(): couldn't write to given stream");
2847
2848 return save_okay;
2849 }
2850
2851
2852
2853 //! load a cube from a file
2854 template<typename eT>
2855 inline
2856 bool
2857 Cube<eT>::load(const std::string name, const file_type type, const bool print_status)
2858 {
2859 arma_extra_debug_sigprint();
2860
2861 bool load_okay;
2862 std::string err_msg;
2863
2864 switch(type)
2865 {
2866 case auto_detect:
2867 load_okay = diskio::load_auto_detect(*this, name, err_msg);
2868 break;
2869
2870 case raw_ascii:
2871 load_okay = diskio::load_raw_ascii(*this, name, err_msg);
2872 break;
2873
2874 case arma_ascii:
2875 load_okay = diskio::load_arma_ascii(*this, name, err_msg);
2876 break;
2877
2878 case raw_binary:
2879 load_okay = diskio::load_raw_binary(*this, name, err_msg);
2880 break;
2881
2882 case arma_binary:
2883 load_okay = diskio::load_arma_binary(*this, name, err_msg);
2884 break;
2885
2886 case ppm_binary:
2887 load_okay = diskio::load_ppm_binary(*this, name, err_msg);
2888 break;
2889
2890 case hdf5_binary:
2891 load_okay = diskio::load_hdf5_binary(*this, name, err_msg);
2892 break;
2893
2894 default:
2895 arma_warn(print_status, "Cube::load(): unsupported file type");
2896 load_okay = false;
2897 }
2898
2899 if( (print_status == true) && (load_okay == false) )
2900 {
2901 if(err_msg.length() > 0)
2902 {
2903 arma_warn(true, "Cube::load(): ", err_msg, name);
2904 }
2905 else
2906 {
2907 arma_warn(true, "Cube::load(): couldn't read ", name);
2908 }
2909 }
2910
2911 if(load_okay == false)
2912 {
2913 (*this).reset();
2914 }
2915
2916 return load_okay;
2917 }
2918
2919
2920
2921 //! load a cube from a stream
2922 template<typename eT>
2923 inline
2924 bool
2925 Cube<eT>::load(std::istream& is, const file_type type, const bool print_status)
2926 {
2927 arma_extra_debug_sigprint();
2928
2929 bool load_okay;
2930 std::string err_msg;
2931
2932 switch(type)
2933 {
2934 case auto_detect:
2935 load_okay = diskio::load_auto_detect(*this, is, err_msg);
2936 break;
2937
2938 case raw_ascii:
2939 load_okay = diskio::load_raw_ascii(*this, is, err_msg);
2940 break;
2941
2942 case arma_ascii:
2943 load_okay = diskio::load_arma_ascii(*this, is, err_msg);
2944 break;
2945
2946 case raw_binary:
2947 load_okay = diskio::load_raw_binary(*this, is, err_msg);
2948 break;
2949
2950 case arma_binary:
2951 load_okay = diskio::load_arma_binary(*this, is, err_msg);
2952 break;
2953
2954 case ppm_binary:
2955 load_okay = diskio::load_ppm_binary(*this, is, err_msg);
2956 break;
2957
2958 default:
2959 arma_warn(print_status, "Cube::load(): unsupported file type");
2960 load_okay = false;
2961 }
2962
2963
2964 if( (print_status == true) && (load_okay == false) )
2965 {
2966 if(err_msg.length() > 0)
2967 {
2968 arma_warn(true, "Cube::load(): ", err_msg, "the given stream");
2969 }
2970 else
2971 {
2972 arma_warn(true, "Cube::load(): couldn't load from the given stream");
2973 }
2974 }
2975
2976 if(load_okay == false)
2977 {
2978 (*this).reset();
2979 }
2980
2981 return load_okay;
2982 }
2983
2984
2985
2986 //! save the cube to a file, without printing any error messages
2987 template<typename eT>
2988 inline
2989 bool
2990 Cube<eT>::quiet_save(const std::string name, const file_type type) const
2991 {
2992 arma_extra_debug_sigprint();
2993
2994 return (*this).save(name, type, false);
2995 }
2996
2997
2998
2999 //! save the cube to a stream, without printing any error messages
3000 template<typename eT>
3001 inline
3002 bool
3003 Cube<eT>::quiet_save(std::ostream& os, const file_type type) const
3004 {
3005 arma_extra_debug_sigprint();
3006
3007 return (*this).save(os, type, false);
3008 }
3009
3010
3011
3012 //! load a cube from a file, without printing any error messages
3013 template<typename eT>
3014 inline
3015 bool
3016 Cube<eT>::quiet_load(const std::string name, const file_type type)
3017 {
3018 arma_extra_debug_sigprint();
3019
3020 return (*this).load(name, type, false);
3021 }
3022
3023
3024
3025 //! load a cube from a stream, without printing any error messages
3026 template<typename eT>
3027 inline
3028 bool
3029 Cube<eT>::quiet_load(std::istream& is, const file_type type)
3030 {
3031 arma_extra_debug_sigprint();
3032
3033 return (*this).load(is, type, false);
3034 }
3035
3036
3037
3038 template<typename eT>
3039 inline
3040 typename Cube<eT>::iterator
3041 Cube<eT>::begin()
3042 {
3043 arma_extra_debug_sigprint();
3044
3045 return memptr();
3046 }
3047
3048
3049
3050 template<typename eT>
3051 inline
3052 typename Cube<eT>::const_iterator
3053 Cube<eT>::begin() const
3054 {
3055 arma_extra_debug_sigprint();
3056
3057 return memptr();
3058 }
3059
3060
3061
3062 template<typename eT>
3063 inline
3064 typename Cube<eT>::const_iterator
3065 Cube<eT>::cbegin() const
3066 {
3067 arma_extra_debug_sigprint();
3068
3069 return memptr();
3070 }
3071
3072
3073
3074 template<typename eT>
3075 inline
3076 typename Cube<eT>::iterator
3077 Cube<eT>::end()
3078 {
3079 arma_extra_debug_sigprint();
3080
3081 return memptr() + n_elem;
3082 }
3083
3084
3085
3086 template<typename eT>
3087 inline
3088 typename Cube<eT>::const_iterator
3089 Cube<eT>::end() const
3090 {
3091 arma_extra_debug_sigprint();
3092
3093 return memptr() + n_elem;
3094 }
3095
3096
3097
3098 template<typename eT>
3099 inline
3100 typename Cube<eT>::const_iterator
3101 Cube<eT>::cend() const
3102 {
3103 arma_extra_debug_sigprint();
3104
3105 return memptr() + n_elem;
3106 }
3107
3108
3109
3110 template<typename eT>
3111 inline
3112 typename Cube<eT>::slice_iterator
3113 Cube<eT>::begin_slice(const uword slice_num)
3114 {
3115 arma_extra_debug_sigprint();
3116
3117 arma_debug_check( (slice_num >= n_slices), "begin_slice(): index out of bounds");
3118
3119 return slice_memptr(slice_num);
3120 }
3121
3122
3123
3124 template<typename eT>
3125 inline
3126 typename Cube<eT>::const_slice_iterator
3127 Cube<eT>::begin_slice(const uword slice_num) const
3128 {
3129 arma_extra_debug_sigprint();
3130
3131 arma_debug_check( (slice_num >= n_slices), "begin_slice(): index out of bounds");
3132
3133 return slice_memptr(slice_num);
3134 }
3135
3136
3137
3138 template<typename eT>
3139 inline
3140 typename Cube<eT>::slice_iterator
3141 Cube<eT>::end_slice(const uword slice_num)
3142 {
3143 arma_extra_debug_sigprint();
3144
3145 arma_debug_check( (slice_num >= n_slices), "end_slice(): index out of bounds");
3146
3147 return slice_memptr(slice_num) + n_elem_slice;
3148 }
3149
3150
3151
3152 template<typename eT>
3153 inline
3154 typename Cube<eT>::const_slice_iterator
3155 Cube<eT>::end_slice(const uword slice_num) const
3156 {
3157 arma_extra_debug_sigprint();
3158
3159 arma_debug_check( (slice_num >= n_slices), "end_slice(): index out of bounds");
3160
3161 return slice_memptr(slice_num) + n_elem_slice;
3162 }
3163
3164
3165
3166 //! resets this cube to an empty matrix
3167 template<typename eT>
3168 inline
3169 void
3170 Cube<eT>::clear()
3171 {
3172 reset();
3173 }
3174
3175
3176
3177 //! returns true if the cube has no elements
3178 template<typename eT>
3179 inline
3180 bool
3181 Cube<eT>::empty() const
3182 {
3183 return (n_elem == 0);
3184 }
3185
3186
3187
3188 //! returns the number of elements in this cube
3189 template<typename eT>
3190 inline
3191 uword
3192 Cube<eT>::size() const
3193 {
3194 return n_elem;
3195 }
3196
3197
3198
3199 // template<typename eT>
3200 // inline
3201 // void
3202 // Cube<eT>::swap(Cube<eT>& B)
3203 // {
3204 // // TODO
3205 // }
3206
3207
3208
3209 //! try to steal the memory from a given cube;
3210 //! if memory can't be stolen, copy the given cube
3211 template<typename eT>
3212 inline
3213 void
3214 Cube<eT>::steal_mem(Cube<eT>& x)
3215 {
3216 arma_extra_debug_sigprint();
3217
3218 if(this != &x)
3219 {
3220 if( (x.mem_state == 0) && (x.n_elem > Cube_prealloc::mem_n_elem) )
3221 {
3222 reset();
3223
3224 const uword x_n_slices = x.n_slices;
3225
3226 access::rw(n_rows) = x.n_rows;
3227 access::rw(n_cols) = x.n_cols;
3228 access::rw(n_elem_slice) = x.n_elem_slice;
3229 access::rw(n_slices) = x_n_slices;
3230 access::rw(n_elem) = x.n_elem;
3231 access::rw(mem) = x.mem;
3232
3233 if(x_n_slices > Cube_prealloc::mat_ptrs_size)
3234 {
3235 access::rw( mat_ptrs) = x.mat_ptrs;
3236 access::rw(x.mat_ptrs) = 0;
3237 }
3238 else
3239 {
3240 access::rw(mat_ptrs) = const_cast< const Mat<eT>** >(mat_ptrs_local);
3241
3242 for(uword i=0; i < x_n_slices; ++i)
3243 {
3244 mat_ptrs[i] = x.mat_ptrs[i];
3245 x.mat_ptrs[i] = 0;
3246 }
3247 }
3248
3249 access::rw(x.n_rows) = 0;
3250 access::rw(x.n_cols) = 0;
3251 access::rw(x.n_elem_slice) = 0;
3252 access::rw(x.n_slices) = 0;
3253 access::rw(x.n_elem) = 0;
3254 access::rw(x.mem) = 0;
3255 }
3256 else
3257 {
3258 (*this).operator=(x);
3259 }
3260 }
3261 }
3262
3263
3264
3265 template<typename eT>
3266 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3267 arma_inline
3268 void
3269 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::mem_setup()
3270 {
3271 arma_extra_debug_sigprint_this(this);
3272
3273 if(fixed_n_elem > 0)
3274 {
3275 access::rw(Cube<eT>::n_rows) = fixed_n_rows;
3276 access::rw(Cube<eT>::n_cols) = fixed_n_cols;
3277 access::rw(Cube<eT>::n_elem_slice) = fixed_n_rows * fixed_n_cols;
3278 access::rw(Cube<eT>::n_slices) = fixed_n_slices;
3279 access::rw(Cube<eT>::n_elem) = fixed_n_elem;
3280 access::rw(Cube<eT>::mem_state) = 3;
3281 access::rw(Cube<eT>::mat_ptrs) = const_cast< const Mat<eT>** >( \
3282 (fixed_n_slices > Cube_prealloc::mat_ptrs_size) ? mat_ptrs_local_extra : mat_ptrs_local );
3283 access::rw(Cube<eT>::mem) = (fixed_n_elem > Cube_prealloc::mem_n_elem) ? mem_local_extra : mem_local;
3284
3285 create_mat();
3286 }
3287 else
3288 {
3289 access::rw(Cube<eT>::n_rows) = 0;
3290 access::rw(Cube<eT>::n_cols) = 0;
3291 access::rw(Cube<eT>::n_elem_slice) = 0;
3292 access::rw(Cube<eT>::n_slices) = 0;
3293 access::rw(Cube<eT>::n_elem) = 0;
3294 access::rw(Cube<eT>::mem_state) = 3;
3295 access::rw(Cube<eT>::mat_ptrs) = 0;
3296 access::rw(Cube<eT>::mem) = 0;
3297 }
3298 }
3299
3300
3301
3302 template<typename eT>
3303 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3304 arma_inline
3305 arma_warn_unused
3306 eT&
3307 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::operator[] (const uword i)
3308 {
3309 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3310 }
3311
3312
3313
3314 template<typename eT>
3315 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3316 arma_inline
3317 arma_warn_unused
3318 const eT&
3319 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::operator[] (const uword i) const
3320 {
3321 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3322 }
3323
3324
3325
3326 template<typename eT>
3327 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3328 arma_inline
3329 arma_warn_unused
3330 eT&
3331 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::at(const uword i)
3332 {
3333 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3334 }
3335
3336
3337
3338 template<typename eT>
3339 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3340 arma_inline
3341 arma_warn_unused
3342 const eT&
3343 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::at(const uword i) const
3344 {
3345 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3346 }
3347
3348
3349
3350 template<typename eT>
3351 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3352 arma_inline
3353 arma_warn_unused
3354 eT&
3355 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::operator() (const uword i)
3356 {
3357 arma_debug_check( (i >= fixed_n_elem), "Cube::operator(): index out of bounds");
3358
3359 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3360 }
3361
3362
3363
3364 template<typename eT>
3365 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3366 arma_inline
3367 arma_warn_unused
3368 const eT&
3369 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::operator() (const uword i) const
3370 {
3371 arma_debug_check( (i >= fixed_n_elem), "Cube::operator(): index out of bounds");
3372
3373 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3374 }
3375
3376
3377
3378 template<typename eT>
3379 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3380 arma_inline
3381 arma_warn_unused
3382 eT&
3383 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::at(const uword in_row, const uword in_col, const uword in_slice)
3384 {
3385 const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row;
3386
3387 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3388 }
3389
3390
3391
3392 template<typename eT>
3393 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3394 arma_inline
3395 arma_warn_unused
3396 const eT&
3397 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::at(const uword in_row, const uword in_col, const uword in_slice) const
3398 {
3399 const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row;
3400
3401 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3402 }
3403
3404
3405
3406 template<typename eT>
3407 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3408 arma_inline
3409 arma_warn_unused
3410 eT&
3411 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::operator() (const uword in_row, const uword in_col, const uword in_slice)
3412 {
3413 arma_debug_check
3414 (
3415 (in_row >= fixed_n_rows ) ||
3416 (in_col >= fixed_n_cols ) ||
3417 (in_slice >= fixed_n_slices)
3418 ,
3419 "operator(): index out of bounds"
3420 );
3421
3422 const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row;
3423
3424 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3425 }
3426
3427
3428
3429 template<typename eT>
3430 template<uword fixed_n_rows, uword fixed_n_cols, uword fixed_n_slices>
3431 arma_inline
3432 arma_warn_unused
3433 const eT&
3434 Cube<eT>::fixed<fixed_n_rows, fixed_n_cols, fixed_n_slices>::operator() (const uword in_row, const uword in_col, const uword in_slice) const
3435 {
3436 arma_debug_check
3437 (
3438 (in_row >= fixed_n_rows ) ||
3439 (in_col >= fixed_n_cols ) ||
3440 (in_slice >= fixed_n_slices)
3441 ,
3442 "Cube::operator(): index out of bounds"
3443 );
3444
3445 const uword i = in_slice*fixed_n_elem_slice + in_col*fixed_n_rows + in_row;
3446
3447 return (use_extra) ? mem_local_extra[i] : mem_local[i];
3448 }
3449
3450
3451
3452 //! prefix ++
3453 template<typename eT>
3454 arma_inline
3455 void
3456 Cube_aux::prefix_pp(Cube<eT>& x)
3457 {
3458 eT* memptr = x.memptr();
3459 const uword n_elem = x.n_elem;
3460
3461 uword i,j;
3462
3463 for(i=0, j=1; j<n_elem; i+=2, j+=2)
3464 {
3465 ++(memptr[i]);
3466 ++(memptr[j]);
3467 }
3468
3469 if(i < n_elem)
3470 {
3471 ++(memptr[i]);
3472 }
3473 }
3474
3475
3476
3477 //! prefix ++ for complex numbers (work around for limitations of the std::complex class)
3478 template<typename T>
3479 arma_inline
3480 void
3481 Cube_aux::prefix_pp(Cube< std::complex<T> >& x)
3482 {
3483 x += T(1);
3484 }
3485
3486
3487
3488 //! postfix ++
3489 template<typename eT>
3490 arma_inline
3491 void
3492 Cube_aux::postfix_pp(Cube<eT>& x)
3493 {
3494 eT* memptr = x.memptr();
3495 const uword n_elem = x.n_elem;
3496
3497 uword i,j;
3498
3499 for(i=0, j=1; j<n_elem; i+=2, j+=2)
3500 {
3501 (memptr[i])++;
3502 (memptr[j])++;
3503 }
3504
3505 if(i < n_elem)
3506 {
3507 (memptr[i])++;
3508 }
3509 }
3510
3511
3512
3513 //! postfix ++ for complex numbers (work around for limitations of the std::complex class)
3514 template<typename T>
3515 arma_inline
3516 void
3517 Cube_aux::postfix_pp(Cube< std::complex<T> >& x)
3518 {
3519 x += T(1);
3520 }
3521
3522
3523
3524 //! prefix --
3525 template<typename eT>
3526 arma_inline
3527 void
3528 Cube_aux::prefix_mm(Cube<eT>& x)
3529 {
3530 eT* memptr = x.memptr();
3531 const uword n_elem = x.n_elem;
3532
3533 uword i,j;
3534
3535 for(i=0, j=1; j<n_elem; i+=2, j+=2)
3536 {
3537 --(memptr[i]);
3538 --(memptr[j]);
3539 }
3540
3541 if(i < n_elem)
3542 {
3543 --(memptr[i]);
3544 }
3545 }
3546
3547
3548
3549 //! prefix -- for complex numbers (work around for limitations of the std::complex class)
3550 template<typename T>
3551 arma_inline
3552 void
3553 Cube_aux::prefix_mm(Cube< std::complex<T> >& x)
3554 {
3555 x -= T(1);
3556 }
3557
3558
3559
3560 //! postfix --
3561 template<typename eT>
3562 arma_inline
3563 void
3564 Cube_aux::postfix_mm(Cube<eT>& x)
3565 {
3566 eT* memptr = x.memptr();
3567 const uword n_elem = x.n_elem;
3568
3569 uword i,j;
3570
3571 for(i=0, j=1; j<n_elem; i+=2, j+=2)
3572 {
3573 (memptr[i])--;
3574 (memptr[j])--;
3575 }
3576
3577 if(i < n_elem)
3578 {
3579 (memptr[i])--;
3580 }
3581 }
3582
3583
3584
3585 //! postfix ++ for complex numbers (work around for limitations of the std::complex class)
3586 template<typename T>
3587 arma_inline
3588 void
3589 Cube_aux::postfix_mm(Cube< std::complex<T> >& x)
3590 {
3591 x -= T(1);
3592 }
3593
3594
3595
3596 template<typename eT, typename T1>
3597 inline
3598 void
3599 Cube_aux::set_real(Cube<eT>& out, const BaseCube<eT,T1>& X)
3600 {
3601 arma_extra_debug_sigprint();
3602
3603 const unwrap_cube<T1> tmp(X.get_ref());
3604 const Cube<eT>& A = tmp.M;
3605
3606 arma_debug_assert_same_size( out, A, "Cube::set_real()" );
3607
3608 out = A;
3609 }
3610
3611
3612
3613 template<typename eT, typename T1>
3614 inline
3615 void
3616 Cube_aux::set_imag(Cube<eT>&, const BaseCube<eT,T1>&)
3617 {
3618 arma_extra_debug_sigprint();
3619 }
3620
3621
3622
3623 template<typename T, typename T1>
3624 inline
3625 void
3626 Cube_aux::set_real(Cube< std::complex<T> >& out, const BaseCube<T,T1>& X)
3627 {
3628 arma_extra_debug_sigprint();
3629
3630 typedef typename std::complex<T> eT;
3631
3632 const ProxyCube<T1> P(X.get_ref());
3633
3634 const uword local_n_rows = P.get_n_rows();
3635 const uword local_n_cols = P.get_n_cols();
3636 const uword local_n_slices = P.get_n_slices();
3637
3638 arma_debug_assert_same_size
3639 (
3640 out.n_rows, out.n_cols, out.n_slices,
3641 local_n_rows, local_n_cols, local_n_slices,
3642 "Cube::set_real()"
3643 );
3644
3645 eT* out_mem = out.memptr();
3646
3647 if(ProxyCube<T1>::prefer_at_accessor == false)
3648 {
3649 typedef typename ProxyCube<T1>::ea_type ea_type;
3650
3651 ea_type A = P.get_ea();
3652
3653 const uword N = out.n_elem;
3654
3655 for(uword i=0; i<N; ++i)
3656 {
3657 //out_mem[i].real() = PA[i];
3658 out_mem[i] = std::complex<T>( A[i], out_mem[i].imag() );
3659 }
3660 }
3661 else
3662 {
3663 for(uword slice = 0; slice < local_n_slices; ++slice)
3664 for(uword col = 0; col < local_n_cols; ++col )
3665 for(uword row = 0; row < local_n_rows; ++row )
3666 {
3667 (*out_mem) = std::complex<T>( P.at(row,col,slice), (*out_mem).imag() );
3668 out_mem++;
3669 }
3670 }
3671 }
3672
3673
3674
3675 template<typename T, typename T1>
3676 inline
3677 void
3678 Cube_aux::set_imag(Cube< std::complex<T> >& out, const BaseCube<T,T1>& X)
3679 {
3680 arma_extra_debug_sigprint();
3681
3682 typedef typename std::complex<T> eT;
3683
3684 const ProxyCube<T1> P(X.get_ref());
3685
3686 const uword local_n_rows = P.get_n_rows();
3687 const uword local_n_cols = P.get_n_cols();
3688 const uword local_n_slices = P.get_n_slices();
3689
3690 arma_debug_assert_same_size
3691 (
3692 out.n_rows, out.n_cols, out.n_slices,
3693 local_n_rows, local_n_cols, local_n_slices,
3694 "Cube::set_imag()"
3695 );
3696
3697 eT* out_mem = out.memptr();
3698
3699 if(ProxyCube<T1>::prefer_at_accessor == false)
3700 {
3701 typedef typename ProxyCube<T1>::ea_type ea_type;
3702
3703 ea_type A = P.get_ea();
3704
3705 const uword N = out.n_elem;
3706
3707 for(uword i=0; i<N; ++i)
3708 {
3709 //out_mem[i].imag() = PA[i];
3710 out_mem[i] = std::complex<T>( out_mem[i].real(), A[i] );
3711 }
3712 }
3713 else
3714 {
3715 for(uword slice = 0; slice < local_n_slices; ++slice)
3716 for(uword col = 0; col < local_n_cols; ++col )
3717 for(uword row = 0; row < local_n_rows; ++row )
3718 {
3719 (*out_mem) = std::complex<T>( (*out_mem).real(), P.at(row,col,slice) );
3720 out_mem++;
3721 }
3722 }
3723 }
3724
3725
3726
3727 #ifdef ARMA_EXTRA_CUBE_MEAT
3728 #include ARMA_INCFILE_WRAP(ARMA_EXTRA_CUBE_MEAT)
3729 #endif
3730
3731
3732
3733 //! @}