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 class SpSubview : public SpBase< eT, SpSubview<eT> >
25   {
26   public:
27 
28   const SpMat<eT>& m;
29 
30   typedef eT elem_type;
31   typedef typename get_pod_type<elem_type>::result pod_type;
32 
33   static constexpr bool is_row  = false;
34   static constexpr bool is_col  = false;
35   static constexpr bool is_xvec = false;
36 
37   const uword aux_row1;
38   const uword aux_col1;
39   const uword n_rows;
40   const uword n_cols;
41   const uword n_elem;
42   const uword n_nonzero;
43 
44   protected:
45 
46   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);
47 
48   public:
49 
50   inline ~SpSubview();
51   inline  SpSubview() = delete;
52 
53   inline  SpSubview(const SpSubview&  in);
54   inline  SpSubview(      SpSubview&& in);
55 
56   inline const SpSubview& operator+= (const eT val);
57   inline const SpSubview& operator-= (const eT val);
58   inline const SpSubview& operator*= (const eT val);
59   inline const SpSubview& operator/= (const eT val);
60 
61   inline const SpSubview& operator=(const SpSubview& x);
62 
63   template<typename T1> inline const SpSubview& operator= (const Base<eT, T1>& x);
64   template<typename T1> inline const SpSubview& operator+=(const Base<eT, T1>& x);
65   template<typename T1> inline const SpSubview& operator-=(const Base<eT, T1>& x);
66   template<typename T1> inline const SpSubview& operator*=(const Base<eT, T1>& x);
67   template<typename T1> inline const SpSubview& operator%=(const Base<eT, T1>& x);
68   template<typename T1> inline const SpSubview& operator/=(const Base<eT, T1>& x);
69 
70   template<typename T1> inline const SpSubview& operator_equ_common(const SpBase<eT, T1>& x);
71 
72   template<typename T1> inline const SpSubview& operator= (const SpBase<eT, T1>& x);
73   template<typename T1> inline const SpSubview& operator+=(const SpBase<eT, T1>& x);
74   template<typename T1> inline const SpSubview& operator-=(const SpBase<eT, T1>& x);
75   template<typename T1> inline const SpSubview& operator*=(const SpBase<eT, T1>& x);
76   template<typename T1> inline const SpSubview& operator%=(const SpBase<eT, T1>& x);
77   template<typename T1> inline const SpSubview& operator/=(const SpBase<eT, T1>& x);
78 
79   /*
80   inline static void extract(SpMat<eT>& out, const SpSubview& in);
81 
82   inline static void  plus_inplace(Mat<eT>& out, const subview& in);
83   inline static void minus_inplace(Mat<eT>& out, const subview& in);
84   inline static void schur_inplace(Mat<eT>& out, const subview& in);
85   inline static void   div_inplace(Mat<eT>& out, const subview& in);
86   */
87 
88   template<typename functor> inline void  for_each(functor F);
89   template<typename functor> inline void  for_each(functor F) const;
90 
91   template<typename functor> inline void transform(functor F);
92 
93   inline void replace(const eT old_val, const eT new_val);
94 
95   inline void clean(const pod_type threshold);
96 
97   inline void clamp(const eT min_val, const eT max_val);
98 
99   inline void fill(const eT val);
100   inline void zeros();
101   inline void ones();
102   inline void eye();
103   inline void randu();
104   inline void randn();
105 
106 
107   arma_hot inline SpSubview_MapMat_val<eT> operator[](const uword i);
108   arma_hot inline eT                       operator[](const uword i) const;
109 
110   arma_hot inline SpSubview_MapMat_val<eT> operator()(const uword i);
111   arma_hot inline eT                       operator()(const uword i) const;
112 
113   arma_hot inline SpSubview_MapMat_val<eT> operator()(const uword in_row, const uword in_col);
114   arma_hot inline eT                       operator()(const uword in_row, const uword in_col) const;
115 
116   arma_hot inline SpSubview_MapMat_val<eT> at(const uword i);
117   arma_hot inline eT                       at(const uword i) const;
118 
119   arma_hot inline SpSubview_MapMat_val<eT> at(const uword in_row, const uword in_col);
120   arma_hot inline eT                       at(const uword in_row, const uword in_col) const;
121 
122   inline bool check_overlap(const SpSubview& x) const;
123 
124   inline bool is_vec() const;
125 
126   inline       SpSubview_row<eT> row(const uword row_num);
127   inline const SpSubview_row<eT> row(const uword row_num) const;
128 
129   inline       SpSubview_col<eT> col(const uword col_num);
130   inline const SpSubview_col<eT> col(const uword col_num) const;
131 
132   inline       SpSubview rows(const uword in_row1, const uword in_row2);
133   inline const SpSubview rows(const uword in_row1, const uword in_row2) const;
134 
135   inline       SpSubview cols(const uword in_col1, const uword in_col2);
136   inline const SpSubview cols(const uword in_col1, const uword in_col2) const;
137 
138   inline       SpSubview submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2);
139   inline const SpSubview submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const;
140 
141   inline       SpSubview submat(const span& row_span, const span& col_span);
142   inline const SpSubview submat(const span& row_span, const span& col_span) const;
143 
144   inline       SpSubview operator()(const uword row_num, const span& col_span);
145   inline const SpSubview operator()(const uword row_num, const span& col_span) const;
146 
147   inline       SpSubview operator()(const span& row_span, const uword col_num);
148   inline const SpSubview operator()(const span& row_span, const uword col_num) const;
149 
150   inline       SpSubview operator()(const span& row_span, const span& col_span);
151   inline const SpSubview operator()(const span& row_span, const span& col_span) const;
152 
153 
154   inline void swap_rows(const uword in_row1, const uword in_row2);
155   inline void swap_cols(const uword in_col1, const uword in_col2);
156 
157   // Forward declarations.
158   class iterator_base;
159   class const_iterator;
160   class iterator;
161   class const_row_iterator;
162   class row_iterator;
163 
164   // Similar to SpMat iterators but automatically iterates past and ignores values not in the subview.
165   class iterator_base
166     {
167     public:
168 
169     inline iterator_base(const SpSubview& in_M);
170     inline iterator_base(const SpSubview& in_M, const uword col, const uword pos);
171 
col() const172     arma_inline uword col() const { return internal_col; }
pos() const173     arma_inline uword pos() const { return internal_pos; }
174 
175     arma_aligned const SpSubview* M;
176     arma_aligned       uword      internal_col;
177     arma_aligned       uword      internal_pos;
178 
179     typedef std::bidirectional_iterator_tag iterator_category;
180     typedef eT                              value_type;
181     typedef std::ptrdiff_t                  difference_type;  // TODO: not certain on this one
182     typedef const eT*                       pointer;
183     typedef const eT&                       reference;
184     };
185 
186   class const_iterator : public iterator_base
187     {
188     public:
189 
190     inline const_iterator(const SpSubview& in_M, uword initial_pos = 0);
191     inline const_iterator(const SpSubview& in_M, uword in_row, uword in_col);
192     inline const_iterator(const SpSubview& in_M, uword in_row, uword in_col, uword in_pos, uword skip_pos);
193     inline const_iterator(const const_iterator& other);
194 
195     arma_inline eT operator*() const;
196 
197     // Don't hold location internally; call "dummy" methods to get that information.
row() const198     arma_inline uword row() const { return iterator_base::M->m.row_indices[iterator_base::internal_pos + skip_pos] - iterator_base::M->aux_row1; }
199 
200     inline arma_hot         const_iterator& operator++();
201     inline arma_warn_unused const_iterator  operator++(int);
202 
203     inline arma_hot         const_iterator& operator--();
204     inline arma_warn_unused const_iterator  operator--(int);
205 
206     inline arma_hot bool operator!=(const const_iterator& rhs) const;
207     inline arma_hot bool operator==(const const_iterator& rhs) const;
208 
209     inline arma_hot bool operator!=(const typename SpMat<eT>::const_iterator& rhs) const;
210     inline arma_hot bool operator==(const typename SpMat<eT>::const_iterator& rhs) const;
211 
212     inline arma_hot bool operator!=(const const_row_iterator& rhs) const;
213     inline arma_hot bool operator==(const const_row_iterator& rhs) const;
214 
215     inline arma_hot bool operator!=(const typename SpMat<eT>::const_row_iterator& rhs) const;
216     inline arma_hot bool operator==(const typename SpMat<eT>::const_row_iterator& rhs) const;
217 
218     arma_aligned uword skip_pos; // not used in row_iterator or const_row_iterator
219     };
220 
221   class iterator : public const_iterator
222     {
223     public:
224 
iterator(SpSubview & in_M,const uword initial_pos=0)225     inline iterator(SpSubview& in_M, const uword initial_pos = 0) : const_iterator(in_M, initial_pos) { }
iterator(SpSubview & in_M,const uword in_row,const uword in_col)226     inline iterator(SpSubview& in_M, const uword in_row, const uword in_col) : const_iterator(in_M, in_row, in_col) { }
iterator(SpSubview & in_M,const uword in_row,const uword in_col,const uword in_pos,const uword in_skip_pos)227     inline iterator(SpSubview& in_M, const uword in_row, const uword in_col, const uword in_pos, const uword in_skip_pos) : const_iterator(in_M, in_row, in_col, in_pos, in_skip_pos) { }
iterator(const iterator & other)228     inline iterator(const iterator& other) : const_iterator(other) { }
229 
230     inline arma_hot SpValProxy< SpSubview<eT> > operator*();
231 
232     // overloads needed for return type correctness
233     inline arma_hot         iterator& operator++();
234     inline arma_warn_unused iterator  operator++(int);
235 
236     inline arma_hot         iterator& operator--();
237     inline arma_warn_unused iterator  operator--(int);
238 
239     // This has a different value_type than iterator_base.
240     typedef       SpValProxy< SpSubview<eT> >  value_type;
241     typedef const SpValProxy< SpSubview<eT> >* pointer;
242     typedef const SpValProxy< SpSubview<eT> >& reference;
243     };
244 
245   class const_row_iterator : public iterator_base
246     {
247     public:
248 
249     inline const_row_iterator();
250     inline const_row_iterator(const SpSubview& in_M, uword initial_pos = 0);
251     inline const_row_iterator(const SpSubview& in_M, uword in_row, uword in_col);
252     inline const_row_iterator(const const_row_iterator& other);
253 
254     inline arma_hot         const_row_iterator& operator++();
255     inline arma_warn_unused const_row_iterator  operator++(int);
256 
257     inline arma_hot         const_row_iterator& operator--();
258     inline arma_warn_unused const_row_iterator  operator--(int);
259 
260     uword internal_row; // Hold row internally because we use internal_pos differently.
261     uword actual_pos; // Actual position in subview's parent matrix.
262 
operator *() const263     arma_inline eT operator*() const { return iterator_base::M->m.values[actual_pos]; }
264 
row() const265     arma_inline uword row() const { return internal_row; }
266 
267     inline arma_hot bool operator!=(const const_iterator& rhs) const;
268     inline arma_hot bool operator==(const const_iterator& rhs) const;
269 
270     inline arma_hot bool operator!=(const typename SpMat<eT>::const_iterator& rhs) const;
271     inline arma_hot bool operator==(const typename SpMat<eT>::const_iterator& rhs) const;
272 
273     inline arma_hot bool operator!=(const const_row_iterator& rhs) const;
274     inline arma_hot bool operator==(const const_row_iterator& rhs) const;
275 
276     inline arma_hot bool operator!=(const typename SpMat<eT>::const_row_iterator& rhs) const;
277     inline arma_hot bool operator==(const typename SpMat<eT>::const_row_iterator& rhs) const;
278     };
279 
280   class row_iterator : public const_row_iterator
281     {
282     public:
283 
row_iterator(SpSubview & in_M,uword initial_pos=0)284     inline row_iterator(SpSubview& in_M, uword initial_pos = 0) : const_row_iterator(in_M, initial_pos) { }
row_iterator(SpSubview & in_M,uword in_row,uword in_col)285     inline row_iterator(SpSubview& in_M, uword in_row, uword in_col) : const_row_iterator(in_M, in_row, in_col) { }
row_iterator(const row_iterator & other)286     inline row_iterator(const row_iterator& other) : const_row_iterator(other) { }
287 
288     inline arma_hot SpValProxy< SpSubview<eT> > operator*();
289 
290     // overloads needed for return type correctness
291     inline arma_hot         row_iterator& operator++();
292     inline arma_warn_unused row_iterator  operator++(int);
293 
294     inline arma_hot         row_iterator& operator--();
295     inline arma_warn_unused row_iterator  operator--(int);
296 
297     // This has a different value_type than iterator_base.
298     typedef       SpValProxy< SpSubview<eT> >  value_type;
299     typedef const SpValProxy< SpSubview<eT> >* pointer;
300     typedef const SpValProxy< SpSubview<eT> >& reference;
301     };
302 
303   inline       iterator     begin();
304   inline const_iterator     begin() const;
305   inline const_iterator    cbegin() const;
306 
307   inline       iterator     begin_col(const uword col_num);
308   inline const_iterator     begin_col(const uword col_num) const;
309 
310   inline       row_iterator begin_row(const uword row_num = 0);
311   inline const_row_iterator begin_row(const uword row_num = 0) const;
312 
313   inline       iterator     end();
314   inline const_iterator     end() const;
315   inline const_iterator    cend() const;
316 
317   inline       row_iterator end_row();
318   inline const_row_iterator end_row() const;
319 
320   inline       row_iterator end_row(const uword row_num);
321   inline const_row_iterator end_row(const uword row_num) const;
322 
323   //! don't use this unless you're writing internal Armadillo code
324   arma_inline bool is_alias(const SpMat<eT>& X) const;
325 
326 
327   private:
328 
329   friend class SpMat<eT>;
330   friend class SpSubview_col<eT>;
331   friend class SpSubview_row<eT>;
332   friend class SpValProxy< SpSubview<eT> >;   // allow SpValProxy to call insert_element() and delete_element()
333 
334   inline arma_warn_unused eT&  insert_element(const uword in_row, const uword in_col, const eT in_val = eT(0));
335   inline                  void delete_element(const uword in_row, const uword in_col);
336 
337   inline void invalidate_cache() const;
338   };
339 
340 
341 
342 template<typename eT>
343 class SpSubview_col : public SpSubview<eT>
344   {
345   public:
346 
347   typedef eT                                       elem_type;
348   typedef typename get_pod_type<elem_type>::result pod_type;
349 
350   static constexpr bool is_row  = false;
351   static constexpr bool is_col  = true;
352   static constexpr bool is_xvec = false;
353 
354   inline void operator= (const SpSubview<eT>& x);
355   inline void operator= (const SpSubview_col& x);
356 
357   template<typename T1> inline void operator= (const SpBase<eT,T1>& x);
358   template<typename T1> inline void operator= (const   Base<eT,T1>& x);
359 
360   inline arma_warn_unused const SpOp<SpSubview_col<eT>,spop_htrans>  t() const;
361   inline arma_warn_unused const SpOp<SpSubview_col<eT>,spop_htrans> ht() const;
362   inline arma_warn_unused const SpOp<SpSubview_col<eT>,spop_strans> st() const;
363 
364 
365   protected:
366 
367   inline SpSubview_col(const SpMat<eT>& in_m, const uword in_col);
368   inline SpSubview_col(const SpMat<eT>& in_m, const uword in_col, const uword in_row1, const uword in_n_rows);
369   inline SpSubview_col() = delete;
370 
371 
372   private:
373 
374   friend class SpMat<eT>;
375   friend class SpSubview<eT>;
376   };
377 
378 
379 
380 template<typename eT>
381 class SpSubview_row : public SpSubview<eT>
382   {
383   public:
384 
385   typedef eT                                       elem_type;
386   typedef typename get_pod_type<elem_type>::result pod_type;
387 
388   static constexpr bool is_row  = true;
389   static constexpr bool is_col  = false;
390   static constexpr bool is_xvec = false;
391 
392   inline void operator= (const SpSubview<eT>& x);
393   inline void operator= (const SpSubview_row& x);
394 
395   template<typename T1> inline void operator= (const SpBase<eT,T1>& x);
396   template<typename T1> inline void operator= (const   Base<eT,T1>& x);
397 
398   inline arma_warn_unused const SpOp<SpSubview_row<eT>,spop_htrans>  t() const;
399   inline arma_warn_unused const SpOp<SpSubview_row<eT>,spop_htrans> ht() const;
400   inline arma_warn_unused const SpOp<SpSubview_row<eT>,spop_strans> st() const;
401 
402 
403   protected:
404 
405   inline SpSubview_row(const SpMat<eT>& in_m, const uword in_row);
406   inline SpSubview_row(const SpMat<eT>& in_m, const uword in_row, const uword in_col1, const uword in_n_cols);
407   inline SpSubview_row() = delete;
408 
409 
410   private:
411 
412   friend class SpMat<eT>;
413   friend class SpSubview<eT>;
414   };
415 
416 
417 
418 //! @}
419