1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup subview_cube_each
20 //! @{
21 
22 
23 //
24 //
25 // subview_cube_each_common
26 
27 template<typename eT>
28 inline
subview_cube_each_common(const Cube<eT> & in_p)29 subview_cube_each_common<eT>::subview_cube_each_common(const Cube<eT>& in_p)
30   : P(in_p)
31   {
32   arma_extra_debug_sigprint();
33   }
34 
35 
36 
37 template<typename eT>
38 inline
39 void
check_size(const Mat<eT> & A) const40 subview_cube_each_common<eT>::check_size(const Mat<eT>& A) const
41   {
42   if(arma_config::debug)
43     {
44     if( (A.n_rows != P.n_rows) || (A.n_cols != P.n_cols) )
45       {
46       arma_stop_logic_error( incompat_size_string(A) );
47       }
48     }
49   }
50 
51 
52 
53 template<typename eT>
54 arma_cold
55 inline
56 const std::string
incompat_size_string(const Mat<eT> & A) const57 subview_cube_each_common<eT>::incompat_size_string(const Mat<eT>& A) const
58   {
59   std::ostringstream tmp;
60 
61   tmp << "each_slice(): incompatible size; expected " << P.n_rows << 'x' << P.n_cols << ", got " << A.n_rows << 'x' << A.n_cols;
62 
63   return tmp.str();
64   }
65 
66 
67 
68 //
69 //
70 // subview_cube_each1
71 
72 
73 
74 template<typename eT>
75 inline
~subview_cube_each1()76 subview_cube_each1<eT>::~subview_cube_each1()
77   {
78   arma_extra_debug_sigprint();
79   }
80 
81 
82 
83 template<typename eT>
84 inline
subview_cube_each1(const Cube<eT> & in_p)85 subview_cube_each1<eT>::subview_cube_each1(const Cube<eT>& in_p)
86   : subview_cube_each_common<eT>::subview_cube_each_common(in_p)
87   {
88   arma_extra_debug_sigprint();
89   }
90 
91 
92 
93 template<typename eT>
94 template<typename T1>
95 inline
96 void
operator =(const Base<eT,T1> & in)97 subview_cube_each1<eT>::operator= (const Base<eT,T1>& in)
98   {
99   arma_extra_debug_sigprint();
100 
101   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
102 
103   const unwrap<T1>   tmp( in.get_ref() );
104   const Mat<eT>& A = tmp.M;
105 
106   subview_cube_each_common<eT>::check_size(A);
107 
108   const uword p_n_slices     = p.n_slices;
109   const uword p_n_elem_slice = p.n_elem_slice;
110 
111   const eT* A_mem = A.memptr();
112 
113   for(uword i=0; i < p_n_slices; ++i)  { arrayops::copy( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
114   }
115 
116 
117 
118 template<typename eT>
119 template<typename T1>
120 inline
121 void
operator +=(const Base<eT,T1> & in)122 subview_cube_each1<eT>::operator+= (const Base<eT,T1>& in)
123   {
124   arma_extra_debug_sigprint();
125 
126   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
127 
128   const unwrap<T1>   tmp( in.get_ref() );
129   const Mat<eT>& A = tmp.M;
130 
131   subview_cube_each_common<eT>::check_size(A);
132 
133   const uword p_n_slices     = p.n_slices;
134   const uword p_n_elem_slice = p.n_elem_slice;
135 
136   const eT* A_mem = A.memptr();
137 
138   for(uword i=0; i < p_n_slices; ++i)  { arrayops::inplace_plus( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
139   }
140 
141 
142 
143 template<typename eT>
144 template<typename T1>
145 inline
146 void
operator -=(const Base<eT,T1> & in)147 subview_cube_each1<eT>::operator-= (const Base<eT,T1>& in)
148   {
149   arma_extra_debug_sigprint();
150 
151   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
152 
153   const unwrap<T1>   tmp( in.get_ref() );
154   const Mat<eT>& A = tmp.M;
155 
156   subview_cube_each_common<eT>::check_size(A);
157 
158   const uword p_n_slices     = p.n_slices;
159   const uword p_n_elem_slice = p.n_elem_slice;
160 
161   const eT* A_mem = A.memptr();
162 
163   for(uword i=0; i < p_n_slices; ++i)  { arrayops::inplace_minus( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
164   }
165 
166 
167 
168 template<typename eT>
169 template<typename T1>
170 inline
171 void
operator %=(const Base<eT,T1> & in)172 subview_cube_each1<eT>::operator%= (const Base<eT,T1>& in)
173   {
174   arma_extra_debug_sigprint();
175 
176   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
177 
178   const unwrap<T1>   tmp( in.get_ref() );
179   const Mat<eT>& A = tmp.M;
180 
181   subview_cube_each_common<eT>::check_size(A);
182 
183   const uword p_n_slices     = p.n_slices;
184   const uword p_n_elem_slice = p.n_elem_slice;
185 
186   const eT* A_mem = A.memptr();
187 
188   for(uword i=0; i < p_n_slices; ++i)  { arrayops::inplace_mul( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
189   }
190 
191 
192 
193 template<typename eT>
194 template<typename T1>
195 inline
196 void
operator /=(const Base<eT,T1> & in)197 subview_cube_each1<eT>::operator/= (const Base<eT,T1>& in)
198   {
199   arma_extra_debug_sigprint();
200 
201   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
202 
203   const unwrap<T1>   tmp( in.get_ref() );
204   const Mat<eT>& A = tmp.M;
205 
206   subview_cube_each_common<eT>::check_size(A);
207 
208   const uword p_n_slices     = p.n_slices;
209   const uword p_n_elem_slice = p.n_elem_slice;
210 
211   const eT* A_mem = A.memptr();
212 
213   for(uword i=0; i < p_n_slices; ++i)  { arrayops::inplace_div( p.slice_memptr(i), A_mem, p_n_elem_slice ); }
214   }
215 
216 
217 
218 template<typename eT>
219 template<typename T1>
220 inline
221 void
operator *=(const Base<eT,T1> & in)222 subview_cube_each1<eT>::operator*= (const Base<eT,T1>& in)
223   {
224   arma_extra_debug_sigprint();
225 
226   Cube<eT>& C = access::rw(subview_cube_each_common<eT>::P);
227 
228   C = C.each_slice() * in.get_ref();
229   }
230 
231 
232 
233 //
234 //
235 // subview_cube_each2
236 
237 
238 
239 template<typename eT, typename TB>
240 inline
~subview_cube_each2()241 subview_cube_each2<eT,TB>::~subview_cube_each2()
242   {
243   arma_extra_debug_sigprint();
244   }
245 
246 
247 
248 template<typename eT, typename TB>
249 inline
subview_cube_each2(const Cube<eT> & in_p,const Base<uword,TB> & in_indices)250 subview_cube_each2<eT,TB>::subview_cube_each2(const Cube<eT>& in_p, const Base<uword, TB>& in_indices)
251   : subview_cube_each_common<eT>::subview_cube_each_common(in_p)
252   , base_indices(in_indices)
253   {
254   arma_extra_debug_sigprint();
255   }
256 
257 
258 
259 template<typename eT, typename TB>
260 inline
261 void
check_indices(const Mat<uword> & indices) const262 subview_cube_each2<eT,TB>::check_indices(const Mat<uword>& indices) const
263   {
264   arma_debug_check( ((indices.is_vec() == false) && (indices.is_empty() == false)), "each_slice(): list of indices must be a vector" );
265   }
266 
267 
268 
269 template<typename eT, typename TB>
270 template<typename T1>
271 inline
272 void
operator =(const Base<eT,T1> & in)273 subview_cube_each2<eT,TB>::operator= (const Base<eT,T1>& in)
274   {
275   arma_extra_debug_sigprint();
276 
277   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
278 
279   const unwrap<T1>   tmp( in.get_ref() );
280   const Mat<eT>& A = tmp.M;
281 
282   subview_cube_each_common<eT>::check_size(A);
283 
284   const unwrap<TB> U( base_indices.get_ref() );
285 
286   check_indices(U.M);
287 
288   const uword p_n_slices     = p.n_slices;
289   const uword p_n_elem_slice = p.n_elem_slice;
290 
291   const uword* indices_mem = U.M.memptr();
292   const uword  N           = U.M.n_elem;
293 
294   const eT* A_mem = A.memptr();
295 
296   for(uword i=0; i < N; ++i)
297     {
298     const uword slice = indices_mem[i];
299 
300     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
301 
302     arrayops::copy(p.slice_memptr(slice), A_mem, p_n_elem_slice);
303     }
304   }
305 
306 
307 
308 template<typename eT, typename TB>
309 template<typename T1>
310 inline
311 void
operator +=(const Base<eT,T1> & in)312 subview_cube_each2<eT,TB>::operator+= (const Base<eT,T1>& in)
313   {
314   arma_extra_debug_sigprint();
315 
316   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
317 
318   const unwrap<T1>   tmp( in.get_ref() );
319   const Mat<eT>& A = tmp.M;
320 
321   subview_cube_each_common<eT>::check_size(A);
322 
323   const unwrap<TB> U( base_indices.get_ref() );
324 
325   check_indices(U.M);
326 
327   const uword p_n_slices     = p.n_slices;
328   const uword p_n_elem_slice = p.n_elem_slice;
329 
330   const uword* indices_mem = U.M.memptr();
331   const uword  N           = U.M.n_elem;
332 
333   const eT* A_mem = A.memptr();
334 
335   for(uword i=0; i < N; ++i)
336     {
337     const uword slice = indices_mem[i];
338 
339     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
340 
341     arrayops::inplace_plus(p.slice_memptr(slice), A_mem, p_n_elem_slice);
342     }
343   }
344 
345 
346 
347 template<typename eT, typename TB>
348 template<typename T1>
349 inline
350 void
operator -=(const Base<eT,T1> & in)351 subview_cube_each2<eT,TB>::operator-= (const Base<eT,T1>& in)
352   {
353   arma_extra_debug_sigprint();
354 
355   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
356 
357   const unwrap<T1>   tmp( in.get_ref() );
358   const Mat<eT>& A = tmp.M;
359 
360   subview_cube_each_common<eT>::check_size(A);
361 
362   const unwrap<TB> U( base_indices.get_ref() );
363 
364   check_indices(U.M);
365 
366   const uword p_n_slices     = p.n_slices;
367   const uword p_n_elem_slice = p.n_elem_slice;
368 
369   const uword* indices_mem = U.M.memptr();
370   const uword  N           = U.M.n_elem;
371 
372   const eT* A_mem = A.memptr();
373 
374   for(uword i=0; i < N; ++i)
375     {
376     const uword slice = indices_mem[i];
377 
378     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
379 
380     arrayops::inplace_minus(p.slice_memptr(slice), A_mem, p_n_elem_slice);
381     }
382   }
383 
384 
385 
386 template<typename eT, typename TB>
387 template<typename T1>
388 inline
389 void
operator %=(const Base<eT,T1> & in)390 subview_cube_each2<eT,TB>::operator%= (const Base<eT,T1>& in)
391   {
392   arma_extra_debug_sigprint();
393 
394   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
395 
396   const unwrap<T1>   tmp( in.get_ref() );
397   const Mat<eT>& A = tmp.M;
398 
399   subview_cube_each_common<eT>::check_size(A);
400 
401   const unwrap<TB> U( base_indices.get_ref() );
402 
403   check_indices(U.M);
404 
405   const uword p_n_slices     = p.n_slices;
406   const uword p_n_elem_slice = p.n_elem_slice;
407 
408   const uword* indices_mem = U.M.memptr();
409   const uword  N           = U.M.n_elem;
410 
411   const eT* A_mem = A.memptr();
412 
413   for(uword i=0; i < N; ++i)
414     {
415     const uword slice = indices_mem[i];
416 
417     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
418 
419     arrayops::inplace_mul(p.slice_memptr(slice), A_mem, p_n_elem_slice);
420     }
421   }
422 
423 
424 
425 template<typename eT, typename TB>
426 template<typename T1>
427 inline
428 void
operator /=(const Base<eT,T1> & in)429 subview_cube_each2<eT,TB>::operator/= (const Base<eT,T1>& in)
430   {
431   arma_extra_debug_sigprint();
432 
433   Cube<eT>& p = access::rw(subview_cube_each_common<eT>::P);
434 
435   const unwrap<T1>   tmp( in.get_ref() );
436   const Mat<eT>& A = tmp.M;
437 
438   subview_cube_each_common<eT>::check_size(A);
439 
440   const unwrap<TB> U( base_indices.get_ref() );
441 
442   check_indices(U.M);
443 
444   const uword p_n_slices     = p.n_slices;
445   const uword p_n_elem_slice = p.n_elem_slice;
446 
447   const uword* indices_mem = U.M.memptr();
448   const uword  N           = U.M.n_elem;
449 
450   const eT* A_mem = A.memptr();
451 
452   for(uword i=0; i < N; ++i)
453     {
454     const uword slice = indices_mem[i];
455 
456     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
457 
458     arrayops::inplace_div(p.slice_memptr(slice), A_mem, p_n_elem_slice);
459     }
460   }
461 
462 
463 
464 //
465 //
466 // subview_cube_each1_aux
467 
468 
469 
470 template<typename eT, typename T2>
471 inline
472 Cube<eT>
operator_plus(const subview_cube_each1<eT> & X,const Base<eT,T2> & Y)473 subview_cube_each1_aux::operator_plus
474   (
475   const subview_cube_each1<eT>& X,
476   const Base<eT,T2>&            Y
477   )
478   {
479   arma_extra_debug_sigprint();
480 
481   const Cube<eT>& p = X.P;
482 
483   const uword p_n_rows   = p.n_rows;
484   const uword p_n_cols   = p.n_cols;
485   const uword p_n_slices = p.n_slices;
486 
487   Cube<eT> out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator());
488 
489   const unwrap<T2>   tmp(Y.get_ref());
490   const Mat<eT>& A = tmp.M;
491 
492   X.check_size(A);
493 
494   for(uword i=0; i < p_n_slices; ++i)
495     {
496           Mat<eT> out_slice(              out.slice_memptr(i),  p_n_rows, p_n_cols, false, true);
497     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
498 
499     out_slice = p_slice + A;
500     }
501 
502   return out;
503   }
504 
505 
506 
507 template<typename eT, typename T2>
508 inline
509 Cube<eT>
operator_minus(const subview_cube_each1<eT> & X,const Base<eT,T2> & Y)510 subview_cube_each1_aux::operator_minus
511   (
512   const subview_cube_each1<eT>& X,
513   const Base<eT,T2>&            Y
514   )
515   {
516   arma_extra_debug_sigprint();
517 
518   const Cube<eT>& p = X.P;
519 
520   const uword p_n_rows   = p.n_rows;
521   const uword p_n_cols   = p.n_cols;
522   const uword p_n_slices = p.n_slices;
523 
524   Cube<eT> out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator());
525 
526   const unwrap<T2>   tmp(Y.get_ref());
527   const Mat<eT>& A = tmp.M;
528 
529   X.check_size(A);
530 
531   for(uword i=0; i < p_n_slices; ++i)
532     {
533           Mat<eT> out_slice(              out.slice_memptr(i),  p_n_rows, p_n_cols, false, true);
534     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
535 
536     out_slice = p_slice - A;
537     }
538 
539   return out;
540   }
541 
542 
543 
544 template<typename T1, typename eT>
545 inline
546 Cube<eT>
operator_minus(const Base<eT,T1> & X,const subview_cube_each1<eT> & Y)547 subview_cube_each1_aux::operator_minus
548   (
549   const Base<eT,T1>&            X,
550   const subview_cube_each1<eT>& Y
551   )
552   {
553   arma_extra_debug_sigprint();
554 
555   const Cube<eT>& p = Y.P;
556 
557   const uword p_n_rows   = p.n_rows;
558   const uword p_n_cols   = p.n_cols;
559   const uword p_n_slices = p.n_slices;
560 
561   Cube<eT> out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator());
562 
563   const unwrap<T1>   tmp(X.get_ref());
564   const Mat<eT>& A = tmp.M;
565 
566   Y.check_size(A);
567 
568   for(uword i=0; i < p_n_slices; ++i)
569     {
570           Mat<eT> out_slice(              out.slice_memptr(i),  p_n_rows, p_n_cols, false, true);
571     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
572 
573     out_slice = A - p_slice;
574     }
575 
576   return out;
577   }
578 
579 
580 
581 template<typename eT, typename T2>
582 inline
583 Cube<eT>
operator_schur(const subview_cube_each1<eT> & X,const Base<eT,T2> & Y)584 subview_cube_each1_aux::operator_schur
585   (
586   const subview_cube_each1<eT>& X,
587   const Base<eT,T2>&            Y
588   )
589   {
590   arma_extra_debug_sigprint();
591 
592   const Cube<eT>& p = X.P;
593 
594   const uword p_n_rows   = p.n_rows;
595   const uword p_n_cols   = p.n_cols;
596   const uword p_n_slices = p.n_slices;
597 
598   Cube<eT> out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator());
599 
600   const unwrap<T2>   tmp(Y.get_ref());
601   const Mat<eT>& A = tmp.M;
602 
603   X.check_size(A);
604 
605   for(uword i=0; i < p_n_slices; ++i)
606     {
607           Mat<eT> out_slice(              out.slice_memptr(i),  p_n_rows, p_n_cols, false, true);
608     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
609 
610     out_slice = p_slice % A;
611     }
612 
613   return out;
614   }
615 
616 
617 
618 template<typename eT, typename T2>
619 inline
620 Cube<eT>
operator_div(const subview_cube_each1<eT> & X,const Base<eT,T2> & Y)621 subview_cube_each1_aux::operator_div
622   (
623   const subview_cube_each1<eT>& X,
624   const Base<eT,T2>&            Y
625   )
626   {
627   arma_extra_debug_sigprint();
628 
629   const Cube<eT>& p = X.P;
630 
631   const uword p_n_rows   = p.n_rows;
632   const uword p_n_cols   = p.n_cols;
633   const uword p_n_slices = p.n_slices;
634 
635   Cube<eT> out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator());
636 
637   const unwrap<T2>   tmp(Y.get_ref());
638   const Mat<eT>& A = tmp.M;
639 
640   X.check_size(A);
641 
642   for(uword i=0; i < p_n_slices; ++i)
643     {
644           Mat<eT> out_slice(              out.slice_memptr(i),  p_n_rows, p_n_cols, false, true);
645     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
646 
647     out_slice = p_slice / A;
648     }
649 
650   return out;
651   }
652 
653 
654 
655 template<typename T1, typename eT>
656 inline
657 Cube<eT>
operator_div(const Base<eT,T1> & X,const subview_cube_each1<eT> & Y)658 subview_cube_each1_aux::operator_div
659   (
660   const Base<eT,T1>&            X,
661   const subview_cube_each1<eT>& Y
662   )
663   {
664   arma_extra_debug_sigprint();
665 
666   const Cube<eT>& p = Y.P;
667 
668   const uword p_n_rows   = p.n_rows;
669   const uword p_n_cols   = p.n_cols;
670   const uword p_n_slices = p.n_slices;
671 
672   Cube<eT> out(p_n_rows, p_n_cols, p_n_slices, arma_nozeros_indicator());
673 
674   const unwrap<T1>   tmp(X.get_ref());
675   const Mat<eT>& A = tmp.M;
676 
677   Y.check_size(A);
678 
679   for(uword i=0; i < p_n_slices; ++i)
680     {
681           Mat<eT> out_slice(              out.slice_memptr(i),  p_n_rows, p_n_cols, false, true);
682     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(i)), p_n_rows, p_n_cols, false, true);
683 
684     out_slice = A / p_slice;
685     }
686 
687   return out;
688   }
689 
690 
691 
692 template<typename eT, typename T2>
693 inline
694 Cube<eT>
operator_times(const subview_cube_each1<eT> & X,const Base<eT,T2> & Y)695 subview_cube_each1_aux::operator_times
696   (
697   const subview_cube_each1<eT>& X,
698   const Base<eT,T2>&            Y
699   )
700   {
701   arma_extra_debug_sigprint();
702 
703   const Cube<eT>& C = X.P;
704 
705   const unwrap<T2>   tmp(Y.get_ref());
706   const Mat<eT>& M = tmp.M;
707 
708   Cube<eT> out(C.n_rows, M.n_cols, C.n_slices, arma_nozeros_indicator());
709 
710   for(uword i=0; i < C.n_slices; ++i)
711     {
712           Mat<eT> out_slice(              out.slice_memptr(i),  C.n_rows, M.n_cols, false, true);
713     const Mat<eT>   C_slice(const_cast<eT*>(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true);
714 
715     out_slice = C_slice * M;
716     }
717 
718   return out;
719   }
720 
721 
722 
723 template<typename T1, typename eT>
724 inline
725 Cube<eT>
operator_times(const Base<eT,T1> & X,const subview_cube_each1<eT> & Y)726 subview_cube_each1_aux::operator_times
727   (
728   const Base<eT,T1>&            X,
729   const subview_cube_each1<eT>& Y
730   )
731   {
732   arma_extra_debug_sigprint();
733 
734   const unwrap<T1>   tmp(X.get_ref());
735   const Mat<eT>& M = tmp.M;
736 
737   const Cube<eT>& C = Y.P;
738 
739   Cube<eT> out(M.n_rows, C.n_cols, C.n_slices, arma_nozeros_indicator());
740 
741   for(uword i=0; i < C.n_slices; ++i)
742     {
743           Mat<eT> out_slice(              out.slice_memptr(i),  M.n_rows, C.n_cols, false, true);
744     const Mat<eT>   C_slice(const_cast<eT*>(C.slice_memptr(i)), C.n_rows, C.n_cols, false, true);
745 
746     out_slice = M * C_slice;
747     }
748 
749   return out;
750   }
751 
752 
753 
754 //
755 //
756 // subview_cube_each2_aux
757 
758 
759 
760 template<typename eT, typename TB, typename T2>
761 inline
762 Cube<eT>
operator_plus(const subview_cube_each2<eT,TB> & X,const Base<eT,T2> & Y)763 subview_cube_each2_aux::operator_plus
764   (
765   const subview_cube_each2<eT,TB>& X,
766   const Base<eT,T2>&               Y
767   )
768   {
769   arma_extra_debug_sigprint();
770 
771   const Cube<eT>& p = X.P;
772 
773   const uword p_n_slices     = p.n_slices;
774   const uword p_n_elem_slice = p.n_elem_slice;
775 
776   Cube<eT> out = p;
777 
778   const unwrap<T2>   tmp(Y.get_ref());
779   const Mat<eT>& A = tmp.M;
780 
781   const unwrap<TB> U(X.base_indices.get_ref());
782 
783   X.check_size(A);
784   X.check_indices(U.M);
785 
786   const uword* indices_mem = U.M.memptr();
787   const uword  N           = U.M.n_elem;
788 
789   const eT* A_mem = A.memptr();
790 
791   for(uword i=0; i < N; ++i)
792     {
793     const uword slice = indices_mem[i];
794 
795     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
796 
797     arrayops::inplace_plus(out.slice_memptr(slice), A_mem, p_n_elem_slice);
798     }
799 
800   return out;
801   }
802 
803 
804 
805 template<typename eT, typename TB, typename T2>
806 inline
807 Cube<eT>
operator_minus(const subview_cube_each2<eT,TB> & X,const Base<eT,T2> & Y)808 subview_cube_each2_aux::operator_minus
809   (
810   const subview_cube_each2<eT,TB>& X,
811   const Base<eT,T2>&               Y
812   )
813   {
814   arma_extra_debug_sigprint();
815 
816   const Cube<eT>& p = X.P;
817 
818   const uword p_n_slices     = p.n_slices;
819   const uword p_n_elem_slice = p.n_elem_slice;
820 
821   Cube<eT> out = p;
822 
823   const unwrap<T2>   tmp(Y.get_ref());
824   const Mat<eT>& A = tmp.M;
825 
826   const unwrap<TB> U(X.base_indices.get_ref());
827 
828   X.check_size(A);
829   X.check_indices(U.M);
830 
831   const uword* indices_mem = U.M.memptr();
832   const uword  N           = U.M.n_elem;
833 
834   const eT* A_mem = A.memptr();
835 
836   for(uword i=0; i < N; ++i)
837     {
838     const uword slice = indices_mem[i];
839 
840     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
841 
842     arrayops::inplace_minus(out.slice_memptr(slice), A_mem, p_n_elem_slice);
843     }
844 
845   return out;
846   }
847 
848 
849 
850 template<typename T1, typename eT, typename TB>
851 inline
852 Cube<eT>
operator_minus(const Base<eT,T1> & X,const subview_cube_each2<eT,TB> & Y)853 subview_cube_each2_aux::operator_minus
854   (
855   const Base<eT,T1>&               X,
856   const subview_cube_each2<eT,TB>& Y
857   )
858   {
859   arma_extra_debug_sigprint();
860 
861   const Cube<eT>& p = Y.P;
862 
863   const uword p_n_rows   = p.n_rows;
864   const uword p_n_cols   = p.n_cols;
865   const uword p_n_slices = p.n_slices;
866 
867   Cube<eT> out = p;
868 
869   const unwrap<T1>   tmp(X.get_ref());
870   const Mat<eT>& A = tmp.M;
871 
872   const unwrap<TB> U(Y.base_indices.get_ref());
873 
874   Y.check_size(A);
875   Y.check_indices(U.M);
876 
877   const uword* indices_mem = U.M.memptr();
878   const uword  N           = U.M.n_elem;
879 
880   for(uword i=0; i < N; ++i)
881     {
882     const uword slice = indices_mem[i];
883 
884     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
885 
886           Mat<eT> out_slice(              out.slice_memptr(slice),  p_n_rows, p_n_cols, false, true);
887     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(slice)), p_n_rows, p_n_cols, false, true);
888 
889     out_slice = A - p_slice;
890     }
891 
892   return out;
893   }
894 
895 
896 
897 template<typename eT, typename TB, typename T2>
898 inline
899 Cube<eT>
operator_schur(const subview_cube_each2<eT,TB> & X,const Base<eT,T2> & Y)900 subview_cube_each2_aux::operator_schur
901   (
902   const subview_cube_each2<eT,TB>& X,
903   const Base<eT,T2>&               Y
904   )
905   {
906   arma_extra_debug_sigprint();
907 
908   const Cube<eT>& p = X.P;
909 
910   const uword p_n_slices     = p.n_slices;
911   const uword p_n_elem_slice = p.n_elem_slice;
912 
913   Cube<eT> out = p;
914 
915   const unwrap<T2>   tmp(Y.get_ref());
916   const Mat<eT>& A = tmp.M;
917 
918   const unwrap<TB> U(X.base_indices.get_ref());
919 
920   X.check_size(A);
921   X.check_indices(U.M);
922 
923   const uword* indices_mem = U.M.memptr();
924   const uword  N           = U.M.n_elem;
925 
926   const eT* A_mem = A.memptr();
927 
928   for(uword i=0; i < N; ++i)
929     {
930     const uword slice = indices_mem[i];
931 
932     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
933 
934     arrayops::inplace_mul(out.slice_memptr(slice), A_mem, p_n_elem_slice);
935     }
936 
937   return out;
938   }
939 
940 
941 
942 template<typename eT, typename TB, typename T2>
943 inline
944 Cube<eT>
operator_div(const subview_cube_each2<eT,TB> & X,const Base<eT,T2> & Y)945 subview_cube_each2_aux::operator_div
946   (
947   const subview_cube_each2<eT,TB>& X,
948   const Base<eT,T2>&               Y
949   )
950   {
951   arma_extra_debug_sigprint();
952 
953   const Cube<eT>& p = X.P;
954 
955   const uword p_n_slices     = p.n_slices;
956   const uword p_n_elem_slice = p.n_elem_slice;
957 
958   Cube<eT> out = p;
959 
960   const unwrap<T2>   tmp(Y.get_ref());
961   const Mat<eT>& A = tmp.M;
962 
963   const unwrap<TB> U(X.base_indices.get_ref());
964 
965   X.check_size(A);
966   X.check_indices(U.M);
967 
968   const uword* indices_mem = U.M.memptr();
969   const uword  N           = U.M.n_elem;
970 
971   const eT* A_mem = A.memptr();
972 
973   for(uword i=0; i < N; ++i)
974     {
975     const uword slice = indices_mem[i];
976 
977     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
978 
979     arrayops::inplace_div(out.slice_memptr(slice), A_mem, p_n_elem_slice);
980     }
981 
982   return out;
983   }
984 
985 
986 
987 template<typename T1, typename eT, typename TB>
988 inline
989 Cube<eT>
operator_div(const Base<eT,T1> & X,const subview_cube_each2<eT,TB> & Y)990 subview_cube_each2_aux::operator_div
991   (
992   const Base<eT,T1>&               X,
993   const subview_cube_each2<eT,TB>& Y
994   )
995   {
996   arma_extra_debug_sigprint();
997 
998   const Cube<eT>& p = Y.P;
999 
1000   const uword p_n_rows   = p.n_rows;
1001   const uword p_n_cols   = p.n_cols;
1002   const uword p_n_slices = p.n_slices;
1003 
1004   Cube<eT> out = p;
1005 
1006   const unwrap<T1>   tmp(X.get_ref());
1007   const Mat<eT>& A = tmp.M;
1008 
1009   const unwrap<TB> U(Y.base_indices.get_ref());
1010 
1011   Y.check_size(A);
1012   Y.check_indices(U.M);
1013 
1014   const uword* indices_mem = U.M.memptr();
1015   const uword  N           = U.M.n_elem;
1016 
1017   for(uword i=0; i < N; ++i)
1018     {
1019     const uword slice = indices_mem[i];
1020 
1021     arma_debug_check_bounds( (slice >= p_n_slices), "each_slice(): index out of bounds" );
1022 
1023           Mat<eT> out_slice(              out.slice_memptr(slice),  p_n_rows, p_n_cols, false, true);
1024     const Mat<eT>   p_slice(const_cast<eT*>(p.slice_memptr(slice)), p_n_rows, p_n_cols, false, true);
1025 
1026     out_slice = A / p_slice;
1027     }
1028 
1029   return out;
1030   }
1031 
1032 
1033 
1034 //! @}
1035