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 unwrap
20 //! @{
21 
22 
23 // TODO: document the conditions and restrictions for the use of each unwrap variant:
24 // TODO: unwrap, unwrap_check, quasi_unwrap, partial_unwrap, partial_unwrap_check
25 
26 
27 template<typename T1>
28 struct unwrap_default
29   {
30   typedef typename T1::elem_type eT;
31   typedef Mat<eT>                stored_type;
32 
33   inline
unwrap_defaultunwrap_default34   unwrap_default(const T1& A)
35     : M(A)
36     {
37     arma_extra_debug_sigprint();
38     }
39 
40   const Mat<eT> M;
41   };
42 
43 
44 
45 template<typename T1>
46 struct unwrap_fixed
47   {
48   typedef T1 stored_type;
49 
50   inline explicit
unwrap_fixedunwrap_fixed51   unwrap_fixed(const T1& A)
52     : M(A)
53     {
54     arma_extra_debug_sigprint();
55     }
56 
57   const T1& M;
58   };
59 
60 
61 
62 template<typename T1, bool condition>
63 struct unwrap_redirect {};
64 
65 template<typename T1>
66 struct unwrap_redirect<T1, false> { typedef unwrap_default<T1> result; };
67 
68 template<typename T1>
69 struct unwrap_redirect<T1, true>  { typedef unwrap_fixed<T1>   result; };
70 
71 
72 template<typename T1>
73 struct unwrap : public unwrap_redirect<T1, is_Mat_fixed<T1>::value>::result
74   {
75   inline
unwrapunwrap76   unwrap(const T1& A)
77     : unwrap_redirect<T1, is_Mat_fixed<T1>::value>::result(A)
78     {
79     }
80   };
81 
82 
83 
84 template<typename eT>
85 struct unwrap< Mat<eT> >
86   {
87   typedef Mat<eT> stored_type;
88 
89   inline
unwrapunwrap90   unwrap(const Mat<eT>& A)
91     : M(A)
92     {
93     arma_extra_debug_sigprint();
94     }
95 
96   const Mat<eT>& M;
97   };
98 
99 
100 
101 template<typename eT>
102 struct unwrap< Row<eT> >
103   {
104   typedef Row<eT> stored_type;
105 
106   inline
unwrapunwrap107   unwrap(const Row<eT>& A)
108     : M(A)
109     {
110     arma_extra_debug_sigprint();
111     }
112 
113   const Row<eT>& M;
114   };
115 
116 
117 
118 template<typename eT>
119 struct unwrap< Col<eT> >
120   {
121   typedef Col<eT> stored_type;
122 
123   inline
unwrapunwrap124   unwrap(const Col<eT>& A)
125     : M(A)
126     {
127     arma_extra_debug_sigprint();
128     }
129 
130   const Col<eT>& M;
131   };
132 
133 
134 
135 template<typename eT>
136 struct unwrap< subview_col<eT> >
137   {
138   typedef Col<eT> stored_type;
139 
140   inline
unwrapunwrap141   unwrap(const subview_col<eT>& A)
142     : M(A.colmem, A.n_rows)
143     {
144     arma_extra_debug_sigprint();
145     }
146 
147   const Col<eT> M;
148   };
149 
150 
151 
152 template<typename eT>
153 struct unwrap< subview_cols<eT> >
154   {
155   typedef Mat<eT> stored_type;
156 
157   inline
unwrapunwrap158   unwrap(const subview_cols<eT>& A)
159     : M(A.colptr(0), A.n_rows, A.n_cols)
160     {
161     arma_extra_debug_sigprint();
162     }
163 
164   const Mat<eT> M;
165   };
166 
167 
168 
169 template<typename out_eT, typename T1, typename T2, typename glue_type>
170 struct unwrap< mtGlue<out_eT, T1, T2, glue_type> >
171   {
172   typedef Mat<out_eT> stored_type;
173 
174   inline
unwrapunwrap175   unwrap(const mtGlue<out_eT, T1, T2, glue_type>& A)
176     : M(A)
177     {
178     arma_extra_debug_sigprint();
179     }
180 
181   const Mat<out_eT> M;
182   };
183 
184 
185 
186 template<typename out_eT, typename T1, typename op_type>
187 struct unwrap< mtOp<out_eT, T1, op_type> >
188   {
189   typedef Mat<out_eT> stored_type;
190 
191   inline
unwrapunwrap192   unwrap(const mtOp<out_eT, T1, op_type>& A)
193     : M(A)
194     {
195     arma_extra_debug_sigprint();
196     }
197 
198   const Mat<out_eT> M;
199   };
200 
201 
202 
203 //
204 //
205 //
206 
207 
208 
209 template<typename T1>
210 struct quasi_unwrap_default
211   {
212   typedef typename T1::elem_type eT;
213 
214   inline
quasi_unwrap_defaultquasi_unwrap_default215   quasi_unwrap_default(const T1& A)
216     : M(A)
217     {
218     arma_extra_debug_sigprint();
219     }
220 
221   // NOTE: DO NOT DIRECTLY CHECK FOR ALIASING BY TAKING THE ADDRESS OF THE "M" OBJECT IN ANY quasi_unwrap CLASS !!!
222   Mat<eT> M;
223 
224   static constexpr bool is_const     = false;
225   static constexpr bool has_subview  = false;
226   static constexpr bool has_orig_mem = false;
227 
228   template<typename eT2>
is_aliasquasi_unwrap_default229   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
230   };
231 
232 
233 
234 template<typename T1>
235 struct quasi_unwrap_fixed
236   {
237   typedef typename T1::elem_type eT;
238 
239   inline explicit
quasi_unwrap_fixedquasi_unwrap_fixed240   quasi_unwrap_fixed(const T1& A)
241     : M(A)
242     {
243     arma_extra_debug_sigprint();
244     }
245 
246   const T1& M;
247 
248   static constexpr bool is_const     = true;
249   static constexpr bool has_subview  = false;
250   static constexpr bool has_orig_mem = true;
251 
252   template<typename eT2>
is_aliasquasi_unwrap_fixed253   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&M) == void_ptr(&X)); }
254   };
255 
256 
257 
258 template<typename T1, bool condition>
259 struct quasi_unwrap_redirect {};
260 
261 template<typename T1>
262 struct quasi_unwrap_redirect<T1, false> { typedef quasi_unwrap_default<T1> result; };
263 
264 template<typename T1>
265 struct quasi_unwrap_redirect<T1, true>  { typedef quasi_unwrap_fixed<T1>   result; };
266 
267 
268 template<typename T1>
269 struct quasi_unwrap : public quasi_unwrap_redirect<T1, is_Mat_fixed<T1>::value>::result
270   {
271   typedef typename quasi_unwrap_redirect<T1, is_Mat_fixed<T1>::value>::result quasi_unwrap_extra;
272 
273   inline
quasi_unwrapquasi_unwrap274   quasi_unwrap(const T1& A)
275     : quasi_unwrap_extra(A)
276     {
277     }
278 
279   static constexpr bool is_const     = quasi_unwrap_extra::is_const;
280   static constexpr bool has_subview  = quasi_unwrap_extra::has_subview;
281   static constexpr bool has_orig_mem = quasi_unwrap_extra::has_orig_mem;
282 
283   using quasi_unwrap_extra::M;
284   using quasi_unwrap_extra::is_alias;
285   };
286 
287 
288 
289 template<typename eT>
290 struct quasi_unwrap< Mat<eT> >
291   {
292   inline
quasi_unwrapquasi_unwrap293   quasi_unwrap(const Mat<eT>& A)
294     : M(A)
295     {
296     arma_extra_debug_sigprint();
297     }
298 
299   const Mat<eT>& M;
300 
301   static constexpr bool is_const     = true;
302   static constexpr bool has_subview  = false;
303   static constexpr bool has_orig_mem = true;
304 
305   template<typename eT2>
is_aliasquasi_unwrap306   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&M) == void_ptr(&X)); }
307   };
308 
309 
310 
311 template<typename eT>
312 struct quasi_unwrap< Row<eT> >
313   {
314 
315   inline
quasi_unwrapquasi_unwrap316   quasi_unwrap(const Row<eT>& A)
317     : M(A)
318     {
319     arma_extra_debug_sigprint();
320     }
321 
322   const Row<eT>& M;
323 
324   static constexpr bool is_const     = true;
325   static constexpr bool has_subview  = false;
326   static constexpr bool has_orig_mem = true;
327 
328   template<typename eT2>
is_aliasquasi_unwrap329   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&M) == void_ptr(&X)); }
330   };
331 
332 
333 
334 template<typename eT>
335 struct quasi_unwrap< Col<eT> >
336   {
337   inline
quasi_unwrapquasi_unwrap338   quasi_unwrap(const Col<eT>& A)
339     : M(A)
340     {
341     arma_extra_debug_sigprint();
342     }
343 
344   const Col<eT>& M;
345 
346   static constexpr bool is_const     = true;
347   static constexpr bool has_subview  = false;
348   static constexpr bool has_orig_mem = true;
349 
350   template<typename eT2>
is_aliasquasi_unwrap351   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&M) == void_ptr(&X)); }
352   };
353 
354 
355 
356 template<typename eT>
357 struct quasi_unwrap< subview<eT> >
358   {
359   inline
quasi_unwrapquasi_unwrap360   quasi_unwrap(const subview<eT>& A)
361     : sv( A                                                  )
362     , M ( A, ((A.aux_row1 == 0) && (A.n_rows == A.m.n_rows)) )  // reuse memory if the subview is a contiguous chunk
363     {
364     arma_extra_debug_sigprint();
365     }
366 
367   const subview<eT>& sv;
368   const Mat<eT>      M;
369 
370   static constexpr bool is_const     = true;
371   static constexpr bool has_subview  = true;
372   static constexpr bool has_orig_mem = false;  // NOTE: set to false as this is the general case; original memory is only used when the subview is a contiguous chunk
373 
374   template<typename eT2>
is_aliasquasi_unwrap375   arma_inline bool is_alias(const Mat<eT2>& X) const { return ( ((sv.aux_row1 == 0) && (sv.n_rows == sv.m.n_rows)) ? (void_ptr(&(sv.m)) == void_ptr(&X)) : false ); }
376   };
377 
378 
379 
380 template<typename eT>
381 struct quasi_unwrap< subview_row<eT> >
382   {
383   inline
quasi_unwrapquasi_unwrap384   quasi_unwrap(const subview_row<eT>& A)
385     : M(A)
386     {
387     arma_extra_debug_sigprint();
388     }
389 
390   Row<eT> M;
391 
392   static constexpr bool is_const     = false;
393   static constexpr bool has_subview  = false;
394   static constexpr bool has_orig_mem = false;
395 
396   template<typename eT2>
is_aliasquasi_unwrap397   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
398   };
399 
400 
401 
402 template<typename eT>
403 struct quasi_unwrap< subview_col<eT> >
404   {
405   inline
quasi_unwrapquasi_unwrap406   quasi_unwrap(const subview_col<eT>& A)
407     : orig( A.m )
408     , M  ( const_cast<eT*>( A.colmem ), A.n_rows, false, false )
409     {
410     arma_extra_debug_sigprint();
411     }
412 
413   const Mat<eT>& orig;
414   const Col<eT>  M;
415 
416   static constexpr bool is_const     = true;
417   static constexpr bool has_subview  = true;
418   static constexpr bool has_orig_mem = true;
419 
420   template<typename eT2>
is_aliasquasi_unwrap421   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
422   };
423 
424 
425 
426 template<typename eT>
427 struct quasi_unwrap< subview_cols<eT> >
428   {
429   inline
quasi_unwrapquasi_unwrap430   quasi_unwrap(const subview_cols<eT>& A)
431     : orig( A.m )
432     , M   ( const_cast<eT*>( A.colptr(0) ), A.n_rows, A.n_cols, false, false )
433     {
434     arma_extra_debug_sigprint();
435     }
436 
437   const Mat<eT>& orig;
438   const Mat<eT>  M;
439 
440   static constexpr bool is_const     = true;
441   static constexpr bool has_subview  = true;
442   static constexpr bool has_orig_mem = true;
443 
444   template<typename eT2>
is_aliasquasi_unwrap445   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
446   };
447 
448 
449 
450 template<typename out_eT, typename T1, typename T2, typename glue_type>
451 struct quasi_unwrap< mtGlue<out_eT, T1, T2, glue_type> >
452   {
453   inline
quasi_unwrapquasi_unwrap454   quasi_unwrap(const mtGlue<out_eT, T1, T2, glue_type>& A)
455     : M(A)
456     {
457     arma_extra_debug_sigprint();
458     }
459 
460   Mat<out_eT> M;
461 
462   static constexpr bool is_const     = false;
463   static constexpr bool has_subview  = false;
464   static constexpr bool has_orig_mem = false;
465 
466   template<typename eT2>
is_aliasquasi_unwrap467   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
468   };
469 
470 
471 
472 template<typename out_eT, typename T1, typename op_type>
473 struct quasi_unwrap< mtOp<out_eT, T1, op_type> >
474   {
475   inline
quasi_unwrapquasi_unwrap476   quasi_unwrap(const mtOp<out_eT, T1, op_type>& A)
477     : M(A)
478     {
479     arma_extra_debug_sigprint();
480     }
481 
482   Mat<out_eT> M;
483 
484   static constexpr bool is_const     = false;
485   static constexpr bool has_subview  = false;
486   static constexpr bool has_orig_mem = false;
487 
488   template<typename eT2>
is_aliasquasi_unwrap489   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
490   };
491 
492 
493 
494 template<typename T1>
495 struct quasi_unwrap< Op<T1, op_vectorise_col> >
496   {
497   typedef typename T1::elem_type eT;
498 
499   inline
quasi_unwrapquasi_unwrap500   quasi_unwrap(const Op<T1, op_vectorise_col>& A)
501     : U( A.m )
502     , M( const_cast<eT*>(U.M.memptr()), U.M.n_elem, 1, false, false )
503     {
504     arma_extra_debug_sigprint();
505     }
506 
507   const quasi_unwrap<T1> U;
508   const Mat<eT>          M;
509 
510   static constexpr bool is_const     = true;
511   static constexpr bool has_subview  = true;
512   static constexpr bool has_orig_mem = true;
513 
514   template<typename eT2>
is_aliasquasi_unwrap515   arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
516   };
517 
518 
519 
520 template<typename eT>
521 struct quasi_unwrap< Op<Col<eT>, op_strans> >
522   {
523   inline
quasi_unwrapquasi_unwrap524   quasi_unwrap(const Op<Col<eT>, op_strans>& A)
525     : orig(A.m)
526     , M   (const_cast<eT*>(A.m.memptr()), A.m.n_elem, false, false)
527     {
528     arma_extra_debug_sigprint();
529     }
530 
531   const Col<eT>& orig;
532   const Row<eT>  M;
533 
534   static constexpr bool is_const     = true;
535   static constexpr bool has_subview  = true;
536   static constexpr bool has_orig_mem = true;
537 
538   template<typename eT2>
is_aliasquasi_unwrap539   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
540   };
541 
542 
543 
544 template<typename eT>
545 struct quasi_unwrap< Op<Row<eT>, op_strans> >
546   {
547   inline
quasi_unwrapquasi_unwrap548   quasi_unwrap(const Op<Row<eT>, op_strans>& A)
549     : orig(A.m)
550     , M   (const_cast<eT*>(A.m.memptr()), A.m.n_elem, false, false)
551     {
552     arma_extra_debug_sigprint();
553     }
554 
555   const Row<eT>& orig;
556   const Col<eT>  M;
557 
558   static constexpr bool is_const     = true;
559   static constexpr bool has_subview  = true;
560   static constexpr bool has_orig_mem = true;
561 
562   template<typename eT2>
is_aliasquasi_unwrap563   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
564   };
565 
566 
567 
568 template<typename eT>
569 struct quasi_unwrap< Op<subview_col<eT>, op_strans> >
570   {
571   inline
quasi_unwrapquasi_unwrap572   quasi_unwrap(const Op<subview_col<eT>, op_strans>& A)
573     : orig( A.m.m )
574     , M   ( const_cast<eT*>( A.m.colmem ), A.m.n_rows, false, false )
575     {
576     arma_extra_debug_sigprint();
577     }
578 
579   const Mat<eT>& orig;
580   const Row<eT>  M;
581 
582   static constexpr bool is_const     = true;
583   static constexpr bool has_subview  = true;
584   static constexpr bool has_orig_mem = true;
585 
586   template<typename eT2>
is_aliasquasi_unwrap587   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
588   };
589 
590 
591 
592 template<typename T1>
593 struct quasi_unwrap_Col_htrans
594   {
quasi_unwrap_Col_htransquasi_unwrap_Col_htrans595   inline quasi_unwrap_Col_htrans(const T1&) {}
596   };
597 
598 
599 
600 template<typename eT>
601 struct quasi_unwrap_Col_htrans< Op<Col<eT>, op_htrans> >
602   {
603   inline
quasi_unwrap_Col_htransquasi_unwrap_Col_htrans604   quasi_unwrap_Col_htrans(const Op<Col<eT>, op_htrans>& A)
605     : orig(A.m)
606     , M   (const_cast<eT*>(A.m.memptr()), A.m.n_elem, false, false)
607     {
608     arma_extra_debug_sigprint();
609     }
610 
611   const Col<eT>& orig;
612   const Row<eT>  M;
613 
614   static constexpr bool is_const     = true;
615   static constexpr bool has_subview  = true;
616   static constexpr bool has_orig_mem = true;
617 
618   template<typename eT2>
is_aliasquasi_unwrap_Col_htrans619   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
620   };
621 
622 
623 
624 template<typename T1, bool condition>
625 struct quasi_unwrap_Col_htrans_redirect {};
626 
627 template<typename T1>
628 struct quasi_unwrap_Col_htrans_redirect<T1, true>  { typedef quasi_unwrap_default<T1>    result; };
629 
630 template<typename T1>
631 struct quasi_unwrap_Col_htrans_redirect<T1, false> { typedef quasi_unwrap_Col_htrans<T1> result; };
632 
633 
634 template<typename eT>
635 struct quasi_unwrap< Op<Col<eT>, op_htrans> >
636   : public quasi_unwrap_Col_htrans_redirect< Op<Col<eT>, op_htrans>, is_cx<eT>::value >::result
637   {
638   typedef typename quasi_unwrap_Col_htrans_redirect< Op<Col<eT>, op_htrans>, is_cx<eT>::value >::result quasi_unwrap_Col_htrans_extra;
639 
640   inline
quasi_unwrapquasi_unwrap641   quasi_unwrap(const Op<Col<eT>, op_htrans>& A)
642     : quasi_unwrap_Col_htrans_extra(A)
643     {
644     }
645 
646   static constexpr bool is_const     = quasi_unwrap_Col_htrans_extra::is_const;
647   static constexpr bool has_subview  = quasi_unwrap_Col_htrans_extra::has_subview;
648   static constexpr bool has_orig_mem = quasi_unwrap_Col_htrans_extra::has_orig_mem;
649 
650   using quasi_unwrap_Col_htrans_extra::M;
651   using quasi_unwrap_Col_htrans_extra::is_alias;
652   };
653 
654 
655 
656 template<typename T1>
657 struct quasi_unwrap_Row_htrans
658   {
quasi_unwrap_Row_htransquasi_unwrap_Row_htrans659   inline quasi_unwrap_Row_htrans(const T1&) {}
660   };
661 
662 
663 
664 template<typename eT>
665 struct quasi_unwrap_Row_htrans< Op<Row<eT>, op_htrans> >
666   {
667   inline
quasi_unwrap_Row_htransquasi_unwrap_Row_htrans668   quasi_unwrap_Row_htrans(const Op<Row<eT>, op_htrans>& A)
669     : orig(A.m)
670     , M   (const_cast<eT*>(A.m.memptr()), A.m.n_elem, false, false)
671     {
672     arma_extra_debug_sigprint();
673     }
674 
675   const Row<eT>& orig;
676   const Col<eT>  M;
677 
678   static constexpr bool is_const     = true;
679   static constexpr bool has_subview  = true;
680   static constexpr bool has_orig_mem = true;
681 
682   template<typename eT2>
is_aliasquasi_unwrap_Row_htrans683   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
684   };
685 
686 
687 
688 template<typename T1, bool condition>
689 struct quasi_unwrap_Row_htrans_redirect {};
690 
691 template<typename T1>
692 struct quasi_unwrap_Row_htrans_redirect<T1, true>  { typedef quasi_unwrap_default<T1>    result; };
693 
694 template<typename T1>
695 struct quasi_unwrap_Row_htrans_redirect<T1, false> { typedef quasi_unwrap_Row_htrans<T1> result; };
696 
697 
698 template<typename eT>
699 struct quasi_unwrap< Op<Row<eT>, op_htrans> >
700   : public quasi_unwrap_Row_htrans_redirect< Op<Row<eT>, op_htrans>, is_cx<eT>::value >::result
701   {
702   typedef typename quasi_unwrap_Row_htrans_redirect< Op<Row<eT>, op_htrans>, is_cx<eT>::value >::result quasi_unwrap_Row_htrans_extra;
703 
704   inline
quasi_unwrapquasi_unwrap705   quasi_unwrap(const Op<Row<eT>, op_htrans>& A)
706     : quasi_unwrap_Row_htrans_extra(A)
707     {
708     }
709 
710   static constexpr bool is_const     = quasi_unwrap_Row_htrans_extra::is_const;
711   static constexpr bool has_subview  = quasi_unwrap_Row_htrans_extra::has_subview;
712   static constexpr bool has_orig_mem = quasi_unwrap_Row_htrans_extra::has_orig_mem;
713 
714   using quasi_unwrap_Row_htrans_extra::M;
715   using quasi_unwrap_Row_htrans_extra::is_alias;
716   };
717 
718 
719 
720 template<typename T1>
721 struct quasi_unwrap_subview_col_htrans
722   {
quasi_unwrap_subview_col_htransquasi_unwrap_subview_col_htrans723   inline quasi_unwrap_subview_col_htrans(const T1&) {}
724   };
725 
726 
727 
728 template<typename eT>
729 struct quasi_unwrap_subview_col_htrans< Op<subview_col<eT>, op_htrans> >
730   {
731   inline
quasi_unwrap_subview_col_htransquasi_unwrap_subview_col_htrans732   quasi_unwrap_subview_col_htrans(const Op<subview_col<eT>, op_htrans>& A)
733     : orig(A.m.m)
734     , M   (const_cast<eT*>(A.m.colmem), A.m.n_rows, false, false)
735     {
736     arma_extra_debug_sigprint();
737     }
738 
739   const Mat<eT>& orig;
740   const Row<eT>  M;
741 
742   static constexpr bool is_const     = true;
743   static constexpr bool has_subview  = true;
744   static constexpr bool has_orig_mem = true;
745 
746   template<typename eT2>
is_aliasquasi_unwrap_subview_col_htrans747   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
748   };
749 
750 
751 
752 template<typename T1, bool condition>
753 struct quasi_unwrap_subview_col_htrans_redirect {};
754 
755 template<typename T1>
756 struct quasi_unwrap_subview_col_htrans_redirect<T1, true>  { typedef quasi_unwrap_default<T1>            result; };
757 
758 template<typename T1>
759 struct quasi_unwrap_subview_col_htrans_redirect<T1, false> { typedef quasi_unwrap_subview_col_htrans<T1> result; };
760 
761 
762 template<typename eT>
763 struct quasi_unwrap< Op<subview_col<eT>, op_htrans> >
764   : public quasi_unwrap_subview_col_htrans_redirect< Op<subview_col<eT>, op_htrans>, is_cx<eT>::value >::result
765   {
766   typedef typename quasi_unwrap_subview_col_htrans_redirect< Op<subview_col<eT>, op_htrans>, is_cx<eT>::value >::result quasi_unwrap_subview_col_htrans_extra;
767 
768   inline
quasi_unwrapquasi_unwrap769   quasi_unwrap(const Op<subview_col<eT>, op_htrans>& A)
770     : quasi_unwrap_subview_col_htrans_extra(A)
771     {
772     }
773 
774   static constexpr bool is_const     = quasi_unwrap_subview_col_htrans_extra::is_const;
775   static constexpr bool has_subview  = quasi_unwrap_subview_col_htrans_extra::has_subview;
776   static constexpr bool has_orig_mem = quasi_unwrap_subview_col_htrans_extra::has_orig_mem;
777 
778   using quasi_unwrap_subview_col_htrans_extra::M;
779   using quasi_unwrap_subview_col_htrans_extra::is_alias;
780   };
781 
782 
783 
784 template<typename T1>
785 struct quasi_unwrap< CubeToMatOp<T1, op_vectorise_cube_col> >
786   {
787   typedef typename T1::elem_type eT;
788 
789   inline
quasi_unwrapquasi_unwrap790   quasi_unwrap(const CubeToMatOp<T1, op_vectorise_cube_col>& A)
791     : U( A.m )
792     , M( const_cast<eT*>(U.M.memptr()), U.M.n_elem, 1, false, true )
793     {
794     arma_extra_debug_sigprint();
795     }
796 
797   const unwrap_cube<T1> U;
798   const Mat<eT>         M;
799 
800   static constexpr bool is_const     = true;
801   static constexpr bool has_subview  = true;
802   static constexpr bool has_orig_mem = true;
803 
804   template<typename eT2>
is_aliasquasi_unwrap805   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
806   };
807 
808 
809 
810 template<typename T1>
811 struct quasi_unwrap< SpToDOp<T1, op_nonzeros_spmat> >
812   {
813   typedef typename T1::elem_type eT;
814 
815   inline
quasi_unwrapquasi_unwrap816   quasi_unwrap(const SpToDOp<T1, op_nonzeros_spmat>& A)
817     : U( A.m )
818     , M( const_cast<eT*>(U.M.values), U.M.n_nonzero, 1, false, true )
819     {
820     arma_extra_debug_sigprint();
821     }
822 
823   const unwrap_spmat<T1> U;
824   const Mat<eT>          M;
825 
826   static constexpr bool is_const     = true;
827   static constexpr bool has_subview  = true;
828   static constexpr bool has_orig_mem = true;
829 
830   template<typename eT2>
is_aliasquasi_unwrap831   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
832   };
833 
834 
835 
836 //
837 //
838 //
839 
840 
841 
842 template<typename T1>
843 struct unwrap_check_default
844   {
845   typedef typename T1::elem_type eT;
846   typedef Mat<eT>                stored_type;
847 
848   inline
unwrap_check_defaultunwrap_check_default849   unwrap_check_default(const T1& A, const Mat<eT>&)
850     : M(A)
851     {
852     arma_extra_debug_sigprint();
853     }
854 
855   inline
unwrap_check_defaultunwrap_check_default856   unwrap_check_default(const T1& A, const bool)
857     : M(A)
858     {
859     arma_extra_debug_sigprint();
860     }
861 
862   const Mat<eT> M;
863   };
864 
865 
866 
867 template<typename T1>
868 struct unwrap_check_fixed
869   {
870   typedef typename T1::elem_type eT;
871   typedef T1                     stored_type;
872 
873   inline
unwrap_check_fixedunwrap_check_fixed874   unwrap_check_fixed(const T1& A, const Mat<eT>& B)
875     : M_local( (&A == &B) ? new T1(A) : nullptr )
876     , M      ( (&A == &B) ? *M_local  : A       )
877     {
878     arma_extra_debug_sigprint();
879     }
880 
881   inline
unwrap_check_fixedunwrap_check_fixed882   unwrap_check_fixed(const T1& A, const bool is_alias)
883     : M_local( is_alias ? new T1(A) : nullptr )
884     , M      ( is_alias ? *M_local  : A       )
885     {
886     arma_extra_debug_sigprint();
887     }
888 
889   inline
~unwrap_check_fixedunwrap_check_fixed890   ~unwrap_check_fixed()
891     {
892     arma_extra_debug_sigprint();
893 
894     if(M_local) { delete M_local; }
895     }
896 
897 
898   // the order below is important
899   const T1* M_local;
900   const T1& M;
901   };
902 
903 
904 
905 template<typename T1, bool condition>
906 struct unwrap_check_redirect {};
907 
908 template<typename T1>
909 struct unwrap_check_redirect<T1, false> { typedef unwrap_check_default<T1> result; };
910 
911 template<typename T1>
912 struct unwrap_check_redirect<T1, true>  { typedef unwrap_check_fixed<T1>   result; };
913 
914 
915 template<typename T1>
916 struct unwrap_check : public unwrap_check_redirect<T1, is_Mat_fixed<T1>::value>::result
917   {
unwrap_checkunwrap_check918   inline unwrap_check(const T1& A, const Mat<typename T1::elem_type>& B)
919     : unwrap_check_redirect<T1, is_Mat_fixed<T1>::value>::result(A, B)
920     {
921     }
922 
unwrap_checkunwrap_check923   inline unwrap_check(const T1& A, const bool is_alias)
924     : unwrap_check_redirect<T1, is_Mat_fixed<T1>::value>::result(A, is_alias)
925     {
926     }
927   };
928 
929 
930 
931 template<typename eT>
932 struct unwrap_check< Mat<eT> >
933   {
934   typedef Mat<eT> stored_type;
935 
936   inline
unwrap_checkunwrap_check937   unwrap_check(const Mat<eT>& A, const Mat<eT>& B)
938     : M_local( (&A == &B) ? new Mat<eT>(A) : nullptr )
939     , M      ( (&A == &B) ? (*M_local)     : A       )
940     {
941     arma_extra_debug_sigprint();
942     }
943 
944   inline
unwrap_checkunwrap_check945   unwrap_check(const Mat<eT>& A, const bool is_alias)
946     : M_local( is_alias ? new Mat<eT>(A) : nullptr )
947     , M      ( is_alias ? (*M_local)     : A       )
948     {
949     arma_extra_debug_sigprint();
950     }
951 
952   inline
~unwrap_checkunwrap_check953   ~unwrap_check()
954     {
955     arma_extra_debug_sigprint();
956 
957     if(M_local) { delete M_local; }
958     }
959 
960 
961   // the order below is important
962   const Mat<eT>* M_local;
963   const Mat<eT>& M;
964   };
965 
966 
967 
968 template<typename eT>
969 struct unwrap_check< Row<eT> >
970   {
971   typedef Row<eT> stored_type;
972 
973   inline
unwrap_checkunwrap_check974   unwrap_check(const Row<eT>& A, const Mat<eT>& B)
975     : M_local( (&A == &B) ? new Row<eT>(A) : nullptr )
976     , M      ( (&A == &B) ? (*M_local)     : A       )
977     {
978     arma_extra_debug_sigprint();
979     }
980 
981   inline
unwrap_checkunwrap_check982   unwrap_check(const Row<eT>& A, const bool is_alias)
983     : M_local( is_alias ? new Row<eT>(A) : nullptr )
984     , M      ( is_alias ? (*M_local)     : A       )
985     {
986     arma_extra_debug_sigprint();
987     }
988 
989   inline
~unwrap_checkunwrap_check990   ~unwrap_check()
991     {
992     arma_extra_debug_sigprint();
993 
994     if(M_local) { delete M_local; }
995     }
996 
997 
998   // the order below is important
999   const Row<eT>* M_local;
1000   const Row<eT>& M;
1001   };
1002 
1003 
1004 
1005 template<typename eT>
1006 struct unwrap_check< Col<eT> >
1007   {
1008   typedef Col<eT> stored_type;
1009 
1010   inline
unwrap_checkunwrap_check1011   unwrap_check(const Col<eT>& A, const Mat<eT>& B)
1012     : M_local( (&A == &B) ? new Col<eT>(A) : nullptr )
1013     , M      ( (&A == &B) ? (*M_local)     : A       )
1014     {
1015     arma_extra_debug_sigprint();
1016     }
1017 
1018   inline
unwrap_checkunwrap_check1019   unwrap_check(const Col<eT>& A, const bool is_alias)
1020     : M_local( is_alias ? new Col<eT>(A) : nullptr )
1021     , M      ( is_alias ? (*M_local)     : A       )
1022     {
1023     arma_extra_debug_sigprint();
1024     }
1025 
1026   inline
~unwrap_checkunwrap_check1027   ~unwrap_check()
1028     {
1029     arma_extra_debug_sigprint();
1030 
1031     if(M_local) { delete M_local; }
1032     }
1033 
1034 
1035   // the order below is important
1036   const Col<eT>* M_local;
1037   const Col<eT>& M;
1038   };
1039 
1040 
1041 
1042 //
1043 //
1044 //
1045 
1046 
1047 
1048 template<typename T1>
1049 struct unwrap_check_mixed
1050   {
1051   typedef typename T1::elem_type eT1;
1052 
1053   template<typename eT2>
1054   inline
unwrap_check_mixedunwrap_check_mixed1055   unwrap_check_mixed(const T1& A, const Mat<eT2>&)
1056     : M(A)
1057     {
1058     arma_extra_debug_sigprint();
1059     }
1060 
1061   //template<typename eT2>
1062   inline
unwrap_check_mixedunwrap_check_mixed1063   unwrap_check_mixed(const T1& A, const bool)
1064     : M(A)
1065     {
1066     arma_extra_debug_sigprint();
1067     }
1068 
1069   const Mat<eT1> M;
1070   };
1071 
1072 
1073 
1074 template<typename eT1>
1075 struct unwrap_check_mixed< Mat<eT1> >
1076   {
1077   template<typename eT2>
1078   inline
unwrap_check_mixedunwrap_check_mixed1079   unwrap_check_mixed(const Mat<eT1>& A, const Mat<eT2>& B)
1080     : M_local( (void_ptr(&A) == void_ptr(&B)) ? new Mat<eT1>(A) : nullptr )
1081     , M      ( (void_ptr(&A) == void_ptr(&B)) ? (*M_local)      : A       )
1082     {
1083     arma_extra_debug_sigprint();
1084     }
1085 
1086   //template<typename eT2>
1087   inline
unwrap_check_mixedunwrap_check_mixed1088   unwrap_check_mixed(const Mat<eT1>& A, const bool is_alias)
1089     : M_local( is_alias ? new Mat<eT1>(A) : nullptr )
1090     , M      ( is_alias ? (*M_local)      : A       )
1091     {
1092     arma_extra_debug_sigprint();
1093     }
1094 
1095   inline
~unwrap_check_mixedunwrap_check_mixed1096   ~unwrap_check_mixed()
1097     {
1098     arma_extra_debug_sigprint();
1099 
1100     if(M_local) { delete M_local; }
1101     }
1102 
1103 
1104   // the order below is important
1105   const Mat<eT1>* M_local;
1106   const Mat<eT1>& M;
1107   };
1108 
1109 
1110 
1111 template<typename eT1>
1112 struct unwrap_check_mixed< Row<eT1> >
1113   {
1114   template<typename eT2>
1115   inline
unwrap_check_mixedunwrap_check_mixed1116   unwrap_check_mixed(const Row<eT1>& A, const Mat<eT2>& B)
1117     : M_local( (void_ptr(&A) == void_ptr(&B)) ? new Row<eT1>(A) : nullptr )
1118     , M      ( (void_ptr(&A) == void_ptr(&B)) ? (*M_local)      : A       )
1119     {
1120     arma_extra_debug_sigprint();
1121     }
1122 
1123 
1124   //template<typename eT2>
1125   inline
unwrap_check_mixedunwrap_check_mixed1126   unwrap_check_mixed(const Row<eT1>& A, const bool is_alias)
1127     : M_local( is_alias ? new Row<eT1>(A) : nullptr )
1128     , M      ( is_alias ? (*M_local)      : A       )
1129     {
1130     arma_extra_debug_sigprint();
1131     }
1132 
1133   inline
~unwrap_check_mixedunwrap_check_mixed1134   ~unwrap_check_mixed()
1135     {
1136     arma_extra_debug_sigprint();
1137 
1138     if(M_local) { delete M_local; }
1139     }
1140 
1141 
1142   // the order below is important
1143   const Row<eT1>* M_local;
1144   const Row<eT1>& M;
1145   };
1146 
1147 
1148 
1149 template<typename eT1>
1150 struct unwrap_check_mixed< Col<eT1> >
1151   {
1152   template<typename eT2>
1153   inline
unwrap_check_mixedunwrap_check_mixed1154   unwrap_check_mixed(const Col<eT1>& A, const Mat<eT2>& B)
1155     : M_local( (void_ptr(&A) == void_ptr(&B)) ? new Col<eT1>(A) : nullptr )
1156     , M      ( (void_ptr(&A) == void_ptr(&B)) ? (*M_local)      : A       )
1157     {
1158     arma_extra_debug_sigprint();
1159     }
1160 
1161   //template<typename eT2>
1162   inline
unwrap_check_mixedunwrap_check_mixed1163   unwrap_check_mixed(const Col<eT1>& A, const bool is_alias)
1164     : M_local( is_alias ? new Col<eT1>(A) : nullptr )
1165     , M      ( is_alias ? (*M_local)      : A       )
1166     {
1167     arma_extra_debug_sigprint();
1168     }
1169 
1170   inline
~unwrap_check_mixedunwrap_check_mixed1171   ~unwrap_check_mixed()
1172     {
1173     arma_extra_debug_sigprint();
1174 
1175     if(M_local) { delete M_local; }
1176     }
1177 
1178 
1179   // the order below is important
1180   const Col<eT1>* M_local;
1181   const Col<eT1>& M;
1182   };
1183 
1184 
1185 
1186 //
1187 //
1188 //
1189 
1190 
1191 
1192 template<typename T1>
1193 struct partial_unwrap_default
1194   {
1195   typedef typename T1::elem_type eT;
1196   typedef Mat<eT>                stored_type;
1197 
1198   inline
partial_unwrap_defaultpartial_unwrap_default1199   partial_unwrap_default(const T1& A)
1200     : M(A)
1201     {
1202     arma_extra_debug_sigprint();
1203     }
1204 
get_valpartial_unwrap_default1205   constexpr eT get_val() const { return eT(1); }
1206 
1207   template<typename eT2>
is_aliaspartial_unwrap_default1208   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1209 
1210   static constexpr bool do_trans = false;
1211   static constexpr bool do_times = false;
1212 
1213   const Mat<eT> M;
1214   };
1215 
1216 
1217 template<typename T1>
1218 struct partial_unwrap_fixed
1219   {
1220   typedef typename T1::elem_type eT;
1221   typedef T1                     stored_type;
1222 
1223   inline explicit
partial_unwrap_fixedpartial_unwrap_fixed1224   partial_unwrap_fixed(const T1& A)
1225     : M(A)
1226     {
1227     arma_extra_debug_sigprint();
1228     }
1229 
get_valpartial_unwrap_fixed1230   constexpr eT get_val() const { return eT(1); }
1231 
1232   template<typename eT2>
is_aliaspartial_unwrap_fixed1233   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1234 
1235   static constexpr bool do_trans = false;
1236   static constexpr bool do_times = false;
1237 
1238   const T1& M;
1239   };
1240 
1241 
1242 
1243 template<typename T1, bool condition>
1244 struct partial_unwrap_redirect {};
1245 
1246 template<typename T1>
1247 struct partial_unwrap_redirect<T1, false> { typedef partial_unwrap_default<T1> result; };
1248 
1249 template<typename T1>
1250 struct partial_unwrap_redirect<T1, true>  { typedef partial_unwrap_fixed<T1>   result; };
1251 
1252 template<typename T1>
1253 struct partial_unwrap : public partial_unwrap_redirect<T1, is_Mat_fixed<T1>::value>::result
1254   {
1255   inline
partial_unwrappartial_unwrap1256   partial_unwrap(const T1& A)
1257     : partial_unwrap_redirect< T1, is_Mat_fixed<T1>::value>::result(A)
1258     {
1259     }
1260   };
1261 
1262 
1263 
1264 template<typename eT>
1265 struct partial_unwrap< Mat<eT> >
1266   {
1267   typedef Mat<eT> stored_type;
1268 
1269   inline
partial_unwrappartial_unwrap1270   partial_unwrap(const Mat<eT>& A)
1271     : M(A)
1272     {
1273     arma_extra_debug_sigprint();
1274     }
1275 
get_valpartial_unwrap1276   constexpr eT get_val() const { return eT(1); }
1277 
1278   template<typename eT2>
is_aliaspartial_unwrap1279   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1280 
1281   static constexpr bool do_trans = false;
1282   static constexpr bool do_times = false;
1283 
1284   const Mat<eT>& M;
1285   };
1286 
1287 
1288 
1289 template<typename eT>
1290 struct partial_unwrap< Row<eT> >
1291   {
1292   typedef Row<eT> stored_type;
1293 
1294   inline
partial_unwrappartial_unwrap1295   partial_unwrap(const Row<eT>& A)
1296     : M(A)
1297     {
1298     arma_extra_debug_sigprint();
1299     }
1300 
get_valpartial_unwrap1301   constexpr eT get_val() const { return eT(1); }
1302 
1303   template<typename eT2>
is_aliaspartial_unwrap1304   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1305 
1306   static constexpr bool do_trans = false;
1307   static constexpr bool do_times = false;
1308 
1309   const Row<eT>& M;
1310   };
1311 
1312 
1313 
1314 template<typename eT>
1315 struct partial_unwrap< Col<eT> >
1316   {
1317   typedef Col<eT> stored_type;
1318 
1319   inline
partial_unwrappartial_unwrap1320   partial_unwrap(const Col<eT>& A)
1321     : M(A)
1322     {
1323     arma_extra_debug_sigprint();
1324     }
1325 
get_valpartial_unwrap1326   constexpr eT get_val() const { return eT(1); }
1327 
1328   template<typename eT2>
is_aliaspartial_unwrap1329   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1330 
1331   static constexpr bool do_trans = false;
1332   static constexpr bool do_times = false;
1333 
1334   const Col<eT>& M;
1335   };
1336 
1337 
1338 
1339 template<typename eT>
1340 struct partial_unwrap< subview<eT> >
1341   {
1342   typedef Mat<eT> stored_type;
1343 
1344   inline
partial_unwrappartial_unwrap1345   partial_unwrap(const subview<eT>& A)
1346     : sv( A                                                  )
1347     , M ( A, ((A.aux_row1 == 0) && (A.n_rows == A.m.n_rows)) )  // reuse memory if the subview is a contiguous chunk
1348     {
1349     arma_extra_debug_sigprint();
1350     }
1351 
get_valpartial_unwrap1352   constexpr eT get_val() const { return eT(1); }
1353 
1354   template<typename eT2>
is_aliaspartial_unwrap1355   arma_inline bool is_alias(const Mat<eT2>& X) const { return ( ((sv.aux_row1 == 0) && (sv.n_rows == sv.m.n_rows)) ? (void_ptr(&(sv.m)) == void_ptr(&X)) : false ); }
1356 
1357   static constexpr bool do_trans = false;
1358   static constexpr bool do_times = false;
1359 
1360   const subview<eT>& sv;
1361   const Mat<eT>      M;
1362   };
1363 
1364 
1365 
1366 template<typename eT>
1367 struct partial_unwrap< subview_col<eT> >
1368   {
1369   typedef Col<eT> stored_type;
1370 
1371   inline
partial_unwrappartial_unwrap1372   partial_unwrap(const subview_col<eT>& A)
1373     : orig( A.m )
1374     , M   ( const_cast<eT*>( A.colmem ), A.n_rows, false, false )
1375     {
1376     arma_extra_debug_sigprint();
1377     }
1378 
get_valpartial_unwrap1379   constexpr eT get_val() const { return eT(1); }
1380 
1381   template<typename eT2>
is_aliaspartial_unwrap1382   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
1383 
1384   static constexpr bool do_trans = false;
1385   static constexpr bool do_times = false;
1386 
1387   const Mat<eT>& orig;
1388   const Col<eT>  M;
1389   };
1390 
1391 
1392 
1393 template<typename eT>
1394 struct partial_unwrap< subview_cols<eT> >
1395   {
1396   typedef Mat<eT> stored_type;
1397 
1398   inline
partial_unwrappartial_unwrap1399   partial_unwrap(const subview_cols<eT>& A)
1400     : orig( A.m )
1401     , M   ( const_cast<eT*>( A.colptr(0) ), A.n_rows, A.n_cols, false, false )
1402     {
1403     arma_extra_debug_sigprint();
1404     }
1405 
get_valpartial_unwrap1406   constexpr eT get_val() const { return eT(1); }
1407 
1408   template<typename eT2>
is_aliaspartial_unwrap1409   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
1410 
1411   static constexpr bool do_trans = false;
1412   static constexpr bool do_times = false;
1413 
1414   const Mat<eT>& orig;
1415   const Mat<eT>  M;
1416   };
1417 
1418 
1419 
1420 template<typename eT>
1421 struct partial_unwrap< subview_row<eT> >
1422   {
1423   typedef Row<eT> stored_type;
1424 
1425   inline
partial_unwrappartial_unwrap1426   partial_unwrap(const subview_row<eT>& A)
1427     : M(A)
1428     {
1429     arma_extra_debug_sigprint();
1430     }
1431 
get_valpartial_unwrap1432   constexpr eT get_val() const { return eT(1); }
1433 
1434   template<typename eT2>
is_aliaspartial_unwrap1435   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1436 
1437   static constexpr bool do_trans = false;
1438   static constexpr bool do_times = false;
1439 
1440   const Row<eT> M;
1441   };
1442 
1443 
1444 
1445 template<typename T1>
1446 struct partial_unwrap_htrans_default
1447   {
1448   typedef typename T1::elem_type eT;
1449   typedef Mat<eT>                stored_type;
1450 
1451   inline
partial_unwrap_htrans_defaultpartial_unwrap_htrans_default1452   partial_unwrap_htrans_default(const Op<T1, op_htrans>& A)
1453     : M(A.m)
1454     {
1455     arma_extra_debug_sigprint();
1456     }
1457 
get_valpartial_unwrap_htrans_default1458   constexpr eT get_val() const { return eT(1); }
1459 
1460   template<typename eT2>
is_aliaspartial_unwrap_htrans_default1461   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1462 
1463   static constexpr bool do_trans = true;
1464   static constexpr bool do_times = false;
1465 
1466   const Mat<eT> M;
1467   };
1468 
1469 
1470 template<typename T1>
1471 struct partial_unwrap_htrans_fixed
1472   {
1473   typedef typename T1::elem_type eT;
1474   typedef T1                     stored_type;
1475 
1476   inline explicit
partial_unwrap_htrans_fixedpartial_unwrap_htrans_fixed1477   partial_unwrap_htrans_fixed(const Op<T1, op_htrans>& A)
1478     : M(A.m)
1479     {
1480     arma_extra_debug_sigprint();
1481     }
1482 
get_valpartial_unwrap_htrans_fixed1483   constexpr eT get_val() const { return eT(1); }
1484 
1485   template<typename eT2>
is_aliaspartial_unwrap_htrans_fixed1486   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1487 
1488   static constexpr bool do_trans = true;
1489   static constexpr bool do_times = false;
1490 
1491   const T1& M;
1492   };
1493 
1494 
1495 
1496 template<typename T1, bool condition>
1497 struct partial_unwrap_htrans_redirect {};
1498 
1499 template<typename T1>
1500 struct partial_unwrap_htrans_redirect<T1, false> { typedef partial_unwrap_htrans_default<T1> result; };
1501 
1502 template<typename T1>
1503 struct partial_unwrap_htrans_redirect<T1, true>  { typedef partial_unwrap_htrans_fixed<T1>   result; };
1504 
1505 template<typename T1>
1506 struct partial_unwrap< Op<T1, op_htrans> > : public partial_unwrap_htrans_redirect<T1, is_Mat_fixed<T1>::value>::result
1507   {
partial_unwrappartial_unwrap1508   inline partial_unwrap(const Op<T1, op_htrans>& A)
1509     : partial_unwrap_htrans_redirect<T1, is_Mat_fixed<T1>::value>::result(A)
1510     {
1511     }
1512   };
1513 
1514 
1515 
1516 template<typename eT>
1517 struct partial_unwrap< Op< Mat<eT>, op_htrans> >
1518   {
1519   typedef Mat<eT> stored_type;
1520 
1521   inline
partial_unwrappartial_unwrap1522   partial_unwrap(const Op< Mat<eT>, op_htrans>& A)
1523     : M(A.m)
1524     {
1525     arma_extra_debug_sigprint();
1526     }
1527 
get_valpartial_unwrap1528   constexpr eT get_val() const { return eT(1); }
1529 
1530   template<typename eT2>
is_aliaspartial_unwrap1531   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1532 
1533   static constexpr bool do_trans = true;
1534   static constexpr bool do_times = false;
1535 
1536   const Mat<eT>& M;
1537   };
1538 
1539 
1540 
1541 template<typename eT>
1542 struct partial_unwrap< Op< Row<eT>, op_htrans> >
1543   {
1544   typedef Row<eT> stored_type;
1545 
1546   inline
partial_unwrappartial_unwrap1547   partial_unwrap(const Op< Row<eT>, op_htrans>& A)
1548     : M(A.m)
1549     {
1550     arma_extra_debug_sigprint();
1551     }
1552 
get_valpartial_unwrap1553   constexpr eT get_val() const { return eT(1); }
1554 
1555   template<typename eT2>
is_aliaspartial_unwrap1556   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1557 
1558   static constexpr bool do_trans = true;
1559   static constexpr bool do_times = false;
1560 
1561   const Row<eT>& M;
1562   };
1563 
1564 
1565 
1566 template<typename eT>
1567 struct partial_unwrap< Op< Col<eT>, op_htrans> >
1568   {
1569   typedef Col<eT> stored_type;
1570 
1571   inline
partial_unwrappartial_unwrap1572   partial_unwrap(const Op< Col<eT>, op_htrans>& A)
1573     : M(A.m)
1574     {
1575     arma_extra_debug_sigprint();
1576     }
1577 
get_valpartial_unwrap1578   constexpr eT get_val() const { return eT(1); }
1579 
1580   template<typename eT2>
is_aliaspartial_unwrap1581   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1582 
1583   static constexpr bool do_trans = true;
1584   static constexpr bool do_times = false;
1585 
1586   const Col<eT>& M;
1587   };
1588 
1589 
1590 
1591 template<typename eT>
1592 struct partial_unwrap< Op< subview<eT>, op_htrans> >
1593   {
1594   typedef Mat<eT> stored_type;
1595 
1596   inline
partial_unwrappartial_unwrap1597   partial_unwrap(const Op< subview<eT>, op_htrans>& A)
1598     : sv( A.m                                                        )
1599     , M ( A.m, ((A.m.aux_row1 == 0) && (A.m.n_rows == A.m.m.n_rows)) )  // reuse memory if the subview is a contiguous chunk
1600     {
1601     arma_extra_debug_sigprint();
1602     }
1603 
get_valpartial_unwrap1604   constexpr eT get_val() const { return eT(1); }
1605 
1606   template<typename eT2>
is_aliaspartial_unwrap1607   arma_inline bool is_alias(const Mat<eT2>& X) const { return ( ((sv.aux_row1 == 0) && (sv.n_rows == sv.m.n_rows)) ? (void_ptr(&(sv.m)) == void_ptr(&X)) : false ); }
1608 
1609   static constexpr bool do_trans = true;
1610   static constexpr bool do_times = false;
1611 
1612   const subview<eT>& sv;
1613   const Mat<eT>      M;
1614   };
1615 
1616 
1617 
1618 template<typename eT>
1619 struct partial_unwrap< Op< subview_cols<eT>, op_htrans> >
1620   {
1621   typedef Mat<eT> stored_type;
1622 
1623   inline
partial_unwrappartial_unwrap1624   partial_unwrap(const Op< subview_cols<eT>, op_htrans>& A)
1625     : orig( A.m.m )
1626     , M   ( const_cast<eT*>( A.m.colptr(0) ), A.m.n_rows, A.m.n_cols, false, false )
1627     {
1628     arma_extra_debug_sigprint();
1629     }
1630 
get_valpartial_unwrap1631   constexpr eT get_val() const { return eT(1); }
1632 
1633   template<typename eT2>
is_aliaspartial_unwrap1634   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
1635 
1636   static constexpr bool do_trans = true;
1637   static constexpr bool do_times = false;
1638 
1639   const Mat<eT>& orig;
1640   const Mat<eT>  M;
1641   };
1642 
1643 
1644 
1645 template<typename eT>
1646 struct partial_unwrap< Op< subview_col<eT>, op_htrans> >
1647   {
1648   typedef Col<eT> stored_type;
1649 
1650   inline
partial_unwrappartial_unwrap1651   partial_unwrap(const Op< subview_col<eT>, op_htrans>& A)
1652     : orig( A.m.m )
1653     , M   ( const_cast<eT*>( A.m.colmem ), A.m.n_rows, false, false )
1654     {
1655     arma_extra_debug_sigprint();
1656     }
1657 
get_valpartial_unwrap1658   constexpr eT get_val() const { return eT(1); }
1659 
1660   template<typename eT2>
is_aliaspartial_unwrap1661   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
1662 
1663   static constexpr bool do_trans = true;
1664   static constexpr bool do_times = false;
1665 
1666   const Mat<eT>& orig;
1667   const Col<eT>  M;
1668   };
1669 
1670 
1671 
1672 template<typename eT>
1673 struct partial_unwrap< Op< subview_row<eT>, op_htrans> >
1674   {
1675   typedef Row<eT> stored_type;
1676 
1677   inline
partial_unwrappartial_unwrap1678   partial_unwrap(const Op< subview_row<eT>, op_htrans>& A)
1679     : M(A.m)
1680     {
1681     arma_extra_debug_sigprint();
1682     }
1683 
get_valpartial_unwrap1684   constexpr eT get_val() const { return eT(1); }
1685 
1686   template<typename eT2>
is_aliaspartial_unwrap1687   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1688 
1689   static constexpr bool do_trans = true;
1690   static constexpr bool do_times = false;
1691 
1692   const Row<eT> M;
1693   };
1694 
1695 
1696 
1697 template<typename T1>
1698 struct partial_unwrap_htrans2_default
1699   {
1700   typedef typename T1::elem_type eT;
1701   typedef Mat<eT>                stored_type;
1702 
1703   inline
partial_unwrap_htrans2_defaultpartial_unwrap_htrans2_default1704   partial_unwrap_htrans2_default(const Op<T1, op_htrans2>& A)
1705     : val(A.aux)
1706     , M  (A.m)
1707     {
1708     arma_extra_debug_sigprint();
1709     }
1710 
get_valpartial_unwrap_htrans2_default1711   arma_inline eT get_val() const { return val; }
1712 
1713   template<typename eT2>
is_aliaspartial_unwrap_htrans2_default1714   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1715 
1716   static constexpr bool do_trans = true;
1717   static constexpr bool do_times = true;
1718 
1719   const eT      val;
1720   const Mat<eT> M;
1721   };
1722 
1723 
1724 template<typename T1>
1725 struct partial_unwrap_htrans2_fixed
1726   {
1727   typedef typename T1::elem_type eT;
1728   typedef T1                     stored_type;
1729 
1730   inline explicit
partial_unwrap_htrans2_fixedpartial_unwrap_htrans2_fixed1731   partial_unwrap_htrans2_fixed(const Op<T1, op_htrans2>& A)
1732     : val(A.aux)
1733     , M  (A.m)
1734     {
1735     arma_extra_debug_sigprint();
1736     }
1737 
get_valpartial_unwrap_htrans2_fixed1738   arma_inline eT get_val() const { return val; }
1739 
1740   template<typename eT2>
is_aliaspartial_unwrap_htrans2_fixed1741   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1742 
1743   static constexpr bool do_trans = true;
1744   static constexpr bool do_times = true;
1745 
1746   const eT  val;
1747   const T1& M;
1748   };
1749 
1750 
1751 
1752 template<typename T1, bool condition>
1753 struct partial_unwrap_htrans2_redirect {};
1754 
1755 template<typename T1>
1756 struct partial_unwrap_htrans2_redirect<T1, false> { typedef partial_unwrap_htrans2_default<T1> result; };
1757 
1758 template<typename T1>
1759 struct partial_unwrap_htrans2_redirect<T1, true>  { typedef partial_unwrap_htrans2_fixed<T1>   result; };
1760 
1761 template<typename T1>
1762 struct partial_unwrap< Op<T1, op_htrans2> > : public partial_unwrap_htrans2_redirect<T1, is_Mat_fixed<T1>::value>::result
1763   {
partial_unwrappartial_unwrap1764   inline partial_unwrap(const Op<T1, op_htrans2>& A)
1765     : partial_unwrap_htrans2_redirect<T1, is_Mat_fixed<T1>::value>::result(A)
1766     {
1767     }
1768   };
1769 
1770 
1771 
1772 template<typename eT>
1773 struct partial_unwrap< Op< Mat<eT>, op_htrans2> >
1774   {
1775   typedef Mat<eT> stored_type;
1776 
1777   inline
partial_unwrappartial_unwrap1778   partial_unwrap(const Op< Mat<eT>, op_htrans2>& A)
1779     : val(A.aux)
1780     , M  (A.m)
1781     {
1782     arma_extra_debug_sigprint();
1783     }
1784 
get_valpartial_unwrap1785   inline eT get_val() const { return val; }
1786 
1787   template<typename eT2>
is_aliaspartial_unwrap1788   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1789 
1790   static constexpr bool do_trans = true;
1791   static constexpr bool do_times = true;
1792 
1793   const eT       val;
1794   const Mat<eT>& M;
1795   };
1796 
1797 
1798 
1799 template<typename eT>
1800 struct partial_unwrap< Op< Row<eT>, op_htrans2> >
1801   {
1802   typedef Row<eT> stored_type;
1803 
1804   inline
partial_unwrappartial_unwrap1805   partial_unwrap(const Op< Row<eT>, op_htrans2>& A)
1806     : val(A.aux)
1807     , M  (A.m)
1808     {
1809     arma_extra_debug_sigprint();
1810     }
1811 
get_valpartial_unwrap1812   inline eT get_val() const { return val; }
1813 
1814   template<typename eT2>
is_aliaspartial_unwrap1815   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1816 
1817   static constexpr bool do_trans = true;
1818   static constexpr bool do_times = true;
1819 
1820   const eT       val;
1821   const Row<eT>& M;
1822   };
1823 
1824 
1825 
1826 template<typename eT>
1827 struct partial_unwrap< Op< Col<eT>, op_htrans2> >
1828   {
1829   typedef Col<eT> stored_type;
1830 
1831   inline
partial_unwrappartial_unwrap1832   partial_unwrap(const Op< Col<eT>, op_htrans2>& A)
1833     : val(A.aux)
1834     , M  (A.m)
1835     {
1836     arma_extra_debug_sigprint();
1837     }
1838 
get_valpartial_unwrap1839   inline eT get_val() const { return val; }
1840 
1841   template<typename eT2>
is_aliaspartial_unwrap1842   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
1843 
1844   static constexpr bool do_trans = true;
1845   static constexpr bool do_times = true;
1846 
1847   const eT       val;
1848   const Col<eT>& M;
1849   };
1850 
1851 
1852 
1853 template<typename eT>
1854 struct partial_unwrap< Op< subview<eT>, op_htrans2> >
1855   {
1856   typedef Mat<eT> stored_type;
1857 
1858   inline
partial_unwrappartial_unwrap1859   partial_unwrap(const Op< subview<eT>, op_htrans2>& A)
1860     : sv ( A.m   )
1861     , val( A.aux )
1862     , M  ( A.m, ((A.m.aux_row1 == 0) && (A.m.n_rows == A.m.m.n_rows)) )  // reuse memory if the subview is a contiguous chunk
1863     {
1864     arma_extra_debug_sigprint();
1865     }
1866 
get_valpartial_unwrap1867   inline eT get_val() const { return val; }
1868 
1869   template<typename eT2>
is_aliaspartial_unwrap1870   arma_inline bool is_alias(const Mat<eT2>& X) const { return ( ((sv.aux_row1 == 0) && (sv.n_rows == sv.m.n_rows)) ? (void_ptr(&(sv.m)) == void_ptr(&X)) : false ); }
1871 
1872   static constexpr bool do_trans = true;
1873   static constexpr bool do_times = true;
1874 
1875   const subview<eT>& sv;
1876   const eT           val;
1877   const Mat<eT>      M;
1878   };
1879 
1880 
1881 
1882 template<typename eT>
1883 struct partial_unwrap< Op< subview_cols<eT>, op_htrans2> >
1884   {
1885   typedef Mat<eT> stored_type;
1886 
1887   inline
partial_unwrappartial_unwrap1888   partial_unwrap(const Op< subview_cols<eT>, op_htrans2>& A)
1889     : orig( A.m.m )
1890     , val ( A.aux )
1891     , M   ( const_cast<eT*>( A.m.colptr(0) ), A.m.n_rows, A.m.n_cols, false, false )
1892     {
1893     arma_extra_debug_sigprint();
1894     }
1895 
get_valpartial_unwrap1896   inline eT get_val() const { return val; }
1897 
1898   template<typename eT2>
is_aliaspartial_unwrap1899   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&orig) == void_ptr(&X)); }
1900 
1901   static constexpr bool do_trans = true;
1902   static constexpr bool do_times = true;
1903 
1904   const Mat<eT>& orig;
1905   const eT       val;
1906   const Mat<eT>  M;
1907   };
1908 
1909 
1910 
1911 template<typename eT>
1912 struct partial_unwrap< Op< subview_col<eT>, op_htrans2> >
1913   {
1914   typedef Col<eT> stored_type;
1915 
1916   inline
partial_unwrappartial_unwrap1917   partial_unwrap(const Op< subview_col<eT>, op_htrans2>& A)
1918     : orig( A.m.m )
1919     , val ( A.aux )
1920     , M   ( const_cast<eT*>( A.m.colmem ), A.m.n_rows, false, false )
1921     {
1922     arma_extra_debug_sigprint();
1923     }
1924 
get_valpartial_unwrap1925   inline eT get_val() const { return val; }
1926 
1927   template<typename eT2>
is_aliaspartial_unwrap1928   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
1929 
1930   static constexpr bool do_trans = true;
1931   static constexpr bool do_times = true;
1932 
1933   const Mat<eT>& orig;
1934 
1935   const eT      val;
1936   const Col<eT> M;
1937   };
1938 
1939 
1940 
1941 template<typename eT>
1942 struct partial_unwrap< Op< subview_row<eT>, op_htrans2> >
1943   {
1944   typedef Row<eT> stored_type;
1945 
1946   inline
partial_unwrappartial_unwrap1947   partial_unwrap(const Op< subview_row<eT>, op_htrans2>& A)
1948     : val(A.aux)
1949     , M  (A.m  )
1950     {
1951     arma_extra_debug_sigprint();
1952     }
1953 
get_valpartial_unwrap1954   arma_inline eT get_val() const { return val; }
1955 
1956   template<typename eT2>
is_aliaspartial_unwrap1957   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1958 
1959   static constexpr bool do_trans = true;
1960   static constexpr bool do_times = true;
1961 
1962   const eT      val;
1963   const Row<eT> M;
1964   };
1965 
1966 
1967 
1968 template<typename T1>
1969 struct partial_unwrap_scalar_times_default
1970   {
1971   typedef typename T1::elem_type eT;
1972   typedef Mat<eT>                stored_type;
1973 
1974   inline
partial_unwrap_scalar_times_defaultpartial_unwrap_scalar_times_default1975   partial_unwrap_scalar_times_default(const eOp<T1, eop_scalar_times>& A)
1976     : val(A.aux)
1977     , M  (A.P.Q)
1978     {
1979     arma_extra_debug_sigprint();
1980     }
1981 
get_valpartial_unwrap_scalar_times_default1982   arma_inline eT get_val() const { return val; }
1983 
1984   template<typename eT2>
is_aliaspartial_unwrap_scalar_times_default1985   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
1986 
1987   static constexpr bool do_trans = false;
1988   static constexpr bool do_times = true;
1989 
1990   const eT      val;
1991   const Mat<eT> M;
1992   };
1993 
1994 
1995 
1996 template<typename T1>
1997 struct partial_unwrap_scalar_times_fixed
1998   {
1999   typedef typename T1::elem_type eT;
2000   typedef T1                     stored_type;
2001 
2002   inline explicit
partial_unwrap_scalar_times_fixedpartial_unwrap_scalar_times_fixed2003   partial_unwrap_scalar_times_fixed(const eOp<T1, eop_scalar_times>& A)
2004     : val(A.aux)
2005     , M  (A.P.Q)
2006     {
2007     arma_extra_debug_sigprint();
2008     }
2009 
get_valpartial_unwrap_scalar_times_fixed2010   arma_inline eT get_val() const { return val; }
2011 
2012   template<typename eT2>
is_aliaspartial_unwrap_scalar_times_fixed2013   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2014 
2015   static constexpr bool do_trans = false;
2016   static constexpr bool do_times = true;
2017 
2018   const eT  val;
2019   const T1& M;
2020   };
2021 
2022 
2023 
2024 template<typename T1, bool condition>
2025 struct partial_unwrap_scalar_times_redirect {};
2026 
2027 template<typename T1>
2028 struct partial_unwrap_scalar_times_redirect<T1, false> { typedef partial_unwrap_scalar_times_default<T1> result; };
2029 
2030 template<typename T1>
2031 struct partial_unwrap_scalar_times_redirect<T1, true>  { typedef partial_unwrap_scalar_times_fixed<T1>   result; };
2032 
2033 
2034 template<typename T1>
2035 struct partial_unwrap< eOp<T1, eop_scalar_times> > : public partial_unwrap_scalar_times_redirect<T1, is_Mat_fixed<T1>::value>::result
2036   {
2037   typedef typename T1::elem_type eT;
2038 
2039   inline
partial_unwrappartial_unwrap2040   partial_unwrap(const eOp<T1, eop_scalar_times>& A)
2041     : partial_unwrap_scalar_times_redirect< T1, is_Mat_fixed<T1>::value>::result(A)
2042     {
2043     }
2044   };
2045 
2046 
2047 
2048 template<typename eT>
2049 struct partial_unwrap< eOp<Mat<eT>, eop_scalar_times> >
2050   {
2051   typedef Mat<eT> stored_type;
2052 
2053   inline
partial_unwrappartial_unwrap2054   partial_unwrap(const eOp<Mat<eT>,eop_scalar_times>& A)
2055     : val(A.aux)
2056     , M  (A.P.Q)
2057     {
2058     arma_extra_debug_sigprint();
2059     }
2060 
get_valpartial_unwrap2061   inline eT get_val() const { return val; }
2062 
2063   template<typename eT2>
is_aliaspartial_unwrap2064   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2065 
2066   static constexpr bool do_trans = false;
2067   static constexpr bool do_times = true;
2068 
2069   const eT       val;
2070   const Mat<eT>& M;
2071   };
2072 
2073 
2074 
2075 template<typename eT>
2076 struct partial_unwrap< eOp<Row<eT>, eop_scalar_times> >
2077   {
2078   typedef Row<eT> stored_type;
2079 
2080   inline
partial_unwrappartial_unwrap2081   partial_unwrap(const eOp<Row<eT>,eop_scalar_times>& A)
2082     : val(A.aux)
2083     , M  (A.P.Q)
2084     {
2085     arma_extra_debug_sigprint();
2086     }
2087 
get_valpartial_unwrap2088   inline eT get_val() const { return val; }
2089 
2090   template<typename eT2>
is_aliaspartial_unwrap2091   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2092 
2093   static constexpr bool do_trans = false;
2094   static constexpr bool do_times = true;
2095 
2096   const eT       val;
2097   const Row<eT>& M;
2098   };
2099 
2100 
2101 
2102 template<typename eT>
2103 struct partial_unwrap< eOp<Col<eT>, eop_scalar_times> >
2104   {
2105   typedef Col<eT> stored_type;
2106 
2107   inline
partial_unwrappartial_unwrap2108   partial_unwrap(const eOp<Col<eT>,eop_scalar_times>& A)
2109     : val(A.aux)
2110     , M  (A.P.Q)
2111     {
2112     arma_extra_debug_sigprint();
2113     }
2114 
get_valpartial_unwrap2115   inline eT get_val() const { return val; }
2116 
2117   template<typename eT2>
is_aliaspartial_unwrap2118   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2119 
2120   static constexpr bool do_trans = false;
2121   static constexpr bool do_times = true;
2122 
2123   const eT       val;
2124   const Col<eT>& M;
2125   };
2126 
2127 
2128 
2129 template<typename eT>
2130 struct partial_unwrap< eOp<subview_col<eT>, eop_scalar_times> >
2131   {
2132   typedef Col<eT> stored_type;
2133 
2134   inline
partial_unwrappartial_unwrap2135   partial_unwrap(const eOp<subview_col<eT>,eop_scalar_times>& A)
2136     : orig( A.P.Q.m )
2137     , val ( A.aux   )
2138     , M   ( const_cast<eT*>( A.P.Q.colmem ), A.P.Q.n_rows, false, false )
2139     {
2140     arma_extra_debug_sigprint();
2141     }
2142 
get_valpartial_unwrap2143   arma_inline eT get_val() const { return val; }
2144 
2145   template<typename eT2>
is_aliaspartial_unwrap2146   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
2147 
2148   static constexpr bool do_trans = false;
2149   static constexpr bool do_times = true;
2150 
2151   const Mat<eT>& orig;
2152 
2153   const eT      val;
2154   const Col<eT> M;
2155   };
2156 
2157 
2158 
2159 template<typename eT>
2160 struct partial_unwrap< eOp<subview_row<eT>, eop_scalar_times> >
2161   {
2162   typedef Row<eT> stored_type;
2163 
2164   inline
partial_unwrappartial_unwrap2165   partial_unwrap(const eOp<subview_row<eT>,eop_scalar_times>& A)
2166     : val(A.aux)
2167     , M  (A.P.Q)
2168     {
2169     arma_extra_debug_sigprint();
2170     }
2171 
get_valpartial_unwrap2172   arma_inline eT get_val() const { return val; }
2173 
2174   template<typename eT2>
is_aliaspartial_unwrap2175   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
2176 
2177   static constexpr bool do_trans = false;
2178   static constexpr bool do_times = true;
2179 
2180   const eT      val;
2181   const Row<eT> M;
2182   };
2183 
2184 
2185 
2186 template<typename T1>
2187 struct partial_unwrap_neg_default
2188   {
2189   typedef typename T1::elem_type eT;
2190   typedef Mat<eT>                stored_type;
2191 
2192   inline
partial_unwrap_neg_defaultpartial_unwrap_neg_default2193   partial_unwrap_neg_default(const eOp<T1, eop_neg>& A)
2194     : M(A.P.Q)
2195     {
2196     arma_extra_debug_sigprint();
2197     }
2198 
get_valpartial_unwrap_neg_default2199   constexpr eT get_val() const { return eT(-1); }
2200 
2201   template<typename eT2>
is_aliaspartial_unwrap_neg_default2202   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
2203 
2204   static constexpr bool do_trans = false;
2205   static constexpr bool do_times = true;
2206 
2207   const Mat<eT> M;
2208   };
2209 
2210 
2211 
2212 template<typename T1>
2213 struct partial_unwrap_neg_fixed
2214   {
2215   typedef typename T1::elem_type eT;
2216   typedef T1                     stored_type;
2217 
2218   inline explicit
partial_unwrap_neg_fixedpartial_unwrap_neg_fixed2219   partial_unwrap_neg_fixed(const eOp<T1, eop_neg>& A)
2220     : M(A.P.Q)
2221     {
2222     arma_extra_debug_sigprint();
2223     }
2224 
get_valpartial_unwrap_neg_fixed2225   constexpr eT get_val() const { return eT(-1); }
2226 
2227   template<typename eT2>
is_aliaspartial_unwrap_neg_fixed2228   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2229 
2230   static constexpr bool do_trans = false;
2231   static constexpr bool do_times = true;
2232 
2233   const T1& M;
2234   };
2235 
2236 
2237 
2238 template<typename T1, bool condition>
2239 struct partial_unwrap_neg_redirect {};
2240 
2241 template<typename T1>
2242 struct partial_unwrap_neg_redirect<T1, false> { typedef partial_unwrap_neg_default<T1> result; };
2243 
2244 template<typename T1>
2245 struct partial_unwrap_neg_redirect<T1, true>  { typedef partial_unwrap_neg_fixed<T1>   result; };
2246 
2247 
2248 template<typename T1>
2249 struct partial_unwrap< eOp<T1, eop_neg> > : public partial_unwrap_neg_redirect<T1, is_Mat_fixed<T1>::value>::result
2250   {
2251   typedef typename T1::elem_type eT;
2252 
2253   inline
partial_unwrappartial_unwrap2254   partial_unwrap(const eOp<T1, eop_neg>& A)
2255     : partial_unwrap_neg_redirect< T1, is_Mat_fixed<T1>::value>::result(A)
2256     {
2257     }
2258   };
2259 
2260 
2261 
2262 template<typename eT>
2263 struct partial_unwrap< eOp<Mat<eT>, eop_neg> >
2264   {
2265   typedef Mat<eT> stored_type;
2266 
2267   inline
partial_unwrappartial_unwrap2268   partial_unwrap(const eOp<Mat<eT>,eop_neg>& A)
2269     : M(A.P.Q)
2270     {
2271     arma_extra_debug_sigprint();
2272     }
2273 
get_valpartial_unwrap2274   constexpr eT get_val() const { return eT(-1); }
2275 
2276   template<typename eT2>
is_aliaspartial_unwrap2277   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2278 
2279   static constexpr bool do_trans = false;
2280   static constexpr bool do_times = true;
2281 
2282   const Mat<eT>& M;
2283   };
2284 
2285 
2286 
2287 template<typename eT>
2288 struct partial_unwrap< eOp<Row<eT>, eop_neg> >
2289   {
2290   typedef Row<eT> stored_type;
2291 
2292   inline
partial_unwrappartial_unwrap2293   partial_unwrap(const eOp<Row<eT>,eop_neg>& A)
2294     : M(A.P.Q)
2295     {
2296     arma_extra_debug_sigprint();
2297     }
2298 
get_valpartial_unwrap2299   constexpr eT get_val() const { return eT(-1); }
2300 
2301   template<typename eT2>
is_aliaspartial_unwrap2302   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2303 
2304   static constexpr bool do_trans = false;
2305   static constexpr bool do_times = true;
2306 
2307   const Row<eT>& M;
2308   };
2309 
2310 
2311 
2312 template<typename eT>
2313 struct partial_unwrap< eOp<Col<eT>, eop_neg> >
2314   {
2315   typedef Col<eT> stored_type;
2316 
2317   inline
partial_unwrappartial_unwrap2318   partial_unwrap(const eOp<Col<eT>,eop_neg>& A)
2319     : M(A.P.Q)
2320     {
2321     arma_extra_debug_sigprint();
2322     }
2323 
get_valpartial_unwrap2324   constexpr eT get_val() const { return eT(-1); }
2325 
2326   template<typename eT2>
is_aliaspartial_unwrap2327   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&M)); }
2328 
2329   static constexpr bool do_trans = false;
2330   static constexpr bool do_times = true;
2331 
2332   const Col<eT>& M;
2333   };
2334 
2335 
2336 
2337 template<typename eT>
2338 struct partial_unwrap< eOp<subview_col<eT>, eop_neg> >
2339   {
2340   typedef Col<eT> stored_type;
2341 
2342   inline
partial_unwrappartial_unwrap2343   partial_unwrap(const eOp<subview_col<eT>,eop_neg>& A)
2344     : orig( A.P.Q.m )
2345     , M   ( const_cast<eT*>( A.P.Q.colmem ), A.P.Q.n_rows, false, false )
2346     {
2347     arma_extra_debug_sigprint();
2348     }
2349 
get_valpartial_unwrap2350   constexpr eT get_val() const { return eT(-1); }
2351 
2352   template<typename eT2>
is_aliaspartial_unwrap2353   arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&X) == void_ptr(&orig)); }
2354 
2355   static constexpr bool do_trans = false;
2356   static constexpr bool do_times = true;
2357 
2358   const Mat<eT>& orig;
2359   const Col<eT>  M;
2360   };
2361 
2362 
2363 
2364 template<typename eT>
2365 struct partial_unwrap< eOp<subview_row<eT>, eop_neg> >
2366   {
2367   typedef Row<eT> stored_type;
2368 
2369   inline
partial_unwrappartial_unwrap2370   partial_unwrap(const eOp<subview_row<eT>,eop_neg>& A)
2371     : M(A.P.Q)
2372     {
2373     arma_extra_debug_sigprint();
2374     }
2375 
get_valpartial_unwrap2376   constexpr eT get_val() const { return eT(-1); }
2377 
2378   template<typename eT2>
is_aliaspartial_unwrap2379   constexpr bool is_alias(const Mat<eT2>&) const { return false; }
2380 
2381   static constexpr bool do_trans = false;
2382   static constexpr bool do_times = true;
2383 
2384   const Row<eT> M;
2385   };
2386 
2387 
2388 
2389 //
2390 
2391 
2392 
2393 template<typename T1>
2394 struct partial_unwrap_check_default
2395   {
2396   typedef typename T1::elem_type eT;
2397   typedef Mat<eT>                stored_type;
2398 
2399   inline
partial_unwrap_check_defaultpartial_unwrap_check_default2400   partial_unwrap_check_default(const T1& A, const Mat<eT>&)
2401     : M(A)
2402     {
2403     arma_extra_debug_sigprint();
2404     }
2405 
get_valpartial_unwrap_check_default2406   constexpr eT get_val() const { return eT(1); }
2407 
2408   static constexpr bool do_trans = false;
2409   static constexpr bool do_times = false;
2410 
2411   const Mat<eT> M;
2412   };
2413 
2414 
2415 template<typename T1>
2416 struct partial_unwrap_check_fixed
2417   {
2418   typedef typename T1::elem_type eT;
2419   typedef T1                     stored_type;
2420 
2421   inline explicit
partial_unwrap_check_fixedpartial_unwrap_check_fixed2422   partial_unwrap_check_fixed(const T1& A, const Mat<eT>& B)
2423     : M_local( (&A == &B) ? new T1(A)  : nullptr )
2424     , M      ( (&A == &B) ? (*M_local) : A       )
2425     {
2426     arma_extra_debug_sigprint();
2427     }
2428 
2429   inline
~partial_unwrap_check_fixedpartial_unwrap_check_fixed2430   ~partial_unwrap_check_fixed()
2431     {
2432     arma_extra_debug_sigprint();
2433 
2434     if(M_local) { delete M_local; }
2435     }
2436 
get_valpartial_unwrap_check_fixed2437   constexpr eT get_val() const { return eT(1); }
2438 
2439   static constexpr bool do_trans = false;
2440   static constexpr bool do_times = false;
2441 
2442   const T1* M_local;
2443   const T1& M;
2444   };
2445 
2446 
2447 
2448 template<typename T1, bool condition>
2449 struct partial_unwrap_check_redirect {};
2450 
2451 template<typename T1>
2452 struct partial_unwrap_check_redirect<T1, false> { typedef partial_unwrap_check_default<T1> result; };
2453 
2454 template<typename T1>
2455 struct partial_unwrap_check_redirect<T1, true>  { typedef partial_unwrap_check_fixed<T1>   result; };
2456 
2457 template<typename T1>
2458 struct partial_unwrap_check : public partial_unwrap_check_redirect<T1, is_Mat_fixed<T1>::value>::result
2459   {
2460   typedef typename T1::elem_type eT;
2461 
partial_unwrap_checkpartial_unwrap_check2462   inline partial_unwrap_check(const T1& A, const Mat<eT>& B)
2463     : partial_unwrap_check_redirect<T1, is_Mat_fixed<T1>::value>::result(A, B)
2464     {
2465     }
2466   };
2467 
2468 
2469 
2470 template<typename eT>
2471 struct partial_unwrap_check< Mat<eT> >
2472   {
2473   typedef Mat<eT> stored_type;
2474 
2475   inline
partial_unwrap_checkpartial_unwrap_check2476   partial_unwrap_check(const Mat<eT>& A, const Mat<eT>& B)
2477     : M_local ( (&A == &B) ? new Mat<eT>(A) : nullptr )
2478     , M       ( (&A == &B) ? (*M_local)     : A       )
2479     {
2480     arma_extra_debug_sigprint();
2481     }
2482 
2483 
2484   inline
~partial_unwrap_checkpartial_unwrap_check2485   ~partial_unwrap_check()
2486     {
2487     arma_extra_debug_sigprint();
2488 
2489     if(M_local) { delete M_local; }
2490     }
2491 
get_valpartial_unwrap_check2492   constexpr eT get_val() const { return eT(1); }
2493 
2494   static constexpr bool do_trans = false;
2495   static constexpr bool do_times = false;
2496 
2497   // the order below is important
2498   const Mat<eT>* M_local;
2499   const Mat<eT>& M;
2500   };
2501 
2502 
2503 
2504 template<typename eT>
2505 struct partial_unwrap_check< Row<eT> >
2506   {
2507   typedef Row<eT> stored_type;
2508 
2509   inline
partial_unwrap_checkpartial_unwrap_check2510   partial_unwrap_check(const Row<eT>& A, const Mat<eT>& B)
2511     : M_local ( (&A == &B) ? new Row<eT>(A) : nullptr )
2512     , M       ( (&A == &B) ? (*M_local)     : A       )
2513     {
2514     arma_extra_debug_sigprint();
2515     }
2516 
2517 
2518   inline
~partial_unwrap_checkpartial_unwrap_check2519   ~partial_unwrap_check()
2520     {
2521     arma_extra_debug_sigprint();
2522 
2523     if(M_local) { delete M_local; }
2524     }
2525 
get_valpartial_unwrap_check2526   constexpr eT get_val() const { return eT(1); }
2527 
2528   static constexpr bool do_trans = false;
2529   static constexpr bool do_times = false;
2530 
2531   // the order below is important
2532   const Row<eT>* M_local;
2533   const Row<eT>& M;
2534   };
2535 
2536 
2537 
2538 template<typename eT>
2539 struct partial_unwrap_check< Col<eT> >
2540   {
2541   typedef Col<eT> stored_type;
2542 
2543   inline
partial_unwrap_checkpartial_unwrap_check2544   partial_unwrap_check(const Col<eT>& A, const Mat<eT>& B)
2545     : M_local ( (&A == &B) ? new Col<eT>(A) : nullptr )
2546     , M       ( (&A == &B) ? (*M_local)     : A       )
2547     {
2548     arma_extra_debug_sigprint();
2549     }
2550 
2551 
2552   inline
~partial_unwrap_checkpartial_unwrap_check2553   ~partial_unwrap_check()
2554     {
2555     arma_extra_debug_sigprint();
2556 
2557     if(M_local) { delete M_local; }
2558     }
2559 
get_valpartial_unwrap_check2560   constexpr eT get_val() const { return eT(1); }
2561 
2562   static constexpr bool do_trans = false;
2563   static constexpr bool do_times = false;
2564 
2565   // the order below is important
2566   const Col<eT>* M_local;
2567   const Col<eT>& M;
2568   };
2569 
2570 
2571 
2572 // NOTE: we can get away with this shortcut as the partial_unwrap_check class is only used by the glue_times class,
2573 // NOTE: which relies on partial_unwrap_check to check for aliasing
2574 template<typename eT>
2575 struct partial_unwrap_check< subview_col<eT> >
2576   {
2577   typedef Col<eT> stored_type;
2578 
2579   inline
partial_unwrap_checkpartial_unwrap_check2580   partial_unwrap_check(const subview_col<eT>& A, const Mat<eT>& B)
2581     : M  ( const_cast<eT*>( A.colmem ), A.n_rows, (&(A.m) == &B), false )
2582     {
2583     arma_extra_debug_sigprint();
2584     }
2585 
get_valpartial_unwrap_check2586   constexpr eT get_val() const { return eT(1); }
2587 
2588   static constexpr bool do_trans = false;
2589   static constexpr bool do_times = false;
2590 
2591   const Col<eT> M;
2592   };
2593 
2594 
2595 
2596 template<typename T1>
2597 struct partial_unwrap_check_htrans_default
2598   {
2599   typedef typename T1::elem_type eT;
2600   typedef Mat<eT>                stored_type;
2601 
2602   inline
partial_unwrap_check_htrans_defaultpartial_unwrap_check_htrans_default2603   partial_unwrap_check_htrans_default(const Op<T1, op_htrans>& A, const Mat<eT>&)
2604     : M(A.m)
2605     {
2606     arma_extra_debug_sigprint();
2607     }
2608 
get_valpartial_unwrap_check_htrans_default2609   constexpr eT get_val() const { return eT(1); }
2610 
2611   static constexpr bool do_trans = true;
2612   static constexpr bool do_times = false;
2613 
2614   const Mat<eT> M;
2615   };
2616 
2617 
2618 template<typename T1>
2619 struct partial_unwrap_check_htrans_fixed
2620   {
2621   typedef typename T1::elem_type eT;
2622   typedef T1                     stored_type;
2623 
2624   inline explicit
partial_unwrap_check_htrans_fixedpartial_unwrap_check_htrans_fixed2625   partial_unwrap_check_htrans_fixed(const Op<T1, op_htrans>& A, const Mat<eT>& B)
2626     : M_local( (&(A.m) == &B) ? new T1(A.m) : nullptr )
2627     , M      ( (&(A.m) == &B) ? (*M_local)  : A.m     )
2628     {
2629     arma_extra_debug_sigprint();
2630     }
2631 
2632   inline
~partial_unwrap_check_htrans_fixedpartial_unwrap_check_htrans_fixed2633   ~partial_unwrap_check_htrans_fixed()
2634     {
2635     arma_extra_debug_sigprint();
2636 
2637     if(M_local) { delete M_local; }
2638     }
2639 
get_valpartial_unwrap_check_htrans_fixed2640   constexpr eT get_val() const { return eT(1); }
2641 
2642   static constexpr bool do_trans = true;
2643   static constexpr bool do_times = false;
2644 
2645   const T1* M_local;
2646   const T1& M;
2647   };
2648 
2649 
2650 
2651 template<typename T1, bool condition>
2652 struct partial_unwrap_check_htrans_redirect {};
2653 
2654 template<typename T1>
2655 struct partial_unwrap_check_htrans_redirect<T1, false> { typedef partial_unwrap_check_htrans_default<T1> result; };
2656 
2657 template<typename T1>
2658 struct partial_unwrap_check_htrans_redirect<T1, true>  { typedef partial_unwrap_check_htrans_fixed<T1>   result; };
2659 
2660 
2661 template<typename T1>
2662 struct partial_unwrap_check< Op<T1, op_htrans> > : public partial_unwrap_check_htrans_redirect<T1, is_Mat_fixed<T1>::value>::result
2663   {
2664   typedef typename T1::elem_type eT;
2665 
partial_unwrap_checkpartial_unwrap_check2666   inline partial_unwrap_check(const Op<T1, op_htrans>& A, const Mat<eT>& B)
2667     : partial_unwrap_check_htrans_redirect<T1, is_Mat_fixed<T1>::value>::result(A, B)
2668     {
2669     }
2670   };
2671 
2672 
2673 
2674 template<typename eT>
2675 struct partial_unwrap_check< Op< Mat<eT>, op_htrans> >
2676   {
2677   typedef Mat<eT> stored_type;
2678 
2679   inline
partial_unwrap_checkpartial_unwrap_check2680   partial_unwrap_check(const Op< Mat<eT>, op_htrans>& A, const Mat<eT>& B)
2681     : M_local ( (&A.m == &B) ? new Mat<eT>(A.m) : nullptr )
2682     , M       ( (&A.m == &B) ? (*M_local)       : A.m     )
2683     {
2684     arma_extra_debug_sigprint();
2685     }
2686 
2687   inline
~partial_unwrap_checkpartial_unwrap_check2688   ~partial_unwrap_check()
2689     {
2690     arma_extra_debug_sigprint();
2691 
2692     if(M_local) { delete M_local; }
2693     }
2694 
get_valpartial_unwrap_check2695   constexpr eT get_val() const { return eT(1); }
2696 
2697   static constexpr bool do_trans = true;
2698   static constexpr bool do_times = false;
2699 
2700   // the order below is important
2701   const Mat<eT>* M_local;
2702   const Mat<eT>& M;
2703   };
2704 
2705 
2706 
2707 template<typename eT>
2708 struct partial_unwrap_check< Op< Row<eT>, op_htrans> >
2709   {
2710   typedef Row<eT> stored_type;
2711 
2712   inline
partial_unwrap_checkpartial_unwrap_check2713   partial_unwrap_check(const Op< Row<eT>, op_htrans>& A, const Mat<eT>& B)
2714     : M_local ( (&A.m == &B) ? new Row<eT>(A.m) : nullptr )
2715     , M       ( (&A.m == &B) ? (*M_local)       : A.m     )
2716     {
2717     arma_extra_debug_sigprint();
2718     }
2719 
2720   inline
~partial_unwrap_checkpartial_unwrap_check2721   ~partial_unwrap_check()
2722     {
2723     arma_extra_debug_sigprint();
2724 
2725     if(M_local) { delete M_local; }
2726     }
2727 
get_valpartial_unwrap_check2728   constexpr eT get_val() const { return eT(1); }
2729 
2730   static constexpr bool do_trans = true;
2731   static constexpr bool do_times = false;
2732 
2733   // the order below is important
2734   const Row<eT>* M_local;
2735   const Row<eT>& M;
2736   };
2737 
2738 
2739 
2740 template<typename eT>
2741 struct partial_unwrap_check< Op< Col<eT>, op_htrans> >
2742   {
2743   typedef Col<eT> stored_type;
2744 
2745   inline
partial_unwrap_checkpartial_unwrap_check2746   partial_unwrap_check(const Op< Col<eT>, op_htrans>& A, const Mat<eT>& B)
2747     : M_local ( (&A.m == &B) ? new Col<eT>(A.m) : nullptr )
2748     , M       ( (&A.m == &B) ? (*M_local)       : A.m     )
2749     {
2750     arma_extra_debug_sigprint();
2751     }
2752 
2753   inline
~partial_unwrap_checkpartial_unwrap_check2754   ~partial_unwrap_check()
2755     {
2756     arma_extra_debug_sigprint();
2757 
2758     if(M_local) { delete M_local; }
2759     }
2760 
get_valpartial_unwrap_check2761   constexpr eT get_val() const { return eT(1); }
2762 
2763   static constexpr bool do_trans = true;
2764   static constexpr bool do_times = false;
2765 
2766   // the order below is important
2767   const Col<eT>* M_local;
2768   const Col<eT>& M;
2769   };
2770 
2771 
2772 
2773 // NOTE: we can get away with this shortcut as the partial_unwrap_check class is only used by the glue_times class,
2774 // NOTE: which relies on partial_unwrap_check to check for aliasing
2775 template<typename eT>
2776 struct partial_unwrap_check< Op< subview_col<eT>, op_htrans> >
2777   {
2778   typedef Col<eT> stored_type;
2779 
2780   inline
partial_unwrap_checkpartial_unwrap_check2781   partial_unwrap_check(const Op< subview_col<eT>, op_htrans>& A, const Mat<eT>& B)
2782     : M  ( const_cast<eT*>( A.m.colmem ), A.m.n_rows, (&(A.m.m) == &B), false )
2783     {
2784     arma_extra_debug_sigprint();
2785     }
2786 
get_valpartial_unwrap_check2787   constexpr eT get_val() const { return eT(1); }
2788 
2789   static constexpr bool do_trans = true;
2790   static constexpr bool do_times = false;
2791 
2792   const Col<eT> M;
2793   };
2794 
2795 
2796 
2797 template<typename T1>
2798 struct partial_unwrap_check_htrans2_default
2799   {
2800   typedef typename T1::elem_type eT;
2801   typedef Mat<eT>                stored_type;
2802 
2803   inline
partial_unwrap_check_htrans2_defaultpartial_unwrap_check_htrans2_default2804   partial_unwrap_check_htrans2_default(const Op<T1, op_htrans2>& A, const Mat<eT>&)
2805     : val(A.aux)
2806     , M  (A.m)
2807     {
2808     arma_extra_debug_sigprint();
2809     }
2810 
get_valpartial_unwrap_check_htrans2_default2811   arma_inline eT get_val() const { return val; }
2812 
2813   static constexpr bool do_trans = true;
2814   static constexpr bool do_times = true;
2815 
2816   const eT      val;
2817   const Mat<eT> M;
2818   };
2819 
2820 
2821 
2822 template<typename T1>
2823 struct partial_unwrap_check_htrans2_fixed
2824   {
2825   typedef typename T1::elem_type eT;
2826   typedef T1                     stored_type;
2827 
2828   inline explicit
partial_unwrap_check_htrans2_fixedpartial_unwrap_check_htrans2_fixed2829   partial_unwrap_check_htrans2_fixed(const Op<T1, op_htrans2>& A, const Mat<eT>& B)
2830     : val    (A.aux)
2831     , M_local( (&(A.m) == &B) ? new T1(A.m) : nullptr )
2832     , M      ( (&(A.m) == &B) ? (*M_local)  : A.m     )
2833     {
2834     arma_extra_debug_sigprint();
2835     }
2836 
2837   inline
~partial_unwrap_check_htrans2_fixedpartial_unwrap_check_htrans2_fixed2838   ~partial_unwrap_check_htrans2_fixed()
2839     {
2840     arma_extra_debug_sigprint();
2841 
2842     if(M_local) { delete M_local; }
2843     }
2844 
get_valpartial_unwrap_check_htrans2_fixed2845   arma_inline eT get_val() const { return val; }
2846 
2847   static constexpr bool do_trans = true;
2848   static constexpr bool do_times = true;
2849 
2850   const eT  val;
2851   const T1* M_local;
2852   const T1& M;
2853   };
2854 
2855 
2856 
2857 template<typename T1, bool condition>
2858 struct partial_unwrap_check_htrans2_redirect {};
2859 
2860 template<typename T1>
2861 struct partial_unwrap_check_htrans2_redirect<T1, false> { typedef partial_unwrap_check_htrans2_default<T1> result; };
2862 
2863 template<typename T1>
2864 struct partial_unwrap_check_htrans2_redirect<T1, true>  { typedef partial_unwrap_check_htrans2_fixed<T1>   result; };
2865 
2866 
2867 template<typename T1>
2868 struct partial_unwrap_check< Op<T1, op_htrans2> > : public partial_unwrap_check_htrans2_redirect<T1, is_Mat_fixed<T1>::value>::result
2869   {
2870   typedef typename T1::elem_type eT;
2871 
partial_unwrap_checkpartial_unwrap_check2872   inline partial_unwrap_check(const Op<T1, op_htrans2>& A, const Mat<eT>& B)
2873     : partial_unwrap_check_htrans2_redirect<T1, is_Mat_fixed<T1>::value>::result(A, B)
2874     {
2875     }
2876   };
2877 
2878 
2879 
2880 template<typename eT>
2881 struct partial_unwrap_check< Op< Mat<eT>, op_htrans2> >
2882   {
2883   typedef Mat<eT> stored_type;
2884 
2885   inline
partial_unwrap_checkpartial_unwrap_check2886   partial_unwrap_check(const Op< Mat<eT>, op_htrans2>& A, const Mat<eT>& B)
2887     : val     (A.aux)
2888     , M_local ( (&A.m == &B) ? new Mat<eT>(A.m) : nullptr )
2889     , M       ( (&A.m == &B) ? (*M_local)       : A.m     )
2890     {
2891     arma_extra_debug_sigprint();
2892     }
2893 
2894   inline
~partial_unwrap_checkpartial_unwrap_check2895   ~partial_unwrap_check()
2896     {
2897     arma_extra_debug_sigprint();
2898 
2899     if(M_local) { delete M_local; }
2900     }
2901 
get_valpartial_unwrap_check2902   arma_inline eT get_val() const { return val; }
2903 
2904   static constexpr bool do_trans = true;
2905   static constexpr bool do_times = true;
2906 
2907   // the order below is important
2908   const eT       val;
2909   const Mat<eT>* M_local;
2910   const Mat<eT>& M;
2911   };
2912 
2913 
2914 
2915 template<typename eT>
2916 struct partial_unwrap_check< Op< Row<eT>, op_htrans2> >
2917   {
2918   typedef Row<eT> stored_type;
2919 
2920   inline
partial_unwrap_checkpartial_unwrap_check2921   partial_unwrap_check(const Op< Row<eT>, op_htrans2>& A, const Mat<eT>& B)
2922     : val     (A.aux)
2923     , M_local ( (&A.m == &B) ? new Row<eT>(A.m) : nullptr )
2924     , M       ( (&A.m == &B) ? (*M_local)       : A.m     )
2925     {
2926     arma_extra_debug_sigprint();
2927     }
2928 
2929   inline
~partial_unwrap_checkpartial_unwrap_check2930   ~partial_unwrap_check()
2931     {
2932     arma_extra_debug_sigprint();
2933 
2934     if(M_local) { delete M_local; }
2935     }
2936 
get_valpartial_unwrap_check2937   arma_inline eT get_val() const { return val; }
2938 
2939   static constexpr bool do_trans = true;
2940   static constexpr bool do_times = true;
2941 
2942   // the order below is important
2943   const eT       val;
2944   const Row<eT>* M_local;
2945   const Row<eT>& M;
2946   };
2947 
2948 
2949 
2950 template<typename eT>
2951 struct partial_unwrap_check< Op< Col<eT>, op_htrans2> >
2952   {
2953   typedef Col<eT> stored_type;
2954 
2955   inline
partial_unwrap_checkpartial_unwrap_check2956   partial_unwrap_check(const Op< Col<eT>, op_htrans2>& A, const Mat<eT>& B)
2957     : val     (A.aux)
2958     , M_local ( (&A.m == &B) ? new Col<eT>(A.m) : nullptr )
2959     , M       ( (&A.m == &B) ? (*M_local)       : A.m     )
2960     {
2961     arma_extra_debug_sigprint();
2962     }
2963 
2964   inline
~partial_unwrap_checkpartial_unwrap_check2965   ~partial_unwrap_check()
2966     {
2967     arma_extra_debug_sigprint();
2968 
2969     if(M_local) { delete M_local; }
2970     }
2971 
get_valpartial_unwrap_check2972   arma_inline eT get_val() const { return val; }
2973 
2974   static constexpr bool do_trans = true;
2975   static constexpr bool do_times = true;
2976 
2977   // the order below is important
2978   const eT       val;
2979   const Col<eT>* M_local;
2980   const Col<eT>& M;
2981   };
2982 
2983 
2984 
2985 // NOTE: we can get away with this shortcut as the partial_unwrap_check class is only used by the glue_times class,
2986 // NOTE: which relies on partial_unwrap_check to check for aliasing
2987 template<typename eT>
2988 struct partial_unwrap_check< Op< subview_col<eT>, op_htrans2> >
2989   {
2990   typedef Col<eT> stored_type;
2991 
2992   inline
partial_unwrap_checkpartial_unwrap_check2993   partial_unwrap_check(const Op< subview_col<eT>, op_htrans2>& A, const Mat<eT>& B)
2994     : val( A.aux )
2995     , M  ( const_cast<eT*>( A.m.colmem ), A.m.n_rows, (&(A.m.m) == &B), false )
2996     {
2997     arma_extra_debug_sigprint();
2998     }
2999 
get_valpartial_unwrap_check3000   arma_inline eT get_val() const { return val; }
3001 
3002   static constexpr bool do_trans = true;
3003   static constexpr bool do_times = true;
3004 
3005   const eT      val;
3006   const Col<eT> M;
3007   };
3008 
3009 
3010 
3011 template<typename T1>
3012 struct partial_unwrap_check_scalar_times_default
3013   {
3014   typedef typename T1::elem_type eT;
3015   typedef Mat<eT>                stored_type;
3016 
3017   inline
partial_unwrap_check_scalar_times_defaultpartial_unwrap_check_scalar_times_default3018   partial_unwrap_check_scalar_times_default(const eOp<T1, eop_scalar_times>& A, const Mat<eT>&)
3019     : val(A.aux)
3020     , M  (A.P.Q)
3021     {
3022     arma_extra_debug_sigprint();
3023     }
3024 
get_valpartial_unwrap_check_scalar_times_default3025   arma_inline eT get_val() const { return val; }
3026 
3027   static constexpr bool do_trans = false;
3028   static constexpr bool do_times = true;
3029 
3030   const eT      val;
3031   const Mat<eT> M;
3032   };
3033 
3034 
3035 
3036 template<typename T1>
3037 struct partial_unwrap_check_scalar_times_fixed
3038   {
3039   typedef typename T1::elem_type eT;
3040   typedef T1                     stored_type;
3041 
3042   inline explicit
partial_unwrap_check_scalar_times_fixedpartial_unwrap_check_scalar_times_fixed3043   partial_unwrap_check_scalar_times_fixed(const eOp<T1, eop_scalar_times>& A, const Mat<eT>& B)
3044     : val    ( A.aux )
3045     , M_local( (&(A.P.Q) == &B) ? new T1(A.P.Q) : nullptr )
3046     , M      ( (&(A.P.Q) == &B) ? (*M_local)    : A.P.Q   )
3047     {
3048     arma_extra_debug_sigprint();
3049     }
3050 
3051   inline
~partial_unwrap_check_scalar_times_fixedpartial_unwrap_check_scalar_times_fixed3052   ~partial_unwrap_check_scalar_times_fixed()
3053     {
3054     arma_extra_debug_sigprint();
3055 
3056     if(M_local) { delete M_local; }
3057     }
3058 
get_valpartial_unwrap_check_scalar_times_fixed3059   arma_inline eT get_val() const { return val; }
3060 
3061   static constexpr bool do_trans = false;
3062   static constexpr bool do_times = true;
3063 
3064   const eT  val;
3065   const T1* M_local;
3066   const T1& M;
3067   };
3068 
3069 
3070 
3071 template<typename T1, bool condition>
3072 struct partial_unwrap_check_scalar_times_redirect {};
3073 
3074 template<typename T1>
3075 struct partial_unwrap_check_scalar_times_redirect<T1, false> { typedef partial_unwrap_check_scalar_times_default<T1> result; };
3076 
3077 template<typename T1>
3078 struct partial_unwrap_check_scalar_times_redirect<T1, true>  { typedef partial_unwrap_check_scalar_times_fixed<T1>   result; };
3079 
3080 
3081 template<typename T1>
3082 struct partial_unwrap_check< eOp<T1, eop_scalar_times> > : public partial_unwrap_check_scalar_times_redirect<T1, is_Mat_fixed<T1>::value>::result
3083   {
3084   typedef typename T1::elem_type eT;
3085 
partial_unwrap_checkpartial_unwrap_check3086   inline partial_unwrap_check(const eOp<T1, eop_scalar_times>& A, const Mat<eT>& B)
3087     : partial_unwrap_check_scalar_times_redirect<T1, is_Mat_fixed<T1>::value>::result(A, B)
3088     {
3089     }
3090   };
3091 
3092 
3093 
3094 template<typename eT>
3095 struct partial_unwrap_check< eOp<Mat<eT>, eop_scalar_times> >
3096   {
3097   typedef Mat<eT> stored_type;
3098 
3099   inline
partial_unwrap_checkpartial_unwrap_check3100   partial_unwrap_check(const eOp<Mat<eT>,eop_scalar_times>& A, const Mat<eT>& B)
3101     : val    (A.aux)
3102     , M_local( (&(A.P.Q) == &B) ? new Mat<eT>(A.P.Q) : nullptr )
3103     , M      ( (&(A.P.Q) == &B) ? *M_local           : A.P.Q   )
3104     {
3105     arma_extra_debug_sigprint();
3106     }
3107 
3108   inline
~partial_unwrap_checkpartial_unwrap_check3109   ~partial_unwrap_check()
3110     {
3111     arma_extra_debug_sigprint();
3112 
3113     if(M_local) { delete M_local; }
3114     }
3115 
get_valpartial_unwrap_check3116   arma_inline eT get_val() const { return val; }
3117 
3118   static constexpr bool do_trans = false;
3119   static constexpr bool do_times = true;
3120 
3121   const eT       val;
3122   const Mat<eT>* M_local;
3123   const Mat<eT>& M;
3124   };
3125 
3126 
3127 
3128 template<typename eT>
3129 struct partial_unwrap_check< eOp<Row<eT>, eop_scalar_times> >
3130   {
3131   typedef Row<eT> stored_type;
3132 
3133   inline
partial_unwrap_checkpartial_unwrap_check3134   partial_unwrap_check(const eOp<Row<eT>,eop_scalar_times>& A, const Mat<eT>& B)
3135     : val(A.aux)
3136     , M_local( (&(A.P.Q) == &B) ? new Row<eT>(A.P.Q) : nullptr )
3137     , M      ( (&(A.P.Q) == &B) ? *M_local           : A.P.Q   )
3138     {
3139     arma_extra_debug_sigprint();
3140     }
3141 
3142   inline
~partial_unwrap_checkpartial_unwrap_check3143   ~partial_unwrap_check()
3144     {
3145     arma_extra_debug_sigprint();
3146 
3147     if(M_local) { delete M_local; }
3148     }
3149 
get_valpartial_unwrap_check3150   arma_inline eT get_val() const { return val; }
3151 
3152   static constexpr bool do_trans = false;
3153   static constexpr bool do_times = true;
3154 
3155   const eT       val;
3156   const Row<eT>* M_local;
3157   const Row<eT>& M;
3158   };
3159 
3160 
3161 
3162 template<typename eT>
3163 struct partial_unwrap_check< eOp<Col<eT>, eop_scalar_times> >
3164   {
3165   typedef Col<eT> stored_type;
3166 
3167   inline
partial_unwrap_checkpartial_unwrap_check3168   partial_unwrap_check(const eOp<Col<eT>,eop_scalar_times>& A, const Mat<eT>& B)
3169     : val    ( A.aux )
3170     , M_local( (&(A.P.Q) == &B) ? new Col<eT>(A.P.Q) : nullptr )
3171     , M      ( (&(A.P.Q) == &B) ? *M_local           : A.P.Q   )
3172     {
3173     arma_extra_debug_sigprint();
3174     }
3175 
3176   inline
~partial_unwrap_checkpartial_unwrap_check3177   ~partial_unwrap_check()
3178     {
3179     arma_extra_debug_sigprint();
3180 
3181     if(M_local) { delete M_local; }
3182     }
3183 
get_valpartial_unwrap_check3184   arma_inline eT get_val() const { return val; }
3185 
3186   static constexpr bool do_trans = false;
3187   static constexpr bool do_times = true;
3188 
3189   const eT       val;
3190   const Col<eT>* M_local;
3191   const Col<eT>& M;
3192   };
3193 
3194 
3195 
3196 // NOTE: we can get away with this shortcut as the partial_unwrap_check class is only used by the glue_times class,
3197 // NOTE: which relies on partial_unwrap_check to check for aliasing
3198 template<typename eT>
3199 struct partial_unwrap_check< eOp<subview_col<eT>, eop_scalar_times> >
3200   {
3201   typedef Col<eT> stored_type;
3202 
3203   inline
partial_unwrap_checkpartial_unwrap_check3204   partial_unwrap_check(const eOp<subview_col<eT>,eop_scalar_times>& A, const Mat<eT>& B)
3205     : val( A.aux )
3206     , M  ( const_cast<eT*>( A.P.Q.colmem ), A.P.Q.n_rows, (&(A.P.Q.m) == &B), false )
3207     {
3208     arma_extra_debug_sigprint();
3209     }
3210 
get_valpartial_unwrap_check3211   arma_inline eT get_val() const { return val; }
3212 
3213   static constexpr bool do_trans = false;
3214   static constexpr bool do_times = true;
3215 
3216   const eT      val;
3217   const Col<eT> M;
3218   };
3219 
3220 
3221 
3222 template<typename T1>
3223 struct partial_unwrap_check_neg_default
3224   {
3225   typedef typename T1::elem_type eT;
3226   typedef Mat<eT>                stored_type;
3227 
3228   inline
partial_unwrap_check_neg_defaultpartial_unwrap_check_neg_default3229   partial_unwrap_check_neg_default(const eOp<T1, eop_neg>& A, const Mat<eT>&)
3230     : M(A.P.Q)
3231     {
3232     arma_extra_debug_sigprint();
3233     }
3234 
get_valpartial_unwrap_check_neg_default3235   constexpr eT get_val() const { return eT(-1); }
3236 
3237   static constexpr bool do_trans = false;
3238   static constexpr bool do_times = true;
3239 
3240   const Mat<eT> M;
3241   };
3242 
3243 
3244 
3245 template<typename T1>
3246 struct partial_unwrap_check_neg_fixed
3247   {
3248   typedef typename T1::elem_type eT;
3249   typedef T1                     stored_type;
3250 
3251   inline explicit
partial_unwrap_check_neg_fixedpartial_unwrap_check_neg_fixed3252   partial_unwrap_check_neg_fixed(const eOp<T1, eop_neg>& A, const Mat<eT>& B)
3253     : M_local( (&(A.P.Q) == &B) ? new T1(A.P.Q) : nullptr )
3254     , M      ( (&(A.P.Q) == &B) ? (*M_local)    : A.P.Q   )
3255     {
3256     arma_extra_debug_sigprint();
3257     }
3258 
3259   inline
~partial_unwrap_check_neg_fixedpartial_unwrap_check_neg_fixed3260   ~partial_unwrap_check_neg_fixed()
3261     {
3262     arma_extra_debug_sigprint();
3263 
3264     if(M_local) { delete M_local; }
3265     }
3266 
get_valpartial_unwrap_check_neg_fixed3267   constexpr eT get_val() const { return eT(-1); }
3268 
3269   static constexpr bool do_trans = false;
3270   static constexpr bool do_times = true;
3271 
3272   const T1* M_local;
3273   const T1& M;
3274   };
3275 
3276 
3277 
3278 template<typename T1, bool condition>
3279 struct partial_unwrap_check_neg_redirect {};
3280 
3281 template<typename T1>
3282 struct partial_unwrap_check_neg_redirect<T1, false> { typedef partial_unwrap_check_neg_default<T1> result; };
3283 
3284 template<typename T1>
3285 struct partial_unwrap_check_neg_redirect<T1, true>  { typedef partial_unwrap_check_neg_fixed<T1>   result; };
3286 
3287 
3288 template<typename T1>
3289 struct partial_unwrap_check< eOp<T1, eop_neg> > : public partial_unwrap_check_neg_redirect<T1, is_Mat_fixed<T1>::value>::result
3290   {
3291   typedef typename T1::elem_type eT;
3292 
partial_unwrap_checkpartial_unwrap_check3293   inline partial_unwrap_check(const eOp<T1, eop_neg>& A, const Mat<eT>& B)
3294     : partial_unwrap_check_neg_redirect<T1, is_Mat_fixed<T1>::value>::result(A, B)
3295     {
3296     }
3297   };
3298 
3299 
3300 
3301 template<typename eT>
3302 struct partial_unwrap_check< eOp<Mat<eT>, eop_neg> >
3303   {
3304   typedef Mat<eT> stored_type;
3305 
3306   inline
partial_unwrap_checkpartial_unwrap_check3307   partial_unwrap_check(const eOp<Mat<eT>,eop_neg>& A, const Mat<eT>& B)
3308     : M_local( (&(A.P.Q) == &B) ? new Mat<eT>(A.P.Q) : nullptr )
3309     , M      ( (&(A.P.Q) == &B) ? *M_local           : A.P.Q   )
3310     {
3311     arma_extra_debug_sigprint();
3312     }
3313 
3314   inline
~partial_unwrap_checkpartial_unwrap_check3315   ~partial_unwrap_check()
3316     {
3317     arma_extra_debug_sigprint();
3318 
3319     if(M_local) { delete M_local; }
3320     }
3321 
get_valpartial_unwrap_check3322   constexpr eT get_val() const { return eT(-1); }
3323 
3324   static constexpr bool do_trans = false;
3325   static constexpr bool do_times = true;
3326 
3327   const Mat<eT>* M_local;
3328   const Mat<eT>& M;
3329   };
3330 
3331 
3332 
3333 template<typename eT>
3334 struct partial_unwrap_check< eOp<Row<eT>, eop_neg> >
3335   {
3336   typedef Row<eT> stored_type;
3337 
3338   inline
partial_unwrap_checkpartial_unwrap_check3339   partial_unwrap_check(const eOp<Row<eT>,eop_neg>& A, const Mat<eT>& B)
3340     : M_local( (&(A.P.Q) == &B) ? new Row<eT>(A.P.Q) : nullptr )
3341     , M      ( (&(A.P.Q) == &B) ? *M_local           : A.P.Q   )
3342     {
3343     arma_extra_debug_sigprint();
3344     }
3345 
3346   inline
~partial_unwrap_checkpartial_unwrap_check3347   ~partial_unwrap_check()
3348     {
3349     arma_extra_debug_sigprint();
3350 
3351     if(M_local) { delete M_local; }
3352     }
3353 
get_valpartial_unwrap_check3354   constexpr eT get_val() const { return eT(-1); }
3355 
3356   static constexpr bool do_trans = false;
3357   static constexpr bool do_times = true;
3358 
3359   const Row<eT>* M_local;
3360   const Row<eT>& M;
3361   };
3362 
3363 
3364 
3365 template<typename eT>
3366 struct partial_unwrap_check< eOp<Col<eT>, eop_neg> >
3367   {
3368   typedef Col<eT> stored_type;
3369 
3370   inline
partial_unwrap_checkpartial_unwrap_check3371   partial_unwrap_check(const eOp<Col<eT>,eop_neg>& A, const Mat<eT>& B)
3372     : M_local( (&(A.P.Q) == &B) ? new Col<eT>(A.P.Q) : nullptr )
3373     , M      ( (&(A.P.Q) == &B) ? *M_local           : A.P.Q   )
3374     {
3375     arma_extra_debug_sigprint();
3376     }
3377 
3378   inline
~partial_unwrap_checkpartial_unwrap_check3379   ~partial_unwrap_check()
3380     {
3381     arma_extra_debug_sigprint();
3382 
3383     if(M_local) { delete M_local; }
3384     }
3385 
get_valpartial_unwrap_check3386   constexpr eT get_val() const { return eT(-1); }
3387 
3388   static constexpr bool do_trans = false;
3389   static constexpr bool do_times = true;
3390 
3391   const Col<eT>* M_local;
3392   const Col<eT>& M;
3393   };
3394 
3395 
3396 
3397 // NOTE: we can get away with this shortcut as the partial_unwrap_check class is only used by the glue_times class,
3398 // NOTE: which relies on partial_unwrap_check to check for aliasing
3399 template<typename eT>
3400 struct partial_unwrap_check< eOp<subview_col<eT>, eop_neg> >
3401   {
3402   typedef Col<eT> stored_type;
3403 
3404   inline
partial_unwrap_checkpartial_unwrap_check3405   partial_unwrap_check(const eOp<subview_col<eT>,eop_neg>& A, const Mat<eT>& B)
3406     : M  ( const_cast<eT*>( A.P.Q.colmem ), A.P.Q.n_rows, (&(A.P.Q.m) == &B), false )
3407     {
3408     arma_extra_debug_sigprint();
3409     }
3410 
get_valpartial_unwrap_check3411   constexpr eT get_val() const { return eT(-1); }
3412 
3413   static constexpr bool do_trans = false;
3414   static constexpr bool do_times = true;
3415 
3416   const Col<eT> M;
3417   };
3418 
3419 
3420 
3421 //! @}
3422