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 SpSubview
20 //! @{
21 
22 
23 template<typename eT>
24 inline
~SpSubview()25 SpSubview<eT>::~SpSubview()
26   {
27   arma_extra_debug_sigprint_this(this);
28   }
29 
30 
31 
32 template<typename eT>
33 inline
SpSubview(const SpMat<eT> & in_m,const uword in_row1,const uword in_col1,const uword in_n_rows,const uword in_n_cols)34 SpSubview<eT>::SpSubview(const SpMat<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   , n_nonzero(0)
42   {
43   arma_extra_debug_sigprint_this(this);
44 
45   m.sync_csc();
46 
47   // There must be a O(1) way to do this
48   uword lend     = m.col_ptrs[in_col1 + in_n_cols];
49   uword lend_row = in_row1 + in_n_rows;
50   uword count   = 0;
51 
52   for(uword i = m.col_ptrs[in_col1]; i < lend; ++i)
53     {
54     const uword m_row_indices_i = m.row_indices[i];
55 
56     const bool condition = (m_row_indices_i >= in_row1) && (m_row_indices_i < lend_row);
57 
58     count += condition ? uword(1) : uword(0);
59     }
60 
61   access::rw(n_nonzero) = count;
62   }
63 
64 
65 
66 template<typename eT>
67 inline
SpSubview(const SpSubview<eT> & in)68 SpSubview<eT>::SpSubview(const SpSubview<eT>& in)
69   : m        (in.m        )
70   , aux_row1 (in.aux_row1 )
71   , aux_col1 (in.aux_col1 )
72   , n_rows   (in.n_rows   )
73   , n_cols   (in.n_cols   )
74   , n_elem   (in.n_elem   )
75   , n_nonzero(in.n_nonzero)
76   {
77   arma_extra_debug_sigprint(arma_str::format("this = %x   in = %x") % this % &in);
78   }
79 
80 
81 
82 template<typename eT>
83 inline
SpSubview(SpSubview<eT> && in)84 SpSubview<eT>::SpSubview(SpSubview<eT>&& in)
85   : m        (in.m        )
86   , aux_row1 (in.aux_row1 )
87   , aux_col1 (in.aux_col1 )
88   , n_rows   (in.n_rows   )
89   , n_cols   (in.n_cols   )
90   , n_elem   (in.n_elem   )
91   , n_nonzero(in.n_nonzero)
92   {
93   arma_extra_debug_sigprint(arma_str::format("this = %x   in = %x") % this % &in);
94 
95   // for paranoia
96 
97   access::rw(in.aux_row1 ) = 0;
98   access::rw(in.aux_col1 ) = 0;
99   access::rw(in.n_rows   ) = 0;
100   access::rw(in.n_cols   ) = 0;
101   access::rw(in.n_elem   ) = 0;
102   access::rw(in.n_nonzero) = 0;
103   }
104 
105 
106 
107 template<typename eT>
108 inline
109 const SpSubview<eT>&
operator +=(const eT val)110 SpSubview<eT>::operator+=(const eT val)
111   {
112   arma_extra_debug_sigprint();
113 
114   if(val == eT(0))  { return *this; }
115 
116   Mat<eT> tmp( (*this).n_rows, (*this).n_cols, arma_nozeros_indicator() );
117 
118   tmp.fill(val);
119 
120   return (*this).operator=( (*this) + tmp );
121   }
122 
123 
124 
125 template<typename eT>
126 inline
127 const SpSubview<eT>&
operator -=(const eT val)128 SpSubview<eT>::operator-=(const eT val)
129   {
130   arma_extra_debug_sigprint();
131 
132   if(val == eT(0))  { return *this; }
133 
134   Mat<eT> tmp( (*this).n_rows, (*this).n_cols, arma_nozeros_indicator() );
135 
136   tmp.fill(val);
137 
138   return (*this).operator=( (*this) - tmp );
139   }
140 
141 
142 
143 template<typename eT>
144 inline
145 const SpSubview<eT>&
operator *=(const eT val)146 SpSubview<eT>::operator*=(const eT val)
147   {
148   arma_extra_debug_sigprint();
149 
150   if(val == eT(0))  { (*this).zeros(); return *this; }
151 
152   if((n_elem == 0) || (n_nonzero == 0))  { return *this; }
153 
154   m.sync_csc();
155   m.invalidate_cache();
156 
157   const uword lstart_row = aux_row1;
158   const uword lend_row   = aux_row1 + n_rows;
159 
160   const uword lstart_col = aux_col1;
161   const uword lend_col   = aux_col1 + n_cols;
162 
163   const uword* m_row_indices = m.row_indices;
164         eT*    m_values      = access::rwp(m.values);
165 
166   bool has_zero = false;
167 
168   for(uword c = lstart_col; c < lend_col; ++c)
169     {
170     const uword r_start = m.col_ptrs[c    ];
171     const uword r_end   = m.col_ptrs[c + 1];
172 
173     for(uword r = r_start; r < r_end; ++r)
174       {
175       const uword m_row_indices_r = m_row_indices[r];
176 
177       if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
178         {
179         eT& m_values_r = m_values[r];
180 
181         m_values_r *= val;
182 
183         if(m_values_r == eT(0))  { has_zero = true; }
184         }
185       }
186     }
187 
188   if(has_zero)
189     {
190     const uword old_m_n_nonzero = m.n_nonzero;
191 
192     access::rw(m).remove_zeros();
193 
194     if(m.n_nonzero != old_m_n_nonzero)
195       {
196       access::rw(n_nonzero) = n_nonzero - (old_m_n_nonzero - m.n_nonzero);
197       }
198     }
199 
200   return *this;
201   }
202 
203 
204 
205 template<typename eT>
206 inline
207 const SpSubview<eT>&
operator /=(const eT val)208 SpSubview<eT>::operator/=(const eT val)
209   {
210   arma_extra_debug_sigprint();
211 
212   arma_debug_check( (val == eT(0)), "element-wise division: division by zero" );
213 
214   m.sync_csc();
215   m.invalidate_cache();
216 
217   const uword lstart_row = aux_row1;
218   const uword lend_row   = aux_row1 + n_rows;
219 
220   const uword lstart_col = aux_col1;
221   const uword lend_col   = aux_col1 + n_cols;
222 
223   const uword* m_row_indices = m.row_indices;
224         eT*    m_values      = access::rwp(m.values);
225 
226   bool has_zero = false;
227 
228   for(uword c = lstart_col; c < lend_col; ++c)
229     {
230     const uword r_start = m.col_ptrs[c    ];
231     const uword r_end   = m.col_ptrs[c + 1];
232 
233     for(uword r = r_start; r < r_end; ++r)
234       {
235       const uword m_row_indices_r = m_row_indices[r];
236 
237       if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
238         {
239         eT& m_values_r = m_values[r];
240 
241         m_values_r /= val;
242 
243         if(m_values_r == eT(0))  { has_zero = true; }
244         }
245       }
246     }
247 
248   if(has_zero)
249     {
250     const uword old_m_n_nonzero = m.n_nonzero;
251 
252     access::rw(m).remove_zeros();
253 
254     if(m.n_nonzero != old_m_n_nonzero)
255       {
256       access::rw(n_nonzero) = n_nonzero - (old_m_n_nonzero - m.n_nonzero);
257       }
258     }
259 
260   return *this;
261   }
262 
263 
264 
265 template<typename eT>
266 template<typename T1>
267 inline
268 const SpSubview<eT>&
operator =(const Base<eT,T1> & in)269 SpSubview<eT>::operator=(const Base<eT, T1>& in)
270   {
271   arma_extra_debug_sigprint();
272 
273   if(is_same_type< T1, Gen<Mat<eT>, gen_zeros> >::yes)
274     {
275     const Proxy<T1> P(in.get_ref());
276 
277     arma_debug_assert_same_size(n_rows, n_cols, P.get_n_rows(), P.get_n_cols(), "insertion into sparse submatrix");
278 
279     (*this).zeros();
280 
281     return *this;
282     }
283 
284   if(is_same_type< T1, Gen<Mat<eT>, gen_eye> >::yes)
285     {
286     const Proxy<T1> P(in.get_ref());
287 
288     arma_debug_assert_same_size(n_rows, n_cols, P.get_n_rows(), P.get_n_cols(), "insertion into sparse submatrix");
289 
290     (*this).eye();
291 
292     return *this;
293     }
294 
295   const quasi_unwrap<T1> U(in.get_ref());
296 
297   arma_debug_assert_same_size(n_rows, n_cols, U.M.n_rows, U.M.n_cols, "insertion into sparse submatrix");
298 
299   spglue_merge::subview_merge(*this, U.M);
300 
301   return *this;
302   }
303 
304 
305 
306 template<typename eT>
307 template<typename T1>
308 inline
309 const SpSubview<eT>&
operator +=(const Base<eT,T1> & x)310 SpSubview<eT>::operator+=(const Base<eT, T1>& x)
311   {
312   arma_extra_debug_sigprint();
313 
314   return (*this).operator=( (*this) + x.get_ref() );
315   }
316 
317 
318 
319 template<typename eT>
320 template<typename T1>
321 inline
322 const SpSubview<eT>&
operator -=(const Base<eT,T1> & x)323 SpSubview<eT>::operator-=(const Base<eT, T1>& x)
324   {
325   arma_extra_debug_sigprint();
326 
327   return (*this).operator=( (*this) - x.get_ref() );
328   }
329 
330 
331 
332 template<typename eT>
333 template<typename T1>
334 inline
335 const SpSubview<eT>&
operator *=(const Base<eT,T1> & x)336 SpSubview<eT>::operator*=(const Base<eT, T1>& x)
337   {
338   arma_extra_debug_sigprint();
339 
340   SpMat<eT> tmp(*this);
341 
342   tmp *= x.get_ref();
343 
344   return (*this).operator=(tmp);
345   }
346 
347 
348 
349 template<typename eT>
350 template<typename T1>
351 inline
352 const SpSubview<eT>&
operator %=(const Base<eT,T1> & x)353 SpSubview<eT>::operator%=(const Base<eT, T1>& x)
354   {
355   arma_extra_debug_sigprint();
356 
357   return (*this).operator=( (*this) % x.get_ref() );
358   }
359 
360 
361 
362 template<typename eT>
363 template<typename T1>
364 inline
365 const SpSubview<eT>&
operator /=(const Base<eT,T1> & x)366 SpSubview<eT>::operator/=(const Base<eT, T1>& x)
367   {
368   arma_extra_debug_sigprint();
369 
370   return (*this).operator=( (*this) / x.get_ref() );
371   }
372 
373 
374 
375 template<typename eT>
376 inline
377 const SpSubview<eT>&
operator =(const SpSubview<eT> & x)378 SpSubview<eT>::operator=(const SpSubview<eT>& x)
379   {
380   arma_extra_debug_sigprint();
381 
382   return (*this).operator_equ_common(x);
383   }
384 
385 
386 
387 template<typename eT>
388 template<typename T1>
389 inline
390 const SpSubview<eT>&
operator =(const SpBase<eT,T1> & x)391 SpSubview<eT>::operator=(const SpBase<eT, T1>& x)
392   {
393   arma_extra_debug_sigprint();
394 
395   return (*this).operator_equ_common( x.get_ref() );
396   }
397 
398 
399 
400 template<typename eT>
401 template<typename T1>
402 inline
403 const SpSubview<eT>&
operator_equ_common(const SpBase<eT,T1> & in)404 SpSubview<eT>::operator_equ_common(const SpBase<eT, T1>& in)
405   {
406   arma_extra_debug_sigprint();
407 
408   const unwrap_spmat<T1> U(in.get_ref());
409 
410   arma_debug_assert_same_size(n_rows, n_cols, U.M.n_rows, U.M.n_cols, "insertion into sparse submatrix");
411 
412   if(U.is_alias(m))
413     {
414     const SpMat<eT> tmp(U.M);
415 
416     spglue_merge::subview_merge(*this, tmp);
417     }
418   else
419     {
420     spglue_merge::subview_merge(*this, U.M);
421     }
422 
423   return *this;
424   }
425 
426 
427 
428 template<typename eT>
429 template<typename T1>
430 inline
431 const SpSubview<eT>&
operator +=(const SpBase<eT,T1> & x)432 SpSubview<eT>::operator+=(const SpBase<eT, T1>& x)
433   {
434   arma_extra_debug_sigprint();
435 
436   // TODO: implement dedicated machinery
437   return (*this).operator=( (*this) + x.get_ref() );
438   }
439 
440 
441 
442 template<typename eT>
443 template<typename T1>
444 inline
445 const SpSubview<eT>&
operator -=(const SpBase<eT,T1> & x)446 SpSubview<eT>::operator-=(const SpBase<eT, T1>& x)
447   {
448   arma_extra_debug_sigprint();
449 
450   // TODO: implement dedicated machinery
451   return (*this).operator=( (*this) - x.get_ref() );
452   }
453 
454 
455 
456 template<typename eT>
457 template<typename T1>
458 inline
459 const SpSubview<eT>&
operator *=(const SpBase<eT,T1> & x)460 SpSubview<eT>::operator*=(const SpBase<eT, T1>& x)
461   {
462   arma_extra_debug_sigprint();
463 
464   return (*this).operator=( (*this) * x.get_ref() );
465   }
466 
467 
468 
469 template<typename eT>
470 template<typename T1>
471 inline
472 const SpSubview<eT>&
operator %=(const SpBase<eT,T1> & x)473 SpSubview<eT>::operator%=(const SpBase<eT, T1>& x)
474   {
475   arma_extra_debug_sigprint();
476 
477   // TODO: implement dedicated machinery
478   return (*this).operator=( (*this) % x.get_ref() );
479   }
480 
481 
482 
483 template<typename eT>
484 template<typename T1>
485 inline
486 const SpSubview<eT>&
operator /=(const SpBase<eT,T1> & x)487 SpSubview<eT>::operator/=(const SpBase<eT, T1>& x)
488   {
489   arma_extra_debug_sigprint();
490 
491   // NOTE: use of this function is not advised; it is implemented only for completeness
492 
493   SpProxy<T1> p(x.get_ref());
494 
495   arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise division");
496 
497   if(p.is_alias(m) == false)
498     {
499     for(uword lcol = 0; lcol < n_cols; ++lcol)
500     for(uword lrow = 0; lrow < n_rows; ++lrow)
501       {
502       at(lrow,lcol) /= p.at(lrow,lcol);
503       }
504     }
505   else
506     {
507     const SpMat<eT> tmp(p.Q);
508 
509     (*this).operator/=(tmp);
510     }
511 
512   return *this;
513   }
514 
515 
516 
517 //! apply a functor to each element
518 template<typename eT>
519 template<typename functor>
520 inline
521 void
for_each(functor F)522 SpSubview<eT>::for_each(functor F)
523   {
524   arma_extra_debug_sigprint();
525 
526   m.sync_csc();
527   m.invalidate_cache();
528 
529   const uword lstart_row = aux_row1;
530   const uword lend_row   = aux_row1 + n_rows;
531 
532   const uword lstart_col = aux_col1;
533   const uword lend_col   = aux_col1 + n_cols;
534 
535   const uword* m_row_indices = m.row_indices;
536         eT*    m_values      = access::rwp(m.values);
537 
538   bool has_zero = false;
539 
540   for(uword c = lstart_col; c < lend_col; ++c)
541     {
542     const uword r_start = m.col_ptrs[c    ];
543     const uword r_end   = m.col_ptrs[c + 1];
544 
545     for(uword r = r_start; r < r_end; ++r)
546       {
547       const uword m_row_indices_r = m_row_indices[r];
548 
549       if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
550         {
551         eT& m_values_r = m_values[r];
552 
553         F(m_values_r);
554 
555         if(m_values_r == eT(0))  { has_zero = true; }
556         }
557       }
558     }
559 
560   if(has_zero)
561     {
562     const uword old_m_n_nonzero = m.n_nonzero;
563 
564     access::rw(m).remove_zeros();
565 
566     if(m.n_nonzero != old_m_n_nonzero)
567       {
568       access::rw(n_nonzero) = n_nonzero - (old_m_n_nonzero - m.n_nonzero);
569       }
570     }
571   }
572 
573 
574 
575 template<typename eT>
576 template<typename functor>
577 inline
578 void
for_each(functor F) const579 SpSubview<eT>::for_each(functor F) const
580   {
581   arma_extra_debug_sigprint();
582 
583   m.sync_csc();
584 
585   const uword lstart_row = aux_row1;
586   const uword lend_row   = aux_row1 + n_rows;
587 
588   const uword lstart_col = aux_col1;
589   const uword lend_col   = aux_col1 + n_cols;
590 
591   const uword* m_row_indices = m.row_indices;
592 
593   for(uword c = lstart_col; c < lend_col; ++c)
594     {
595     const uword r_start = m.col_ptrs[c    ];
596     const uword r_end   = m.col_ptrs[c + 1];
597 
598     for(uword r = r_start; r < r_end; ++r)
599       {
600       const uword m_row_indices_r = m_row_indices[r];
601 
602       if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
603         {
604         F(m.values[r]);
605         }
606       }
607     }
608   }
609 
610 
611 
612 //! transform each element using a functor
613 template<typename eT>
614 template<typename functor>
615 inline
616 void
transform(functor F)617 SpSubview<eT>::transform(functor F)
618   {
619   arma_extra_debug_sigprint();
620 
621   m.sync_csc();
622   m.invalidate_cache();
623 
624   const uword lstart_row = aux_row1;
625   const uword lend_row   = aux_row1 + n_rows;
626 
627   const uword lstart_col = aux_col1;
628   const uword lend_col   = aux_col1 + n_cols;
629 
630   const uword* m_row_indices = m.row_indices;
631         eT*    m_values      = access::rwp(m.values);
632 
633   bool has_zero = false;
634 
635   for(uword c = lstart_col; c < lend_col; ++c)
636     {
637     const uword r_start = m.col_ptrs[c    ];
638     const uword r_end   = m.col_ptrs[c + 1];
639 
640     for(uword r = r_start; r < r_end; ++r)
641       {
642       const uword m_row_indices_r = m_row_indices[r];
643 
644       if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
645         {
646         eT& m_values_r = m_values[r];
647 
648         m_values_r = eT( F(m_values_r) );
649 
650         if(m_values_r == eT(0))  { has_zero = true; }
651         }
652       }
653     }
654 
655   if(has_zero)
656     {
657     const uword old_m_n_nonzero = m.n_nonzero;
658 
659     access::rw(m).remove_zeros();
660 
661     if(m.n_nonzero != old_m_n_nonzero)
662       {
663       access::rw(n_nonzero) = n_nonzero - (old_m_n_nonzero - m.n_nonzero);
664       }
665     }
666   }
667 
668 
669 
670 template<typename eT>
671 inline
672 void
replace(const eT old_val,const eT new_val)673 SpSubview<eT>::replace(const eT old_val, const eT new_val)
674   {
675   arma_extra_debug_sigprint();
676 
677   if(old_val == eT(0))
678     {
679     if(new_val != eT(0))
680       {
681       Mat<eT> tmp(*this);
682 
683       tmp.replace(old_val, new_val);
684 
685       (*this).operator=(tmp);
686       }
687 
688     return;
689     }
690 
691   m.sync_csc();
692   m.invalidate_cache();
693 
694   const uword lstart_row = aux_row1;
695   const uword lend_row   = aux_row1 + n_rows;
696 
697   const uword lstart_col = aux_col1;
698   const uword lend_col   = aux_col1 + n_cols;
699 
700   const uword* m_row_indices = m.row_indices;
701         eT*    m_values      = access::rwp(m.values);
702 
703   if(arma_isnan(old_val))
704     {
705     for(uword c = lstart_col; c < lend_col; ++c)
706       {
707       const uword r_start = m.col_ptrs[c    ];
708       const uword r_end   = m.col_ptrs[c + 1];
709 
710       for(uword r = r_start; r < r_end; ++r)
711         {
712         const uword m_row_indices_r = m_row_indices[r];
713 
714         if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
715           {
716           eT& val = m_values[r];
717 
718           val = (arma_isnan(val)) ? new_val : val;
719           }
720         }
721       }
722     }
723   else
724     {
725     for(uword c = lstart_col; c < lend_col; ++c)
726       {
727       const uword r_start = m.col_ptrs[c    ];
728       const uword r_end   = m.col_ptrs[c + 1];
729 
730       for(uword r = r_start; r < r_end; ++r)
731         {
732         const uword m_row_indices_r = m_row_indices[r];
733 
734         if( (m_row_indices_r >= lstart_row) && (m_row_indices_r < lend_row) )
735           {
736           eT& val = m_values[r];
737 
738           val = (val == old_val) ? new_val : val;
739           }
740         }
741       }
742     }
743 
744   if(new_val == eT(0))  { access::rw(m).remove_zeros(); }
745   }
746 
747 
748 
749 template<typename eT>
750 inline
751 void
clean(const typename get_pod_type<eT>::result threshold)752 SpSubview<eT>::clean(const typename get_pod_type<eT>::result threshold)
753   {
754   arma_extra_debug_sigprint();
755 
756   if((n_elem == 0) || (n_nonzero == 0))  { return; }
757 
758   // TODO: replace with a more efficient implementation
759 
760   SpMat<eT> tmp(*this);
761 
762   tmp.clean(threshold);
763 
764   if(is_cx<eT>::yes)
765     {
766     (*this).operator=(tmp);
767     }
768   else
769   if(tmp.n_nonzero != n_nonzero)
770     {
771     (*this).operator=(tmp);
772     }
773   }
774 
775 
776 
777 template<typename eT>
778 inline
779 void
clamp(const eT min_val,const eT max_val)780 SpSubview<eT>::clamp(const eT min_val, const eT max_val)
781   {
782   arma_extra_debug_sigprint();
783 
784   if(is_cx<eT>::no)
785     {
786     arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "SpSubview::clamp(): min_val must be less than max_val" );
787     }
788   else
789     {
790     arma_debug_check( (access::tmp_real(min_val) > access::tmp_real(max_val)), "SpSubview::clamp(): real(min_val) must be less than real(max_val)" );
791     arma_debug_check( (access::tmp_imag(min_val) > access::tmp_imag(max_val)), "SpSubview::clamp(): imag(min_val) must be less than imag(max_val)" );
792     }
793 
794   if((n_elem == 0) || (n_nonzero == 0))  { return; }
795 
796   // TODO: replace with a more efficient implementation
797 
798   SpMat<eT> tmp(*this);
799 
800   tmp.clamp(min_val, max_val);
801 
802   (*this).operator=(tmp);
803   }
804 
805 
806 
807 template<typename eT>
808 inline
809 void
fill(const eT val)810 SpSubview<eT>::fill(const eT val)
811   {
812   arma_extra_debug_sigprint();
813 
814   if(val != eT(0))
815     {
816     Mat<eT> tmp( (*this).n_rows, (*this).n_cols, arma_nozeros_indicator() );
817 
818     tmp.fill(val);
819 
820     (*this).operator=(tmp);
821     }
822   else
823     {
824     (*this).zeros();
825     }
826   }
827 
828 
829 
830 template<typename eT>
831 inline
832 void
zeros()833 SpSubview<eT>::zeros()
834   {
835   arma_extra_debug_sigprint();
836 
837   if((n_elem == 0) || (n_nonzero == 0))  { return; }
838 
839   if((m.n_nonzero - n_nonzero) == 0)
840     {
841     access::rw(m).zeros();
842     access::rw(n_nonzero) = 0;
843     return;
844     }
845 
846   SpMat<eT> tmp(arma_reserve_indicator(), m.n_rows, m.n_cols, m.n_nonzero - n_nonzero);
847 
848   const uword sv_row_start = aux_row1;
849   const uword sv_col_start = aux_col1;
850 
851   const uword sv_row_end   = aux_row1 + n_rows - 1;
852   const uword sv_col_end   = aux_col1 + n_cols - 1;
853 
854   typename SpMat<eT>::const_iterator m_it     = m.begin();
855   typename SpMat<eT>::const_iterator m_it_end = m.end();
856 
857   uword tmp_count = 0;
858 
859   for(; m_it != m_it_end; ++m_it)
860     {
861     const uword m_it_row = m_it.row();
862     const uword m_it_col = m_it.col();
863 
864     const bool inside_box = ((m_it_row >= sv_row_start) && (m_it_row <= sv_row_end)) && ((m_it_col >= sv_col_start) && (m_it_col <= sv_col_end));
865 
866     if(inside_box == false)
867       {
868       access::rw(tmp.values[tmp_count])      = (*m_it);
869       access::rw(tmp.row_indices[tmp_count]) = m_it_row;
870       access::rw(tmp.col_ptrs[m_it_col + 1])++;
871       ++tmp_count;
872       }
873     }
874 
875   for(uword i=0; i < tmp.n_cols; ++i)
876     {
877     access::rw(tmp.col_ptrs[i + 1]) += tmp.col_ptrs[i];
878     }
879 
880   access::rw(m).steal_mem(tmp);
881 
882   access::rw(n_nonzero) = 0;
883   }
884 
885 
886 
887 template<typename eT>
888 inline
889 void
ones()890 SpSubview<eT>::ones()
891   {
892   arma_extra_debug_sigprint();
893 
894   (*this).fill(eT(1));
895   }
896 
897 
898 
899 template<typename eT>
900 inline
901 void
eye()902 SpSubview<eT>::eye()
903   {
904   arma_extra_debug_sigprint();
905 
906   SpMat<eT> tmp;
907 
908   tmp.eye( (*this).n_rows, (*this).n_cols );
909 
910   (*this).operator=(tmp);
911   }
912 
913 
914 
915 template<typename eT>
916 inline
917 void
randu()918 SpSubview<eT>::randu()
919   {
920   arma_extra_debug_sigprint();
921 
922   Mat<eT> tmp( (*this).n_rows, (*this).n_cols, fill::randu );
923 
924   (*this).operator=(tmp);
925   }
926 
927 
928 
929 template<typename eT>
930 inline
931 void
randn()932 SpSubview<eT>::randn()
933   {
934   arma_extra_debug_sigprint();
935 
936   Mat<eT> tmp( (*this).n_rows, (*this).n_cols, fill::randn );
937 
938   (*this).operator=(tmp);
939   }
940 
941 
942 
943 template<typename eT>
944 arma_hot
945 inline
946 SpSubview_MapMat_val<eT>
operator [](const uword i)947 SpSubview<eT>::operator[](const uword i)
948   {
949   const uword lrow = i % n_rows;
950   const uword lcol = i / n_rows;
951 
952   return (*this).at(lrow, lcol);
953   }
954 
955 
956 
957 template<typename eT>
958 arma_hot
959 inline
960 eT
operator [](const uword i) const961 SpSubview<eT>::operator[](const uword i) const
962   {
963   const uword lrow = i % n_rows;
964   const uword lcol = i / n_rows;
965 
966   return (*this).at(lrow, lcol);
967   }
968 
969 
970 
971 template<typename eT>
972 arma_hot
973 inline
974 SpSubview_MapMat_val<eT>
operator ()(const uword i)975 SpSubview<eT>::operator()(const uword i)
976   {
977   arma_debug_check_bounds( (i >= n_elem), "SpSubview::operator(): index out of bounds" );
978 
979   const uword lrow = i % n_rows;
980   const uword lcol = i / n_rows;
981 
982   return (*this).at(lrow, lcol);
983   }
984 
985 
986 
987 template<typename eT>
988 arma_hot
989 inline
990 eT
operator ()(const uword i) const991 SpSubview<eT>::operator()(const uword i) const
992   {
993   arma_debug_check_bounds( (i >= n_elem), "SpSubview::operator(): index out of bounds" );
994 
995   const uword lrow = i % n_rows;
996   const uword lcol = i / n_rows;
997 
998   return (*this).at(lrow, lcol);
999   }
1000 
1001 
1002 
1003 template<typename eT>
1004 arma_hot
1005 inline
1006 SpSubview_MapMat_val<eT>
operator ()(const uword in_row,const uword in_col)1007 SpSubview<eT>::operator()(const uword in_row, const uword in_col)
1008   {
1009   arma_debug_check_bounds( (in_row >= n_rows) || (in_col >= n_cols), "SpSubview::operator(): index out of bounds" );
1010 
1011   return (*this).at(in_row, in_col);
1012   }
1013 
1014 
1015 
1016 template<typename eT>
1017 arma_hot
1018 inline
1019 eT
operator ()(const uword in_row,const uword in_col) const1020 SpSubview<eT>::operator()(const uword in_row, const uword in_col) const
1021   {
1022   arma_debug_check_bounds( (in_row >= n_rows) || (in_col >= n_cols), "SpSubview::operator(): index out of bounds" );
1023 
1024   return (*this).at(in_row, in_col);
1025   }
1026 
1027 
1028 
1029 template<typename eT>
1030 arma_hot
1031 inline
1032 SpSubview_MapMat_val<eT>
at(const uword i)1033 SpSubview<eT>::at(const uword i)
1034   {
1035   const uword lrow = i % n_rows;
1036   const uword lcol = i / n_cols;
1037 
1038   return (*this).at(lrow, lcol);
1039   }
1040 
1041 
1042 
1043 template<typename eT>
1044 arma_hot
1045 inline
1046 eT
at(const uword i) const1047 SpSubview<eT>::at(const uword i) const
1048   {
1049   const uword lrow = i % n_rows;
1050   const uword lcol = i / n_cols;
1051 
1052   return (*this).at(lrow, lcol);
1053   }
1054 
1055 
1056 
1057 template<typename eT>
1058 arma_hot
1059 inline
1060 SpSubview_MapMat_val<eT>
at(const uword in_row,const uword in_col)1061 SpSubview<eT>::at(const uword in_row, const uword in_col)
1062   {
1063   return SpSubview_MapMat_val<eT>((*this), m.cache, aux_row1 + in_row, aux_col1 + in_col);
1064   }
1065 
1066 
1067 
1068 template<typename eT>
1069 arma_hot
1070 inline
1071 eT
at(const uword in_row,const uword in_col) const1072 SpSubview<eT>::at(const uword in_row, const uword in_col) const
1073   {
1074   return m.at(aux_row1 + in_row, aux_col1 + in_col);
1075   }
1076 
1077 
1078 
1079 template<typename eT>
1080 inline
1081 bool
check_overlap(const SpSubview<eT> & x) const1082 SpSubview<eT>::check_overlap(const SpSubview<eT>& x) const
1083   {
1084   const SpSubview<eT>& t = *this;
1085 
1086   if(&t.m != &x.m)
1087     {
1088     return false;
1089     }
1090   else
1091     {
1092     if( (t.n_elem == 0) || (x.n_elem == 0) )
1093       {
1094       return false;
1095       }
1096     else
1097       {
1098       const uword t_row_start  = t.aux_row1;
1099       const uword t_row_end_p1 = t_row_start + t.n_rows;
1100 
1101       const uword t_col_start  = t.aux_col1;
1102       const uword t_col_end_p1 = t_col_start + t.n_cols;
1103 
1104       const uword x_row_start  = x.aux_row1;
1105       const uword x_row_end_p1 = x_row_start + x.n_rows;
1106 
1107       const uword x_col_start  = x.aux_col1;
1108       const uword x_col_end_p1 = x_col_start + x.n_cols;
1109 
1110       const bool outside_rows = ( (x_row_start >= t_row_end_p1) || (t_row_start >= x_row_end_p1) );
1111       const bool outside_cols = ( (x_col_start >= t_col_end_p1) || (t_col_start >= x_col_end_p1) );
1112 
1113       return ( (outside_rows == false) && (outside_cols == false) );
1114       }
1115     }
1116   }
1117 
1118 
1119 
1120 template<typename eT>
1121 inline
1122 bool
is_vec() const1123 SpSubview<eT>::is_vec() const
1124   {
1125   return ( (n_rows == 1) || (n_cols == 1) );
1126   }
1127 
1128 
1129 
1130 template<typename eT>
1131 inline
1132 SpSubview_row<eT>
row(const uword row_num)1133 SpSubview<eT>::row(const uword row_num)
1134   {
1135   arma_extra_debug_sigprint();
1136 
1137   arma_debug_check_bounds(row_num >= n_rows, "SpSubview::row(): out of bounds");
1138 
1139   return SpSubview_row<eT>(const_cast< SpMat<eT>& >(m), row_num + aux_row1, aux_col1, n_cols);
1140   }
1141 
1142 
1143 
1144 template<typename eT>
1145 inline
1146 const SpSubview_row<eT>
row(const uword row_num) const1147 SpSubview<eT>::row(const uword row_num) const
1148   {
1149   arma_extra_debug_sigprint();
1150 
1151   arma_debug_check_bounds(row_num >= n_rows, "SpSubview::row(): out of bounds");
1152 
1153   return SpSubview_row<eT>(m, row_num + aux_row1, aux_col1, n_cols);
1154   }
1155 
1156 
1157 
1158 template<typename eT>
1159 inline
1160 SpSubview_col<eT>
col(const uword col_num)1161 SpSubview<eT>::col(const uword col_num)
1162   {
1163   arma_extra_debug_sigprint();
1164 
1165   arma_debug_check_bounds(col_num >= n_cols, "SpSubview::col(): out of bounds");
1166 
1167   return SpSubview_col<eT>(const_cast< SpMat<eT>& >(m), col_num + aux_col1, aux_row1, n_rows);
1168   }
1169 
1170 
1171 
1172 template<typename eT>
1173 inline
1174 const SpSubview_col<eT>
col(const uword col_num) const1175 SpSubview<eT>::col(const uword col_num) const
1176   {
1177   arma_extra_debug_sigprint();
1178 
1179   arma_debug_check_bounds(col_num >= n_cols, "SpSubview::col(): out of bounds");
1180 
1181   return SpSubview_col<eT>(m, col_num + aux_col1, aux_row1, n_rows);
1182   }
1183 
1184 
1185 
1186 template<typename eT>
1187 inline
1188 SpSubview<eT>
rows(const uword in_row1,const uword in_row2)1189 SpSubview<eT>::rows(const uword in_row1, const uword in_row2)
1190   {
1191   arma_extra_debug_sigprint();
1192 
1193   arma_debug_check_bounds
1194     (
1195     (in_row1 > in_row2) || (in_row2 >= n_rows),
1196     "SpSubview::rows(): indices out of bounds or incorrectly used"
1197     );
1198 
1199   return submat(in_row1, 0, in_row2, n_cols - 1);
1200   }
1201 
1202 
1203 
1204 template<typename eT>
1205 inline
1206 const SpSubview<eT>
rows(const uword in_row1,const uword in_row2) const1207 SpSubview<eT>::rows(const uword in_row1, const uword in_row2) const
1208   {
1209   arma_extra_debug_sigprint();
1210 
1211   arma_debug_check_bounds
1212     (
1213     (in_row1 > in_row2) || (in_row2 >= n_rows),
1214     "SpSubview::rows(): indices out of bounds or incorrectly used"
1215     );
1216 
1217   return submat(in_row1, 0, in_row2, n_cols - 1);
1218   }
1219 
1220 
1221 
1222 template<typename eT>
1223 inline
1224 SpSubview<eT>
cols(const uword in_col1,const uword in_col2)1225 SpSubview<eT>::cols(const uword in_col1, const uword in_col2)
1226   {
1227   arma_extra_debug_sigprint();
1228 
1229   arma_debug_check_bounds
1230     (
1231     (in_col1 > in_col2) || (in_col2 >= n_cols),
1232     "SpSubview::cols(): indices out of bounds or incorrectly used"
1233     );
1234 
1235   return submat(0, in_col1, n_rows - 1, in_col2);
1236   }
1237 
1238 
1239 
1240 template<typename eT>
1241 inline
1242 const SpSubview<eT>
cols(const uword in_col1,const uword in_col2) const1243 SpSubview<eT>::cols(const uword in_col1, const uword in_col2) const
1244   {
1245   arma_extra_debug_sigprint();
1246 
1247   arma_debug_check_bounds
1248     (
1249     (in_col1 > in_col2) || (in_col2 >= n_cols),
1250     "SpSubview::cols(): indices out of bounds or incorrectly used"
1251     );
1252 
1253   return submat(0, in_col1, n_rows - 1, in_col2);
1254   }
1255 
1256 
1257 
1258 template<typename eT>
1259 inline
1260 SpSubview<eT>
submat(const uword in_row1,const uword in_col1,const uword in_row2,const uword in_col2)1261 SpSubview<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2)
1262   {
1263   arma_extra_debug_sigprint();
1264 
1265   arma_debug_check_bounds
1266     (
1267     (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
1268     "SpSubview::submat(): indices out of bounds or incorrectly used"
1269     );
1270 
1271   return access::rw(m).submat(in_row1 + aux_row1, in_col1 + aux_col1, in_row2 + aux_row1, in_col2 + aux_col1);
1272   }
1273 
1274 
1275 
1276 template<typename eT>
1277 inline
1278 const SpSubview<eT>
submat(const uword in_row1,const uword in_col1,const uword in_row2,const uword in_col2) const1279 SpSubview<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const
1280   {
1281   arma_extra_debug_sigprint();
1282 
1283   arma_debug_check_bounds
1284     (
1285     (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
1286     "SpSubview::submat(): indices out of bounds or incorrectly used"
1287     );
1288 
1289   return m.submat(in_row1 + aux_row1, in_col1 + aux_col1, in_row2 + aux_row1, in_col2 + aux_col1);
1290   }
1291 
1292 
1293 
1294 template<typename eT>
1295 inline
1296 SpSubview<eT>
submat(const span & row_span,const span & col_span)1297 SpSubview<eT>::submat(const span& row_span, const span& col_span)
1298   {
1299   arma_extra_debug_sigprint();
1300 
1301   const bool row_all = row_span.whole;
1302   const bool col_all = row_span.whole;
1303 
1304   const uword in_row1 = row_all ? 0      : row_span.a;
1305   const uword in_row2 = row_all ? n_rows : row_span.b;
1306 
1307   const uword in_col1 = col_all ? 0      : col_span.a;
1308   const uword in_col2 = col_all ? n_cols : col_span.b;
1309 
1310   arma_debug_check_bounds
1311     (
1312     ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= n_rows)))
1313     ||
1314     ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= n_cols))),
1315     "SpSubview::submat(): indices out of bounds or incorrectly used"
1316     );
1317 
1318   return submat(in_row1, in_col1, in_row2, in_col2);
1319   }
1320 
1321 
1322 
1323 template<typename eT>
1324 inline
1325 const SpSubview<eT>
submat(const span & row_span,const span & col_span) const1326 SpSubview<eT>::submat(const span& row_span, const span& col_span) const
1327   {
1328   arma_extra_debug_sigprint();
1329 
1330   const bool row_all = row_span.whole;
1331   const bool col_all = row_span.whole;
1332 
1333   const uword in_row1 = row_all ? 0          : row_span.a;
1334   const uword in_row2 = row_all ? n_rows - 1 : row_span.b;
1335 
1336   const uword in_col1 = col_all ? 0          : col_span.a;
1337   const uword in_col2 = col_all ? n_cols - 1 : col_span.b;
1338 
1339   arma_debug_check_bounds
1340     (
1341     ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= n_rows)))
1342     ||
1343     ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= n_cols))),
1344     "SpSubview::submat(): indices out of bounds or incorrectly used"
1345     );
1346 
1347   return submat(in_row1, in_col1, in_row2, in_col2);
1348   }
1349 
1350 
1351 
1352 template<typename eT>
1353 inline
1354 SpSubview<eT>
operator ()(const uword row_num,const span & col_span)1355 SpSubview<eT>::operator()(const uword row_num, const span& col_span)
1356   {
1357   arma_extra_debug_sigprint();
1358 
1359   return submat(span(row_num, row_num), col_span);
1360   }
1361 
1362 
1363 
1364 template<typename eT>
1365 inline
1366 const SpSubview<eT>
operator ()(const uword row_num,const span & col_span) const1367 SpSubview<eT>::operator()(const uword row_num, const span& col_span) const
1368   {
1369   arma_extra_debug_sigprint();
1370 
1371   return submat(span(row_num, row_num), col_span);
1372   }
1373 
1374 
1375 
1376 template<typename eT>
1377 inline
1378 SpSubview<eT>
operator ()(const span & row_span,const uword col_num)1379 SpSubview<eT>::operator()(const span& row_span, const uword col_num)
1380   {
1381   arma_extra_debug_sigprint();
1382 
1383   return submat(row_span, span(col_num, col_num));
1384   }
1385 
1386 
1387 
1388 template<typename eT>
1389 inline
1390 const SpSubview<eT>
operator ()(const span & row_span,const uword col_num) const1391 SpSubview<eT>::operator()(const span& row_span, const uword col_num) const
1392   {
1393   arma_extra_debug_sigprint();
1394 
1395   return submat(row_span, span(col_num, col_num));
1396   }
1397 
1398 
1399 
1400 template<typename eT>
1401 inline
1402 SpSubview<eT>
operator ()(const span & row_span,const span & col_span)1403 SpSubview<eT>::operator()(const span& row_span, const span& col_span)
1404   {
1405   arma_extra_debug_sigprint();
1406 
1407   return submat(row_span, col_span);
1408   }
1409 
1410 
1411 
1412 template<typename eT>
1413 inline
1414 const SpSubview<eT>
operator ()(const span & row_span,const span & col_span) const1415 SpSubview<eT>::operator()(const span& row_span, const span& col_span) const
1416   {
1417   arma_extra_debug_sigprint();
1418 
1419   return submat(row_span, col_span);
1420   }
1421 
1422 
1423 
1424 template<typename eT>
1425 inline
1426 void
swap_rows(const uword in_row1,const uword in_row2)1427 SpSubview<eT>::swap_rows(const uword in_row1, const uword in_row2)
1428   {
1429   arma_extra_debug_sigprint();
1430 
1431   arma_debug_check((in_row1 >= n_rows) || (in_row2 >= n_rows), "SpSubview::swap_rows(): invalid row index");
1432 
1433   const uword lstart_col = aux_col1;
1434   const uword lend_col   = aux_col1 + n_cols;
1435 
1436   for(uword c = lstart_col; c < lend_col; ++c)
1437     {
1438     const eT val = access::rw(m).at(in_row1 + aux_row1, c);
1439     access::rw(m).at(in_row2 + aux_row1, c) = eT( access::rw(m).at(in_row1 + aux_row1, c) );
1440     access::rw(m).at(in_row1 + aux_row1, c) = val;
1441     }
1442   }
1443 
1444 
1445 
1446 template<typename eT>
1447 inline
1448 void
swap_cols(const uword in_col1,const uword in_col2)1449 SpSubview<eT>::swap_cols(const uword in_col1, const uword in_col2)
1450   {
1451   arma_extra_debug_sigprint();
1452 
1453   arma_debug_check((in_col1 >= n_cols) || (in_col2 >= n_cols), "SpSubview::swap_cols(): invalid column index");
1454 
1455   const uword lstart_row = aux_row1;
1456   const uword lend_row   = aux_row1 + n_rows;
1457 
1458   for(uword r = lstart_row; r < lend_row; ++r)
1459     {
1460     const eT val = access::rw(m).at(r, in_col1 + aux_col1);
1461     access::rw(m).at(r, in_col1 + aux_col1) = eT( access::rw(m).at(r, in_col2 + aux_col1) );
1462     access::rw(m).at(r, in_col2 + aux_col1) = val;
1463     }
1464   }
1465 
1466 
1467 
1468 template<typename eT>
1469 inline
1470 typename SpSubview<eT>::iterator
begin()1471 SpSubview<eT>::begin()
1472   {
1473   return iterator(*this);
1474   }
1475 
1476 
1477 
1478 template<typename eT>
1479 inline
1480 typename SpSubview<eT>::const_iterator
begin() const1481 SpSubview<eT>::begin() const
1482   {
1483   m.sync_csc();
1484 
1485   return const_iterator(*this);
1486   }
1487 
1488 
1489 
1490 template<typename eT>
1491 inline
1492 typename SpSubview<eT>::const_iterator
cbegin() const1493 SpSubview<eT>::cbegin() const
1494   {
1495   m.sync_csc();
1496 
1497   return const_iterator(*this);
1498   }
1499 
1500 
1501 
1502 template<typename eT>
1503 inline
1504 typename SpSubview<eT>::iterator
begin_col(const uword col_num)1505 SpSubview<eT>::begin_col(const uword col_num)
1506   {
1507   m.sync_csc();
1508 
1509   return iterator(*this, 0, col_num);
1510   }
1511 
1512 
1513 template<typename eT>
1514 inline
1515 typename SpSubview<eT>::const_iterator
begin_col(const uword col_num) const1516 SpSubview<eT>::begin_col(const uword col_num) const
1517   {
1518   m.sync_csc();
1519 
1520   return const_iterator(*this, 0, col_num);
1521   }
1522 
1523 
1524 
1525 template<typename eT>
1526 inline
1527 typename SpSubview<eT>::row_iterator
begin_row(const uword row_num)1528 SpSubview<eT>::begin_row(const uword row_num)
1529   {
1530   m.sync_csc();
1531 
1532   return row_iterator(*this, row_num, 0);
1533   }
1534 
1535 
1536 
1537 template<typename eT>
1538 inline
1539 typename SpSubview<eT>::const_row_iterator
begin_row(const uword row_num) const1540 SpSubview<eT>::begin_row(const uword row_num) const
1541   {
1542   m.sync_csc();
1543 
1544   return const_row_iterator(*this, row_num, 0);
1545   }
1546 
1547 
1548 
1549 template<typename eT>
1550 inline
1551 typename SpSubview<eT>::iterator
end()1552 SpSubview<eT>::end()
1553   {
1554   m.sync_csc();
1555 
1556   return iterator(*this, 0, n_cols, n_nonzero, m.n_nonzero - n_nonzero);
1557   }
1558 
1559 
1560 
1561 template<typename eT>
1562 inline
1563 typename SpSubview<eT>::const_iterator
end() const1564 SpSubview<eT>::end() const
1565   {
1566   m.sync_csc();
1567 
1568   return const_iterator(*this, 0, n_cols, n_nonzero, m.n_nonzero - n_nonzero);
1569   }
1570 
1571 
1572 
1573 template<typename eT>
1574 inline
1575 typename SpSubview<eT>::const_iterator
cend() const1576 SpSubview<eT>::cend() const
1577   {
1578   m.sync_csc();
1579 
1580   return const_iterator(*this, 0, n_cols, n_nonzero, m.n_nonzero - n_nonzero);
1581   }
1582 
1583 
1584 
1585 template<typename eT>
1586 inline
1587 typename SpSubview<eT>::row_iterator
end_row()1588 SpSubview<eT>::end_row()
1589   {
1590   m.sync_csc();
1591 
1592   return row_iterator(*this, n_nonzero);
1593   }
1594 
1595 
1596 
1597 template<typename eT>
1598 inline
1599 typename SpSubview<eT>::const_row_iterator
end_row() const1600 SpSubview<eT>::end_row() const
1601   {
1602   m.sync_csc();
1603 
1604   return const_row_iterator(*this, n_nonzero);
1605   }
1606 
1607 
1608 
1609 template<typename eT>
1610 inline
1611 typename SpSubview<eT>::row_iterator
end_row(const uword row_num)1612 SpSubview<eT>::end_row(const uword row_num)
1613   {
1614   m.sync_csc();
1615 
1616   return row_iterator(*this, row_num + 1, 0);
1617   }
1618 
1619 
1620 
1621 template<typename eT>
1622 inline
1623 typename SpSubview<eT>::const_row_iterator
end_row(const uword row_num) const1624 SpSubview<eT>::end_row(const uword row_num) const
1625   {
1626   m.sync_csc();
1627 
1628   return const_row_iterator(*this, row_num + 1, 0);
1629   }
1630 
1631 
1632 
1633 template<typename eT>
1634 arma_inline
1635 bool
is_alias(const SpMat<eT> & X) const1636 SpSubview<eT>::is_alias(const SpMat<eT>& X) const
1637   {
1638   return m.is_alias(X);
1639   }
1640 
1641 
1642 
1643 template<typename eT>
1644 inline
1645 arma_warn_unused
1646 eT&
insert_element(const uword in_row,const uword in_col,const eT in_val)1647 SpSubview<eT>::insert_element(const uword in_row, const uword in_col, const eT in_val)
1648   {
1649   arma_extra_debug_sigprint();
1650 
1651   // This may not actually insert an element.
1652   const uword old_n_nonzero = m.n_nonzero;
1653   eT& retval = access::rw(m).insert_element(in_row + aux_row1, in_col + aux_col1, in_val);
1654   // Update n_nonzero (if necessary).
1655   access::rw(n_nonzero) += (m.n_nonzero - old_n_nonzero);
1656 
1657   return retval;
1658   }
1659 
1660 
1661 
1662 template<typename eT>
1663 inline
1664 void
delete_element(const uword in_row,const uword in_col)1665 SpSubview<eT>::delete_element(const uword in_row, const uword in_col)
1666   {
1667   arma_extra_debug_sigprint();
1668 
1669   // This may not actually delete an element.
1670   const uword old_n_nonzero = m.n_nonzero;
1671   access::rw(m).delete_element(in_row + aux_row1, in_col + aux_col1);
1672   access::rw(n_nonzero) -= (old_n_nonzero - m.n_nonzero);
1673   }
1674 
1675 
1676 
1677 template<typename eT>
1678 inline
1679 void
invalidate_cache() const1680 SpSubview<eT>::invalidate_cache() const
1681   {
1682   arma_extra_debug_sigprint();
1683 
1684   m.invalidate_cache();
1685   }
1686 
1687 
1688 
1689 //
1690 //
1691 //
1692 
1693 
1694 
1695 template<typename eT>
1696 inline
SpSubview_col(const SpMat<eT> & in_m,const uword in_col)1697 SpSubview_col<eT>::SpSubview_col(const SpMat<eT>& in_m, const uword in_col)
1698   : SpSubview<eT>(in_m, 0, in_col, in_m.n_rows, 1)
1699   {
1700   arma_extra_debug_sigprint();
1701   }
1702 
1703 
1704 
1705 template<typename eT>
1706 inline
SpSubview_col(const SpMat<eT> & in_m,const uword in_col,const uword in_row1,const uword in_n_rows)1707 SpSubview_col<eT>::SpSubview_col(const SpMat<eT>& in_m, const uword in_col, const uword in_row1, const uword in_n_rows)
1708   : SpSubview<eT>(in_m, in_row1, in_col, in_n_rows, 1)
1709   {
1710   arma_extra_debug_sigprint();
1711   }
1712 
1713 
1714 
1715 template<typename eT>
1716 inline
1717 void
operator =(const SpSubview<eT> & x)1718 SpSubview_col<eT>::operator=(const SpSubview<eT>& x)
1719   {
1720   arma_extra_debug_sigprint();
1721 
1722   SpSubview<eT>::operator=(x);
1723   }
1724 
1725 
1726 
1727 template<typename eT>
1728 inline
1729 void
operator =(const SpSubview_col<eT> & x)1730 SpSubview_col<eT>::operator=(const SpSubview_col<eT>& x)
1731   {
1732   arma_extra_debug_sigprint();
1733 
1734   SpSubview<eT>::operator=(x); // interprets 'SpSubview_col' as 'SpSubview'
1735   }
1736 
1737 
1738 
1739 template<typename eT>
1740 template<typename T1>
1741 inline
1742 void
operator =(const SpBase<eT,T1> & x)1743 SpSubview_col<eT>::operator=(const SpBase<eT,T1>& x)
1744   {
1745   arma_extra_debug_sigprint();
1746 
1747   SpSubview<eT>::operator=(x);
1748   }
1749 
1750 
1751 
1752 template<typename eT>
1753 template<typename T1>
1754 inline
1755 void
operator =(const Base<eT,T1> & x)1756 SpSubview_col<eT>::operator=(const Base<eT,T1>& x)
1757   {
1758   arma_extra_debug_sigprint();
1759 
1760   SpSubview<eT>::operator=(x);
1761   }
1762 
1763 
1764 
1765 template<typename eT>
1766 inline
1767 arma_warn_unused
1768 const SpOp<SpSubview_col<eT>,spop_htrans>
t() const1769 SpSubview_col<eT>::t() const
1770   {
1771   return SpOp<SpSubview_col<eT>,spop_htrans>(*this);
1772   }
1773 
1774 
1775 
1776 template<typename eT>
1777 inline
1778 arma_warn_unused
1779 const SpOp<SpSubview_col<eT>,spop_htrans>
ht() const1780 SpSubview_col<eT>::ht() const
1781   {
1782   return SpOp<SpSubview_col<eT>,spop_htrans>(*this);
1783   }
1784 
1785 
1786 
1787 template<typename eT>
1788 inline
1789 arma_warn_unused
1790 const SpOp<SpSubview_col<eT>,spop_strans>
st() const1791 SpSubview_col<eT>::st() const
1792   {
1793   return SpOp<SpSubview_col<eT>,spop_strans>(*this);
1794   }
1795 
1796 
1797 
1798 //
1799 //
1800 //
1801 
1802 
1803 
1804 template<typename eT>
1805 inline
SpSubview_row(const SpMat<eT> & in_m,const uword in_row)1806 SpSubview_row<eT>::SpSubview_row(const SpMat<eT>& in_m, const uword in_row)
1807   : SpSubview<eT>(in_m, in_row, 0, 1, in_m.n_cols)
1808   {
1809   arma_extra_debug_sigprint();
1810   }
1811 
1812 
1813 
1814 template<typename eT>
1815 inline
SpSubview_row(const SpMat<eT> & in_m,const uword in_row,const uword in_col1,const uword in_n_cols)1816 SpSubview_row<eT>::SpSubview_row(const SpMat<eT>& in_m, const uword in_row, const uword in_col1, const uword in_n_cols)
1817   : SpSubview<eT>(in_m, in_row, in_col1, 1, in_n_cols)
1818   {
1819   arma_extra_debug_sigprint();
1820   }
1821 
1822 
1823 
1824 template<typename eT>
1825 inline
1826 void
operator =(const SpSubview<eT> & x)1827 SpSubview_row<eT>::operator=(const SpSubview<eT>& x)
1828   {
1829   arma_extra_debug_sigprint();
1830 
1831   SpSubview<eT>::operator=(x);
1832   }
1833 
1834 
1835 
1836 template<typename eT>
1837 inline
1838 void
operator =(const SpSubview_row<eT> & x)1839 SpSubview_row<eT>::operator=(const SpSubview_row<eT>& x)
1840   {
1841   arma_extra_debug_sigprint();
1842 
1843   SpSubview<eT>::operator=(x); // interprets 'SpSubview_row' as 'SpSubview'
1844   }
1845 
1846 
1847 
1848 template<typename eT>
1849 template<typename T1>
1850 inline
1851 void
operator =(const SpBase<eT,T1> & x)1852 SpSubview_row<eT>::operator=(const SpBase<eT,T1>& x)
1853   {
1854   arma_extra_debug_sigprint();
1855 
1856   SpSubview<eT>::operator=(x);
1857   }
1858 
1859 
1860 
1861 template<typename eT>
1862 template<typename T1>
1863 inline
1864 void
operator =(const Base<eT,T1> & x)1865 SpSubview_row<eT>::operator=(const Base<eT,T1>& x)
1866   {
1867   arma_extra_debug_sigprint();
1868 
1869   SpSubview<eT>::operator=(x);
1870   }
1871 
1872 
1873 
1874 template<typename eT>
1875 inline
1876 arma_warn_unused
1877 const SpOp<SpSubview_row<eT>,spop_htrans>
t() const1878 SpSubview_row<eT>::t() const
1879   {
1880   return SpOp<SpSubview_row<eT>,spop_htrans>(*this);
1881   }
1882 
1883 
1884 
1885 template<typename eT>
1886 inline
1887 arma_warn_unused
1888 const SpOp<SpSubview_row<eT>,spop_htrans>
ht() const1889 SpSubview_row<eT>::ht() const
1890   {
1891   return SpOp<SpSubview_row<eT>,spop_htrans>(*this);
1892   }
1893 
1894 
1895 
1896 template<typename eT>
1897 inline
1898 arma_warn_unused
1899 const SpOp<SpSubview_row<eT>,spop_strans>
st() const1900 SpSubview_row<eT>::st() const
1901   {
1902   return SpOp<SpSubview_row<eT>,spop_strans>(*this);
1903   }
1904 
1905 
1906 
1907 //! @}
1908