Chris@49
|
1 // Copyright (C) 2012 Ryan Curtin
|
Chris@49
|
2 // Copyright (C) 2012 Conrad Sanderson
|
Chris@49
|
3 //
|
Chris@49
|
4 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
7
|
Chris@49
|
8 //! \addtogroup SpSubview
|
Chris@49
|
9 //! @{
|
Chris@49
|
10
|
Chris@49
|
11 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
12 // SpSubview::iterator_base implementation //
|
Chris@49
|
13 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
14
|
Chris@49
|
15 template<typename eT>
|
Chris@49
|
16 inline
|
Chris@49
|
17 SpSubview<eT>::iterator_base::iterator_base(const SpSubview<eT>& in_M)
|
Chris@49
|
18 : M(in_M)
|
Chris@49
|
19 , internal_col(0)
|
Chris@49
|
20 , internal_pos(0)
|
Chris@49
|
21 , skip_pos(0)
|
Chris@49
|
22 {
|
Chris@49
|
23 // Technically this iterator is invalid (it may not point to a real element).
|
Chris@49
|
24 }
|
Chris@49
|
25
|
Chris@49
|
26
|
Chris@49
|
27
|
Chris@49
|
28 template<typename eT>
|
Chris@49
|
29 inline
|
Chris@49
|
30 SpSubview<eT>::iterator_base::iterator_base(const SpSubview<eT>& in_M, const uword in_col, const uword in_pos, const uword in_skip_pos)
|
Chris@49
|
31 : M(in_M)
|
Chris@49
|
32 , internal_col(in_col)
|
Chris@49
|
33 , internal_pos(in_pos)
|
Chris@49
|
34 , skip_pos (in_skip_pos)
|
Chris@49
|
35 {
|
Chris@49
|
36 // Nothing to do.
|
Chris@49
|
37 }
|
Chris@49
|
38
|
Chris@49
|
39
|
Chris@49
|
40
|
Chris@49
|
41 template<typename eT>
|
Chris@49
|
42 inline
|
Chris@49
|
43 eT
|
Chris@49
|
44 SpSubview<eT>::iterator_base::operator*() const
|
Chris@49
|
45 {
|
Chris@49
|
46 return M.m.values[internal_pos + skip_pos];
|
Chris@49
|
47 }
|
Chris@49
|
48
|
Chris@49
|
49
|
Chris@49
|
50
|
Chris@49
|
51 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
52 // SpSubview::const_iterator implementation //
|
Chris@49
|
53 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
54
|
Chris@49
|
55 template<typename eT>
|
Chris@49
|
56 inline
|
Chris@49
|
57 SpSubview<eT>::const_iterator::const_iterator(const SpSubview<eT>& in_M, const uword initial_pos)
|
Chris@49
|
58 : iterator_base(in_M, 0, initial_pos, 0)
|
Chris@49
|
59 {
|
Chris@49
|
60 // Corner case for empty subviews.
|
Chris@49
|
61 if(in_M.n_nonzero == 0)
|
Chris@49
|
62 {
|
Chris@49
|
63 iterator_base::internal_col = in_M.n_cols;
|
Chris@49
|
64 iterator_base::skip_pos = in_M.m.n_nonzero;
|
Chris@49
|
65 return;
|
Chris@49
|
66 }
|
Chris@49
|
67
|
Chris@49
|
68 // Figure out the row and column of the position.
|
Chris@49
|
69 // lskip_pos holds the number of values which aren't part of this subview.
|
Chris@49
|
70 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
71 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
72 const uword ln_rows = iterator_base::M.n_rows;
|
Chris@49
|
73 const uword ln_cols = iterator_base::M.n_cols;
|
Chris@49
|
74
|
Chris@49
|
75 uword cur_pos = 0; // off by one because we might be searching for pos 0
|
Chris@49
|
76 uword lskip_pos = iterator_base::M.m.col_ptrs[aux_col];
|
Chris@49
|
77 uword cur_col = 0;
|
Chris@49
|
78
|
Chris@49
|
79 while(cur_pos < (iterator_base::internal_pos + 1))
|
Chris@49
|
80 {
|
Chris@49
|
81 // Have we stepped forward a column (or multiple columns)?
|
Chris@49
|
82 while(((lskip_pos + cur_pos) >= iterator_base::M.m.col_ptrs[cur_col + aux_col + 1]) && (cur_col < ln_cols))
|
Chris@49
|
83 {
|
Chris@49
|
84 ++cur_col;
|
Chris@49
|
85 }
|
Chris@49
|
86
|
Chris@49
|
87 // See if the current position is in the subview.
|
Chris@49
|
88 const uword row_index = iterator_base::M.m.row_indices[cur_pos + lskip_pos];
|
Chris@49
|
89 if(row_index < aux_row)
|
Chris@49
|
90 {
|
Chris@49
|
91 ++lskip_pos; // not valid
|
Chris@49
|
92 }
|
Chris@49
|
93 else if(row_index < (aux_row + ln_rows))
|
Chris@49
|
94 {
|
Chris@49
|
95 ++cur_pos; // valid, in the subview
|
Chris@49
|
96 }
|
Chris@49
|
97 else
|
Chris@49
|
98 {
|
Chris@49
|
99 // skip to end of column
|
Chris@49
|
100 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
101 lskip_pos += (next_colptr - (cur_pos + lskip_pos));
|
Chris@49
|
102 }
|
Chris@49
|
103 }
|
Chris@49
|
104
|
Chris@49
|
105 iterator_base::internal_col = cur_col;
|
Chris@49
|
106 iterator_base::skip_pos = lskip_pos;
|
Chris@49
|
107 }
|
Chris@49
|
108
|
Chris@49
|
109
|
Chris@49
|
110
|
Chris@49
|
111 template<typename eT>
|
Chris@49
|
112 inline
|
Chris@49
|
113 SpSubview<eT>::const_iterator::const_iterator(const SpSubview<eT>& in_M, const uword in_row, const uword in_col)
|
Chris@49
|
114 : iterator_base(in_M, in_col, 0, 0)
|
Chris@49
|
115 {
|
Chris@49
|
116 // Corner case for empty subviews.
|
Chris@49
|
117 if(in_M.n_nonzero == 0)
|
Chris@49
|
118 {
|
Chris@49
|
119 // We must be at the last position.
|
Chris@49
|
120 iterator_base::internal_col = in_M.n_cols;
|
Chris@49
|
121 iterator_base::skip_pos = in_M.m.n_nonzero;
|
Chris@49
|
122 return;
|
Chris@49
|
123 }
|
Chris@49
|
124
|
Chris@49
|
125 // We have a destination we want to be just after, but don't know what position that is.
|
Chris@49
|
126 // Because we have to count the points in this subview and not in this subview, this becomes a little difficult and slow.
|
Chris@49
|
127 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
128 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
129 const uword ln_rows = iterator_base::M.n_rows;
|
Chris@49
|
130 const uword ln_cols = iterator_base::M.n_cols;
|
Chris@49
|
131
|
Chris@49
|
132 uword cur_pos = 0;
|
Chris@49
|
133 uword skip_pos = iterator_base::M.m.col_ptrs[aux_col];
|
Chris@49
|
134 uword cur_col = 0;
|
Chris@49
|
135
|
Chris@49
|
136 while(cur_col < in_col)
|
Chris@49
|
137 {
|
Chris@49
|
138 // See if the current position is in the subview.
|
Chris@49
|
139 const uword row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos];
|
Chris@49
|
140 if(row_index < aux_row)
|
Chris@49
|
141 {
|
Chris@49
|
142 ++skip_pos;
|
Chris@49
|
143 }
|
Chris@49
|
144 else if(row_index < (aux_row + ln_rows))
|
Chris@49
|
145 {
|
Chris@49
|
146 ++cur_pos;
|
Chris@49
|
147 }
|
Chris@49
|
148 else
|
Chris@49
|
149 {
|
Chris@49
|
150 // skip to end of column
|
Chris@49
|
151 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
152 skip_pos += (next_colptr - (cur_pos + skip_pos));
|
Chris@49
|
153 }
|
Chris@49
|
154
|
Chris@49
|
155 // Have we stepped forward a column (or multiple columns)?
|
Chris@49
|
156 while(((skip_pos + cur_pos) >= iterator_base::M.m.col_ptrs[cur_col + aux_col + 1]) && (cur_col < ln_cols))
|
Chris@49
|
157 {
|
Chris@49
|
158 ++cur_col;
|
Chris@49
|
159 }
|
Chris@49
|
160 }
|
Chris@49
|
161
|
Chris@49
|
162 // Now we are either on the right column or ahead of it.
|
Chris@49
|
163 if(cur_col == in_col)
|
Chris@49
|
164 {
|
Chris@49
|
165 // We have to find the right row index.
|
Chris@49
|
166 uword row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos];
|
Chris@49
|
167 while((row_index < (in_row + aux_row)))
|
Chris@49
|
168 {
|
Chris@49
|
169 if(row_index < aux_row)
|
Chris@49
|
170 {
|
Chris@49
|
171 ++skip_pos;
|
Chris@49
|
172 }
|
Chris@49
|
173 else
|
Chris@49
|
174 {
|
Chris@49
|
175 ++cur_pos;
|
Chris@49
|
176 }
|
Chris@49
|
177
|
Chris@49
|
178 // Ensure we didn't step forward a column; if we did, we need to stop.
|
Chris@49
|
179 while(((skip_pos + cur_pos) >= iterator_base::M.m.col_ptrs[cur_col + aux_col + 1]) && (cur_col < ln_cols))
|
Chris@49
|
180 {
|
Chris@49
|
181 ++cur_col;
|
Chris@49
|
182 }
|
Chris@49
|
183
|
Chris@49
|
184 if(cur_col != in_col)
|
Chris@49
|
185 {
|
Chris@49
|
186 break;
|
Chris@49
|
187 }
|
Chris@49
|
188
|
Chris@49
|
189 row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos];
|
Chris@49
|
190 }
|
Chris@49
|
191 }
|
Chris@49
|
192
|
Chris@49
|
193 // Now we need to find the next valid position in the subview.
|
Chris@49
|
194 uword row_index;
|
Chris@49
|
195 while(true)
|
Chris@49
|
196 {
|
Chris@49
|
197 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
198 row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos];
|
Chris@49
|
199
|
Chris@49
|
200 // Are we at the last position?
|
Chris@49
|
201 if(cur_col >= ln_cols)
|
Chris@49
|
202 {
|
Chris@49
|
203 cur_col = ln_cols;
|
Chris@49
|
204 // Make sure we will be pointing at the last element in the parent matrix.
|
Chris@49
|
205 skip_pos = iterator_base::M.m.n_nonzero - iterator_base::M.n_nonzero;
|
Chris@49
|
206 break;
|
Chris@49
|
207 }
|
Chris@49
|
208
|
Chris@49
|
209 if(row_index < aux_row)
|
Chris@49
|
210 {
|
Chris@49
|
211 ++skip_pos;
|
Chris@49
|
212 }
|
Chris@49
|
213 else if(row_index < (aux_row + ln_rows))
|
Chris@49
|
214 {
|
Chris@49
|
215 break; // found
|
Chris@49
|
216 }
|
Chris@49
|
217 else
|
Chris@49
|
218 {
|
Chris@49
|
219 skip_pos += (next_colptr - (cur_pos + skip_pos));
|
Chris@49
|
220 }
|
Chris@49
|
221
|
Chris@49
|
222 // Did we move any columns?
|
Chris@49
|
223 while(((skip_pos + cur_pos) >= iterator_base::M.m.col_ptrs[cur_col + aux_col + 1]) && (cur_col < ln_cols))
|
Chris@49
|
224 {
|
Chris@49
|
225 ++cur_col;
|
Chris@49
|
226 }
|
Chris@49
|
227 }
|
Chris@49
|
228
|
Chris@49
|
229 // It is possible we have moved another column.
|
Chris@49
|
230 while(((skip_pos + cur_pos) >= iterator_base::M.m.col_ptrs[cur_col + aux_col + 1]) && (cur_col < ln_cols))
|
Chris@49
|
231 {
|
Chris@49
|
232 ++cur_col;
|
Chris@49
|
233 }
|
Chris@49
|
234
|
Chris@49
|
235 iterator_base::internal_pos = cur_pos;
|
Chris@49
|
236 iterator_base::skip_pos = skip_pos;
|
Chris@49
|
237 iterator_base::internal_col = cur_col;
|
Chris@49
|
238 }
|
Chris@49
|
239
|
Chris@49
|
240
|
Chris@49
|
241
|
Chris@49
|
242 template<typename eT>
|
Chris@49
|
243 inline
|
Chris@49
|
244 SpSubview<eT>::const_iterator::const_iterator(const SpSubview<eT>& in_M, uword in_row, uword in_col, uword in_pos, uword in_skip_pos)
|
Chris@49
|
245 : iterator_base(in_M, in_col, in_pos, in_skip_pos)
|
Chris@49
|
246 {
|
Chris@49
|
247 // Nothing to do.
|
Chris@49
|
248 }
|
Chris@49
|
249
|
Chris@49
|
250
|
Chris@49
|
251
|
Chris@49
|
252 template<typename eT>
|
Chris@49
|
253 inline
|
Chris@49
|
254 SpSubview<eT>::const_iterator::const_iterator(const const_iterator& other)
|
Chris@49
|
255 : iterator_base(other.M, other.internal_col, other.internal_pos, other.skip_pos)
|
Chris@49
|
256 {
|
Chris@49
|
257 // Nothing to do.
|
Chris@49
|
258 }
|
Chris@49
|
259
|
Chris@49
|
260
|
Chris@49
|
261
|
Chris@49
|
262 template<typename eT>
|
Chris@49
|
263 inline
|
Chris@49
|
264 typename SpSubview<eT>::const_iterator&
|
Chris@49
|
265 SpSubview<eT>::const_iterator::operator++()
|
Chris@49
|
266 {
|
Chris@49
|
267 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
268 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
269 const uword ln_rows = iterator_base::M.n_rows;
|
Chris@49
|
270 const uword ln_cols = iterator_base::M.n_cols;
|
Chris@49
|
271
|
Chris@49
|
272 uword cur_col = iterator_base::internal_col;
|
Chris@49
|
273 uword cur_pos = iterator_base::internal_pos + 1;
|
Chris@49
|
274 uword lskip_pos = iterator_base::skip_pos;
|
Chris@49
|
275 uword row_index;
|
Chris@49
|
276
|
Chris@49
|
277 while(true)
|
Chris@49
|
278 {
|
Chris@49
|
279 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
280 row_index = iterator_base::M.m.row_indices[cur_pos + lskip_pos];
|
Chris@49
|
281
|
Chris@49
|
282 // Did we move any columns?
|
Chris@49
|
283 while((cur_col < ln_cols) && ((lskip_pos + cur_pos) >= iterator_base::M.m.col_ptrs[cur_col + aux_col + 1]))
|
Chris@49
|
284 {
|
Chris@49
|
285 ++cur_col;
|
Chris@49
|
286 }
|
Chris@49
|
287
|
Chris@49
|
288 // Are we at the last position?
|
Chris@49
|
289 if(cur_col >= ln_cols)
|
Chris@49
|
290 {
|
Chris@49
|
291 cur_col = ln_cols;
|
Chris@49
|
292 // Make sure we will be pointing at the last element in the parent matrix.
|
Chris@49
|
293 lskip_pos = iterator_base::M.m.n_nonzero - iterator_base::M.n_nonzero;
|
Chris@49
|
294 break;
|
Chris@49
|
295 }
|
Chris@49
|
296
|
Chris@49
|
297 if(row_index < aux_row)
|
Chris@49
|
298 {
|
Chris@49
|
299 ++lskip_pos;
|
Chris@49
|
300 }
|
Chris@49
|
301 else if(row_index < (aux_row + ln_rows))
|
Chris@49
|
302 {
|
Chris@49
|
303 break; // found
|
Chris@49
|
304 }
|
Chris@49
|
305 else
|
Chris@49
|
306 {
|
Chris@49
|
307 lskip_pos += (next_colptr - (cur_pos + lskip_pos));
|
Chris@49
|
308 }
|
Chris@49
|
309 }
|
Chris@49
|
310
|
Chris@49
|
311 iterator_base::internal_pos = cur_pos;
|
Chris@49
|
312 iterator_base::internal_col = cur_col;
|
Chris@49
|
313 iterator_base::skip_pos = lskip_pos;
|
Chris@49
|
314
|
Chris@49
|
315 return *this;
|
Chris@49
|
316 }
|
Chris@49
|
317
|
Chris@49
|
318
|
Chris@49
|
319
|
Chris@49
|
320 template<typename eT>
|
Chris@49
|
321 inline
|
Chris@49
|
322 typename SpSubview<eT>::const_iterator
|
Chris@49
|
323 SpSubview<eT>::const_iterator::operator++(int)
|
Chris@49
|
324 {
|
Chris@49
|
325 typename SpSubview<eT>::const_iterator tmp(*this);
|
Chris@49
|
326
|
Chris@49
|
327 ++(*this);
|
Chris@49
|
328
|
Chris@49
|
329 return tmp;
|
Chris@49
|
330 }
|
Chris@49
|
331
|
Chris@49
|
332
|
Chris@49
|
333
|
Chris@49
|
334 template<typename eT>
|
Chris@49
|
335 inline
|
Chris@49
|
336 typename SpSubview<eT>::const_iterator&
|
Chris@49
|
337 SpSubview<eT>::const_iterator::operator--()
|
Chris@49
|
338 {
|
Chris@49
|
339 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
340 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
341 const uword ln_rows = iterator_base::M.n_rows;
|
Chris@49
|
342
|
Chris@49
|
343 uword cur_col = iterator_base::internal_col;
|
Chris@49
|
344 uword cur_pos = iterator_base::internal_pos - 1;
|
Chris@49
|
345 uword skip_pos = iterator_base::skip_pos;
|
Chris@49
|
346
|
Chris@49
|
347 // Special condition for end of iterator.
|
Chris@49
|
348 if((skip_pos + cur_pos + 1) == iterator_base::M.m.n_nonzero)
|
Chris@49
|
349 {
|
Chris@49
|
350 // We are at the last element. So we need to set skip_pos back to what it
|
Chris@49
|
351 // would be if we didn't manually modify it back in operator++().
|
Chris@49
|
352 skip_pos = iterator_base::M.m.col_ptrs[cur_col + aux_col] - iterator_base::internal_pos;
|
Chris@49
|
353 }
|
Chris@49
|
354
|
Chris@49
|
355 uword row_index;
|
Chris@49
|
356
|
Chris@49
|
357 while(true)
|
Chris@49
|
358 {
|
Chris@49
|
359 const uword colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col];
|
Chris@49
|
360 row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos];
|
Chris@49
|
361
|
Chris@49
|
362 // Did we move back any columns?
|
Chris@49
|
363 while((skip_pos + cur_pos) < iterator_base::M.m.col_ptrs[cur_col + aux_col])
|
Chris@49
|
364 {
|
Chris@49
|
365 --cur_col;
|
Chris@49
|
366 }
|
Chris@49
|
367
|
Chris@49
|
368 if(row_index < aux_row)
|
Chris@49
|
369 {
|
Chris@49
|
370 skip_pos -= (colptr - (cur_pos + skip_pos) + 1);
|
Chris@49
|
371 }
|
Chris@49
|
372 else if(row_index < (aux_row + ln_rows))
|
Chris@49
|
373 {
|
Chris@49
|
374 break; // found
|
Chris@49
|
375 }
|
Chris@49
|
376 else
|
Chris@49
|
377 {
|
Chris@49
|
378 --skip_pos;
|
Chris@49
|
379 }
|
Chris@49
|
380 }
|
Chris@49
|
381
|
Chris@49
|
382 iterator_base::internal_pos = cur_pos;
|
Chris@49
|
383 iterator_base::skip_pos = skip_pos;
|
Chris@49
|
384 iterator_base::internal_col = cur_col;
|
Chris@49
|
385
|
Chris@49
|
386 return *this;
|
Chris@49
|
387 }
|
Chris@49
|
388
|
Chris@49
|
389
|
Chris@49
|
390
|
Chris@49
|
391 template<typename eT>
|
Chris@49
|
392 inline
|
Chris@49
|
393 typename SpSubview<eT>::const_iterator
|
Chris@49
|
394 SpSubview<eT>::const_iterator::operator--(int)
|
Chris@49
|
395 {
|
Chris@49
|
396 typename SpSubview<eT>::const_iterator tmp(*this);
|
Chris@49
|
397
|
Chris@49
|
398 --(*this);
|
Chris@49
|
399
|
Chris@49
|
400 return tmp;
|
Chris@49
|
401 }
|
Chris@49
|
402
|
Chris@49
|
403
|
Chris@49
|
404
|
Chris@49
|
405 template<typename eT>
|
Chris@49
|
406 inline
|
Chris@49
|
407 bool
|
Chris@49
|
408 SpSubview<eT>::const_iterator::operator==(const const_iterator& rhs) const
|
Chris@49
|
409 {
|
Chris@49
|
410 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
411 }
|
Chris@49
|
412
|
Chris@49
|
413
|
Chris@49
|
414
|
Chris@49
|
415 template<typename eT>
|
Chris@49
|
416 inline
|
Chris@49
|
417 bool
|
Chris@49
|
418 SpSubview<eT>::const_iterator::operator!=(const const_iterator& rhs) const
|
Chris@49
|
419 {
|
Chris@49
|
420 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
421 }
|
Chris@49
|
422
|
Chris@49
|
423
|
Chris@49
|
424
|
Chris@49
|
425 template<typename eT>
|
Chris@49
|
426 inline
|
Chris@49
|
427 bool
|
Chris@49
|
428 SpSubview<eT>::const_iterator::operator==(const typename SpMat<eT>::const_iterator& rhs) const
|
Chris@49
|
429 {
|
Chris@49
|
430 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
431 }
|
Chris@49
|
432
|
Chris@49
|
433
|
Chris@49
|
434
|
Chris@49
|
435 template<typename eT>
|
Chris@49
|
436 inline
|
Chris@49
|
437 bool
|
Chris@49
|
438 SpSubview<eT>::const_iterator::operator!=(const typename SpMat<eT>::const_iterator& rhs) const
|
Chris@49
|
439 {
|
Chris@49
|
440 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
441 }
|
Chris@49
|
442
|
Chris@49
|
443
|
Chris@49
|
444
|
Chris@49
|
445 template<typename eT>
|
Chris@49
|
446 inline
|
Chris@49
|
447 bool
|
Chris@49
|
448 SpSubview<eT>::const_iterator::operator==(const const_row_iterator& rhs) const
|
Chris@49
|
449 {
|
Chris@49
|
450 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
451 }
|
Chris@49
|
452
|
Chris@49
|
453
|
Chris@49
|
454
|
Chris@49
|
455 template<typename eT>
|
Chris@49
|
456 inline
|
Chris@49
|
457 bool
|
Chris@49
|
458 SpSubview<eT>::const_iterator::operator!=(const const_row_iterator& rhs) const
|
Chris@49
|
459 {
|
Chris@49
|
460 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
461 }
|
Chris@49
|
462
|
Chris@49
|
463
|
Chris@49
|
464
|
Chris@49
|
465 template<typename eT>
|
Chris@49
|
466 inline
|
Chris@49
|
467 bool
|
Chris@49
|
468 SpSubview<eT>::const_iterator::operator==(const typename SpMat<eT>::const_row_iterator& rhs) const
|
Chris@49
|
469 {
|
Chris@49
|
470 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
471 }
|
Chris@49
|
472
|
Chris@49
|
473
|
Chris@49
|
474
|
Chris@49
|
475 template<typename eT>
|
Chris@49
|
476 inline
|
Chris@49
|
477 bool
|
Chris@49
|
478 SpSubview<eT>::const_iterator::operator!=(const typename SpMat<eT>::const_row_iterator& rhs) const
|
Chris@49
|
479 {
|
Chris@49
|
480 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
481 }
|
Chris@49
|
482
|
Chris@49
|
483
|
Chris@49
|
484
|
Chris@49
|
485 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
486 // SpSubview<eT>::iterator implementation //
|
Chris@49
|
487 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
488
|
Chris@49
|
489 template<typename eT>
|
Chris@49
|
490 inline
|
Chris@49
|
491 SpValProxy<SpSubview<eT> >
|
Chris@49
|
492 SpSubview<eT>::iterator::operator*()
|
Chris@49
|
493 {
|
Chris@49
|
494 return SpValProxy<SpSubview<eT> >(
|
Chris@49
|
495 iterator_base::row(),
|
Chris@49
|
496 iterator_base::col(),
|
Chris@49
|
497 access::rw(iterator_base::M),
|
Chris@49
|
498 &(access::rw(iterator_base::M.m.values[iterator_base::internal_pos + iterator_base::skip_pos])));
|
Chris@49
|
499 }
|
Chris@49
|
500
|
Chris@49
|
501
|
Chris@49
|
502
|
Chris@49
|
503 template<typename eT>
|
Chris@49
|
504 inline
|
Chris@49
|
505 typename SpSubview<eT>::iterator&
|
Chris@49
|
506 SpSubview<eT>::iterator::operator++()
|
Chris@49
|
507 {
|
Chris@49
|
508 const_iterator::operator++();
|
Chris@49
|
509 return *this;
|
Chris@49
|
510 }
|
Chris@49
|
511
|
Chris@49
|
512
|
Chris@49
|
513
|
Chris@49
|
514 template<typename eT>
|
Chris@49
|
515 inline
|
Chris@49
|
516 typename SpSubview<eT>::iterator
|
Chris@49
|
517 SpSubview<eT>::iterator::operator++(int)
|
Chris@49
|
518 {
|
Chris@49
|
519 typename SpSubview<eT>::iterator tmp(*this);
|
Chris@49
|
520
|
Chris@49
|
521 const_iterator::operator++();
|
Chris@49
|
522
|
Chris@49
|
523 return tmp;
|
Chris@49
|
524 }
|
Chris@49
|
525
|
Chris@49
|
526
|
Chris@49
|
527
|
Chris@49
|
528 template<typename eT>
|
Chris@49
|
529 inline
|
Chris@49
|
530 typename SpSubview<eT>::iterator&
|
Chris@49
|
531 SpSubview<eT>::iterator::operator--()
|
Chris@49
|
532 {
|
Chris@49
|
533 const_iterator::operator--();
|
Chris@49
|
534 return *this;
|
Chris@49
|
535 }
|
Chris@49
|
536
|
Chris@49
|
537
|
Chris@49
|
538
|
Chris@49
|
539 template<typename eT>
|
Chris@49
|
540 inline
|
Chris@49
|
541 typename SpSubview<eT>::iterator
|
Chris@49
|
542 SpSubview<eT>::iterator::operator--(int)
|
Chris@49
|
543 {
|
Chris@49
|
544 typename SpSubview<eT>::iterator tmp(*this);
|
Chris@49
|
545
|
Chris@49
|
546 const_iterator::operator--();
|
Chris@49
|
547
|
Chris@49
|
548 return tmp;
|
Chris@49
|
549 }
|
Chris@49
|
550
|
Chris@49
|
551
|
Chris@49
|
552
|
Chris@49
|
553 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
554 // SpSubview<eT>::const_row_iterator implementation //
|
Chris@49
|
555 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
556
|
Chris@49
|
557 template<typename eT>
|
Chris@49
|
558 inline
|
Chris@49
|
559 SpSubview<eT>::const_row_iterator::const_row_iterator(const SpSubview<eT>& in_M, uword initial_pos)
|
Chris@49
|
560 : iterator_base(in_M, 0, initial_pos, 0)
|
Chris@49
|
561 , internal_row(0)
|
Chris@49
|
562 , actual_pos(0)
|
Chris@49
|
563 {
|
Chris@49
|
564 // Corner case for empty subviews.
|
Chris@49
|
565 if(in_M.n_nonzero == 0)
|
Chris@49
|
566 {
|
Chris@49
|
567 iterator_base::internal_col = 0;
|
Chris@49
|
568 internal_row = in_M.n_rows;
|
Chris@49
|
569 iterator_base::skip_pos = in_M.m.n_nonzero;
|
Chris@49
|
570 return;
|
Chris@49
|
571 }
|
Chris@49
|
572
|
Chris@49
|
573 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
574 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
575 const uword ln_cols = iterator_base::M.n_cols;
|
Chris@49
|
576
|
Chris@49
|
577 // We don't know where the elements are in each row. What we will do is
|
Chris@49
|
578 // loop across all valid columns looking for elements in row 0 (and add to
|
Chris@49
|
579 // our sum), then in row 1, and so forth, until we get to the desired
|
Chris@49
|
580 // position.
|
Chris@49
|
581 uword cur_pos = -1;
|
Chris@49
|
582 uword cur_row = 0;
|
Chris@49
|
583 uword cur_col = 0;
|
Chris@49
|
584
|
Chris@49
|
585 while(true)
|
Chris@49
|
586 {
|
Chris@49
|
587 // Is there anything in the column we are looking at?
|
Chris@49
|
588 const uword colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col];
|
Chris@49
|
589 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
590
|
Chris@49
|
591 for(uword ind = colptr; (ind < next_colptr) && (iterator_base::M.m.row_indices[ind] <= (cur_row + aux_row)); ++ind)
|
Chris@49
|
592 {
|
Chris@49
|
593 // There is something in this column. Is it in the row we are looking at?
|
Chris@49
|
594 const uword row_index = iterator_base::M.m.row_indices[ind];
|
Chris@49
|
595 if(row_index == (cur_row + aux_row))
|
Chris@49
|
596 {
|
Chris@49
|
597 // Yes, it is in the right row.
|
Chris@49
|
598 if(++cur_pos == iterator_base::internal_pos)
|
Chris@49
|
599 {
|
Chris@49
|
600 iterator_base::internal_col = cur_col;
|
Chris@49
|
601 internal_row = cur_row;
|
Chris@49
|
602 actual_pos = ind;
|
Chris@49
|
603
|
Chris@49
|
604 return;
|
Chris@49
|
605 }
|
Chris@49
|
606
|
Chris@49
|
607 // We are done with this column. Break to the column incrementing code (directly below).
|
Chris@49
|
608 break;
|
Chris@49
|
609 }
|
Chris@49
|
610 else if(row_index > (cur_row + aux_row))
|
Chris@49
|
611 {
|
Chris@49
|
612 break; // Can't be in this column.
|
Chris@49
|
613 }
|
Chris@49
|
614 }
|
Chris@49
|
615
|
Chris@49
|
616 cur_col++; // Done with the column. Move on.
|
Chris@49
|
617 if(cur_col == ln_cols)
|
Chris@49
|
618 {
|
Chris@49
|
619 // Out of columns. Loop back to the beginning and look on the next row.
|
Chris@49
|
620 cur_col = 0;
|
Chris@49
|
621 cur_row++;
|
Chris@49
|
622 }
|
Chris@49
|
623 }
|
Chris@49
|
624 }
|
Chris@49
|
625
|
Chris@49
|
626
|
Chris@49
|
627
|
Chris@49
|
628 template<typename eT>
|
Chris@49
|
629 inline
|
Chris@49
|
630 SpSubview<eT>::const_row_iterator::const_row_iterator(const SpSubview<eT>& in_M, uword in_row, uword in_col)
|
Chris@49
|
631 : iterator_base(in_M, in_col, 0, 0)
|
Chris@49
|
632 , internal_row(0)
|
Chris@49
|
633 , actual_pos(0)
|
Chris@49
|
634 {
|
Chris@49
|
635 // We have a destination we want to be just after, but don't know what that
|
Chris@49
|
636 // position is. Because we will have to loop over everything anyway, create
|
Chris@49
|
637 // another iterator and loop it until it is at the right place, then take its
|
Chris@49
|
638 // information.
|
Chris@49
|
639 const_row_iterator it(in_M, 0);
|
Chris@49
|
640 while((it.row() < in_row) || ((it.row() == in_row) && (it.col() < in_col)))
|
Chris@49
|
641 {
|
Chris@49
|
642 ++it;
|
Chris@49
|
643 }
|
Chris@49
|
644
|
Chris@49
|
645 iterator_base::internal_col = it.col();
|
Chris@49
|
646 iterator_base::internal_pos = it.pos();
|
Chris@49
|
647 iterator_base::skip_pos = it.skip_pos;
|
Chris@49
|
648 internal_row = it.internal_row;
|
Chris@49
|
649 actual_pos = it.actual_pos;
|
Chris@49
|
650 }
|
Chris@49
|
651
|
Chris@49
|
652
|
Chris@49
|
653
|
Chris@49
|
654 template<typename eT>
|
Chris@49
|
655 inline
|
Chris@49
|
656 SpSubview<eT>::const_row_iterator::const_row_iterator(const const_row_iterator& other)
|
Chris@49
|
657 : iterator_base(other.M, other.internal_col, other.internal_pos, other.skip_pos)
|
Chris@49
|
658 , internal_row(other.internal_row)
|
Chris@49
|
659 , actual_pos(other.actual_pos)
|
Chris@49
|
660 {
|
Chris@49
|
661 // Nothing to do.
|
Chris@49
|
662 }
|
Chris@49
|
663
|
Chris@49
|
664
|
Chris@49
|
665
|
Chris@49
|
666 template<typename eT>
|
Chris@49
|
667 inline
|
Chris@49
|
668 typename SpSubview<eT>::const_row_iterator&
|
Chris@49
|
669 SpSubview<eT>::const_row_iterator::operator++()
|
Chris@49
|
670 {
|
Chris@49
|
671 // We just need to find the next nonzero element.
|
Chris@49
|
672 ++iterator_base::internal_pos;
|
Chris@49
|
673
|
Chris@49
|
674 // If we have exceeded the bounds, update accordingly.
|
Chris@49
|
675 if(iterator_base::internal_pos >= iterator_base::M.n_nonzero)
|
Chris@49
|
676 {
|
Chris@49
|
677 internal_row = iterator_base::M.n_rows;
|
Chris@49
|
678 iterator_base::internal_col = 0;
|
Chris@49
|
679 actual_pos = iterator_base::M.m.n_nonzero;
|
Chris@49
|
680
|
Chris@49
|
681 return *this;
|
Chris@49
|
682 }
|
Chris@49
|
683
|
Chris@49
|
684 // Otherwise, we need to search.
|
Chris@49
|
685 uword cur_col = iterator_base::internal_col;
|
Chris@49
|
686 uword cur_row = internal_row;
|
Chris@49
|
687
|
Chris@49
|
688 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
689 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
690 const uword ln_cols = iterator_base::M.n_cols;
|
Chris@49
|
691
|
Chris@49
|
692 while(true)
|
Chris@49
|
693 {
|
Chris@49
|
694 // Increment the current column and see if we are on a new row.
|
Chris@49
|
695 if(++cur_col == ln_cols)
|
Chris@49
|
696 {
|
Chris@49
|
697 cur_col = 0;
|
Chris@49
|
698 ++cur_row;
|
Chris@49
|
699 }
|
Chris@49
|
700
|
Chris@49
|
701 // Is there anything in this new column?
|
Chris@49
|
702 const uword colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col];
|
Chris@49
|
703 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
704
|
Chris@49
|
705 for(uword ind = colptr; (ind < next_colptr) && (iterator_base::M.m.row_indices[ind] <= (cur_row + aux_row)); ++ind)
|
Chris@49
|
706 {
|
Chris@49
|
707 const uword row_index = iterator_base::M.m.row_indices[ind];
|
Chris@49
|
708
|
Chris@49
|
709 if((row_index - aux_row) == cur_row)
|
Chris@49
|
710 {
|
Chris@49
|
711 // We have successfully incremented.
|
Chris@49
|
712 internal_row = cur_row;
|
Chris@49
|
713 actual_pos = ind;
|
Chris@49
|
714 iterator_base::internal_col = cur_col;
|
Chris@49
|
715
|
Chris@49
|
716 return *this;
|
Chris@49
|
717 }
|
Chris@49
|
718 }
|
Chris@49
|
719 }
|
Chris@49
|
720 }
|
Chris@49
|
721
|
Chris@49
|
722
|
Chris@49
|
723
|
Chris@49
|
724 template<typename eT>
|
Chris@49
|
725 inline
|
Chris@49
|
726 typename SpSubview<eT>::const_row_iterator
|
Chris@49
|
727 SpSubview<eT>::const_row_iterator::operator++(int)
|
Chris@49
|
728 {
|
Chris@49
|
729 typename SpSubview<eT>::const_row_iterator tmp(*this);
|
Chris@49
|
730
|
Chris@49
|
731 ++(*this);
|
Chris@49
|
732
|
Chris@49
|
733 return tmp;
|
Chris@49
|
734 }
|
Chris@49
|
735
|
Chris@49
|
736
|
Chris@49
|
737
|
Chris@49
|
738 template<typename eT>
|
Chris@49
|
739 inline
|
Chris@49
|
740 typename SpSubview<eT>::const_row_iterator&
|
Chris@49
|
741 SpSubview<eT>::const_row_iterator::operator--()
|
Chris@49
|
742 {
|
Chris@49
|
743 // We just need to find the previous element.
|
Chris@49
|
744 // if(iterator_base::pos == 0)
|
Chris@49
|
745 // {
|
Chris@49
|
746 // // We cannot decrement.
|
Chris@49
|
747 // return *this;
|
Chris@49
|
748 // }
|
Chris@49
|
749 // else if(iterator_base::pos == iterator_base::M.n_nonzero)
|
Chris@49
|
750 // {
|
Chris@49
|
751 // // We will be coming off the last element. We need to reset the row correctly, because we set row = 0 in the last matrix position.
|
Chris@49
|
752 // iterator_base::row = iterator_base::M.n_rows - 1;
|
Chris@49
|
753 // }
|
Chris@49
|
754 // else if(iterator_base::pos > iterator_base::M.n_nonzero)
|
Chris@49
|
755 // {
|
Chris@49
|
756 // // This shouldn't happen...
|
Chris@49
|
757 // iterator_base::pos--;
|
Chris@49
|
758 // return *this;
|
Chris@49
|
759 // }
|
Chris@49
|
760
|
Chris@49
|
761 iterator_base::internal_pos--;
|
Chris@49
|
762
|
Chris@49
|
763 // We have to search backwards.
|
Chris@49
|
764 uword cur_col = iterator_base::internal_col;
|
Chris@49
|
765 uword cur_row = internal_row;
|
Chris@49
|
766
|
Chris@49
|
767 const uword aux_col = iterator_base::M.aux_col1;
|
Chris@49
|
768 const uword aux_row = iterator_base::M.aux_row1;
|
Chris@49
|
769 const uword ln_cols = iterator_base::M.n_cols;
|
Chris@49
|
770
|
Chris@49
|
771 while(true)
|
Chris@49
|
772 {
|
Chris@49
|
773 // Decrement the current column and see if we are on a new row.
|
Chris@49
|
774 if(--cur_col > ln_cols)
|
Chris@49
|
775 {
|
Chris@49
|
776 cur_col = ln_cols - 1;
|
Chris@49
|
777 cur_row--;
|
Chris@49
|
778 }
|
Chris@49
|
779
|
Chris@49
|
780 // Is there anything in this new column?
|
Chris@49
|
781 const uword colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col];
|
Chris@49
|
782 const uword next_colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col + 1];
|
Chris@49
|
783
|
Chris@49
|
784 for(uword ind = colptr; (ind < next_colptr) && (iterator_base::M.m.row_indices[ind] <= (cur_row + aux_row)); ++ind)
|
Chris@49
|
785 {
|
Chris@49
|
786 const uword row_index = iterator_base::M.m.row_indices[ind];
|
Chris@49
|
787
|
Chris@49
|
788 if((row_index - aux_row) == cur_row)
|
Chris@49
|
789 {
|
Chris@49
|
790 iterator_base::internal_col = cur_col;
|
Chris@49
|
791 internal_row = cur_row;
|
Chris@49
|
792 actual_pos = ind;
|
Chris@49
|
793
|
Chris@49
|
794 return *this;
|
Chris@49
|
795 }
|
Chris@49
|
796 }
|
Chris@49
|
797 }
|
Chris@49
|
798 }
|
Chris@49
|
799
|
Chris@49
|
800
|
Chris@49
|
801
|
Chris@49
|
802 template<typename eT>
|
Chris@49
|
803 inline
|
Chris@49
|
804 typename SpSubview<eT>::const_row_iterator
|
Chris@49
|
805 SpSubview<eT>::const_row_iterator::operator--(int)
|
Chris@49
|
806 {
|
Chris@49
|
807 typename SpSubview<eT>::const_row_iterator tmp(*this);
|
Chris@49
|
808
|
Chris@49
|
809 --(*this);
|
Chris@49
|
810
|
Chris@49
|
811 return tmp;
|
Chris@49
|
812 }
|
Chris@49
|
813
|
Chris@49
|
814
|
Chris@49
|
815
|
Chris@49
|
816 template<typename eT>
|
Chris@49
|
817 inline
|
Chris@49
|
818 bool
|
Chris@49
|
819 SpSubview<eT>::const_row_iterator::operator==(const const_iterator& rhs) const
|
Chris@49
|
820 {
|
Chris@49
|
821 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
822 }
|
Chris@49
|
823
|
Chris@49
|
824
|
Chris@49
|
825
|
Chris@49
|
826 template<typename eT>
|
Chris@49
|
827 inline
|
Chris@49
|
828 bool
|
Chris@49
|
829 SpSubview<eT>::const_row_iterator::operator!=(const const_iterator& rhs) const
|
Chris@49
|
830 {
|
Chris@49
|
831 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
832 }
|
Chris@49
|
833
|
Chris@49
|
834
|
Chris@49
|
835
|
Chris@49
|
836 template<typename eT>
|
Chris@49
|
837 inline
|
Chris@49
|
838 bool
|
Chris@49
|
839 SpSubview<eT>::const_row_iterator::operator==(const typename SpMat<eT>::const_iterator& rhs) const
|
Chris@49
|
840 {
|
Chris@49
|
841 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
842 }
|
Chris@49
|
843
|
Chris@49
|
844
|
Chris@49
|
845
|
Chris@49
|
846 template<typename eT>
|
Chris@49
|
847 inline
|
Chris@49
|
848 bool
|
Chris@49
|
849 SpSubview<eT>::const_row_iterator::operator!=(const typename SpMat<eT>::const_iterator& rhs) const
|
Chris@49
|
850 {
|
Chris@49
|
851 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
852 }
|
Chris@49
|
853
|
Chris@49
|
854
|
Chris@49
|
855
|
Chris@49
|
856 template<typename eT>
|
Chris@49
|
857 inline
|
Chris@49
|
858 bool
|
Chris@49
|
859 SpSubview<eT>::const_row_iterator::operator==(const const_row_iterator& rhs) const
|
Chris@49
|
860 {
|
Chris@49
|
861 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
862 }
|
Chris@49
|
863
|
Chris@49
|
864
|
Chris@49
|
865
|
Chris@49
|
866 template<typename eT>
|
Chris@49
|
867 inline
|
Chris@49
|
868 bool
|
Chris@49
|
869 SpSubview<eT>::const_row_iterator::operator!=(const const_row_iterator& rhs) const
|
Chris@49
|
870 {
|
Chris@49
|
871 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
872 }
|
Chris@49
|
873
|
Chris@49
|
874
|
Chris@49
|
875
|
Chris@49
|
876 template<typename eT>
|
Chris@49
|
877 inline
|
Chris@49
|
878 bool
|
Chris@49
|
879 SpSubview<eT>::const_row_iterator::operator==(const typename SpMat<eT>::const_row_iterator& rhs) const
|
Chris@49
|
880 {
|
Chris@49
|
881 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
882 }
|
Chris@49
|
883
|
Chris@49
|
884
|
Chris@49
|
885
|
Chris@49
|
886 template<typename eT>
|
Chris@49
|
887 inline
|
Chris@49
|
888 bool
|
Chris@49
|
889 SpSubview<eT>::const_row_iterator::operator!=(const typename SpMat<eT>::const_row_iterator& rhs) const
|
Chris@49
|
890 {
|
Chris@49
|
891 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
892 }
|
Chris@49
|
893
|
Chris@49
|
894
|
Chris@49
|
895
|
Chris@49
|
896 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
897 // SpSubview<eT>::row_iterator implementation //
|
Chris@49
|
898 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
899
|
Chris@49
|
900 template<typename eT>
|
Chris@49
|
901 inline
|
Chris@49
|
902 SpValProxy<SpSubview<eT> >
|
Chris@49
|
903 SpSubview<eT>::row_iterator::operator*()
|
Chris@49
|
904 {
|
Chris@49
|
905 return SpValProxy<SpSubview<eT> >(
|
Chris@49
|
906 const_row_iterator::internal_row,
|
Chris@49
|
907 iterator_base::internal_col,
|
Chris@49
|
908 access::rw(iterator_base::M),
|
Chris@49
|
909 &access::rw(iterator_base::M.m.values[const_row_iterator::actual_pos]));
|
Chris@49
|
910 }
|
Chris@49
|
911
|
Chris@49
|
912
|
Chris@49
|
913
|
Chris@49
|
914 template<typename eT>
|
Chris@49
|
915 inline
|
Chris@49
|
916 typename SpSubview<eT>::row_iterator&
|
Chris@49
|
917 SpSubview<eT>::row_iterator::operator++()
|
Chris@49
|
918 {
|
Chris@49
|
919 const_row_iterator::operator++();
|
Chris@49
|
920 return *this;
|
Chris@49
|
921 }
|
Chris@49
|
922
|
Chris@49
|
923
|
Chris@49
|
924
|
Chris@49
|
925 template<typename eT>
|
Chris@49
|
926 inline
|
Chris@49
|
927 typename SpSubview<eT>::row_iterator
|
Chris@49
|
928 SpSubview<eT>::row_iterator::operator++(int)
|
Chris@49
|
929 {
|
Chris@49
|
930 typename SpSubview<eT>::row_iterator tmp(*this);
|
Chris@49
|
931
|
Chris@49
|
932 ++(*this);
|
Chris@49
|
933
|
Chris@49
|
934 return tmp;
|
Chris@49
|
935 }
|
Chris@49
|
936
|
Chris@49
|
937
|
Chris@49
|
938
|
Chris@49
|
939 template<typename eT>
|
Chris@49
|
940 inline
|
Chris@49
|
941 typename SpSubview<eT>::row_iterator&
|
Chris@49
|
942 SpSubview<eT>::row_iterator::operator--()
|
Chris@49
|
943 {
|
Chris@49
|
944 const_row_iterator::operator--();
|
Chris@49
|
945 return *this;
|
Chris@49
|
946 }
|
Chris@49
|
947
|
Chris@49
|
948
|
Chris@49
|
949
|
Chris@49
|
950 template<typename eT>
|
Chris@49
|
951 inline
|
Chris@49
|
952 typename SpSubview<eT>::row_iterator
|
Chris@49
|
953 SpSubview<eT>::row_iterator::operator--(int)
|
Chris@49
|
954 {
|
Chris@49
|
955 typename SpSubview<eT>::row_iterator tmp(*this);
|
Chris@49
|
956
|
Chris@49
|
957 --(*this);
|
Chris@49
|
958
|
Chris@49
|
959 return tmp;
|
Chris@49
|
960 }
|
Chris@49
|
961
|
Chris@49
|
962 //! @}
|