1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup subview
20 //! @{
21 
22 
23 template<typename eT>
24 inline
~subview()25 subview<eT>::~subview()
26   {
27   arma_extra_debug_sigprint_this(this);
28   }
29 
30 
31 
32 template<typename eT>
33 inline
subview(const Mat<eT> & in_m,const uword in_row1,const uword in_col1,const uword in_n_rows,const uword in_n_cols)34 subview<eT>::subview(const Mat<eT>& in_m, const uword in_row1, const uword in_col1, const uword in_n_rows, const uword in_n_cols)
35   : m       (in_m     )
36   , aux_row1(in_row1  )
37   , aux_col1(in_col1  )
38   , n_rows  (in_n_rows)
39   , n_cols  (in_n_cols)
40   , n_elem  (in_n_rows*in_n_cols)
41   {
42   arma_extra_debug_sigprint_this(this);
43   }
44 
45 
46 
47 template<typename eT>
48 inline
subview(const subview<eT> & in)49 subview<eT>::subview(const subview<eT>& in)
50   : m       (in.m       )
51   , aux_row1(in.aux_row1)
52   , aux_col1(in.aux_col1)
53   , n_rows  (in.n_rows  )
54   , n_cols  (in.n_cols  )
55   , n_elem  (in.n_elem  )
56   {
57   arma_extra_debug_sigprint(arma_str::format("this = %x   in = %x") % this % &in);
58   }
59 
60 
61 
62 template<typename eT>
63 inline
subview(subview<eT> && in)64 subview<eT>::subview(subview<eT>&& in)
65   : m       (in.m       )
66   , aux_row1(in.aux_row1)
67   , aux_col1(in.aux_col1)
68   , n_rows  (in.n_rows  )
69   , n_cols  (in.n_cols  )
70   , n_elem  (in.n_elem  )
71   {
72   arma_extra_debug_sigprint(arma_str::format("this = %x   in = %x") % this % &in);
73 
74   // for paranoia
75 
76   access::rw(in.aux_row1) = 0;
77   access::rw(in.aux_col1) = 0;
78   access::rw(in.n_rows  ) = 0;
79   access::rw(in.n_cols  ) = 0;
80   access::rw(in.n_elem  ) = 0;
81   }
82 
83 
84 
85 template<typename eT>
86 template<typename op_type>
87 inline
88 void
inplace_op(const eT val)89 subview<eT>::inplace_op(const eT val)
90   {
91   arma_extra_debug_sigprint();
92 
93   subview<eT>& s = *this;
94 
95   const uword s_n_rows = s.n_rows;
96   const uword s_n_cols = s.n_cols;
97 
98   if(s_n_rows == 1)
99     {
100     Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
101 
102     const uword A_n_rows = A.n_rows;
103 
104     eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
105 
106     uword jj;
107     for(jj=1; jj < s_n_cols; jj+=2)
108       {
109       if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += val; Aptr += A_n_rows;  (*Aptr) += val; Aptr += A_n_rows; }
110       if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= val; Aptr += A_n_rows;  (*Aptr) -= val; Aptr += A_n_rows; }
111       if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= val; Aptr += A_n_rows;  (*Aptr) *= val; Aptr += A_n_rows; }
112       if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= val; Aptr += A_n_rows;  (*Aptr) /= val; Aptr += A_n_rows; }
113       }
114 
115     if((jj-1) < s_n_cols)
116       {
117       if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += val; }
118       if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= val; }
119       if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= val; }
120       if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= val; }
121       }
122     }
123   else
124     {
125     for(uword ucol=0; ucol < s_n_cols; ++ucol)
126       {
127       if(is_same_type<op_type, op_internal_plus >::yes)  { arrayops::inplace_plus ( colptr(ucol), val, s_n_rows ); }
128       if(is_same_type<op_type, op_internal_minus>::yes)  { arrayops::inplace_minus( colptr(ucol), val, s_n_rows ); }
129       if(is_same_type<op_type, op_internal_schur>::yes)  { arrayops::inplace_mul  ( colptr(ucol), val, s_n_rows ); }
130       if(is_same_type<op_type, op_internal_div  >::yes)  { arrayops::inplace_div  ( colptr(ucol), val, s_n_rows ); }
131       }
132     }
133   }
134 
135 
136 
137 template<typename eT>
138 template<typename op_type, typename T1>
139 inline
140 void
inplace_op(const Base<eT,T1> & in,const char * identifier)141 subview<eT>::inplace_op(const Base<eT,T1>& in, const char* identifier)
142   {
143   arma_extra_debug_sigprint();
144 
145   const Proxy<T1> P(in.get_ref());
146 
147   subview<eT>& s = *this;
148 
149   const uword s_n_rows = s.n_rows;
150   const uword s_n_cols = s.n_cols;
151 
152   arma_debug_assert_same_size(s, P, identifier);
153 
154   const bool use_mp      = arma_config::openmp && Proxy<T1>::use_mp && mp_gate<eT>::eval(s.n_elem);
155   const bool has_overlap = P.has_overlap(s);
156 
157   if(has_overlap)  { arma_extra_debug_print("aliasing or overlap detected"); }
158 
159   if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (use_mp) || (has_overlap) )
160     {
161     const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, has_overlap);
162     const Mat<eT>& B = tmp.M;
163 
164     if(s_n_rows == 1)
165       {
166       Mat<eT>& A = const_cast< Mat<eT>& >(m);
167 
168       const uword A_n_rows = A.n_rows;
169 
170             eT* Aptr = &(A.at(aux_row1,aux_col1));
171       const eT* Bptr = B.memptr();
172 
173       uword jj;
174       for(jj=1; jj < s_n_cols; jj+=2)
175         {
176         const eT tmp1 = (*Bptr);  Bptr++;
177         const eT tmp2 = (*Bptr);  Bptr++;
178 
179         if(is_same_type<op_type, op_internal_equ  >::yes)  { (*Aptr) =  tmp1; Aptr += A_n_rows;  (*Aptr) =  tmp2; Aptr += A_n_rows; }
180         if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += tmp1; Aptr += A_n_rows;  (*Aptr) += tmp2; Aptr += A_n_rows; }
181         if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= tmp1; Aptr += A_n_rows;  (*Aptr) -= tmp2; Aptr += A_n_rows; }
182         if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= tmp1; Aptr += A_n_rows;  (*Aptr) *= tmp2; Aptr += A_n_rows; }
183         if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= tmp1; Aptr += A_n_rows;  (*Aptr) /= tmp2; Aptr += A_n_rows; }
184         }
185 
186       if((jj-1) < s_n_cols)
187         {
188         if(is_same_type<op_type, op_internal_equ  >::yes)  { (*Aptr) =  (*Bptr); }
189         if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += (*Bptr); }
190         if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= (*Bptr); }
191         if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= (*Bptr); }
192         if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= (*Bptr); }
193         }
194       }
195     else  // not a row vector
196       {
197       if((s.aux_row1 == 0) && (s_n_rows == s.m.n_rows))
198         {
199         if(is_same_type<op_type, op_internal_equ  >::yes)  { arrayops::copy         ( s.colptr(0), B.memptr(), s.n_elem ); }
200         if(is_same_type<op_type, op_internal_plus >::yes)  { arrayops::inplace_plus ( s.colptr(0), B.memptr(), s.n_elem ); }
201         if(is_same_type<op_type, op_internal_minus>::yes)  { arrayops::inplace_minus( s.colptr(0), B.memptr(), s.n_elem ); }
202         if(is_same_type<op_type, op_internal_schur>::yes)  { arrayops::inplace_mul  ( s.colptr(0), B.memptr(), s.n_elem ); }
203         if(is_same_type<op_type, op_internal_div  >::yes)  { arrayops::inplace_div  ( s.colptr(0), B.memptr(), s.n_elem ); }
204         }
205       else
206         {
207         for(uword ucol=0; ucol < s_n_cols; ++ucol)
208           {
209           if(is_same_type<op_type, op_internal_equ  >::yes)  { arrayops::copy         ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); }
210           if(is_same_type<op_type, op_internal_plus >::yes)  { arrayops::inplace_plus ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); }
211           if(is_same_type<op_type, op_internal_minus>::yes)  { arrayops::inplace_minus( s.colptr(ucol), B.colptr(ucol), s_n_rows ); }
212           if(is_same_type<op_type, op_internal_schur>::yes)  { arrayops::inplace_mul  ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); }
213           if(is_same_type<op_type, op_internal_div  >::yes)  { arrayops::inplace_div  ( s.colptr(ucol), B.colptr(ucol), s_n_rows ); }
214           }
215         }
216       }
217     }
218   else  // use the Proxy
219     {
220     if(s_n_rows == 1)
221       {
222       Mat<eT>& A = const_cast< Mat<eT>& >(m);
223 
224       const uword A_n_rows = A.n_rows;
225 
226       eT* Aptr = &(A.at(aux_row1,aux_col1));
227 
228       uword jj;
229       for(jj=1; jj < s_n_cols; jj+=2)
230         {
231         const uword ii = (jj-1);
232 
233         const eT tmp1 = (Proxy<T1>::use_at) ? P.at(0,ii) : P[ii];
234         const eT tmp2 = (Proxy<T1>::use_at) ? P.at(0,jj) : P[jj];
235 
236         if(is_same_type<op_type, op_internal_equ  >::yes)  { (*Aptr) =  tmp1; Aptr += A_n_rows;  (*Aptr) =  tmp2; Aptr += A_n_rows; }
237         if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += tmp1; Aptr += A_n_rows;  (*Aptr) += tmp2; Aptr += A_n_rows; }
238         if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= tmp1; Aptr += A_n_rows;  (*Aptr) -= tmp2; Aptr += A_n_rows; }
239         if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= tmp1; Aptr += A_n_rows;  (*Aptr) *= tmp2; Aptr += A_n_rows; }
240         if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= tmp1; Aptr += A_n_rows;  (*Aptr) /= tmp2; Aptr += A_n_rows; }
241         }
242 
243       const uword ii = (jj-1);
244       if(ii < s_n_cols)
245         {
246         if(is_same_type<op_type, op_internal_equ  >::yes)  { (*Aptr) =  (Proxy<T1>::use_at) ? P.at(0,ii) : P[ii]; }
247         if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += (Proxy<T1>::use_at) ? P.at(0,ii) : P[ii]; }
248         if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= (Proxy<T1>::use_at) ? P.at(0,ii) : P[ii]; }
249         if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= (Proxy<T1>::use_at) ? P.at(0,ii) : P[ii]; }
250         if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= (Proxy<T1>::use_at) ? P.at(0,ii) : P[ii]; }
251         }
252       }
253     else  // not a row vector
254       {
255       if(Proxy<T1>::use_at)
256         {
257         for(uword ucol=0; ucol < s_n_cols; ++ucol)
258           {
259           eT* s_col_data = s.colptr(ucol);
260 
261           uword jj;
262           for(jj=1; jj < s_n_rows; jj+=2)
263             {
264             const uword ii = (jj-1);
265 
266             const eT tmp1 = P.at(ii,ucol);
267             const eT tmp2 = P.at(jj,ucol);
268 
269             if(is_same_type<op_type, op_internal_equ  >::yes)  { (*s_col_data) =  tmp1; s_col_data++;  (*s_col_data) =  tmp2; s_col_data++; }
270             if(is_same_type<op_type, op_internal_plus >::yes)  { (*s_col_data) += tmp1; s_col_data++;  (*s_col_data) += tmp2; s_col_data++; }
271             if(is_same_type<op_type, op_internal_minus>::yes)  { (*s_col_data) -= tmp1; s_col_data++;  (*s_col_data) -= tmp2; s_col_data++; }
272             if(is_same_type<op_type, op_internal_schur>::yes)  { (*s_col_data) *= tmp1; s_col_data++;  (*s_col_data) *= tmp2; s_col_data++; }
273             if(is_same_type<op_type, op_internal_div  >::yes)  { (*s_col_data) /= tmp1; s_col_data++;  (*s_col_data) /= tmp2; s_col_data++; }
274             }
275 
276           const uword ii = (jj-1);
277           if(ii < s_n_rows)
278             {
279             if(is_same_type<op_type, op_internal_equ  >::yes)  { (*s_col_data) =  P.at(ii,ucol); }
280             if(is_same_type<op_type, op_internal_plus >::yes)  { (*s_col_data) += P.at(ii,ucol); }
281             if(is_same_type<op_type, op_internal_minus>::yes)  { (*s_col_data) -= P.at(ii,ucol); }
282             if(is_same_type<op_type, op_internal_schur>::yes)  { (*s_col_data) *= P.at(ii,ucol); }
283             if(is_same_type<op_type, op_internal_div  >::yes)  { (*s_col_data) /= P.at(ii,ucol); }
284             }
285           }
286         }
287       else
288         {
289         typename Proxy<T1>::ea_type Pea = P.get_ea();
290 
291         uword count = 0;
292 
293         for(uword ucol=0; ucol < s_n_cols; ++ucol)
294           {
295           eT* s_col_data = s.colptr(ucol);
296 
297           uword jj;
298           for(jj=1; jj < s_n_rows; jj+=2)
299             {
300             const eT tmp1 = Pea[count];  count++;
301             const eT tmp2 = Pea[count];  count++;
302 
303             if(is_same_type<op_type, op_internal_equ  >::yes)  { (*s_col_data) =  tmp1; s_col_data++;  (*s_col_data) =  tmp2; s_col_data++; }
304             if(is_same_type<op_type, op_internal_plus >::yes)  { (*s_col_data) += tmp1; s_col_data++;  (*s_col_data) += tmp2; s_col_data++; }
305             if(is_same_type<op_type, op_internal_minus>::yes)  { (*s_col_data) -= tmp1; s_col_data++;  (*s_col_data) -= tmp2; s_col_data++; }
306             if(is_same_type<op_type, op_internal_schur>::yes)  { (*s_col_data) *= tmp1; s_col_data++;  (*s_col_data) *= tmp2; s_col_data++; }
307             if(is_same_type<op_type, op_internal_div  >::yes)  { (*s_col_data) /= tmp1; s_col_data++;  (*s_col_data) /= tmp2; s_col_data++; }
308             }
309 
310           if((jj-1) < s_n_rows)
311             {
312             if(is_same_type<op_type, op_internal_equ  >::yes)  { (*s_col_data) =  Pea[count];  count++; }
313             if(is_same_type<op_type, op_internal_plus >::yes)  { (*s_col_data) += Pea[count];  count++; }
314             if(is_same_type<op_type, op_internal_minus>::yes)  { (*s_col_data) -= Pea[count];  count++; }
315             if(is_same_type<op_type, op_internal_schur>::yes)  { (*s_col_data) *= Pea[count];  count++; }
316             if(is_same_type<op_type, op_internal_div  >::yes)  { (*s_col_data) /= Pea[count];  count++; }
317             }
318           }
319         }
320       }
321     }
322   }
323 
324 
325 
326 template<typename eT>
327 template<typename op_type>
328 inline
329 void
inplace_op(const subview<eT> & x,const char * identifier)330 subview<eT>::inplace_op(const subview<eT>& x, const char* identifier)
331   {
332   arma_extra_debug_sigprint();
333 
334   if(check_overlap(x))
335     {
336     const Mat<eT> tmp(x);
337 
338     if(is_same_type<op_type, op_internal_equ  >::yes)  { (*this).operator= (tmp); }
339     if(is_same_type<op_type, op_internal_plus >::yes)  { (*this).operator+=(tmp); }
340     if(is_same_type<op_type, op_internal_minus>::yes)  { (*this).operator-=(tmp); }
341     if(is_same_type<op_type, op_internal_schur>::yes)  { (*this).operator%=(tmp); }
342     if(is_same_type<op_type, op_internal_div  >::yes)  { (*this).operator/=(tmp); }
343 
344     return;
345     }
346 
347   subview<eT>& s = *this;
348 
349   arma_debug_assert_same_size(s, x, identifier);
350 
351   const uword s_n_cols = s.n_cols;
352   const uword s_n_rows = s.n_rows;
353 
354   if(s_n_rows == 1)
355     {
356           Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
357     const Mat<eT>& B = x.m;
358 
359     const uword A_n_rows = A.n_rows;
360     const uword B_n_rows = B.n_rows;
361 
362           eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
363     const eT* Bptr = &(B.at(x.aux_row1,x.aux_col1));
364 
365     uword jj;
366     for(jj=1; jj < s_n_cols; jj+=2)
367       {
368       const eT tmp1 = (*Bptr);  Bptr += B_n_rows;
369       const eT tmp2 = (*Bptr);  Bptr += B_n_rows;
370 
371       if(is_same_type<op_type, op_internal_equ  >::yes)  { (*Aptr) =  tmp1; Aptr += A_n_rows;  (*Aptr) =  tmp2; Aptr += A_n_rows; }
372       if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += tmp1; Aptr += A_n_rows;  (*Aptr) += tmp2; Aptr += A_n_rows; }
373       if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= tmp1; Aptr += A_n_rows;  (*Aptr) -= tmp2; Aptr += A_n_rows; }
374       if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= tmp1; Aptr += A_n_rows;  (*Aptr) *= tmp2; Aptr += A_n_rows; }
375       if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= tmp1; Aptr += A_n_rows;  (*Aptr) /= tmp2; Aptr += A_n_rows; }
376       }
377 
378     if((jj-1) < s_n_cols)
379       {
380       if(is_same_type<op_type, op_internal_equ  >::yes)  { (*Aptr) =  (*Bptr); }
381       if(is_same_type<op_type, op_internal_plus >::yes)  { (*Aptr) += (*Bptr); }
382       if(is_same_type<op_type, op_internal_minus>::yes)  { (*Aptr) -= (*Bptr); }
383       if(is_same_type<op_type, op_internal_schur>::yes)  { (*Aptr) *= (*Bptr); }
384       if(is_same_type<op_type, op_internal_div  >::yes)  { (*Aptr) /= (*Bptr); }
385       }
386     }
387   else
388     {
389     for(uword ucol=0; ucol < s_n_cols; ++ucol)
390       {
391       if(is_same_type<op_type, op_internal_equ  >::yes)  { arrayops::copy         ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); }
392       if(is_same_type<op_type, op_internal_plus >::yes)  { arrayops::inplace_plus ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); }
393       if(is_same_type<op_type, op_internal_minus>::yes)  { arrayops::inplace_minus( s.colptr(ucol), x.colptr(ucol), s_n_rows ); }
394       if(is_same_type<op_type, op_internal_schur>::yes)  { arrayops::inplace_mul  ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); }
395       if(is_same_type<op_type, op_internal_div  >::yes)  { arrayops::inplace_div  ( s.colptr(ucol), x.colptr(ucol), s_n_rows ); }
396       }
397     }
398   }
399 
400 
401 
402 template<typename eT>
403 inline
404 void
operator =(const eT val)405 subview<eT>::operator= (const eT val)
406   {
407   arma_extra_debug_sigprint();
408 
409   if(n_elem != 1)
410     {
411     arma_debug_assert_same_size(n_rows, n_cols, 1, 1, "copy into submatrix");
412     }
413 
414   Mat<eT>& X = const_cast< Mat<eT>& >(m);
415 
416   X.at(aux_row1, aux_col1) = val;
417   }
418 
419 
420 
421 template<typename eT>
422 inline
423 void
operator +=(const eT val)424 subview<eT>::operator+= (const eT val)
425   {
426   arma_extra_debug_sigprint();
427 
428   inplace_op<op_internal_plus>(val);
429   }
430 
431 
432 
433 template<typename eT>
434 inline
435 void
operator -=(const eT val)436 subview<eT>::operator-= (const eT val)
437   {
438   arma_extra_debug_sigprint();
439 
440   inplace_op<op_internal_minus>(val);
441   }
442 
443 
444 
445 template<typename eT>
446 inline
447 void
operator *=(const eT val)448 subview<eT>::operator*= (const eT val)
449   {
450   arma_extra_debug_sigprint();
451 
452   inplace_op<op_internal_schur>(val);
453   }
454 
455 
456 
457 template<typename eT>
458 inline
459 void
operator /=(const eT val)460 subview<eT>::operator/= (const eT val)
461   {
462   arma_extra_debug_sigprint();
463 
464   inplace_op<op_internal_div>(val);
465   }
466 
467 
468 
469 template<typename eT>
470 inline
471 void
operator =(const subview<eT> & x)472 subview<eT>::operator= (const subview<eT>& x)
473   {
474   arma_extra_debug_sigprint();
475 
476   inplace_op<op_internal_equ>(x, "copy into submatrix");
477   }
478 
479 
480 
481 template<typename eT>
482 inline
483 void
operator +=(const subview<eT> & x)484 subview<eT>::operator+= (const subview<eT>& x)
485   {
486   arma_extra_debug_sigprint();
487 
488   inplace_op<op_internal_plus>(x, "addition");
489   }
490 
491 
492 
493 template<typename eT>
494 inline
495 void
operator -=(const subview<eT> & x)496 subview<eT>::operator-= (const subview<eT>& x)
497   {
498   arma_extra_debug_sigprint();
499 
500   inplace_op<op_internal_minus>(x, "subtraction");
501   }
502 
503 
504 
505 template<typename eT>
506 inline
507 void
operator %=(const subview & x)508 subview<eT>::operator%= (const subview& x)
509   {
510   arma_extra_debug_sigprint();
511 
512   inplace_op<op_internal_schur>(x, "element-wise multiplication");
513   }
514 
515 
516 
517 template<typename eT>
518 inline
519 void
operator /=(const subview & x)520 subview<eT>::operator/= (const subview& x)
521   {
522   arma_extra_debug_sigprint();
523 
524   inplace_op<op_internal_div>(x, "element-wise division");
525   }
526 
527 
528 
529 template<typename eT>
530 template<typename T1>
531 inline
532 void
operator =(const Base<eT,T1> & in)533 subview<eT>::operator= (const Base<eT,T1>& in)
534   {
535   arma_extra_debug_sigprint();
536 
537   inplace_op<op_internal_equ>(in, "copy into submatrix");
538   }
539 
540 
541 
542 template<typename eT>
543 template<typename T1>
544 inline
545 void
operator +=(const Base<eT,T1> & in)546 subview<eT>::operator+= (const Base<eT,T1>& in)
547   {
548   arma_extra_debug_sigprint();
549 
550   inplace_op<op_internal_plus>(in, "addition");
551   }
552 
553 
554 
555 template<typename eT>
556 template<typename T1>
557 inline
558 void
operator -=(const Base<eT,T1> & in)559 subview<eT>::operator-= (const Base<eT,T1>& in)
560   {
561   arma_extra_debug_sigprint();
562 
563   inplace_op<op_internal_minus>(in, "subtraction");
564   }
565 
566 
567 
568 template<typename eT>
569 template<typename T1>
570 inline
571 void
operator %=(const Base<eT,T1> & in)572 subview<eT>::operator%= (const Base<eT,T1>& in)
573   {
574   arma_extra_debug_sigprint();
575 
576   inplace_op<op_internal_schur>(in, "element-wise multiplication");
577   }
578 
579 
580 
581 template<typename eT>
582 template<typename T1>
583 inline
584 void
operator /=(const Base<eT,T1> & in)585 subview<eT>::operator/= (const Base<eT,T1>& in)
586   {
587   arma_extra_debug_sigprint();
588 
589   inplace_op<op_internal_div>(in, "element-wise division");
590   }
591 
592 
593 
594 template<typename eT>
595 template<typename T1>
596 inline
597 void
operator =(const SpBase<eT,T1> & x)598 subview<eT>::operator=(const SpBase<eT, T1>& x)
599   {
600   arma_extra_debug_sigprint();
601 
602   const SpProxy<T1> p(x.get_ref());
603 
604   arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "copy into submatrix");
605 
606   // Clear the subview.
607   zeros();
608 
609   // Iterate through the sparse subview and set the nonzero values appropriately.
610   typename SpProxy<T1>::const_iterator_type cit     = p.begin();
611   typename SpProxy<T1>::const_iterator_type cit_end = p.end();
612 
613   while(cit != cit_end)
614     {
615     at(cit.row(), cit.col()) = *cit;
616     ++cit;
617     }
618   }
619 
620 
621 
622 template<typename eT>
623 template<typename T1>
624 inline
625 void
operator +=(const SpBase<eT,T1> & x)626 subview<eT>::operator+=(const SpBase<eT, T1>& x)
627   {
628   arma_extra_debug_sigprint();
629 
630   const SpProxy<T1> p(x.get_ref());
631 
632   arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "addition");
633 
634   // Iterate through the sparse subview and add its values.
635   typename SpProxy<T1>::const_iterator_type cit     = p.begin();
636   typename SpProxy<T1>::const_iterator_type cit_end = p.end();
637 
638   while(cit != cit_end)
639     {
640     at(cit.row(), cit.col()) += *cit;
641     ++cit;
642     }
643   }
644 
645 
646 
647 template<typename eT>
648 template<typename T1>
649 inline
650 void
operator -=(const SpBase<eT,T1> & x)651 subview<eT>::operator-=(const SpBase<eT, T1>& x)
652   {
653   arma_extra_debug_sigprint();
654 
655   const SpProxy<T1> p(x.get_ref());
656 
657   arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "subtraction");
658 
659   // Iterate through the sparse subview and subtract its values.
660   typename SpProxy<T1>::const_iterator_type cit     = p.begin();
661   typename SpProxy<T1>::const_iterator_type cit_end = p.end();
662 
663   while(cit != cit_end)
664     {
665     at(cit.row(), cit.col()) -= *cit;
666     ++cit;
667     }
668   }
669 
670 
671 
672 template<typename eT>
673 template<typename T1>
674 inline
675 void
operator %=(const SpBase<eT,T1> & x)676 subview<eT>::operator%=(const SpBase<eT, T1>& x)
677   {
678   arma_extra_debug_sigprint();
679 
680   const uword s_n_rows = (*this).n_rows;
681   const uword s_n_cols = (*this).n_cols;
682 
683   const SpProxy<T1> p(x.get_ref());
684 
685   arma_debug_assert_same_size(s_n_rows, s_n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise multiplication");
686 
687   if(n_elem == 0)  { return; }
688 
689   if(p.get_n_nonzero() == 0)  { (*this).zeros(); return; }
690 
691   // Iterate over nonzero values.
692   // Any zero values in the sparse expression will result in a zero in our subview.
693   typename SpProxy<T1>::const_iterator_type cit     = p.begin();
694   typename SpProxy<T1>::const_iterator_type cit_end = p.end();
695 
696   uword r = 0;
697   uword c = 0;
698 
699   while(cit != cit_end)
700     {
701     const uword cit_row = cit.row();
702     const uword cit_col = cit.col();
703 
704     while( ((r == cit_row) && (c == cit_col)) == false )
705       {
706       at(r,c) = eT(0);
707 
708       r++;  if(r >= s_n_rows)  { r = 0; c++; }
709       }
710 
711     at(r, c) *= (*cit);
712 
713     ++cit;
714     r++;  if(r >= s_n_rows)  { r = 0; c++; }
715     }
716   }
717 
718 
719 
720 template<typename eT>
721 template<typename T1>
722 inline
723 void
operator /=(const SpBase<eT,T1> & x)724 subview<eT>::operator/=(const SpBase<eT, T1>& x)
725   {
726   arma_extra_debug_sigprint();
727 
728   const SpProxy<T1> p(x.get_ref());
729 
730   arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise division");
731 
732   // This is probably going to fill your subview with a bunch of NaNs,
733   // so I'm not going to bother to implement it fast.
734   // You can have slow NaNs.  They're fine too.
735   for(uword c = 0; c < n_cols; ++c)
736   for(uword r = 0; r < n_rows; ++r)
737     {
738     at(r, c) /= p.at(r, c);
739     }
740   }
741 
742 
743 
744 template<typename eT>
745 template<typename T1, typename gen_type>
746 inline
747 typename enable_if2< is_same_type<typename T1::elem_type, eT>::value, void>::result
operator =(const Gen<T1,gen_type> & in)748 subview<eT>::operator= (const Gen<T1,gen_type>& in)
749   {
750   arma_extra_debug_sigprint();
751 
752   arma_debug_assert_same_size(n_rows, n_cols, in.n_rows, in.n_cols, "copy into submatrix");
753 
754   in.apply(*this);
755   }
756 
757 
758 
759 template<typename eT>
760 inline
761 void
operator =(const std::initializer_list<eT> & list)762 subview<eT>::operator=(const std::initializer_list<eT>& list)
763   {
764   arma_extra_debug_sigprint();
765 
766   arma_debug_check( (is_vec() == false), "copy into submatrix: size mismatch" );
767 
768   const uword N = uword(list.size());
769 
770   if(n_rows == 1)
771     {
772     arma_debug_assert_same_size(1, n_cols, 1, N, "copy into submatrix");
773 
774     auto it = list.begin();
775 
776     for(uword ii=0; ii < N; ++ii)  { (*this).at(0,ii) = (*it); ++it; }
777     }
778   else
779   if(n_cols == 1)
780     {
781     arma_debug_assert_same_size(n_rows, 1, N, 1, "copy into submatrix");
782 
783     arrayops::copy( (*this).colptr(0), list.begin(), N );
784     }
785   }
786 
787 
788 
789 template<typename eT>
790 inline
791 void
operator =(const std::initializer_list<std::initializer_list<eT>> & list)792 subview<eT>::operator=(const std::initializer_list< std::initializer_list<eT> >& list)
793   {
794   arma_extra_debug_sigprint();
795 
796   const Mat<eT> tmp(list);
797 
798   (*this).operator=(tmp);
799   }
800 
801 
802 
803 //! apply a functor to each element
804 template<typename eT>
805 template<typename functor>
806 inline
807 void
for_each(functor F)808 subview<eT>::for_each(functor F)
809   {
810   arma_extra_debug_sigprint();
811 
812   Mat<eT>& X = const_cast< Mat<eT>& >(m);
813 
814   if(n_rows == 1)
815     {
816     const uword urow          = aux_row1;
817     const uword start_col     = aux_col1;
818     const uword end_col_plus1 = start_col + n_cols;
819 
820     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
821       {
822       F( X.at(urow, ucol) );
823       }
824     }
825   else
826     {
827     const uword start_col = aux_col1;
828     const uword start_row = aux_row1;
829 
830     const uword end_col_plus1 = start_col + n_cols;
831     const uword end_row_plus1 = start_row + n_rows;
832 
833     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
834     for(uword urow = start_row; urow < end_row_plus1; ++urow)
835       {
836       F( X.at(urow, ucol) );
837       }
838     }
839   }
840 
841 
842 
843 template<typename eT>
844 template<typename functor>
845 inline
846 void
for_each(functor F) const847 subview<eT>::for_each(functor F) const
848   {
849   arma_extra_debug_sigprint();
850 
851   const Mat<eT>& X = m;
852 
853   if(n_rows == 1)
854     {
855     const uword urow          = aux_row1;
856     const uword start_col     = aux_col1;
857     const uword end_col_plus1 = start_col + n_cols;
858 
859     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
860       {
861       F( X.at(urow, ucol) );
862       }
863     }
864   else
865     {
866     const uword start_col = aux_col1;
867     const uword start_row = aux_row1;
868 
869     const uword end_col_plus1 = start_col + n_cols;
870     const uword end_row_plus1 = start_row + n_rows;
871 
872     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
873     for(uword urow = start_row; urow < end_row_plus1; ++urow)
874       {
875       F( X.at(urow, ucol) );
876       }
877     }
878   }
879 
880 
881 
882 //! transform each element in the subview using a functor
883 template<typename eT>
884 template<typename functor>
885 inline
886 void
transform(functor F)887 subview<eT>::transform(functor F)
888   {
889   arma_extra_debug_sigprint();
890 
891   Mat<eT>& X = const_cast< Mat<eT>& >(m);
892 
893   if(n_rows == 1)
894     {
895     const uword urow          = aux_row1;
896     const uword start_col     = aux_col1;
897     const uword end_col_plus1 = start_col + n_cols;
898 
899     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
900       {
901       X.at(urow, ucol) = eT( F( X.at(urow, ucol) ) );
902       }
903     }
904   else
905     {
906     const uword start_col = aux_col1;
907     const uword start_row = aux_row1;
908 
909     const uword end_col_plus1 = start_col + n_cols;
910     const uword end_row_plus1 = start_row + n_rows;
911 
912     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
913     for(uword urow = start_row; urow < end_row_plus1; ++urow)
914       {
915       X.at(urow, ucol) = eT( F( X.at(urow, ucol) ) );
916       }
917     }
918   }
919 
920 
921 
922 //! imbue (fill) the subview with values provided by a functor
923 template<typename eT>
924 template<typename functor>
925 inline
926 void
imbue(functor F)927 subview<eT>::imbue(functor F)
928   {
929   arma_extra_debug_sigprint();
930 
931   Mat<eT>& X = const_cast< Mat<eT>& >(m);
932 
933   if(n_rows == 1)
934     {
935     const uword urow          = aux_row1;
936     const uword start_col     = aux_col1;
937     const uword end_col_plus1 = start_col + n_cols;
938 
939     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
940       {
941       X.at(urow, ucol) = eT( F() );
942       }
943     }
944   else
945     {
946     const uword start_col = aux_col1;
947     const uword start_row = aux_row1;
948 
949     const uword end_col_plus1 = start_col + n_cols;
950     const uword end_row_plus1 = start_row + n_rows;
951 
952     for(uword ucol = start_col; ucol < end_col_plus1; ++ucol)
953     for(uword urow = start_row; urow < end_row_plus1; ++urow)
954       {
955       X.at(urow, ucol) = eT( F() );
956       }
957     }
958   }
959 
960 
961 
962 template<typename eT>
963 inline
964 void
replace(const eT old_val,const eT new_val)965 subview<eT>::replace(const eT old_val, const eT new_val)
966   {
967   arma_extra_debug_sigprint();
968 
969   subview<eT>& s = *this;
970 
971   const uword s_n_cols = s.n_cols;
972   const uword s_n_rows = s.n_rows;
973 
974   if(s_n_rows == 1)
975     {
976     Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
977 
978     const uword A_n_rows = A.n_rows;
979 
980     eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
981 
982     if(arma_isnan(old_val))
983       {
984       for(uword ucol=0; ucol < s_n_cols; ++ucol)
985         {
986         (*Aptr) = (arma_isnan(*Aptr)) ? new_val : (*Aptr);
987 
988         Aptr += A_n_rows;
989         }
990       }
991     else
992       {
993       for(uword ucol=0; ucol < s_n_cols; ++ucol)
994         {
995         (*Aptr) = ((*Aptr) == old_val) ? new_val : (*Aptr);
996 
997         Aptr += A_n_rows;
998         }
999       }
1000     }
1001   else
1002     {
1003     for(uword ucol=0; ucol < s_n_cols; ++ucol)
1004       {
1005       arrayops::replace(s.colptr(ucol), s_n_rows, old_val, new_val);
1006       }
1007     }
1008   }
1009 
1010 
1011 
1012 template<typename eT>
1013 inline
1014 void
clean(const typename get_pod_type<eT>::result threshold)1015 subview<eT>::clean(const typename get_pod_type<eT>::result threshold)
1016   {
1017   arma_extra_debug_sigprint();
1018 
1019   subview<eT>& s = *this;
1020 
1021   const uword s_n_cols = s.n_cols;
1022   const uword s_n_rows = s.n_rows;
1023 
1024   for(uword ucol=0; ucol < s_n_cols; ++ucol)
1025     {
1026     arrayops::clean( s.colptr(ucol), s_n_rows, threshold );
1027     }
1028   }
1029 
1030 
1031 
1032 template<typename eT>
1033 inline
1034 void
clamp(const eT min_val,const eT max_val)1035 subview<eT>::clamp(const eT min_val, const eT max_val)
1036   {
1037   arma_extra_debug_sigprint();
1038 
1039   if(is_cx<eT>::no)
1040     {
1041     arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview::clamp(): min_val must be less than max_val" );
1042     }
1043   else
1044     {
1045     arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "subview::clamp(): real(min_val) must be less than real(max_val)" );
1046     arma_debug_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "subview::clamp(): imag(min_val) must be less than imag(max_val)" );
1047     }
1048 
1049   subview<eT>& s = *this;
1050 
1051   const uword s_n_cols = s.n_cols;
1052   const uword s_n_rows = s.n_rows;
1053 
1054   for(uword ucol=0; ucol < s_n_cols; ++ucol)
1055     {
1056     arrayops::clamp( s.colptr(ucol), s_n_rows, min_val, max_val );
1057     }
1058   }
1059 
1060 
1061 
1062 template<typename eT>
1063 inline
1064 void
fill(const eT val)1065 subview<eT>::fill(const eT val)
1066   {
1067   arma_extra_debug_sigprint();
1068 
1069   subview<eT>& s = *this;
1070 
1071   const uword s_n_cols = s.n_cols;
1072   const uword s_n_rows = s.n_rows;
1073 
1074   if(s_n_rows == 1)
1075     {
1076     Mat<eT>& A = const_cast< Mat<eT>& >(s.m);
1077 
1078     const uword A_n_rows = A.n_rows;
1079 
1080     eT* Aptr = &(A.at(s.aux_row1,s.aux_col1));
1081 
1082     uword jj;
1083     for(jj=1; jj < s_n_cols; jj+=2)
1084       {
1085       (*Aptr) = val;  Aptr += A_n_rows;
1086       (*Aptr) = val;  Aptr += A_n_rows;
1087       }
1088 
1089     if((jj-1) < s_n_cols)
1090       {
1091       (*Aptr) = val;
1092       }
1093     }
1094   else
1095     {
1096     if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
1097       {
1098       arrayops::inplace_set( s.colptr(0), val, s.n_elem );
1099       }
1100     else
1101       {
1102       for(uword ucol=0; ucol < s_n_cols; ++ucol)
1103         {
1104         arrayops::inplace_set( s.colptr(ucol), val, s_n_rows );
1105         }
1106       }
1107     }
1108   }
1109 
1110 
1111 
1112 template<typename eT>
1113 inline
1114 void
zeros()1115 subview<eT>::zeros()
1116   {
1117   arma_extra_debug_sigprint();
1118 
1119   (*this).fill(eT(0));
1120   }
1121 
1122 
1123 
1124 template<typename eT>
1125 inline
1126 void
ones()1127 subview<eT>::ones()
1128   {
1129   arma_extra_debug_sigprint();
1130 
1131   (*this).fill(eT(1));
1132   }
1133 
1134 
1135 
1136 template<typename eT>
1137 inline
1138 void
eye()1139 subview<eT>::eye()
1140   {
1141   arma_extra_debug_sigprint();
1142 
1143   (*this).zeros();
1144 
1145   const uword N = (std::min)(n_rows, n_cols);
1146 
1147   for(uword ii=0; ii < N; ++ii)
1148     {
1149     at(ii,ii) = eT(1);
1150     }
1151   }
1152 
1153 
1154 
1155 template<typename eT>
1156 inline
1157 void
randu()1158 subview<eT>::randu()
1159   {
1160   arma_extra_debug_sigprint();
1161 
1162   subview<eT>& s = (*this);
1163 
1164   const uword s_n_rows = s.n_rows;
1165   const uword s_n_cols = s.n_cols;
1166 
1167   if(s_n_rows == 1)
1168     {
1169     podarray<eT> tmp(s_n_cols);
1170 
1171     eT* tmp_mem = tmp.memptr();
1172 
1173     arma_rng::randu<eT>::fill( tmp_mem, s_n_cols );
1174 
1175     for(uword ii=0; ii < s_n_cols; ++ii)  { at(0,ii) = tmp_mem[ii]; }
1176     }
1177   else
1178     {
1179     if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
1180       {
1181       arma_rng::randu<eT>::fill( s.colptr(0), s.n_elem );
1182       }
1183     else
1184       {
1185       for(uword ii=0; ii < s_n_cols; ++ii)
1186         {
1187         arma_rng::randu<eT>::fill( s.colptr(ii), s_n_rows );
1188         }
1189       }
1190     }
1191   }
1192 
1193 
1194 
1195 template<typename eT>
1196 inline
1197 void
randn()1198 subview<eT>::randn()
1199   {
1200   arma_extra_debug_sigprint();
1201 
1202   subview<eT>& s = (*this);
1203 
1204   const uword s_n_rows = s.n_rows;
1205   const uword s_n_cols = s.n_cols;
1206 
1207   if(s_n_rows == 1)
1208     {
1209     podarray<eT> tmp(s_n_cols);
1210 
1211     eT* tmp_mem = tmp.memptr();
1212 
1213     arma_rng::randn<eT>::fill( tmp_mem, s_n_cols );
1214 
1215     for(uword ii=0; ii < s_n_cols; ++ii)  { at(0,ii) = tmp_mem[ii]; }
1216     }
1217   else
1218     {
1219     if( (s.aux_row1 == 0) && (s_n_rows == s.m.n_rows) )
1220       {
1221       arma_rng::randn<eT>::fill( s.colptr(0), s.n_elem );
1222       }
1223     else
1224       {
1225       for(uword ii=0; ii < s_n_cols; ++ii)
1226         {
1227         arma_rng::randn<eT>::fill( s.colptr(ii), s_n_rows );
1228         }
1229       }
1230     }
1231   }
1232 
1233 
1234 
1235 template<typename eT>
1236 inline
1237 arma_warn_unused
1238 eT
at_alt(const uword ii) const1239 subview<eT>::at_alt(const uword ii) const
1240   {
1241   return operator[](ii);
1242   }
1243 
1244 
1245 
1246 template<typename eT>
1247 inline
1248 arma_warn_unused
1249 eT&
operator [](const uword ii)1250 subview<eT>::operator[](const uword ii)
1251   {
1252   const uword in_col = ii / n_rows;
1253   const uword in_row = ii % n_rows;
1254 
1255   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1256 
1257   return access::rw( (const_cast< Mat<eT>& >(m)).mem[index] );
1258   }
1259 
1260 
1261 
1262 template<typename eT>
1263 inline
1264 arma_warn_unused
1265 eT
operator [](const uword ii) const1266 subview<eT>::operator[](const uword ii) const
1267   {
1268   const uword in_col = ii / n_rows;
1269   const uword in_row = ii % n_rows;
1270 
1271   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1272 
1273   return m.mem[index];
1274   }
1275 
1276 
1277 
1278 template<typename eT>
1279 inline
1280 arma_warn_unused
1281 eT&
operator ()(const uword ii)1282 subview<eT>::operator()(const uword ii)
1283   {
1284   arma_debug_check_bounds( (ii >= n_elem), "subview::operator(): index out of bounds" );
1285 
1286   const uword in_col = ii / n_rows;
1287   const uword in_row = ii % n_rows;
1288 
1289   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1290 
1291   return access::rw( (const_cast< Mat<eT>& >(m)).mem[index] );
1292   }
1293 
1294 
1295 
1296 template<typename eT>
1297 inline
1298 arma_warn_unused
1299 eT
operator ()(const uword ii) const1300 subview<eT>::operator()(const uword ii) const
1301   {
1302   arma_debug_check_bounds( (ii >= n_elem), "subview::operator(): index out of bounds" );
1303 
1304   const uword in_col = ii / n_rows;
1305   const uword in_row = ii % n_rows;
1306 
1307   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1308 
1309   return m.mem[index];
1310   }
1311 
1312 
1313 
1314 template<typename eT>
1315 inline
1316 arma_warn_unused
1317 eT&
operator ()(const uword in_row,const uword in_col)1318 subview<eT>::operator()(const uword in_row, const uword in_col)
1319   {
1320   arma_debug_check_bounds( ((in_row >= n_rows) || (in_col >= n_cols)), "subview::operator(): index out of bounds" );
1321 
1322   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1323 
1324   return access::rw( (const_cast< Mat<eT>& >(m)).mem[index] );
1325   }
1326 
1327 
1328 
1329 template<typename eT>
1330 inline
1331 arma_warn_unused
1332 eT
operator ()(const uword in_row,const uword in_col) const1333 subview<eT>::operator()(const uword in_row, const uword in_col) const
1334   {
1335   arma_debug_check_bounds( ((in_row >= n_rows) || (in_col >= n_cols)), "subview::operator(): index out of bounds" );
1336 
1337   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1338 
1339   return m.mem[index];
1340   }
1341 
1342 
1343 
1344 template<typename eT>
1345 inline
1346 arma_warn_unused
1347 eT&
at(const uword in_row,const uword in_col)1348 subview<eT>::at(const uword in_row, const uword in_col)
1349   {
1350   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1351 
1352   return access::rw( (const_cast< Mat<eT>& >(m)).mem[index] );
1353   }
1354 
1355 
1356 
1357 template<typename eT>
1358 inline
1359 arma_warn_unused
1360 eT
at(const uword in_row,const uword in_col) const1361 subview<eT>::at(const uword in_row, const uword in_col) const
1362   {
1363   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1364 
1365   return m.mem[index];
1366   }
1367 
1368 
1369 
1370 template<typename eT>
1371 inline
1372 arma_warn_unused
1373 eT&
front()1374 subview<eT>::front()
1375   {
1376   const uword index = aux_col1*m.n_rows + aux_row1;
1377 
1378   return access::rw( (const_cast< Mat<eT>& >(m)).mem[index] );
1379   }
1380 
1381 
1382 
1383 template<typename eT>
1384 inline
1385 arma_warn_unused
1386 eT
front() const1387 subview<eT>::front() const
1388   {
1389   const uword index = aux_col1*m.n_rows + aux_row1;
1390 
1391   return m.mem[index];
1392   }
1393 
1394 
1395 
1396 template<typename eT>
1397 inline
1398 arma_warn_unused
1399 eT&
back()1400 subview<eT>::back()
1401   {
1402   const uword in_row = n_rows - 1;
1403   const uword in_col = n_cols - 1;
1404 
1405   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1406 
1407   return access::rw( (const_cast< Mat<eT>& >(m)).mem[index] );
1408   }
1409 
1410 
1411 
1412 template<typename eT>
1413 inline
1414 arma_warn_unused
1415 eT
back() const1416 subview<eT>::back() const
1417   {
1418   const uword in_row = n_rows - 1;
1419   const uword in_col = n_cols - 1;
1420 
1421   const uword index = (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
1422 
1423   return m.mem[index];
1424   }
1425 
1426 
1427 
1428 template<typename eT>
1429 arma_inline
1430 eT*
colptr(const uword in_col)1431 subview<eT>::colptr(const uword in_col)
1432   {
1433   return & access::rw((const_cast< Mat<eT>& >(m)).mem[ (in_col + aux_col1)*m.n_rows + aux_row1 ]);
1434   }
1435 
1436 
1437 
1438 template<typename eT>
1439 arma_inline
1440 const eT*
colptr(const uword in_col) const1441 subview<eT>::colptr(const uword in_col) const
1442   {
1443   return & m.mem[ (in_col + aux_col1)*m.n_rows + aux_row1 ];
1444   }
1445 
1446 
1447 
1448 template<typename eT>
1449 template<typename eT2>
1450 inline
1451 bool
check_overlap(const subview<eT2> & x) const1452 subview<eT>::check_overlap(const subview<eT2>& x) const
1453   {
1454   if(is_same_type<eT,eT2>::value == false)  { return false; }
1455 
1456   const subview<eT>& s = (*this);
1457 
1458   if(void_ptr(&(s.m)) != void_ptr(&(x.m)))  { return false; }
1459 
1460   if( (s.n_elem == 0) || (x.n_elem == 0) )  { return false; }
1461 
1462   const uword s_row_start  = s.aux_row1;
1463   const uword s_row_end_p1 = s_row_start + s.n_rows;
1464 
1465   const uword s_col_start  = s.aux_col1;
1466   const uword s_col_end_p1 = s_col_start + s.n_cols;
1467 
1468 
1469   const uword x_row_start  = x.aux_row1;
1470   const uword x_row_end_p1 = x_row_start + x.n_rows;
1471 
1472   const uword x_col_start  = x.aux_col1;
1473   const uword x_col_end_p1 = x_col_start + x.n_cols;
1474 
1475 
1476   const bool outside_rows = ( (x_row_start >= s_row_end_p1) || (s_row_start >= x_row_end_p1) );
1477   const bool outside_cols = ( (x_col_start >= s_col_end_p1) || (s_col_start >= x_col_end_p1) );
1478 
1479   return ( (outside_rows == false) && (outside_cols == false) );
1480   }
1481 
1482 
1483 
1484 template<typename eT>
1485 inline
1486 arma_warn_unused
1487 bool
is_vec() const1488 subview<eT>::is_vec() const
1489   {
1490   return ( (n_rows == 1) || (n_cols == 1) );
1491   }
1492 
1493 
1494 
1495 template<typename eT>
1496 inline
1497 arma_warn_unused
1498 bool
is_finite() const1499 subview<eT>::is_finite() const
1500   {
1501   arma_extra_debug_sigprint();
1502 
1503   const uword local_n_rows = n_rows;
1504   const uword local_n_cols = n_cols;
1505 
1506   for(uword ii=0; ii<local_n_cols; ++ii)
1507     {
1508     if(arrayops::is_finite(colptr(ii), local_n_rows) == false)  { return false; }
1509     }
1510 
1511   return true;
1512   }
1513 
1514 
1515 
1516 template<typename eT>
1517 inline
1518 arma_warn_unused
1519 bool
is_zero(const typename get_pod_type<eT>::result tol) const1520 subview<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
1521   {
1522   arma_extra_debug_sigprint();
1523 
1524   const uword local_n_rows = n_rows;
1525   const uword local_n_cols = n_cols;
1526 
1527   for(uword ii=0; ii<local_n_cols; ++ii)
1528     {
1529     if(arrayops::is_zero(colptr(ii), local_n_rows, tol) == false)  { return false; }
1530     }
1531 
1532   return true;
1533   }
1534 
1535 
1536 
1537 template<typename eT>
1538 inline
1539 arma_warn_unused
1540 bool
has_inf() const1541 subview<eT>::has_inf() const
1542   {
1543   arma_extra_debug_sigprint();
1544 
1545   const uword local_n_rows = n_rows;
1546   const uword local_n_cols = n_cols;
1547 
1548   for(uword ii=0; ii<local_n_cols; ++ii)
1549     {
1550     if(arrayops::has_inf(colptr(ii), local_n_rows))  { return true; }
1551     }
1552 
1553   return false;
1554   }
1555 
1556 
1557 
1558 template<typename eT>
1559 inline
1560 arma_warn_unused
1561 bool
has_nan() const1562 subview<eT>::has_nan() const
1563   {
1564   arma_extra_debug_sigprint();
1565 
1566   const uword local_n_rows = n_rows;
1567   const uword local_n_cols = n_cols;
1568 
1569   for(uword ii=0; ii<local_n_cols; ++ii)
1570     {
1571     if(arrayops::has_nan(colptr(ii), local_n_rows))  { return true; }
1572     }
1573 
1574   return false;
1575   }
1576 
1577 
1578 
1579 //! X = Y.submat(...)
1580 template<typename eT>
1581 inline
1582 void
extract(Mat<eT> & out,const subview<eT> & in)1583 subview<eT>::extract(Mat<eT>& out, const subview<eT>& in)
1584   {
1585   arma_extra_debug_sigprint();
1586 
1587   // NOTE: we're assuming that the matrix has already been set to the correct size and there is no aliasing;
1588   // size setting and alias checking is done by either the Mat contructor or operator=()
1589 
1590   const uword n_rows = in.n_rows;  // number of rows in the subview
1591   const uword n_cols = in.n_cols;  // number of columns in the subview
1592 
1593   arma_extra_debug_print(arma_str::format("out.n_rows = %d   out.n_cols = %d    in.m.n_rows = %d  in.m.n_cols = %d") % out.n_rows % out.n_cols % in.m.n_rows % in.m.n_cols );
1594 
1595 
1596   if(in.is_vec())
1597     {
1598     if(n_cols == 1)   // a column vector
1599       {
1600       arma_extra_debug_print("subview::extract(): copying col (going across rows)");
1601 
1602       // in.colptr(0) the first column of the subview, taking into account any row offset
1603       arrayops::copy( out.memptr(), in.colptr(0), n_rows );
1604       }
1605     else   // a row vector (possibly empty)
1606       {
1607       arma_extra_debug_print("subview::extract(): copying row (going across columns)");
1608 
1609       eT* out_mem = out.memptr();
1610 
1611       const uword X_n_rows = in.m.n_rows;
1612 
1613       const eT* Xptr = &(in.m.at(in.aux_row1,in.aux_col1));
1614 
1615       uword j;
1616 
1617       for(j=1; j < n_cols; j+=2)
1618         {
1619         const eT tmp1 = (*Xptr);  Xptr += X_n_rows;
1620         const eT tmp2 = (*Xptr);  Xptr += X_n_rows;
1621 
1622         (*out_mem) = tmp1;  out_mem++;
1623         (*out_mem) = tmp2;  out_mem++;
1624         }
1625 
1626       if((j-1) < n_cols)
1627         {
1628         (*out_mem) = (*Xptr);
1629         }
1630       }
1631     }
1632   else   // general submatrix
1633     {
1634     arma_extra_debug_print("subview::extract(): general submatrix");
1635 
1636     if( (in.aux_row1 == 0) && (n_rows == in.m.n_rows) )
1637       {
1638       arrayops::copy( out.memptr(), in.colptr(0), in.n_elem );
1639       }
1640     else
1641       {
1642       for(uword col=0; col < n_cols; ++col)
1643         {
1644         arrayops::copy( out.colptr(col), in.colptr(col), n_rows );
1645         }
1646       }
1647     }
1648   }
1649 
1650 
1651 
1652 //! X += Y.submat(...)
1653 template<typename eT>
1654 inline
1655 void
plus_inplace(Mat<eT> & out,const subview<eT> & in)1656 subview<eT>::plus_inplace(Mat<eT>& out, const subview<eT>& in)
1657   {
1658   arma_extra_debug_sigprint();
1659 
1660   arma_debug_assert_same_size(out, in, "addition");
1661 
1662   const uword n_rows = in.n_rows;
1663   const uword n_cols = in.n_cols;
1664 
1665   if(n_rows == 1)
1666     {
1667     eT* out_mem = out.memptr();
1668 
1669     const Mat<eT>& X = in.m;
1670 
1671     const uword row       = in.aux_row1;
1672     const uword start_col = in.aux_col1;
1673 
1674     uword i,j;
1675     for(i=0, j=1; j < n_cols; i+=2, j+=2)
1676       {
1677       const eT tmp1 = X.at(row, start_col+i);
1678       const eT tmp2 = X.at(row, start_col+j);
1679 
1680       out_mem[i] += tmp1;
1681       out_mem[j] += tmp2;
1682       }
1683 
1684     if(i < n_cols)
1685       {
1686       out_mem[i] += X.at(row, start_col+i);
1687       }
1688     }
1689   else
1690     {
1691     for(uword col=0; col < n_cols; ++col)
1692       {
1693       arrayops::inplace_plus(out.colptr(col), in.colptr(col), n_rows);
1694       }
1695     }
1696   }
1697 
1698 
1699 
1700 //! X -= Y.submat(...)
1701 template<typename eT>
1702 inline
1703 void
minus_inplace(Mat<eT> & out,const subview<eT> & in)1704 subview<eT>::minus_inplace(Mat<eT>& out, const subview<eT>& in)
1705   {
1706   arma_extra_debug_sigprint();
1707 
1708   arma_debug_assert_same_size(out, in, "subtraction");
1709 
1710   const uword n_rows = in.n_rows;
1711   const uword n_cols = in.n_cols;
1712 
1713   if(n_rows == 1)
1714     {
1715     eT* out_mem = out.memptr();
1716 
1717     const Mat<eT>& X = in.m;
1718 
1719     const uword row       = in.aux_row1;
1720     const uword start_col = in.aux_col1;
1721 
1722     uword i,j;
1723     for(i=0, j=1; j < n_cols; i+=2, j+=2)
1724       {
1725       const eT tmp1 = X.at(row, start_col+i);
1726       const eT tmp2 = X.at(row, start_col+j);
1727 
1728       out_mem[i] -= tmp1;
1729       out_mem[j] -= tmp2;
1730       }
1731 
1732     if(i < n_cols)
1733       {
1734       out_mem[i] -= X.at(row, start_col+i);
1735       }
1736     }
1737   else
1738     {
1739     for(uword col=0; col < n_cols; ++col)
1740       {
1741       arrayops::inplace_minus(out.colptr(col), in.colptr(col), n_rows);
1742       }
1743     }
1744   }
1745 
1746 
1747 
1748 //! X %= Y.submat(...)
1749 template<typename eT>
1750 inline
1751 void
schur_inplace(Mat<eT> & out,const subview<eT> & in)1752 subview<eT>::schur_inplace(Mat<eT>& out, const subview<eT>& in)
1753   {
1754   arma_extra_debug_sigprint();
1755 
1756   arma_debug_assert_same_size(out, in, "element-wise multiplication");
1757 
1758   const uword n_rows = in.n_rows;
1759   const uword n_cols = in.n_cols;
1760 
1761   if(n_rows == 1)
1762     {
1763     eT* out_mem = out.memptr();
1764 
1765     const Mat<eT>& X = in.m;
1766 
1767     const uword row       = in.aux_row1;
1768     const uword start_col = in.aux_col1;
1769 
1770     uword i,j;
1771     for(i=0, j=1; j < n_cols; i+=2, j+=2)
1772       {
1773       const eT tmp1 = X.at(row, start_col+i);
1774       const eT tmp2 = X.at(row, start_col+j);
1775 
1776       out_mem[i] *= tmp1;
1777       out_mem[j] *= tmp2;
1778       }
1779 
1780     if(i < n_cols)
1781       {
1782       out_mem[i] *= X.at(row, start_col+i);
1783       }
1784     }
1785   else
1786     {
1787     for(uword col=0; col < n_cols; ++col)
1788       {
1789       arrayops::inplace_mul(out.colptr(col), in.colptr(col), n_rows);
1790       }
1791     }
1792   }
1793 
1794 
1795 
1796 //! X /= Y.submat(...)
1797 template<typename eT>
1798 inline
1799 void
div_inplace(Mat<eT> & out,const subview<eT> & in)1800 subview<eT>::div_inplace(Mat<eT>& out, const subview<eT>& in)
1801   {
1802   arma_extra_debug_sigprint();
1803 
1804   arma_debug_assert_same_size(out, in, "element-wise division");
1805 
1806   const uword n_rows = in.n_rows;
1807   const uword n_cols = in.n_cols;
1808 
1809   if(n_rows == 1)
1810     {
1811     eT* out_mem = out.memptr();
1812 
1813     const Mat<eT>& X = in.m;
1814 
1815     const uword row       = in.aux_row1;
1816     const uword start_col = in.aux_col1;
1817 
1818     uword i,j;
1819     for(i=0, j=1; j < n_cols; i+=2, j+=2)
1820       {
1821       const eT tmp1 = X.at(row, start_col+i);
1822       const eT tmp2 = X.at(row, start_col+j);
1823 
1824       out_mem[i] /= tmp1;
1825       out_mem[j] /= tmp2;
1826       }
1827 
1828     if(i < n_cols)
1829       {
1830       out_mem[i] /= X.at(row, start_col+i);
1831       }
1832     }
1833   else
1834     {
1835     for(uword col=0; col < n_cols; ++col)
1836       {
1837       arrayops::inplace_div(out.colptr(col), in.colptr(col), n_rows);
1838       }
1839     }
1840   }
1841 
1842 
1843 
1844 //! creation of subview (row vector)
1845 template<typename eT>
1846 inline
1847 subview_row<eT>
row(const uword row_num)1848 subview<eT>::row(const uword row_num)
1849   {
1850   arma_extra_debug_sigprint();
1851 
1852   arma_debug_check_bounds( row_num >= n_rows, "subview::row(): out of bounds" );
1853 
1854   const uword base_row = aux_row1 + row_num;
1855 
1856   return subview_row<eT>(m, base_row, aux_col1, n_cols);
1857   }
1858 
1859 
1860 
1861 //! creation of subview (row vector)
1862 template<typename eT>
1863 inline
1864 const subview_row<eT>
row(const uword row_num) const1865 subview<eT>::row(const uword row_num) const
1866   {
1867   arma_extra_debug_sigprint();
1868 
1869   arma_debug_check_bounds( row_num >= n_rows, "subview::row(): out of bounds" );
1870 
1871   const uword base_row = aux_row1 + row_num;
1872 
1873   return subview_row<eT>(m, base_row, aux_col1, n_cols);
1874   }
1875 
1876 
1877 
1878 template<typename eT>
1879 inline
1880 subview_row<eT>
operator ()(const uword row_num,const span & col_span)1881 subview<eT>::operator()(const uword row_num, const span& col_span)
1882   {
1883   arma_extra_debug_sigprint();
1884 
1885   const bool col_all = col_span.whole;
1886 
1887   const uword local_n_cols = n_cols;
1888 
1889   const uword in_col1       = col_all ? 0            : col_span.a;
1890   const uword in_col2       =                          col_span.b;
1891   const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
1892 
1893   const uword base_col1     = aux_col1 + in_col1;
1894   const uword base_row      = aux_row1 + row_num;
1895 
1896   arma_debug_check_bounds
1897     (
1898     (row_num >= n_rows)
1899     ||
1900     ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
1901     ,
1902     "subview::operator(): indices out of bounds or incorrectly used"
1903     );
1904 
1905   return subview_row<eT>(m, base_row, base_col1, submat_n_cols);
1906   }
1907 
1908 
1909 
1910 template<typename eT>
1911 inline
1912 const subview_row<eT>
operator ()(const uword row_num,const span & col_span) const1913 subview<eT>::operator()(const uword row_num, const span& col_span) const
1914   {
1915   arma_extra_debug_sigprint();
1916 
1917   const bool col_all = col_span.whole;
1918 
1919   const uword local_n_cols = n_cols;
1920 
1921   const uword in_col1       = col_all ? 0            : col_span.a;
1922   const uword in_col2       =                          col_span.b;
1923   const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
1924 
1925   const uword base_col1     = aux_col1 + in_col1;
1926   const uword base_row      = aux_row1 + row_num;
1927 
1928   arma_debug_check_bounds
1929     (
1930     (row_num >= n_rows)
1931     ||
1932     ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
1933     ,
1934     "subview::operator(): indices out of bounds or incorrectly used"
1935     );
1936 
1937   return subview_row<eT>(m, base_row, base_col1, submat_n_cols);
1938   }
1939 
1940 
1941 
1942 //! creation of subview (column vector)
1943 template<typename eT>
1944 inline
1945 subview_col<eT>
col(const uword col_num)1946 subview<eT>::col(const uword col_num)
1947   {
1948   arma_extra_debug_sigprint();
1949 
1950   arma_debug_check_bounds( col_num >= n_cols, "subview::col(): out of bounds" );
1951 
1952   const uword base_col = aux_col1 + col_num;
1953 
1954   return subview_col<eT>(m, base_col, aux_row1, n_rows);
1955   }
1956 
1957 
1958 
1959 //! creation of subview (column vector)
1960 template<typename eT>
1961 inline
1962 const subview_col<eT>
col(const uword col_num) const1963 subview<eT>::col(const uword col_num) const
1964   {
1965   arma_extra_debug_sigprint();
1966 
1967   arma_debug_check_bounds( col_num >= n_cols, "subview::col(): out of bounds" );
1968 
1969   const uword base_col = aux_col1 + col_num;
1970 
1971   return subview_col<eT>(m, base_col, aux_row1, n_rows);
1972   }
1973 
1974 
1975 
1976 template<typename eT>
1977 inline
1978 subview_col<eT>
operator ()(const span & row_span,const uword col_num)1979 subview<eT>::operator()(const span& row_span, const uword col_num)
1980   {
1981   arma_extra_debug_sigprint();
1982 
1983   const bool row_all = row_span.whole;
1984 
1985   const uword local_n_rows = n_rows;
1986 
1987   const uword in_row1       = row_all ? 0            : row_span.a;
1988   const uword in_row2       =                          row_span.b;
1989   const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
1990 
1991   const uword base_row1       = aux_row1 + in_row1;
1992   const uword base_col        = aux_col1 + col_num;
1993 
1994   arma_debug_check_bounds
1995     (
1996     (col_num >= n_cols)
1997     ||
1998     ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
1999     ,
2000     "subview::operator(): indices out of bounds or incorrectly used"
2001     );
2002 
2003   return subview_col<eT>(m, base_col, base_row1, submat_n_rows);
2004   }
2005 
2006 
2007 
2008 template<typename eT>
2009 inline
2010 const subview_col<eT>
operator ()(const span & row_span,const uword col_num) const2011 subview<eT>::operator()(const span& row_span, const uword col_num) const
2012   {
2013   arma_extra_debug_sigprint();
2014 
2015   const bool row_all = row_span.whole;
2016 
2017   const uword local_n_rows = n_rows;
2018 
2019   const uword in_row1       = row_all ? 0            : row_span.a;
2020   const uword in_row2       =                          row_span.b;
2021   const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
2022 
2023   const uword base_row1       = aux_row1 + in_row1;
2024   const uword base_col        = aux_col1 + col_num;
2025 
2026   arma_debug_check_bounds
2027     (
2028     (col_num >= n_cols)
2029     ||
2030     ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
2031     ,
2032     "subview::operator(): indices out of bounds or incorrectly used"
2033     );
2034 
2035   return subview_col<eT>(m, base_col, base_row1, submat_n_rows);
2036   }
2037 
2038 
2039 
2040 //! create a Col object which uses memory from an existing matrix object.
2041 //! this approach is currently not alias safe
2042 //! and does not take into account that the parent matrix object could be deleted.
2043 //! if deleted memory is accessed by the created Col object,
2044 //! it will cause memory corruption and/or a crash
2045 template<typename eT>
2046 inline
2047 Col<eT>
unsafe_col(const uword col_num)2048 subview<eT>::unsafe_col(const uword col_num)
2049   {
2050   arma_extra_debug_sigprint();
2051 
2052   arma_debug_check_bounds( col_num >= n_cols, "subview::unsafe_col(): out of bounds" );
2053 
2054   return Col<eT>(colptr(col_num), n_rows, false, true);
2055   }
2056 
2057 
2058 
2059 //! create a Col object which uses memory from an existing matrix object.
2060 //! this approach is currently not alias safe
2061 //! and does not take into account that the parent matrix object could be deleted.
2062 //! if deleted memory is accessed by the created Col object,
2063 //! it will cause memory corruption and/or a crash
2064 template<typename eT>
2065 inline
2066 const Col<eT>
unsafe_col(const uword col_num) const2067 subview<eT>::unsafe_col(const uword col_num) const
2068   {
2069   arma_extra_debug_sigprint();
2070 
2071   arma_debug_check_bounds( col_num >= n_cols, "subview::unsafe_col(): out of bounds" );
2072 
2073   return Col<eT>(const_cast<eT*>(colptr(col_num)), n_rows, false, true);
2074   }
2075 
2076 
2077 
2078 //! creation of subview (submatrix comprised of specified row vectors)
2079 template<typename eT>
2080 inline
2081 subview<eT>
rows(const uword in_row1,const uword in_row2)2082 subview<eT>::rows(const uword in_row1, const uword in_row2)
2083   {
2084   arma_extra_debug_sigprint();
2085 
2086   arma_debug_check_bounds
2087     (
2088     (in_row1 > in_row2) || (in_row2 >= n_rows),
2089     "subview::rows(): indices out of bounds or incorrectly used"
2090     );
2091 
2092   const uword subview_n_rows = in_row2 - in_row1 + 1;
2093   const uword base_row1 = aux_row1 + in_row1;
2094 
2095   return subview<eT>(m, base_row1, aux_col1, subview_n_rows, n_cols );
2096   }
2097 
2098 
2099 
2100 //! creation of subview (submatrix comprised of specified row vectors)
2101 template<typename eT>
2102 inline
2103 const subview<eT>
rows(const uword in_row1,const uword in_row2) const2104 subview<eT>::rows(const uword in_row1, const uword in_row2) const
2105   {
2106   arma_extra_debug_sigprint();
2107 
2108   arma_debug_check_bounds
2109     (
2110     (in_row1 > in_row2) || (in_row2 >= n_rows),
2111     "subview::rows(): indices out of bounds or incorrectly used"
2112     );
2113 
2114   const uword subview_n_rows = in_row2 - in_row1 + 1;
2115   const uword base_row1 = aux_row1 + in_row1;
2116 
2117   return subview<eT>(m, base_row1, aux_col1, subview_n_rows, n_cols );
2118   }
2119 
2120 
2121 
2122 //! creation of subview (submatrix comprised of specified column vectors)
2123 template<typename eT>
2124 inline
2125 subview<eT>
cols(const uword in_col1,const uword in_col2)2126 subview<eT>::cols(const uword in_col1, const uword in_col2)
2127   {
2128   arma_extra_debug_sigprint();
2129 
2130   arma_debug_check_bounds
2131     (
2132     (in_col1 > in_col2) || (in_col2 >= n_cols),
2133     "subview::cols(): indices out of bounds or incorrectly used"
2134     );
2135 
2136   const uword subview_n_cols = in_col2 - in_col1 + 1;
2137   const uword base_col1 = aux_col1 + in_col1;
2138 
2139   return subview<eT>(m, aux_row1, base_col1, n_rows, subview_n_cols);
2140   }
2141 
2142 
2143 
2144 //! creation of subview (submatrix comprised of specified column vectors)
2145 template<typename eT>
2146 inline
2147 const subview<eT>
cols(const uword in_col1,const uword in_col2) const2148 subview<eT>::cols(const uword in_col1, const uword in_col2) const
2149   {
2150   arma_extra_debug_sigprint();
2151 
2152   arma_debug_check_bounds
2153     (
2154     (in_col1 > in_col2) || (in_col2 >= n_cols),
2155     "subview::cols(): indices out of bounds or incorrectly used"
2156     );
2157 
2158   const uword subview_n_cols = in_col2 - in_col1 + 1;
2159   const uword base_col1 = aux_col1 + in_col1;
2160 
2161   return subview<eT>(m, aux_row1, base_col1, n_rows, subview_n_cols);
2162   }
2163 
2164 
2165 
2166 //! creation of subview (submatrix)
2167 template<typename eT>
2168 inline
2169 subview<eT>
submat(const uword in_row1,const uword in_col1,const uword in_row2,const uword in_col2)2170 subview<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2)
2171   {
2172   arma_extra_debug_sigprint();
2173 
2174   arma_debug_check_bounds
2175     (
2176     (in_row1 > in_row2) || (in_col1 >  in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
2177     "subview::submat(): indices out of bounds or incorrectly used"
2178     );
2179 
2180   const uword subview_n_rows = in_row2 - in_row1 + 1;
2181   const uword subview_n_cols = in_col2 - in_col1 + 1;
2182 
2183   const uword base_row1 = aux_row1 + in_row1;
2184   const uword base_col1 = aux_col1 + in_col1;
2185 
2186   return subview<eT>(m, base_row1, base_col1, subview_n_rows, subview_n_cols);
2187   }
2188 
2189 
2190 
2191 //! creation of subview (generic submatrix)
2192 template<typename eT>
2193 inline
2194 const subview<eT>
submat(const uword in_row1,const uword in_col1,const uword in_row2,const uword in_col2) const2195 subview<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const
2196   {
2197   arma_extra_debug_sigprint();
2198 
2199   arma_debug_check_bounds
2200     (
2201     (in_row1 > in_row2) || (in_col1 >  in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
2202     "subview::submat(): indices out of bounds or incorrectly used"
2203     );
2204 
2205   const uword subview_n_rows = in_row2 - in_row1 + 1;
2206   const uword subview_n_cols = in_col2 - in_col1 + 1;
2207 
2208   const uword base_row1 = aux_row1 + in_row1;
2209   const uword base_col1 = aux_col1 + in_col1;
2210 
2211   return subview<eT>(m, base_row1, base_col1, subview_n_rows, subview_n_cols);
2212   }
2213 
2214 
2215 
2216 //! creation of subview (submatrix)
2217 template<typename eT>
2218 inline
2219 subview<eT>
submat(const span & row_span,const span & col_span)2220 subview<eT>::submat(const span& row_span, const span& col_span)
2221   {
2222   arma_extra_debug_sigprint();
2223 
2224   const bool row_all = row_span.whole;
2225   const bool col_all = col_span.whole;
2226 
2227   const uword local_n_rows = n_rows;
2228   const uword local_n_cols = n_cols;
2229 
2230   const uword in_row1       = row_all ? 0            : row_span.a;
2231   const uword in_row2       =                          row_span.b;
2232   const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
2233 
2234   const uword in_col1       = col_all ? 0            : col_span.a;
2235   const uword in_col2       =                          col_span.b;
2236   const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
2237 
2238   arma_debug_check_bounds
2239     (
2240     ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
2241     ||
2242     ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
2243     ,
2244     "subview::submat(): indices out of bounds or incorrectly used"
2245     );
2246 
2247   const uword base_row1 = aux_row1 + in_row1;
2248   const uword base_col1 = aux_col1 + in_col1;
2249 
2250   return subview<eT>(m, base_row1, base_col1, submat_n_rows, submat_n_cols);
2251   }
2252 
2253 
2254 
2255 //! creation of subview (generic submatrix)
2256 template<typename eT>
2257 inline
2258 const subview<eT>
submat(const span & row_span,const span & col_span) const2259 subview<eT>::submat(const span& row_span, const span& col_span) const
2260   {
2261   arma_extra_debug_sigprint();
2262 
2263   const bool row_all = row_span.whole;
2264   const bool col_all = col_span.whole;
2265 
2266   const uword local_n_rows = n_rows;
2267   const uword local_n_cols = n_cols;
2268 
2269   const uword in_row1       = row_all ? 0            : row_span.a;
2270   const uword in_row2       =                          row_span.b;
2271   const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
2272 
2273   const uword in_col1       = col_all ? 0            : col_span.a;
2274   const uword in_col2       =                          col_span.b;
2275   const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
2276 
2277   arma_debug_check_bounds
2278     (
2279     ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
2280     ||
2281     ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
2282     ,
2283     "subview::submat(): indices out of bounds or incorrectly used"
2284     );
2285 
2286   const uword base_row1 = aux_row1 + in_row1;
2287   const uword base_col1 = aux_col1 + in_col1;
2288 
2289   return subview<eT>(m, base_row1, base_col1, submat_n_rows, submat_n_cols);
2290   }
2291 
2292 
2293 
2294 template<typename eT>
2295 inline
2296 subview<eT>
operator ()(const span & row_span,const span & col_span)2297 subview<eT>::operator()(const span& row_span, const span& col_span)
2298   {
2299   arma_extra_debug_sigprint();
2300 
2301   return (*this).submat(row_span, col_span);
2302   }
2303 
2304 
2305 
2306 template<typename eT>
2307 inline
2308 const subview<eT>
operator ()(const span & row_span,const span & col_span) const2309 subview<eT>::operator()(const span& row_span, const span& col_span) const
2310   {
2311   arma_extra_debug_sigprint();
2312 
2313   return (*this).submat(row_span, col_span);
2314   }
2315 
2316 
2317 
2318 template<typename eT>
2319 inline
2320 subview_each1< subview<eT>, 0 >
each_col()2321 subview<eT>::each_col()
2322   {
2323   arma_extra_debug_sigprint();
2324 
2325   return subview_each1< subview<eT>, 0 >(*this);
2326   }
2327 
2328 
2329 
2330 template<typename eT>
2331 inline
2332 subview_each1< subview<eT>, 1 >
each_row()2333 subview<eT>::each_row()
2334   {
2335   arma_extra_debug_sigprint();
2336 
2337   return subview_each1< subview<eT>, 1 >(*this);
2338   }
2339 
2340 
2341 
2342 template<typename eT>
2343 template<typename T1>
2344 inline
2345 subview_each2< subview<eT>, 0, T1 >
each_col(const Base<uword,T1> & indices)2346 subview<eT>::each_col(const Base<uword,T1>& indices)
2347   {
2348   arma_extra_debug_sigprint();
2349 
2350   return subview_each2< subview<eT>, 0, T1 >(*this, indices);
2351   }
2352 
2353 
2354 
2355 template<typename eT>
2356 template<typename T1>
2357 inline
2358 subview_each2< subview<eT>, 1, T1 >
each_row(const Base<uword,T1> & indices)2359 subview<eT>::each_row(const Base<uword,T1>& indices)
2360   {
2361   arma_extra_debug_sigprint();
2362 
2363   return subview_each2< subview<eT>, 1, T1 >(*this, indices);
2364   }
2365 
2366 
2367 
2368 //! apply a lambda function to each column, where each column is interpreted as a column vector
2369 template<typename eT>
2370 inline
2371 void
each_col(const std::function<void (Col<eT> &)> & F)2372 subview<eT>::each_col(const std::function< void(Col<eT>&) >& F)
2373   {
2374   arma_extra_debug_sigprint();
2375 
2376   for(uword ii=0; ii < n_cols; ++ii)
2377     {
2378     Col<eT> tmp(colptr(ii), n_rows, false, true);
2379     F(tmp);
2380     }
2381   }
2382 
2383 
2384 
2385 template<typename eT>
2386 inline
2387 void
each_col(const std::function<void (const Col<eT> &)> & F) const2388 subview<eT>::each_col(const std::function< void(const Col<eT>&) >& F) const
2389   {
2390   arma_extra_debug_sigprint();
2391 
2392   for(uword ii=0; ii < n_cols; ++ii)
2393     {
2394     const Col<eT> tmp(colptr(ii), n_rows, false, true);
2395     F(tmp);
2396     }
2397   }
2398 
2399 
2400 
2401 //! apply a lambda function to each row, where each row is interpreted as a row vector
2402 template<typename eT>
2403 inline
2404 void
each_row(const std::function<void (Row<eT> &)> & F)2405 subview<eT>::each_row(const std::function< void(Row<eT>&) >& F)
2406   {
2407   arma_extra_debug_sigprint();
2408 
2409   podarray<eT> array1(n_cols);
2410   podarray<eT> array2(n_cols);
2411 
2412   Row<eT> tmp1( array1.memptr(), n_cols, false, true );
2413   Row<eT> tmp2( array2.memptr(), n_cols, false, true );
2414 
2415   eT* tmp1_mem = tmp1.memptr();
2416   eT* tmp2_mem = tmp2.memptr();
2417 
2418   uword ii, jj;
2419 
2420   for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2)
2421     {
2422     for(uword col_id = 0; col_id < n_cols; ++col_id)
2423       {
2424       const eT* col_mem = colptr(col_id);
2425 
2426       tmp1_mem[col_id] = col_mem[ii];
2427       tmp2_mem[col_id] = col_mem[jj];
2428       }
2429 
2430     F(tmp1);
2431     F(tmp2);
2432 
2433     for(uword col_id = 0; col_id < n_cols; ++col_id)
2434       {
2435       eT* col_mem = colptr(col_id);
2436 
2437       col_mem[ii] = tmp1_mem[col_id];
2438       col_mem[jj] = tmp2_mem[col_id];
2439       }
2440     }
2441 
2442   if(ii < n_rows)
2443     {
2444     tmp1 = (*this).row(ii);
2445 
2446     F(tmp1);
2447 
2448     (*this).row(ii) = tmp1;
2449     }
2450   }
2451 
2452 
2453 
2454 template<typename eT>
2455 inline
2456 void
each_row(const std::function<void (const Row<eT> &)> & F) const2457 subview<eT>::each_row(const std::function< void(const Row<eT>&) >& F) const
2458   {
2459   arma_extra_debug_sigprint();
2460 
2461   podarray<eT> array1(n_cols);
2462   podarray<eT> array2(n_cols);
2463 
2464   Row<eT> tmp1( array1.memptr(), n_cols, false, true );
2465   Row<eT> tmp2( array2.memptr(), n_cols, false, true );
2466 
2467   eT* tmp1_mem = tmp1.memptr();
2468   eT* tmp2_mem = tmp2.memptr();
2469 
2470   uword ii, jj;
2471 
2472   for(ii=0, jj=1; jj < n_rows; ii+=2, jj+=2)
2473     {
2474     for(uword col_id = 0; col_id < n_cols; ++col_id)
2475       {
2476       const eT* col_mem = colptr(col_id);
2477 
2478       tmp1_mem[col_id] = col_mem[ii];
2479       tmp2_mem[col_id] = col_mem[jj];
2480       }
2481 
2482     F(tmp1);
2483     F(tmp2);
2484     }
2485 
2486   if(ii < n_rows)
2487     {
2488     tmp1 = (*this).row(ii);
2489 
2490     F(tmp1);
2491     }
2492   }
2493 
2494 
2495 
2496 //! creation of diagview (diagonal)
2497 template<typename eT>
2498 inline
2499 diagview<eT>
diag(const sword in_id)2500 subview<eT>::diag(const sword in_id)
2501   {
2502   arma_extra_debug_sigprint();
2503 
2504   const uword row_offset = (in_id < 0) ? uword(-in_id) : 0;
2505   const uword col_offset = (in_id > 0) ? uword( in_id) : 0;
2506 
2507   arma_debug_check_bounds
2508     (
2509     ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)),
2510     "subview::diag(): requested diagonal out of bounds"
2511     );
2512 
2513   const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset);
2514 
2515   const uword base_row_offset = aux_row1 + row_offset;
2516   const uword base_col_offset = aux_col1 + col_offset;
2517 
2518   return diagview<eT>(m, base_row_offset, base_col_offset, len);
2519   }
2520 
2521 
2522 
2523 //! creation of diagview (diagonal)
2524 template<typename eT>
2525 inline
2526 const diagview<eT>
diag(const sword in_id) const2527 subview<eT>::diag(const sword in_id) const
2528   {
2529   arma_extra_debug_sigprint();
2530 
2531   const uword row_offset = uword( (in_id < 0) ? -in_id : 0 );
2532   const uword col_offset = uword( (in_id > 0) ?  in_id : 0 );
2533 
2534   arma_debug_check_bounds
2535     (
2536     ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)),
2537     "subview::diag(): requested diagonal out of bounds"
2538     );
2539 
2540   const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset);
2541 
2542   const uword base_row_offset = aux_row1 + row_offset;
2543   const uword base_col_offset = aux_col1 + col_offset;
2544 
2545   return diagview<eT>(m, base_row_offset, base_col_offset, len);
2546   }
2547 
2548 
2549 
2550 template<typename eT>
2551 inline
2552 void
swap_rows(const uword in_row1,const uword in_row2)2553 subview<eT>::swap_rows(const uword in_row1, const uword in_row2)
2554   {
2555   arma_extra_debug_sigprint();
2556 
2557   arma_debug_check_bounds
2558     (
2559     (in_row1 >= n_rows) || (in_row2 >= n_rows),
2560     "subview::swap_rows(): out of bounds"
2561     );
2562 
2563   eT* mem = (const_cast< Mat<eT>& >(m)).memptr();
2564 
2565   if(n_elem > 0)
2566     {
2567     const uword m_n_rows = m.n_rows;
2568 
2569     for(uword ucol=0; ucol < n_cols; ++ucol)
2570       {
2571       const uword offset = (aux_col1 + ucol) * m_n_rows;
2572       const uword pos1   = aux_row1 + in_row1 + offset;
2573       const uword pos2   = aux_row1 + in_row2 + offset;
2574 
2575       std::swap( access::rw(mem[pos1]), access::rw(mem[pos2]) );
2576       }
2577     }
2578   }
2579 
2580 
2581 
2582 template<typename eT>
2583 inline
2584 void
swap_cols(const uword in_col1,const uword in_col2)2585 subview<eT>::swap_cols(const uword in_col1, const uword in_col2)
2586   {
2587   arma_extra_debug_sigprint();
2588 
2589   arma_debug_check_bounds
2590     (
2591     (in_col1 >= n_cols) || (in_col2 >= n_cols),
2592     "subview::swap_cols(): out of bounds"
2593     );
2594 
2595   if(n_elem > 0)
2596     {
2597     eT* ptr1 = colptr(in_col1);
2598     eT* ptr2 = colptr(in_col2);
2599 
2600     for(uword urow=0; urow < n_rows; ++urow)
2601       {
2602       std::swap( ptr1[urow], ptr2[urow] );
2603       }
2604     }
2605   }
2606 
2607 
2608 
2609 template<typename eT>
2610 inline
2611 typename subview<eT>::iterator
begin()2612 subview<eT>::begin()
2613   {
2614   return iterator(*this, aux_row1, aux_col1);
2615   }
2616 
2617 
2618 
2619 template<typename eT>
2620 inline
2621 typename subview<eT>::const_iterator
begin() const2622 subview<eT>::begin() const
2623   {
2624   return const_iterator(*this, aux_row1, aux_col1);
2625   }
2626 
2627 
2628 
2629 template<typename eT>
2630 inline
2631 typename subview<eT>::const_iterator
cbegin() const2632 subview<eT>::cbegin() const
2633   {
2634   return const_iterator(*this, aux_row1, aux_col1);
2635   }
2636 
2637 
2638 
2639 template<typename eT>
2640 inline
2641 typename subview<eT>::iterator
end()2642 subview<eT>::end()
2643   {
2644   return iterator(*this, aux_row1, aux_col1 + n_cols);
2645   }
2646 
2647 
2648 
2649 template<typename eT>
2650 inline
2651 typename subview<eT>::const_iterator
end() const2652 subview<eT>::end() const
2653   {
2654   return const_iterator(*this, aux_row1, aux_col1 + n_cols);
2655   }
2656 
2657 
2658 
2659 template<typename eT>
2660 inline
2661 typename subview<eT>::const_iterator
cend() const2662 subview<eT>::cend() const
2663   {
2664   return const_iterator(*this, aux_row1, aux_col1 + n_cols);
2665   }
2666 
2667 
2668 
2669 //
2670 //
2671 //
2672 
2673 
2674 
2675 template<typename eT>
2676 inline
iterator()2677 subview<eT>::iterator::iterator()
2678   : M          (nullptr)
2679   , current_ptr(nullptr)
2680   , current_row(0      )
2681   , current_col(0      )
2682   , aux_row1   (0      )
2683   , aux_row2_p1(0      )
2684   {
2685   arma_extra_debug_sigprint();
2686   // Technically this iterator is invalid (it does not point to a valid element)
2687   }
2688 
2689 
2690 
2691 template<typename eT>
2692 inline
iterator(const iterator & X)2693 subview<eT>::iterator::iterator(const iterator& X)
2694   : M          (X.M          )
2695   , current_ptr(X.current_ptr)
2696   , current_row(X.current_row)
2697   , current_col(X.current_col)
2698   , aux_row1   (X.aux_row1   )
2699   , aux_row2_p1(X.aux_row2_p1)
2700   {
2701   arma_extra_debug_sigprint();
2702   }
2703 
2704 
2705 
2706 template<typename eT>
2707 inline
iterator(subview<eT> & in_sv,const uword in_row,const uword in_col)2708 subview<eT>::iterator::iterator(subview<eT>& in_sv, const uword in_row, const uword in_col)
2709   : M          (&(const_cast< Mat<eT>& >(in_sv.m)))
2710   , current_ptr(&(M->at(in_row,in_col))           )
2711   , current_row(in_row                            )
2712   , current_col(in_col                            )
2713   , aux_row1   (in_sv.aux_row1                    )
2714   , aux_row2_p1(in_sv.aux_row1 + in_sv.n_rows     )
2715   {
2716   arma_extra_debug_sigprint();
2717   }
2718 
2719 
2720 
2721 template<typename eT>
2722 inline
2723 arma_warn_unused
2724 eT&
operator *()2725 subview<eT>::iterator::operator*()
2726   {
2727   return (*current_ptr);
2728   }
2729 
2730 
2731 
2732 template<typename eT>
2733 inline
2734 typename subview<eT>::iterator&
operator ++()2735 subview<eT>::iterator::operator++()
2736   {
2737   current_row++;
2738 
2739   if(current_row == aux_row2_p1)
2740     {
2741     current_row = aux_row1;
2742     current_col++;
2743 
2744     current_ptr = &( (*M).at(current_row,current_col) );
2745     }
2746   else
2747     {
2748     current_ptr++;
2749     }
2750 
2751   return *this;
2752   }
2753 
2754 
2755 
2756 template<typename eT>
2757 inline
2758 arma_warn_unused
2759 typename subview<eT>::iterator
operator ++(int)2760 subview<eT>::iterator::operator++(int)
2761   {
2762   typename subview<eT>::iterator temp(*this);
2763 
2764   ++(*this);
2765 
2766   return temp;
2767   }
2768 
2769 
2770 
2771 template<typename eT>
2772 inline
2773 arma_warn_unused
2774 bool
operator ==(const iterator & rhs) const2775 subview<eT>::iterator::operator==(const iterator& rhs) const
2776   {
2777   return (current_ptr == rhs.current_ptr);
2778   }
2779 
2780 
2781 
2782 template<typename eT>
2783 inline
2784 arma_warn_unused
2785 bool
operator !=(const iterator & rhs) const2786 subview<eT>::iterator::operator!=(const iterator& rhs) const
2787   {
2788   return (current_ptr != rhs.current_ptr);
2789   }
2790 
2791 
2792 
2793 template<typename eT>
2794 inline
2795 arma_warn_unused
2796 bool
operator ==(const const_iterator & rhs) const2797 subview<eT>::iterator::operator==(const const_iterator& rhs) const
2798   {
2799   return (current_ptr == rhs.current_ptr);
2800   }
2801 
2802 
2803 
2804 template<typename eT>
2805 inline
2806 arma_warn_unused
2807 bool
operator !=(const const_iterator & rhs) const2808 subview<eT>::iterator::operator!=(const const_iterator& rhs) const
2809   {
2810   return (current_ptr != rhs.current_ptr);
2811   }
2812 
2813 
2814 
2815 //
2816 //
2817 //
2818 
2819 
2820 
2821 template<typename eT>
2822 inline
const_iterator()2823 subview<eT>::const_iterator::const_iterator()
2824   : M          (nullptr)
2825   , current_ptr(nullptr)
2826   , current_row(0   )
2827   , current_col(0   )
2828   , aux_row1   (0   )
2829   , aux_row2_p1(0   )
2830   {
2831   arma_extra_debug_sigprint();
2832   // Technically this iterator is invalid (it does not point to a valid element)
2833   }
2834 
2835 
2836 
2837 template<typename eT>
2838 inline
const_iterator(const iterator & X)2839 subview<eT>::const_iterator::const_iterator(const iterator& X)
2840   : M          (X.M          )
2841   , current_ptr(X.current_ptr)
2842   , current_row(X.current_row)
2843   , current_col(X.current_col)
2844   , aux_row1   (X.aux_row1   )
2845   , aux_row2_p1(X.aux_row2_p1)
2846   {
2847   arma_extra_debug_sigprint();
2848   }
2849 
2850 
2851 
2852 template<typename eT>
2853 inline
const_iterator(const const_iterator & X)2854 subview<eT>::const_iterator::const_iterator(const const_iterator& X)
2855   : M          (X.M          )
2856   , current_ptr(X.current_ptr)
2857   , current_row(X.current_row)
2858   , current_col(X.current_col)
2859   , aux_row1   (X.aux_row1   )
2860   , aux_row2_p1(X.aux_row2_p1)
2861   {
2862   arma_extra_debug_sigprint();
2863   }
2864 
2865 
2866 
2867 template<typename eT>
2868 inline
const_iterator(const subview<eT> & in_sv,const uword in_row,const uword in_col)2869 subview<eT>::const_iterator::const_iterator(const subview<eT>& in_sv, const uword in_row, const uword in_col)
2870   : M          (&(in_sv.m)                   )
2871   , current_ptr(&(M->at(in_row,in_col))      )
2872   , current_row(in_row                       )
2873   , current_col(in_col                       )
2874   , aux_row1   (in_sv.aux_row1               )
2875   , aux_row2_p1(in_sv.aux_row1 + in_sv.n_rows)
2876   {
2877   arma_extra_debug_sigprint();
2878   }
2879 
2880 
2881 
2882 template<typename eT>
2883 inline
2884 arma_warn_unused
2885 const eT&
operator *()2886 subview<eT>::const_iterator::operator*()
2887   {
2888   return (*current_ptr);
2889   }
2890 
2891 
2892 
2893 template<typename eT>
2894 inline
2895 typename subview<eT>::const_iterator&
operator ++()2896 subview<eT>::const_iterator::operator++()
2897   {
2898   current_row++;
2899 
2900   if(current_row == aux_row2_p1)
2901     {
2902     current_row = aux_row1;
2903     current_col++;
2904 
2905     current_ptr = &( (*M).at(current_row,current_col) );
2906     }
2907   else
2908     {
2909     current_ptr++;
2910     }
2911 
2912   return *this;
2913   }
2914 
2915 
2916 
2917 template<typename eT>
2918 inline
2919 arma_warn_unused
2920 typename subview<eT>::const_iterator
operator ++(int)2921 subview<eT>::const_iterator::operator++(int)
2922   {
2923   typename subview<eT>::const_iterator temp(*this);
2924 
2925   ++(*this);
2926 
2927   return temp;
2928   }
2929 
2930 
2931 
2932 template<typename eT>
2933 inline
2934 arma_warn_unused
2935 bool
operator ==(const iterator & rhs) const2936 subview<eT>::const_iterator::operator==(const iterator& rhs) const
2937   {
2938   return (current_ptr == rhs.current_ptr);
2939   }
2940 
2941 
2942 
2943 template<typename eT>
2944 inline
2945 arma_warn_unused
2946 bool
operator !=(const iterator & rhs) const2947 subview<eT>::const_iterator::operator!=(const iterator& rhs) const
2948   {
2949   return (current_ptr != rhs.current_ptr);
2950   }
2951 
2952 
2953 
2954 template<typename eT>
2955 inline
2956 arma_warn_unused
2957 bool
operator ==(const const_iterator & rhs) const2958 subview<eT>::const_iterator::operator==(const const_iterator& rhs) const
2959   {
2960   return (current_ptr == rhs.current_ptr);
2961   }
2962 
2963 
2964 
2965 template<typename eT>
2966 inline
2967 arma_warn_unused
2968 bool
operator !=(const const_iterator & rhs) const2969 subview<eT>::const_iterator::operator!=(const const_iterator& rhs) const
2970   {
2971   return (current_ptr != rhs.current_ptr);
2972   }
2973 
2974 
2975 
2976 //
2977 //
2978 //
2979 
2980 
2981 
2982 template<typename eT>
2983 inline
row_iterator()2984 subview<eT>::row_iterator::row_iterator()
2985   : M          (nullptr)
2986   , current_row(0   )
2987   , current_col(0   )
2988   , aux_col1   (0   )
2989   , aux_col2_p1(0   )
2990   {
2991   arma_extra_debug_sigprint();
2992   // Technically this iterator is invalid (it does not point to a valid element)
2993   }
2994 
2995 
2996 
2997 template<typename eT>
2998 inline
row_iterator(const row_iterator & X)2999 subview<eT>::row_iterator::row_iterator(const row_iterator& X)
3000   : M          (X.M          )
3001   , current_row(X.current_row)
3002   , current_col(X.current_col)
3003   , aux_col1   (X.aux_col1   )
3004   , aux_col2_p1(X.aux_col2_p1)
3005   {
3006   arma_extra_debug_sigprint();
3007   }
3008 
3009 
3010 
3011 template<typename eT>
3012 inline
row_iterator(subview<eT> & in_sv,const uword in_row,const uword in_col)3013 subview<eT>::row_iterator::row_iterator(subview<eT>& in_sv, const uword in_row, const uword in_col)
3014   : M          (&(const_cast< Mat<eT>& >(in_sv.m)))
3015   , current_row(in_row                            )
3016   , current_col(in_col                            )
3017   , aux_col1   (in_sv.aux_col1                    )
3018   , aux_col2_p1(in_sv.aux_col1 + in_sv.n_cols     )
3019   {
3020   arma_extra_debug_sigprint();
3021   }
3022 
3023 
3024 
3025 template<typename eT>
3026 inline
3027 arma_warn_unused
3028 eT&
operator *()3029 subview<eT>::row_iterator::operator*()
3030   {
3031   return M->at(current_row,current_col);
3032   }
3033 
3034 
3035 
3036 template<typename eT>
3037 inline
3038 typename subview<eT>::row_iterator&
operator ++()3039 subview<eT>::row_iterator::operator++()
3040   {
3041   current_col++;
3042 
3043   if(current_col == aux_col2_p1)
3044     {
3045     current_col = aux_col1;
3046     current_row++;
3047     }
3048 
3049   return *this;
3050   }
3051 
3052 
3053 
3054 template<typename eT>
3055 inline
3056 arma_warn_unused
3057 typename subview<eT>::row_iterator
operator ++(int)3058 subview<eT>::row_iterator::operator++(int)
3059   {
3060   typename subview<eT>::row_iterator temp(*this);
3061 
3062   ++(*this);
3063 
3064   return temp;
3065   }
3066 
3067 
3068 
3069 template<typename eT>
3070 inline
3071 arma_warn_unused
3072 bool
operator ==(const row_iterator & rhs) const3073 subview<eT>::row_iterator::operator==(const row_iterator& rhs) const
3074   {
3075   return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) );
3076   }
3077 
3078 
3079 
3080 template<typename eT>
3081 inline
3082 arma_warn_unused
3083 bool
operator !=(const row_iterator & rhs) const3084 subview<eT>::row_iterator::operator!=(const row_iterator& rhs) const
3085   {
3086   return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) );
3087   }
3088 
3089 
3090 
3091 template<typename eT>
3092 inline
3093 arma_warn_unused
3094 bool
operator ==(const const_row_iterator & rhs) const3095 subview<eT>::row_iterator::operator==(const const_row_iterator& rhs) const
3096   {
3097   return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) );
3098   }
3099 
3100 
3101 
3102 template<typename eT>
3103 inline
3104 arma_warn_unused
3105 bool
operator !=(const const_row_iterator & rhs) const3106 subview<eT>::row_iterator::operator!=(const const_row_iterator& rhs) const
3107   {
3108   return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) );
3109   }
3110 
3111 
3112 
3113 //
3114 //
3115 //
3116 
3117 
3118 
3119 template<typename eT>
3120 inline
const_row_iterator()3121 subview<eT>::const_row_iterator::const_row_iterator()
3122   : M          (nullptr)
3123   , current_row(0   )
3124   , current_col(0   )
3125   , aux_col1   (0   )
3126   , aux_col2_p1(0   )
3127   {
3128   arma_extra_debug_sigprint();
3129   // Technically this iterator is invalid (it does not point to a valid element)
3130   }
3131 
3132 
3133 
3134 template<typename eT>
3135 inline
const_row_iterator(const row_iterator & X)3136 subview<eT>::const_row_iterator::const_row_iterator(const row_iterator& X)
3137   : M          (X.M          )
3138   , current_row(X.current_row)
3139   , current_col(X.current_col)
3140   , aux_col1   (X.aux_col1   )
3141   , aux_col2_p1(X.aux_col2_p1)
3142   {
3143   arma_extra_debug_sigprint();
3144   }
3145 
3146 
3147 
3148 template<typename eT>
3149 inline
const_row_iterator(const const_row_iterator & X)3150 subview<eT>::const_row_iterator::const_row_iterator(const const_row_iterator& X)
3151   : M          (X.M          )
3152   , current_row(X.current_row)
3153   , current_col(X.current_col)
3154   , aux_col1   (X.aux_col1   )
3155   , aux_col2_p1(X.aux_col2_p1)
3156   {
3157   arma_extra_debug_sigprint();
3158   }
3159 
3160 
3161 
3162 template<typename eT>
3163 inline
const_row_iterator(const subview<eT> & in_sv,const uword in_row,const uword in_col)3164 subview<eT>::const_row_iterator::const_row_iterator(const subview<eT>& in_sv, const uword in_row, const uword in_col)
3165   : M          (&(in_sv.m)                   )
3166   , current_row(in_row                       )
3167   , current_col(in_col                       )
3168   , aux_col1   (in_sv.aux_col1               )
3169   , aux_col2_p1(in_sv.aux_col1 + in_sv.n_cols)
3170   {
3171   arma_extra_debug_sigprint();
3172   }
3173 
3174 
3175 
3176 template<typename eT>
3177 inline
3178 arma_warn_unused
3179 const eT&
operator *() const3180 subview<eT>::const_row_iterator::operator*() const
3181   {
3182   return M->at(current_row,current_col);
3183   }
3184 
3185 
3186 
3187 template<typename eT>
3188 inline
3189 typename subview<eT>::const_row_iterator&
operator ++()3190 subview<eT>::const_row_iterator::operator++()
3191   {
3192   current_col++;
3193 
3194   if(current_col == aux_col2_p1)
3195     {
3196     current_col = aux_col1;
3197     current_row++;
3198     }
3199 
3200   return *this;
3201   }
3202 
3203 
3204 
3205 template<typename eT>
3206 inline
3207 arma_warn_unused
3208 typename subview<eT>::const_row_iterator
operator ++(int)3209 subview<eT>::const_row_iterator::operator++(int)
3210   {
3211   typename subview<eT>::const_row_iterator temp(*this);
3212 
3213   ++(*this);
3214 
3215   return temp;
3216   }
3217 
3218 
3219 
3220 template<typename eT>
3221 inline
3222 arma_warn_unused
3223 bool
operator ==(const row_iterator & rhs) const3224 subview<eT>::const_row_iterator::operator==(const row_iterator& rhs) const
3225   {
3226   return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) );
3227   }
3228 
3229 
3230 
3231 template<typename eT>
3232 inline
3233 arma_warn_unused
3234 bool
operator !=(const row_iterator & rhs) const3235 subview<eT>::const_row_iterator::operator!=(const row_iterator& rhs) const
3236   {
3237   return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) );
3238   }
3239 
3240 
3241 
3242 template<typename eT>
3243 inline
3244 arma_warn_unused
3245 bool
operator ==(const const_row_iterator & rhs) const3246 subview<eT>::const_row_iterator::operator==(const const_row_iterator& rhs) const
3247   {
3248   return ( (current_row == rhs.current_row) && (current_col == rhs.current_col) );
3249   }
3250 
3251 
3252 
3253 template<typename eT>
3254 inline
3255 arma_warn_unused
3256 bool
operator !=(const const_row_iterator & rhs) const3257 subview<eT>::const_row_iterator::operator!=(const const_row_iterator& rhs) const
3258   {
3259   return ( (current_row != rhs.current_row) || (current_col != rhs.current_col) );
3260   }
3261 
3262 
3263 
3264 //
3265 //
3266 //
3267 
3268 
3269 
3270 template<typename eT>
3271 inline
subview_col(const Mat<eT> & in_m,const uword in_col)3272 subview_col<eT>::subview_col(const Mat<eT>& in_m, const uword in_col)
3273   : subview<eT>(in_m, 0, in_col, in_m.n_rows, 1)
3274   , colmem(subview<eT>::colptr(0))
3275   {
3276   arma_extra_debug_sigprint();
3277   }
3278 
3279 
3280 
3281 template<typename eT>
3282 inline
subview_col(const Mat<eT> & in_m,const uword in_col,const uword in_row1,const uword in_n_rows)3283 subview_col<eT>::subview_col(const Mat<eT>& in_m, const uword in_col, const uword in_row1, const uword in_n_rows)
3284   : subview<eT>(in_m, in_row1, in_col, in_n_rows, 1)
3285   , colmem(subview<eT>::colptr(0))
3286   {
3287   arma_extra_debug_sigprint();
3288   }
3289 
3290 
3291 
3292 template<typename eT>
3293 inline
subview_col(const subview_col<eT> & in)3294 subview_col<eT>::subview_col(const subview_col<eT>& in)
3295   : subview<eT>(in)   // interprets 'subview_col' as 'subview'
3296   , colmem(in.colmem)
3297   {
3298   arma_extra_debug_sigprint();
3299   }
3300 
3301 
3302 
3303 template<typename eT>
3304 inline
subview_col(subview_col<eT> && in)3305 subview_col<eT>::subview_col(subview_col<eT>&& in)
3306   : subview<eT>(std::move(in))  // interprets 'subview_col' as 'subview'
3307   , colmem(in.colmem)
3308   {
3309   arma_extra_debug_sigprint();
3310 
3311   access::rw(in.colmem) = nullptr;
3312   }
3313 
3314 
3315 
3316 template<typename eT>
3317 inline
3318 void
operator =(const subview<eT> & X)3319 subview_col<eT>::operator=(const subview<eT>& X)
3320   {
3321   arma_extra_debug_sigprint();
3322 
3323   subview<eT>::operator=(X);
3324   }
3325 
3326 
3327 
3328 template<typename eT>
3329 inline
3330 void
operator =(const subview_col<eT> & X)3331 subview_col<eT>::operator=(const subview_col<eT>& X)
3332   {
3333   arma_extra_debug_sigprint();
3334 
3335   subview<eT>::operator=(X); // interprets 'subview_col' as 'subview'
3336   }
3337 
3338 
3339 
3340 template<typename eT>
3341 inline
3342 void
operator =(const std::initializer_list<eT> & list)3343 subview_col<eT>::operator=(const std::initializer_list<eT>& list)
3344   {
3345   arma_extra_debug_sigprint();
3346 
3347   const uword N = uword(list.size());
3348 
3349   arma_debug_assert_same_size(subview<eT>::n_rows, subview<eT>::n_cols, N, 1, "copy into submatrix");
3350 
3351   arrayops::copy( access::rwp(colmem), list.begin(), N );
3352   }
3353 
3354 
3355 
3356 template<typename eT>
3357 inline
3358 void
operator =(const eT val)3359 subview_col<eT>::operator=(const eT val)
3360   {
3361   arma_extra_debug_sigprint();
3362 
3363   if(subview<eT>::n_elem != 1)
3364     {
3365     arma_debug_assert_same_size(subview<eT>::n_rows, subview<eT>::n_cols, 1, 1, "copy into submatrix");
3366     }
3367 
3368   access::rw( colmem[0] ) = val;
3369   }
3370 
3371 
3372 
3373 template<typename eT>
3374 template<typename T1>
3375 inline
3376 void
operator =(const Base<eT,T1> & X)3377 subview_col<eT>::operator=(const Base<eT,T1>& X)
3378   {
3379   arma_extra_debug_sigprint();
3380 
3381   subview<eT>::operator=(X);
3382   }
3383 
3384 
3385 
3386 template<typename eT>
3387 template<typename T1>
3388 inline
3389 void
operator =(const SpBase<eT,T1> & X)3390 subview_col<eT>::operator=(const SpBase<eT,T1>& X)
3391   {
3392   arma_extra_debug_sigprint();
3393 
3394   subview<eT>::operator=(X.get_ref());
3395   }
3396 
3397 
3398 
3399 template<typename eT>
3400 template<typename T1, typename gen_type>
3401 inline
3402 typename enable_if2< is_same_type<typename T1::elem_type, eT>::value, void>::result
operator =(const Gen<T1,gen_type> & in)3403 subview_col<eT>::operator= (const Gen<T1,gen_type>& in)
3404   {
3405   arma_extra_debug_sigprint();
3406 
3407   arma_debug_assert_same_size(subview<eT>::n_rows, uword(1), in.n_rows, (in.is_col ? uword(1) : in.n_cols), "copy into submatrix");
3408 
3409   in.apply(*this);
3410   }
3411 
3412 
3413 
3414 template<typename eT>
3415 arma_inline
3416 arma_warn_unused
3417 const Op<subview_col<eT>,op_htrans>
t() const3418 subview_col<eT>::t() const
3419   {
3420   return Op<subview_col<eT>,op_htrans>(*this);
3421   }
3422 
3423 
3424 
3425 template<typename eT>
3426 arma_inline
3427 arma_warn_unused
3428 const Op<subview_col<eT>,op_htrans>
ht() const3429 subview_col<eT>::ht() const
3430   {
3431   return Op<subview_col<eT>,op_htrans>(*this);
3432   }
3433 
3434 
3435 
3436 template<typename eT>
3437 arma_inline
3438 arma_warn_unused
3439 const Op<subview_col<eT>,op_strans>
st() const3440 subview_col<eT>::st() const
3441   {
3442   return Op<subview_col<eT>,op_strans>(*this);
3443   }
3444 
3445 
3446 
3447 template<typename eT>
3448 arma_inline
3449 arma_warn_unused
3450 const Op<subview_col<eT>,op_strans>
as_row() const3451 subview_col<eT>::as_row() const
3452   {
3453   return Op<subview_col<eT>,op_strans>(*this);
3454   }
3455 
3456 
3457 
3458 template<typename eT>
3459 inline
3460 void
fill(const eT val)3461 subview_col<eT>::fill(const eT val)
3462   {
3463   arma_extra_debug_sigprint();
3464 
3465   arrayops::inplace_set( access::rwp(colmem), val, subview<eT>::n_rows );
3466   }
3467 
3468 
3469 
3470 template<typename eT>
3471 inline
3472 void
zeros()3473 subview_col<eT>::zeros()
3474   {
3475   arma_extra_debug_sigprint();
3476 
3477   arrayops::fill_zeros( access::rwp(colmem), subview<eT>::n_rows );
3478   }
3479 
3480 
3481 
3482 template<typename eT>
3483 inline
3484 void
ones()3485 subview_col<eT>::ones()
3486   {
3487   arma_extra_debug_sigprint();
3488 
3489   arrayops::inplace_set( access::rwp(colmem), eT(1), subview<eT>::n_rows );
3490   }
3491 
3492 
3493 
3494 template<typename eT>
3495 arma_inline
3496 eT
at_alt(const uword ii) const3497 subview_col<eT>::at_alt(const uword ii) const
3498   {
3499   const eT* colmem_aligned = colmem;
3500   memory::mark_as_aligned(colmem_aligned);
3501 
3502   return colmem_aligned[ii];
3503   }
3504 
3505 
3506 
3507 template<typename eT>
3508 arma_inline
3509 eT&
operator [](const uword ii)3510 subview_col<eT>::operator[](const uword ii)
3511   {
3512   return access::rw( colmem[ii] );
3513   }
3514 
3515 
3516 
3517 template<typename eT>
3518 arma_inline
3519 eT
operator [](const uword ii) const3520 subview_col<eT>::operator[](const uword ii) const
3521   {
3522   return colmem[ii];
3523   }
3524 
3525 
3526 
3527 template<typename eT>
3528 inline
3529 eT&
operator ()(const uword ii)3530 subview_col<eT>::operator()(const uword ii)
3531   {
3532   arma_debug_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
3533 
3534   return access::rw( colmem[ii] );
3535   }
3536 
3537 
3538 
3539 template<typename eT>
3540 inline
3541 eT
operator ()(const uword ii) const3542 subview_col<eT>::operator()(const uword ii) const
3543   {
3544   arma_debug_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
3545 
3546   return colmem[ii];
3547   }
3548 
3549 
3550 
3551 template<typename eT>
3552 inline
3553 eT&
operator ()(const uword in_row,const uword in_col)3554 subview_col<eT>::operator()(const uword in_row, const uword in_col)
3555   {
3556   arma_debug_check_bounds( ((in_row >= subview<eT>::n_rows) || (in_col > 0)), "subview::operator(): index out of bounds" );
3557 
3558   return access::rw( colmem[in_row] );
3559   }
3560 
3561 
3562 
3563 template<typename eT>
3564 inline
3565 eT
operator ()(const uword in_row,const uword in_col) const3566 subview_col<eT>::operator()(const uword in_row, const uword in_col) const
3567   {
3568   arma_debug_check_bounds( ((in_row >= subview<eT>::n_rows) || (in_col > 0)), "subview::operator(): index out of bounds" );
3569 
3570   return colmem[in_row];
3571   }
3572 
3573 
3574 
3575 template<typename eT>
3576 inline
3577 eT&
at(const uword in_row,const uword)3578 subview_col<eT>::at(const uword in_row, const uword)
3579   {
3580   return access::rw( colmem[in_row] );
3581   }
3582 
3583 
3584 
3585 template<typename eT>
3586 inline
3587 eT
at(const uword in_row,const uword) const3588 subview_col<eT>::at(const uword in_row, const uword) const
3589   {
3590   return colmem[in_row];
3591   }
3592 
3593 
3594 
3595 template<typename eT>
3596 arma_inline
3597 eT*
colptr(const uword)3598 subview_col<eT>::colptr(const uword)
3599   {
3600   return const_cast<eT*>(colmem);
3601   }
3602 
3603 
3604 template<typename eT>
3605 arma_inline
3606 const eT*
colptr(const uword) const3607 subview_col<eT>::colptr(const uword) const
3608   {
3609   return colmem;
3610   }
3611 
3612 
3613 template<typename eT>
3614 inline
3615 subview_col<eT>
rows(const uword in_row1,const uword in_row2)3616 subview_col<eT>::rows(const uword in_row1, const uword in_row2)
3617   {
3618   arma_extra_debug_sigprint();
3619 
3620   arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview<eT>::n_rows) ), "subview_col::rows(): indices out of bounds or incorrectly used" );
3621 
3622   const uword subview_n_rows = in_row2 - in_row1 + 1;
3623 
3624   const uword base_row1 = this->aux_row1 + in_row1;
3625 
3626   return subview_col<eT>(this->m, this->aux_col1, base_row1, subview_n_rows);
3627   }
3628 
3629 
3630 
3631 template<typename eT>
3632 inline
3633 const subview_col<eT>
rows(const uword in_row1,const uword in_row2) const3634 subview_col<eT>::rows(const uword in_row1, const uword in_row2) const
3635   {
3636   arma_extra_debug_sigprint();
3637 
3638   arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview<eT>::n_rows) ), "subview_col::rows(): indices out of bounds or incorrectly used" );
3639 
3640   const uword subview_n_rows = in_row2 - in_row1 + 1;
3641 
3642   const uword base_row1 = this->aux_row1 + in_row1;
3643 
3644   return subview_col<eT>(this->m, this->aux_col1, base_row1, subview_n_rows);
3645   }
3646 
3647 
3648 
3649 template<typename eT>
3650 inline
3651 subview_col<eT>
subvec(const uword in_row1,const uword in_row2)3652 subview_col<eT>::subvec(const uword in_row1, const uword in_row2)
3653   {
3654   arma_extra_debug_sigprint();
3655 
3656   arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview<eT>::n_rows) ), "subview_col::subvec(): indices out of bounds or incorrectly used" );
3657 
3658   const uword subview_n_rows = in_row2 - in_row1 + 1;
3659 
3660   const uword base_row1 = this->aux_row1 + in_row1;
3661 
3662   return subview_col<eT>(this->m, this->aux_col1, base_row1, subview_n_rows);
3663   }
3664 
3665 
3666 
3667 template<typename eT>
3668 inline
3669 const subview_col<eT>
subvec(const uword in_row1,const uword in_row2) const3670 subview_col<eT>::subvec(const uword in_row1, const uword in_row2) const
3671   {
3672   arma_extra_debug_sigprint();
3673 
3674   arma_debug_check_bounds( ( (in_row1 > in_row2) || (in_row2 >= subview<eT>::n_rows) ), "subview_col::subvec(): indices out of bounds or incorrectly used" );
3675 
3676   const uword subview_n_rows = in_row2 - in_row1 + 1;
3677 
3678   const uword base_row1 = this->aux_row1 + in_row1;
3679 
3680   return subview_col<eT>(this->m, this->aux_col1, base_row1, subview_n_rows);
3681   }
3682 
3683 
3684 
3685 template<typename eT>
3686 inline
3687 subview_col<eT>
subvec(const uword start_row,const SizeMat & s)3688 subview_col<eT>::subvec(const uword start_row, const SizeMat& s)
3689   {
3690   arma_extra_debug_sigprint();
3691 
3692   arma_debug_check( (s.n_cols != 1), "subview_col::subvec(): given size does not specify a column vector" );
3693 
3694   arma_debug_check_bounds( ( (start_row >= subview<eT>::n_rows) || ((start_row + s.n_rows) > subview<eT>::n_rows) ), "subview_col::subvec(): size out of bounds" );
3695 
3696   const uword base_row1 = this->aux_row1 + start_row;
3697 
3698   return subview_col<eT>(this->m, this->aux_col1, base_row1, s.n_rows);
3699   }
3700 
3701 
3702 
3703 template<typename eT>
3704 inline
3705 const subview_col<eT>
subvec(const uword start_row,const SizeMat & s) const3706 subview_col<eT>::subvec(const uword start_row, const SizeMat& s) const
3707   {
3708   arma_extra_debug_sigprint();
3709 
3710   arma_debug_check( (s.n_cols != 1), "subview_col::subvec(): given size does not specify a column vector" );
3711 
3712   arma_debug_check_bounds( ( (start_row >= subview<eT>::n_rows) || ((start_row + s.n_rows) > subview<eT>::n_rows) ), "subview_col::subvec(): size out of bounds" );
3713 
3714   const uword base_row1 = this->aux_row1 + start_row;
3715 
3716   return subview_col<eT>(this->m, this->aux_col1, base_row1, s.n_rows);
3717   }
3718 
3719 
3720 
3721 template<typename eT>
3722 inline
3723 subview_col<eT>
head(const uword N)3724 subview_col<eT>::head(const uword N)
3725   {
3726   arma_extra_debug_sigprint();
3727 
3728   arma_debug_check_bounds( (N > subview<eT>::n_rows), "subview_col::head(): size out of bounds" );
3729 
3730   return subview_col<eT>(this->m, this->aux_col1, this->aux_row1, N);
3731   }
3732 
3733 
3734 
3735 template<typename eT>
3736 inline
3737 const subview_col<eT>
head(const uword N) const3738 subview_col<eT>::head(const uword N) const
3739   {
3740   arma_extra_debug_sigprint();
3741 
3742   arma_debug_check_bounds( (N > subview<eT>::n_rows), "subview_col::head(): size out of bounds" );
3743 
3744   return subview_col<eT>(this->m, this->aux_col1, this->aux_row1, N);
3745   }
3746 
3747 
3748 
3749 template<typename eT>
3750 inline
3751 subview_col<eT>
tail(const uword N)3752 subview_col<eT>::tail(const uword N)
3753   {
3754   arma_extra_debug_sigprint();
3755 
3756   arma_debug_check_bounds( (N > subview<eT>::n_rows), "subview_col::tail(): size out of bounds" );
3757 
3758   const uword start_row = subview<eT>::aux_row1 + subview<eT>::n_rows - N;
3759 
3760   return subview_col<eT>(this->m, this->aux_col1, start_row, N);
3761   }
3762 
3763 
3764 
3765 template<typename eT>
3766 inline
3767 const subview_col<eT>
tail(const uword N) const3768 subview_col<eT>::tail(const uword N) const
3769   {
3770   arma_extra_debug_sigprint();
3771 
3772   arma_debug_check_bounds( (N > subview<eT>::n_rows), "subview_col::tail(): size out of bounds" );
3773 
3774   const uword start_row = subview<eT>::aux_row1 + subview<eT>::n_rows - N;
3775 
3776   return subview_col<eT>(this->m, this->aux_col1, start_row, N);
3777   }
3778 
3779 
3780 
3781 template<typename eT>
3782 inline
3783 arma_warn_unused
3784 eT
min() const3785 subview_col<eT>::min() const
3786   {
3787   arma_extra_debug_sigprint();
3788 
3789   if(subview<eT>::n_elem == 0)
3790     {
3791     arma_debug_check(true, "min(): object has no elements");
3792 
3793     return Datum<eT>::nan;
3794     }
3795 
3796   return op_min::direct_min(colmem, subview<eT>::n_elem);
3797   }
3798 
3799 
3800 
3801 template<typename eT>
3802 inline
3803 arma_warn_unused
3804 eT
max() const3805 subview_col<eT>::max() const
3806   {
3807   arma_extra_debug_sigprint();
3808 
3809   if(subview<eT>::n_elem == 0)
3810     {
3811     arma_debug_check(true, "max(): object has no elements");
3812 
3813     return Datum<eT>::nan;
3814     }
3815 
3816   return op_max::direct_max(colmem, subview<eT>::n_elem);
3817   }
3818 
3819 
3820 
3821 template<typename eT>
3822 inline
3823 eT
min(uword & index_of_min_val) const3824 subview_col<eT>::min(uword& index_of_min_val) const
3825   {
3826   arma_extra_debug_sigprint();
3827 
3828   if(subview<eT>::n_elem == 0)
3829     {
3830     arma_debug_check(true, "min(): object has no elements");
3831 
3832     index_of_min_val = uword(0);
3833 
3834     return Datum<eT>::nan;
3835     }
3836   else
3837     {
3838     return op_min::direct_min(colmem, subview<eT>::n_elem, index_of_min_val);
3839     }
3840   }
3841 
3842 
3843 
3844 template<typename eT>
3845 inline
3846 eT
max(uword & index_of_max_val) const3847 subview_col<eT>::max(uword& index_of_max_val) const
3848   {
3849   arma_extra_debug_sigprint();
3850 
3851   if(subview<eT>::n_elem == 0)
3852     {
3853     arma_debug_check(true, "max(): object has no elements");
3854 
3855     index_of_max_val = uword(0);
3856 
3857     return Datum<eT>::nan;
3858     }
3859   else
3860     {
3861     return op_max::direct_max(colmem, subview<eT>::n_elem, index_of_max_val);
3862     }
3863   }
3864 
3865 
3866 
3867 template<typename eT>
3868 inline
3869 arma_warn_unused
3870 uword
index_min() const3871 subview_col<eT>::index_min() const
3872   {
3873   arma_extra_debug_sigprint();
3874 
3875   uword index = 0;
3876 
3877   if(subview<eT>::n_elem == 0)
3878     {
3879     arma_debug_check(true, "index_min(): object has no elements");
3880     }
3881   else
3882     {
3883     op_min::direct_min(colmem, subview<eT>::n_elem, index);
3884     }
3885 
3886   return index;
3887   }
3888 
3889 
3890 
3891 template<typename eT>
3892 inline
3893 arma_warn_unused
3894 uword
index_max() const3895 subview_col<eT>::index_max() const
3896   {
3897   arma_extra_debug_sigprint();
3898 
3899   uword index = 0;
3900 
3901   if(subview<eT>::n_elem == 0)
3902     {
3903     arma_debug_check(true, "index_max(): object has no elements");
3904     }
3905   else
3906     {
3907     op_max::direct_max(colmem, subview<eT>::n_elem, index);
3908     }
3909 
3910   return index;
3911   }
3912 
3913 
3914 
3915 //
3916 //
3917 //
3918 
3919 
3920 template<typename eT>
3921 inline
subview_cols(const Mat<eT> & in_m,const uword in_col1,const uword in_n_cols)3922 subview_cols<eT>::subview_cols(const Mat<eT>& in_m, const uword in_col1, const uword in_n_cols)
3923   : subview<eT>(in_m, 0, in_col1, in_m.n_rows, in_n_cols)
3924   {
3925   arma_extra_debug_sigprint();
3926   }
3927 
3928 
3929 
3930 template<typename eT>
3931 inline
subview_cols(const subview_cols<eT> & in)3932 subview_cols<eT>::subview_cols(const subview_cols<eT>& in)
3933   : subview<eT>(in)   // interprets 'subview_cols' as 'subview'
3934   {
3935   arma_extra_debug_sigprint();
3936   }
3937 
3938 
3939 
3940 template<typename eT>
3941 inline
subview_cols(subview_cols<eT> && in)3942 subview_cols<eT>::subview_cols(subview_cols<eT>&& in)
3943   : subview<eT>(std::move(in))  // interprets 'subview_cols' as 'subview'
3944   {
3945   arma_extra_debug_sigprint();
3946   }
3947 
3948 
3949 
3950 template<typename eT>
3951 inline
3952 void
operator =(const subview<eT> & X)3953 subview_cols<eT>::operator=(const subview<eT>& X)
3954   {
3955   arma_extra_debug_sigprint();
3956 
3957   subview<eT>::operator=(X);
3958   }
3959 
3960 
3961 
3962 template<typename eT>
3963 inline
3964 void
operator =(const subview_cols<eT> & X)3965 subview_cols<eT>::operator=(const subview_cols<eT>& X)
3966   {
3967   arma_extra_debug_sigprint();
3968 
3969   subview<eT>::operator=(X); // interprets 'subview_cols' as 'subview'
3970   }
3971 
3972 
3973 
3974 template<typename eT>
3975 inline
3976 void
operator =(const std::initializer_list<eT> & list)3977 subview_cols<eT>::operator=(const std::initializer_list<eT>& list)
3978   {
3979   arma_extra_debug_sigprint();
3980 
3981   subview<eT>::operator=(list);
3982   }
3983 
3984 
3985 
3986 template<typename eT>
3987 inline
3988 void
operator =(const std::initializer_list<std::initializer_list<eT>> & list)3989 subview_cols<eT>::operator=(const std::initializer_list< std::initializer_list<eT> >& list)
3990   {
3991   arma_extra_debug_sigprint();
3992 
3993   subview<eT>::operator=(list);
3994   }
3995 
3996 
3997 
3998 template<typename eT>
3999 inline
4000 void
operator =(const eT val)4001 subview_cols<eT>::operator=(const eT val)
4002   {
4003   arma_extra_debug_sigprint();
4004 
4005   subview<eT>::operator=(val);
4006   }
4007 
4008 
4009 
4010 template<typename eT>
4011 template<typename T1>
4012 inline
4013 void
operator =(const Base<eT,T1> & X)4014 subview_cols<eT>::operator=(const Base<eT,T1>& X)
4015   {
4016   arma_extra_debug_sigprint();
4017 
4018   subview<eT>::operator=(X.get_ref());
4019   }
4020 
4021 
4022 
4023 template<typename eT>
4024 template<typename T1>
4025 inline
4026 void
operator =(const SpBase<eT,T1> & X)4027 subview_cols<eT>::operator=(const SpBase<eT,T1>& X)
4028   {
4029   arma_extra_debug_sigprint();
4030 
4031   subview<eT>::operator=(X.get_ref());
4032   }
4033 
4034 
4035 
4036 template<typename eT>
4037 template<typename T1, typename gen_type>
4038 inline
4039 typename enable_if2< is_same_type<typename T1::elem_type, eT>::value, void>::result
operator =(const Gen<T1,gen_type> & in)4040 subview_cols<eT>::operator= (const Gen<T1,gen_type>& in)
4041   {
4042   arma_extra_debug_sigprint();
4043 
4044   subview<eT>::operator=(in);
4045   }
4046 
4047 
4048 
4049 template<typename eT>
4050 arma_inline
4051 arma_warn_unused
4052 const Op<subview_cols<eT>,op_htrans>
t() const4053 subview_cols<eT>::t() const
4054   {
4055   return Op<subview_cols<eT>,op_htrans>(*this);
4056   }
4057 
4058 
4059 
4060 template<typename eT>
4061 arma_inline
4062 arma_warn_unused
4063 const Op<subview_cols<eT>,op_htrans>
ht() const4064 subview_cols<eT>::ht() const
4065   {
4066   return Op<subview_cols<eT>,op_htrans>(*this);
4067   }
4068 
4069 
4070 
4071 template<typename eT>
4072 arma_inline
4073 arma_warn_unused
4074 const Op<subview_cols<eT>,op_strans>
st() const4075 subview_cols<eT>::st() const
4076   {
4077   return Op<subview_cols<eT>,op_strans>(*this);
4078   }
4079 
4080 
4081 
4082 template<typename eT>
4083 arma_inline
4084 arma_warn_unused
4085 const Op<subview_cols<eT>,op_vectorise_col>
as_col() const4086 subview_cols<eT>::as_col() const
4087   {
4088   return Op<subview_cols<eT>,op_vectorise_col>(*this);
4089   }
4090 
4091 
4092 
4093 template<typename eT>
4094 inline
4095 arma_warn_unused
4096 eT
at_alt(const uword ii) const4097 subview_cols<eT>::at_alt(const uword ii) const
4098   {
4099   return operator[](ii);
4100   }
4101 
4102 
4103 
4104 template<typename eT>
4105 inline
4106 arma_warn_unused
4107 eT&
operator [](const uword ii)4108 subview_cols<eT>::operator[](const uword ii)
4109   {
4110   const uword index = subview<eT>::aux_col1 * subview<eT>::m.n_rows + ii;
4111 
4112   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4113   }
4114 
4115 
4116 
4117 template<typename eT>
4118 inline
4119 arma_warn_unused
4120 eT
operator [](const uword ii) const4121 subview_cols<eT>::operator[](const uword ii) const
4122   {
4123   const uword index = subview<eT>::aux_col1 * subview<eT>::m.n_rows + ii;
4124 
4125   return subview<eT>::m.mem[index];
4126   }
4127 
4128 
4129 
4130 template<typename eT>
4131 inline
4132 arma_warn_unused
4133 eT&
operator ()(const uword ii)4134 subview_cols<eT>::operator()(const uword ii)
4135   {
4136   arma_debug_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
4137 
4138   const uword index = subview<eT>::aux_col1 * subview<eT>::m.n_rows + ii;
4139 
4140   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4141   }
4142 
4143 
4144 
4145 template<typename eT>
4146 inline
4147 arma_warn_unused
4148 eT
operator ()(const uword ii) const4149 subview_cols<eT>::operator()(const uword ii) const
4150   {
4151   arma_debug_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
4152 
4153   const uword index = subview<eT>::aux_col1 * subview<eT>::m.n_rows + ii;
4154 
4155   return subview<eT>::m.mem[index];
4156   }
4157 
4158 
4159 
4160 template<typename eT>
4161 inline
4162 arma_warn_unused
4163 eT&
operator ()(const uword in_row,const uword in_col)4164 subview_cols<eT>::operator()(const uword in_row, const uword in_col)
4165   {
4166   arma_debug_check_bounds( ((in_row >= subview<eT>::n_rows) || (in_col >= subview<eT>::n_cols)), "subview::operator(): index out of bounds" );
4167 
4168   const uword index = (in_col + subview<eT>::aux_col1) * subview<eT>::m.n_rows + in_row;
4169 
4170   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4171   }
4172 
4173 
4174 
4175 template<typename eT>
4176 inline
4177 arma_warn_unused
4178 eT
operator ()(const uword in_row,const uword in_col) const4179 subview_cols<eT>::operator()(const uword in_row, const uword in_col) const
4180   {
4181   arma_debug_check_bounds( ((in_row >= subview<eT>::n_rows) || (in_col >= subview<eT>::n_cols)), "subview::operator(): index out of bounds" );
4182 
4183   const uword index = (in_col + subview<eT>::aux_col1) * subview<eT>::m.n_rows + in_row;
4184 
4185   return subview<eT>::m.mem[index];
4186   }
4187 
4188 
4189 
4190 template<typename eT>
4191 inline
4192 arma_warn_unused
4193 eT&
at(const uword in_row,const uword in_col)4194 subview_cols<eT>::at(const uword in_row, const uword in_col)
4195   {
4196   const uword index = (in_col + subview<eT>::aux_col1) * subview<eT>::m.n_rows + in_row;
4197 
4198   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4199   }
4200 
4201 
4202 
4203 template<typename eT>
4204 inline
4205 arma_warn_unused
4206 eT
at(const uword in_row,const uword in_col) const4207 subview_cols<eT>::at(const uword in_row, const uword in_col) const
4208   {
4209   const uword index = (in_col + subview<eT>::aux_col1) * subview<eT>::m.n_rows + in_row;
4210 
4211   return subview<eT>::m.mem[index];
4212   }
4213 
4214 
4215 
4216 template<typename eT>
4217 arma_inline
4218 eT*
colptr(const uword in_col)4219 subview_cols<eT>::colptr(const uword in_col)
4220   {
4221   return & access::rw((const_cast< Mat<eT>& >(subview<eT>::m)).mem[ (in_col + subview<eT>::aux_col1) * subview<eT>::m.n_rows ]);
4222   }
4223 
4224 
4225 
4226 template<typename eT>
4227 arma_inline
4228 const eT*
colptr(const uword in_col) const4229 subview_cols<eT>::colptr(const uword in_col) const
4230   {
4231   return & subview<eT>::m.mem[ (in_col + subview<eT>::aux_col1) * subview<eT>::m.n_rows ];
4232   }
4233 
4234 
4235 
4236 //
4237 //
4238 //
4239 
4240 
4241 
4242 template<typename eT>
4243 inline
subview_row(const Mat<eT> & in_m,const uword in_row)4244 subview_row<eT>::subview_row(const Mat<eT>& in_m, const uword in_row)
4245   : subview<eT>(in_m, in_row, 0, 1, in_m.n_cols)
4246   {
4247   arma_extra_debug_sigprint();
4248   }
4249 
4250 
4251 
4252 template<typename eT>
4253 inline
subview_row(const Mat<eT> & in_m,const uword in_row,const uword in_col1,const uword in_n_cols)4254 subview_row<eT>::subview_row(const Mat<eT>& in_m, const uword in_row, const uword in_col1, const uword in_n_cols)
4255   : subview<eT>(in_m, in_row, in_col1, 1, in_n_cols)
4256   {
4257   arma_extra_debug_sigprint();
4258   }
4259 
4260 
4261 
4262 template<typename eT>
4263 inline
subview_row(const subview_row<eT> & in)4264 subview_row<eT>::subview_row(const subview_row<eT>& in)
4265   : subview<eT>(in)   // interprets 'subview_row' as 'subview'
4266   {
4267   arma_extra_debug_sigprint();
4268   }
4269 
4270 
4271 
4272 template<typename eT>
4273 inline
subview_row(subview_row<eT> && in)4274 subview_row<eT>::subview_row(subview_row<eT>&& in)
4275   : subview<eT>(std::move(in))  // interprets 'subview_row' as 'subview'
4276   {
4277   arma_extra_debug_sigprint();
4278   }
4279 
4280 
4281 
4282 template<typename eT>
4283 inline
4284 void
operator =(const subview<eT> & X)4285 subview_row<eT>::operator=(const subview<eT>& X)
4286   {
4287   arma_extra_debug_sigprint();
4288 
4289   subview<eT>::operator=(X);
4290   }
4291 
4292 
4293 
4294 template<typename eT>
4295 inline
4296 void
operator =(const subview_row<eT> & X)4297 subview_row<eT>::operator=(const subview_row<eT>& X)
4298   {
4299   arma_extra_debug_sigprint();
4300 
4301   subview<eT>::operator=(X); // interprets 'subview_row' as 'subview'
4302   }
4303 
4304 
4305 
4306 template<typename eT>
4307 inline
4308 void
operator =(const eT val)4309 subview_row<eT>::operator=(const eT val)
4310   {
4311   arma_extra_debug_sigprint();
4312 
4313   subview<eT>::operator=(val); // interprets 'subview_row' as 'subview'
4314   }
4315 
4316 
4317 
4318 template<typename eT>
4319 inline
4320 void
operator =(const std::initializer_list<eT> & list)4321 subview_row<eT>::operator=(const std::initializer_list<eT>& list)
4322   {
4323   arma_extra_debug_sigprint();
4324 
4325   const uword N = uword(list.size());
4326 
4327   arma_debug_assert_same_size(subview<eT>::n_rows, subview<eT>::n_cols, 1, N, "copy into submatrix");
4328 
4329   auto it = list.begin();
4330 
4331   for(uword ii=0; ii < N; ++ii)
4332     {
4333     (*this).operator[](ii) = (*it);
4334     ++it;
4335     }
4336   }
4337 
4338 
4339 
4340 template<typename eT>
4341 template<typename T1>
4342 inline
4343 void
operator =(const Base<eT,T1> & X)4344 subview_row<eT>::operator=(const Base<eT,T1>& X)
4345   {
4346   arma_extra_debug_sigprint();
4347 
4348   subview<eT>::operator=(X);
4349   }
4350 
4351 
4352 
4353 template<typename eT>
4354 template<typename T1>
4355 inline
4356 void
operator =(const SpBase<eT,T1> & X)4357 subview_row<eT>::operator=(const SpBase<eT,T1>& X)
4358   {
4359   arma_extra_debug_sigprint();
4360 
4361   subview<eT>::operator=(X.get_ref());
4362   }
4363 
4364 
4365 
4366 template<typename eT>
4367 template<typename T1, typename gen_type>
4368 inline
4369 typename enable_if2< is_same_type<typename T1::elem_type, eT>::value, void>::result
operator =(const Gen<T1,gen_type> & in)4370 subview_row<eT>::operator= (const Gen<T1,gen_type>& in)
4371   {
4372   arma_extra_debug_sigprint();
4373 
4374   arma_debug_assert_same_size(uword(1), subview<eT>::n_cols, (in.is_row ? uword(1) : in.n_rows), in.n_cols, "copy into submatrix");
4375 
4376   in.apply(*this);
4377   }
4378 
4379 
4380 
4381 template<typename eT>
4382 arma_inline
4383 arma_warn_unused
4384 const Op<subview_row<eT>,op_htrans>
t() const4385 subview_row<eT>::t() const
4386   {
4387   return Op<subview_row<eT>,op_htrans>(*this);
4388   }
4389 
4390 
4391 
4392 template<typename eT>
4393 arma_inline
4394 arma_warn_unused
4395 const Op<subview_row<eT>,op_htrans>
ht() const4396 subview_row<eT>::ht() const
4397   {
4398   return Op<subview_row<eT>,op_htrans>(*this);
4399   }
4400 
4401 
4402 
4403 template<typename eT>
4404 arma_inline
4405 arma_warn_unused
4406 const Op<subview_row<eT>,op_strans>
st() const4407 subview_row<eT>::st() const
4408   {
4409   return Op<subview_row<eT>,op_strans>(*this);
4410   }
4411 
4412 
4413 
4414 template<typename eT>
4415 arma_inline
4416 arma_warn_unused
4417 const Op<subview_row<eT>,op_strans>
as_col() const4418 subview_row<eT>::as_col() const
4419   {
4420   return Op<subview_row<eT>,op_strans>(*this);
4421   }
4422 
4423 
4424 
4425 template<typename eT>
4426 inline
4427 eT
at_alt(const uword ii) const4428 subview_row<eT>::at_alt(const uword ii) const
4429   {
4430   const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4431 
4432   return subview<eT>::m.mem[index];
4433   }
4434 
4435 
4436 
4437 template<typename eT>
4438 inline
4439 eT&
operator [](const uword ii)4440 subview_row<eT>::operator[](const uword ii)
4441   {
4442   const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4443 
4444   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4445   }
4446 
4447 
4448 
4449 template<typename eT>
4450 inline
4451 eT
operator [](const uword ii) const4452 subview_row<eT>::operator[](const uword ii) const
4453   {
4454   const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4455 
4456   return subview<eT>::m.mem[index];
4457   }
4458 
4459 
4460 
4461 template<typename eT>
4462 inline
4463 eT&
operator ()(const uword ii)4464 subview_row<eT>::operator()(const uword ii)
4465   {
4466   arma_debug_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
4467 
4468   const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4469 
4470   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4471   }
4472 
4473 
4474 
4475 template<typename eT>
4476 inline
4477 eT
operator ()(const uword ii) const4478 subview_row<eT>::operator()(const uword ii) const
4479   {
4480   arma_debug_check_bounds( (ii >= subview<eT>::n_elem), "subview::operator(): index out of bounds" );
4481 
4482   const uword index = (ii + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4483 
4484   return subview<eT>::m.mem[index];
4485   }
4486 
4487 
4488 
4489 template<typename eT>
4490 inline
4491 eT&
operator ()(const uword in_row,const uword in_col)4492 subview_row<eT>::operator()(const uword in_row, const uword in_col)
4493   {
4494   arma_debug_check_bounds( ((in_row > 0) || (in_col >= subview<eT>::n_cols)), "subview::operator(): index out of bounds" );
4495 
4496   const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4497 
4498   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4499   }
4500 
4501 
4502 
4503 template<typename eT>
4504 inline
4505 eT
operator ()(const uword in_row,const uword in_col) const4506 subview_row<eT>::operator()(const uword in_row, const uword in_col) const
4507   {
4508   arma_debug_check_bounds( ((in_row > 0) || (in_col >= subview<eT>::n_cols)), "subview::operator(): index out of bounds" );
4509 
4510   const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4511 
4512   return subview<eT>::m.mem[index];
4513   }
4514 
4515 
4516 
4517 template<typename eT>
4518 inline
4519 eT&
at(const uword,const uword in_col)4520 subview_row<eT>::at(const uword, const uword in_col)
4521   {
4522   const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4523 
4524   return access::rw( (const_cast< Mat<eT>& >(subview<eT>::m)).mem[index] );
4525   }
4526 
4527 
4528 
4529 template<typename eT>
4530 inline
4531 eT
at(const uword,const uword in_col) const4532 subview_row<eT>::at(const uword, const uword in_col) const
4533   {
4534   const uword index = (in_col + (subview<eT>::aux_col1))*(subview<eT>::m).n_rows + (subview<eT>::aux_row1);
4535 
4536   return subview<eT>::m.mem[index];
4537   }
4538 
4539 
4540 
4541 template<typename eT>
4542 inline
4543 subview_row<eT>
cols(const uword in_col1,const uword in_col2)4544 subview_row<eT>::cols(const uword in_col1, const uword in_col2)
4545   {
4546   arma_extra_debug_sigprint();
4547 
4548   arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview<eT>::n_cols) ), "subview_row::cols(): indices out of bounds or incorrectly used" );
4549 
4550   const uword subview_n_cols = in_col2 - in_col1 + 1;
4551 
4552   const uword base_col1 = this->aux_col1 + in_col1;
4553 
4554   return subview_row<eT>(this->m, this->aux_row1, base_col1, subview_n_cols);
4555   }
4556 
4557 
4558 
4559 template<typename eT>
4560 inline
4561 const subview_row<eT>
cols(const uword in_col1,const uword in_col2) const4562 subview_row<eT>::cols(const uword in_col1, const uword in_col2) const
4563   {
4564   arma_extra_debug_sigprint();
4565 
4566   arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview<eT>::n_cols) ), "subview_row::cols(): indices out of bounds or incorrectly used" );
4567 
4568   const uword subview_n_cols = in_col2 - in_col1 + 1;
4569 
4570   const uword base_col1 = this->aux_col1 + in_col1;
4571 
4572   return subview_row<eT>(this->m, this->aux_row1, base_col1, subview_n_cols);
4573   }
4574 
4575 
4576 
4577 template<typename eT>
4578 inline
4579 subview_row<eT>
subvec(const uword in_col1,const uword in_col2)4580 subview_row<eT>::subvec(const uword in_col1, const uword in_col2)
4581   {
4582   arma_extra_debug_sigprint();
4583 
4584   arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview<eT>::n_cols) ), "subview_row::subvec(): indices out of bounds or incorrectly used" );
4585 
4586   const uword subview_n_cols = in_col2 - in_col1 + 1;
4587 
4588   const uword base_col1 = this->aux_col1 + in_col1;
4589 
4590   return subview_row<eT>(this->m, this->aux_row1, base_col1, subview_n_cols);
4591   }
4592 
4593 
4594 
4595 template<typename eT>
4596 inline
4597 const subview_row<eT>
subvec(const uword in_col1,const uword in_col2) const4598 subview_row<eT>::subvec(const uword in_col1, const uword in_col2) const
4599   {
4600   arma_extra_debug_sigprint();
4601 
4602   arma_debug_check_bounds( ( (in_col1 > in_col2) || (in_col2 >= subview<eT>::n_cols) ), "subview_row::subvec(): indices out of bounds or incorrectly used" );
4603 
4604   const uword subview_n_cols = in_col2 - in_col1 + 1;
4605 
4606   const uword base_col1 = this->aux_col1 + in_col1;
4607 
4608   return subview_row<eT>(this->m, this->aux_row1, base_col1, subview_n_cols);
4609   }
4610 
4611 
4612 
4613 template<typename eT>
4614 inline
4615 subview_row<eT>
subvec(const uword start_col,const SizeMat & s)4616 subview_row<eT>::subvec(const uword start_col, const SizeMat& s)
4617   {
4618   arma_extra_debug_sigprint();
4619 
4620   arma_debug_check( (s.n_rows != 1), "subview_row::subvec(): given size does not specify a row vector" );
4621 
4622   arma_debug_check_bounds( ( (start_col >= subview<eT>::n_cols) || ((start_col + s.n_cols) > subview<eT>::n_cols) ), "subview_row::subvec(): size out of bounds" );
4623 
4624   const uword base_col1 = this->aux_col1 + start_col;
4625 
4626   return subview_row<eT>(this->m, this->aux_row1, base_col1, s.n_cols);
4627   }
4628 
4629 
4630 
4631 template<typename eT>
4632 inline
4633 const subview_row<eT>
subvec(const uword start_col,const SizeMat & s) const4634 subview_row<eT>::subvec(const uword start_col, const SizeMat& s) const
4635   {
4636   arma_extra_debug_sigprint();
4637 
4638   arma_debug_check( (s.n_rows != 1), "subview_row::subvec(): given size does not specify a row vector" );
4639 
4640   arma_debug_check_bounds( ( (start_col >= subview<eT>::n_cols) || ((start_col + s.n_cols) > subview<eT>::n_cols) ), "subview_row::subvec(): size out of bounds" );
4641 
4642   const uword base_col1 = this->aux_col1 + start_col;
4643 
4644   return subview_row<eT>(this->m, this->aux_row1, base_col1, s.n_cols);
4645   }
4646 
4647 
4648 
4649 template<typename eT>
4650 inline
4651 subview_row<eT>
head(const uword N)4652 subview_row<eT>::head(const uword N)
4653   {
4654   arma_extra_debug_sigprint();
4655 
4656   arma_debug_check_bounds( (N > subview<eT>::n_cols), "subview_row::head(): size out of bounds" );
4657 
4658   return subview_row<eT>(this->m, this->aux_row1, this->aux_col1, N);
4659   }
4660 
4661 
4662 
4663 template<typename eT>
4664 inline
4665 const subview_row<eT>
head(const uword N) const4666 subview_row<eT>::head(const uword N) const
4667   {
4668   arma_extra_debug_sigprint();
4669 
4670   arma_debug_check_bounds( (N > subview<eT>::n_cols), "subview_row::head(): size out of bounds" );
4671 
4672   return subview_row<eT>(this->m, this->aux_row1, this->aux_col1, N);
4673   }
4674 
4675 
4676 
4677 template<typename eT>
4678 inline
4679 subview_row<eT>
tail(const uword N)4680 subview_row<eT>::tail(const uword N)
4681   {
4682   arma_extra_debug_sigprint();
4683 
4684   arma_debug_check_bounds( (N > subview<eT>::n_cols), "subview_row::tail(): size out of bounds" );
4685 
4686   const uword start_col = subview<eT>::aux_col1 + subview<eT>::n_cols - N;
4687 
4688   return subview_row<eT>(this->m, this->aux_row1, start_col, N);
4689   }
4690 
4691 
4692 
4693 template<typename eT>
4694 inline
4695 const subview_row<eT>
tail(const uword N) const4696 subview_row<eT>::tail(const uword N) const
4697   {
4698   arma_extra_debug_sigprint();
4699 
4700   arma_debug_check_bounds( (N > subview<eT>::n_cols), "subview_row::tail(): size out of bounds" );
4701 
4702   const uword start_col = subview<eT>::aux_col1 + subview<eT>::n_cols - N;
4703 
4704   return subview_row<eT>(this->m, this->aux_row1, start_col, N);
4705   }
4706 
4707 
4708 
4709 template<typename eT>
4710 inline
4711 arma_warn_unused
4712 uword
index_min() const4713 subview_row<eT>::index_min() const
4714   {
4715   const Proxy< subview_row<eT> > P(*this);
4716 
4717   uword index = 0;
4718 
4719   if(P.get_n_elem() == 0)
4720     {
4721     arma_debug_check(true, "index_min(): object has no elements");
4722     }
4723   else
4724     {
4725     op_min::min_with_index(P, index);
4726     }
4727 
4728   return index;
4729   }
4730 
4731 
4732 
4733 template<typename eT>
4734 inline
4735 arma_warn_unused
4736 uword
index_max() const4737 subview_row<eT>::index_max() const
4738   {
4739   const Proxy< subview_row<eT> > P(*this);
4740 
4741   uword index = 0;
4742 
4743   if(P.get_n_elem() == 0)
4744     {
4745     arma_debug_check(true, "index_max(): object has no elements");
4746     }
4747   else
4748     {
4749     op_max::max_with_index(P, index);
4750     }
4751 
4752   return index;
4753   }
4754 
4755 
4756 
4757 template<typename eT>
4758 inline
4759 typename subview<eT>::row_iterator
begin()4760 subview_row<eT>::begin()
4761   {
4762   return typename subview<eT>::row_iterator(*this, subview<eT>::aux_row1, subview<eT>::aux_col1);
4763   }
4764 
4765 
4766 
4767 template<typename eT>
4768 inline
4769 typename subview<eT>::const_row_iterator
begin() const4770 subview_row<eT>::begin() const
4771   {
4772   return typename subview<eT>::const_row_iterator(*this, subview<eT>::aux_row1, subview<eT>::aux_col1);
4773   }
4774 
4775 
4776 
4777 template<typename eT>
4778 inline
4779 typename subview<eT>::const_row_iterator
cbegin() const4780 subview_row<eT>::cbegin() const
4781   {
4782   return typename subview<eT>::const_row_iterator(*this, subview<eT>::aux_row1, subview<eT>::aux_col1);
4783   }
4784 
4785 
4786 
4787 template<typename eT>
4788 inline
4789 typename subview<eT>::row_iterator
end()4790 subview_row<eT>::end()
4791   {
4792   return typename subview<eT>::row_iterator(*this, subview<eT>::aux_row1 + subview<eT>::n_rows, subview<eT>::aux_col1);
4793   }
4794 
4795 
4796 
4797 template<typename eT>
4798 inline
4799 typename subview<eT>::const_row_iterator
end() const4800 subview_row<eT>::end() const
4801   {
4802   return typename subview<eT>::const_row_iterator(*this, subview<eT>::aux_row1 + subview<eT>::n_rows, subview<eT>::aux_col1);
4803   }
4804 
4805 
4806 
4807 template<typename eT>
4808 inline
4809 typename subview<eT>::const_row_iterator
cend() const4810 subview_row<eT>::cend() const
4811   {
4812   return typename subview<eT>::const_row_iterator(*this, subview<eT>::aux_row1 + subview<eT>::n_rows, subview<eT>::aux_col1);
4813   }
4814 
4815 
4816 
4817 //
4818 //
4819 //
4820 
4821 
4822 
4823 template<typename eT>
4824 inline
subview_row_strans(const subview_row<eT> & in_sv_row)4825 subview_row_strans<eT>::subview_row_strans(const subview_row<eT>& in_sv_row)
4826   : sv_row(in_sv_row       )
4827   , n_rows(in_sv_row.n_cols)
4828   , n_elem(in_sv_row.n_elem)
4829   {
4830   arma_extra_debug_sigprint();
4831   }
4832 
4833 
4834 
4835 template<typename eT>
4836 inline
4837 void
extract(Mat<eT> & out) const4838 subview_row_strans<eT>::extract(Mat<eT>& out) const
4839   {
4840   arma_extra_debug_sigprint();
4841 
4842   // NOTE: this function assumes that matrix 'out' has already been set to the correct size
4843 
4844   const Mat<eT>& X = sv_row.m;
4845 
4846   eT* out_mem = out.memptr();
4847 
4848   const uword row           = sv_row.aux_row1;
4849   const uword start_col     = sv_row.aux_col1;
4850   const uword sv_row_n_cols = sv_row.n_cols;
4851 
4852   uword ii,jj;
4853 
4854   for(ii=0, jj=1; jj < sv_row_n_cols; ii+=2, jj+=2)
4855     {
4856     const eT tmp1 = X.at(row, start_col+ii);
4857     const eT tmp2 = X.at(row, start_col+jj);
4858 
4859     out_mem[ii] = tmp1;
4860     out_mem[jj] = tmp2;
4861     }
4862 
4863   if(ii < sv_row_n_cols)
4864     {
4865     out_mem[ii] = X.at(row, start_col+ii);
4866     }
4867   }
4868 
4869 
4870 
4871 template<typename eT>
4872 inline
4873 eT
at_alt(const uword ii) const4874 subview_row_strans<eT>::at_alt(const uword ii) const
4875   {
4876   return sv_row[ii];
4877   }
4878 
4879 
4880 
4881 template<typename eT>
4882 inline
4883 eT
operator [](const uword ii) const4884 subview_row_strans<eT>::operator[](const uword ii) const
4885   {
4886   return sv_row[ii];
4887   }
4888 
4889 
4890 
4891 template<typename eT>
4892 inline
4893 eT
operator ()(const uword ii) const4894 subview_row_strans<eT>::operator()(const uword ii) const
4895   {
4896   return sv_row(ii);
4897   }
4898 
4899 
4900 
4901 template<typename eT>
4902 inline
4903 eT
operator ()(const uword in_row,const uword in_col) const4904 subview_row_strans<eT>::operator()(const uword in_row, const uword in_col) const
4905   {
4906   return sv_row(in_col, in_row);  // deliberately swapped
4907   }
4908 
4909 
4910 
4911 template<typename eT>
4912 inline
4913 eT
at(const uword in_row,const uword) const4914 subview_row_strans<eT>::at(const uword in_row, const uword) const
4915   {
4916   return sv_row.at(0, in_row);  // deliberately swapped
4917   }
4918 
4919 
4920 
4921 //
4922 //
4923 //
4924 
4925 
4926 
4927 template<typename eT>
4928 inline
subview_row_htrans(const subview_row<eT> & in_sv_row)4929 subview_row_htrans<eT>::subview_row_htrans(const subview_row<eT>& in_sv_row)
4930   : sv_row(in_sv_row       )
4931   , n_rows(in_sv_row.n_cols)
4932   , n_elem(in_sv_row.n_elem)
4933   {
4934   arma_extra_debug_sigprint();
4935   }
4936 
4937 
4938 
4939 template<typename eT>
4940 inline
4941 void
extract(Mat<eT> & out) const4942 subview_row_htrans<eT>::extract(Mat<eT>& out) const
4943   {
4944   arma_extra_debug_sigprint();
4945 
4946   // NOTE: this function assumes that matrix 'out' has already been set to the correct size
4947 
4948   const Mat<eT>& X = sv_row.m;
4949 
4950   eT* out_mem = out.memptr();
4951 
4952   const uword row           = sv_row.aux_row1;
4953   const uword start_col     = sv_row.aux_col1;
4954   const uword sv_row_n_cols = sv_row.n_cols;
4955 
4956   for(uword ii=0; ii < sv_row_n_cols; ++ii)
4957     {
4958     out_mem[ii] = access::alt_conj( X.at(row, start_col+ii) );
4959     }
4960   }
4961 
4962 
4963 
4964 template<typename eT>
4965 inline
4966 eT
at_alt(const uword ii) const4967 subview_row_htrans<eT>::at_alt(const uword ii) const
4968   {
4969   return access::alt_conj( sv_row[ii] );
4970   }
4971 
4972 
4973 
4974 template<typename eT>
4975 inline
4976 eT
operator [](const uword ii) const4977 subview_row_htrans<eT>::operator[](const uword ii) const
4978   {
4979   return access::alt_conj( sv_row[ii] );
4980   }
4981 
4982 
4983 
4984 template<typename eT>
4985 inline
4986 eT
operator ()(const uword ii) const4987 subview_row_htrans<eT>::operator()(const uword ii) const
4988   {
4989   return access::alt_conj( sv_row(ii) );
4990   }
4991 
4992 
4993 
4994 template<typename eT>
4995 inline
4996 eT
operator ()(const uword in_row,const uword in_col) const4997 subview_row_htrans<eT>::operator()(const uword in_row, const uword in_col) const
4998   {
4999   return access::alt_conj( sv_row(in_col, in_row) );  // deliberately swapped
5000   }
5001 
5002 
5003 
5004 template<typename eT>
5005 inline
5006 eT
at(const uword in_row,const uword) const5007 subview_row_htrans<eT>::at(const uword in_row, const uword) const
5008   {
5009   return access::alt_conj( sv_row.at(0, in_row) );  // deliberately swapped
5010   }
5011 
5012 
5013 
5014 //! @}
5015