comparison armadillo-2.4.4/include/armadillo_bits/Cube_meat.hpp @ 0:8b6102e2a9b0

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