Chris@49
|
1 // Copyright (C) 2011-2012 Ryan Curtin
|
Chris@49
|
2 // Copyright (C) 2011 Matthew Amidon
|
Chris@49
|
3 // Copyright (C) 2012 Conrad Sanderson
|
Chris@49
|
4 //
|
Chris@49
|
5 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
8
|
Chris@49
|
9 //! \addtogroup SpMat
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
13 // SpMat::iterator_base implementation //
|
Chris@49
|
14 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
15
|
Chris@49
|
16 template<typename eT>
|
Chris@49
|
17 inline
|
Chris@49
|
18 SpMat<eT>::iterator_base::iterator_base(const SpMat<eT>& in_M)
|
Chris@49
|
19 : M(in_M)
|
Chris@49
|
20 , internal_col(0)
|
Chris@49
|
21 , internal_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 SpMat<eT>::iterator_base::iterator_base(const SpMat<eT>& in_M, const uword in_col, const uword in_pos)
|
Chris@49
|
31 : M(in_M)
|
Chris@49
|
32 , internal_col(in_col)
|
Chris@49
|
33 , internal_pos(in_pos)
|
Chris@49
|
34 {
|
Chris@49
|
35 // Nothing to do.
|
Chris@49
|
36 }
|
Chris@49
|
37
|
Chris@49
|
38
|
Chris@49
|
39
|
Chris@49
|
40 template<typename eT>
|
Chris@49
|
41 inline
|
Chris@49
|
42 arma_hot
|
Chris@49
|
43 eT
|
Chris@49
|
44 SpMat<eT>::iterator_base::operator*() const
|
Chris@49
|
45 {
|
Chris@49
|
46 return M.values[internal_pos];
|
Chris@49
|
47 }
|
Chris@49
|
48
|
Chris@49
|
49
|
Chris@49
|
50
|
Chris@49
|
51 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
52 // SpMat::const_iterator implementation //
|
Chris@49
|
53 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
54
|
Chris@49
|
55 template<typename eT>
|
Chris@49
|
56 inline
|
Chris@49
|
57 SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, uword initial_pos)
|
Chris@49
|
58 : iterator_base(in_M, 0, initial_pos)
|
Chris@49
|
59 {
|
Chris@49
|
60 // Corner case for empty matrices.
|
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 return;
|
Chris@49
|
65 }
|
Chris@49
|
66
|
Chris@49
|
67 // Determine which column we should be in.
|
Chris@49
|
68 while(iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= iterator_base::internal_pos)
|
Chris@49
|
69 {
|
Chris@49
|
70 iterator_base::internal_col++;
|
Chris@49
|
71 }
|
Chris@49
|
72 }
|
Chris@49
|
73
|
Chris@49
|
74
|
Chris@49
|
75
|
Chris@49
|
76 template<typename eT>
|
Chris@49
|
77 inline
|
Chris@49
|
78 SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, uword in_row, uword in_col)
|
Chris@49
|
79 : iterator_base(in_M, in_col, 0)
|
Chris@49
|
80 {
|
Chris@49
|
81 // So we have a position we want to be right after. Skip to the column.
|
Chris@49
|
82 iterator_base::internal_pos = iterator_base::M.col_ptrs[iterator_base::internal_col];
|
Chris@49
|
83
|
Chris@49
|
84 // Now we have to make sure that is the right column.
|
Chris@49
|
85 while(iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= iterator_base::internal_pos)
|
Chris@49
|
86 {
|
Chris@49
|
87 iterator_base::internal_col++;
|
Chris@49
|
88 }
|
Chris@49
|
89
|
Chris@49
|
90 // Now we have to get to the right row.
|
Chris@49
|
91 while((iterator_base::M.row_indices[iterator_base::internal_pos] < in_row) && (iterator_base::internal_col == in_col))
|
Chris@49
|
92 {
|
Chris@49
|
93 ++(*this); // Increment iterator.
|
Chris@49
|
94 }
|
Chris@49
|
95 }
|
Chris@49
|
96
|
Chris@49
|
97
|
Chris@49
|
98
|
Chris@49
|
99 template<typename eT>
|
Chris@49
|
100 inline
|
Chris@49
|
101 SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, const uword /* in_row */, const uword in_col, const uword in_pos)
|
Chris@49
|
102 : iterator_base(in_M, in_col, in_pos)
|
Chris@49
|
103 {
|
Chris@49
|
104 // Nothing to do.
|
Chris@49
|
105 }
|
Chris@49
|
106
|
Chris@49
|
107
|
Chris@49
|
108
|
Chris@49
|
109 template<typename eT>
|
Chris@49
|
110 inline
|
Chris@49
|
111 SpMat<eT>::const_iterator::const_iterator(const typename SpMat<eT>::const_iterator& other)
|
Chris@49
|
112 : iterator_base(other.M, other.internal_col, other.internal_pos)
|
Chris@49
|
113 {
|
Chris@49
|
114 // Nothing to do.
|
Chris@49
|
115 }
|
Chris@49
|
116
|
Chris@49
|
117
|
Chris@49
|
118
|
Chris@49
|
119 template<typename eT>
|
Chris@49
|
120 inline
|
Chris@49
|
121 arma_hot
|
Chris@49
|
122 typename SpMat<eT>::const_iterator&
|
Chris@49
|
123 SpMat<eT>::const_iterator::operator++()
|
Chris@49
|
124 {
|
Chris@49
|
125 ++iterator_base::internal_pos;
|
Chris@49
|
126
|
Chris@49
|
127 if (iterator_base::internal_pos == iterator_base::M.n_nonzero)
|
Chris@49
|
128 {
|
Chris@49
|
129 iterator_base::internal_col = iterator_base::M.n_cols;
|
Chris@49
|
130 return *this;
|
Chris@49
|
131 }
|
Chris@49
|
132
|
Chris@49
|
133 // Check to see if we moved a column.
|
Chris@49
|
134 while (iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= iterator_base::internal_pos)
|
Chris@49
|
135 {
|
Chris@49
|
136 ++iterator_base::internal_col;
|
Chris@49
|
137 }
|
Chris@49
|
138
|
Chris@49
|
139 return *this;
|
Chris@49
|
140 }
|
Chris@49
|
141
|
Chris@49
|
142
|
Chris@49
|
143
|
Chris@49
|
144 template<typename eT>
|
Chris@49
|
145 inline
|
Chris@49
|
146 arma_hot
|
Chris@49
|
147 typename SpMat<eT>::const_iterator
|
Chris@49
|
148 SpMat<eT>::const_iterator::operator++(int)
|
Chris@49
|
149 {
|
Chris@49
|
150 typename SpMat<eT>::const_iterator tmp(*this);
|
Chris@49
|
151
|
Chris@49
|
152 ++(*this);
|
Chris@49
|
153
|
Chris@49
|
154 return tmp;
|
Chris@49
|
155 }
|
Chris@49
|
156
|
Chris@49
|
157
|
Chris@49
|
158
|
Chris@49
|
159 template<typename eT>
|
Chris@49
|
160 inline
|
Chris@49
|
161 arma_hot
|
Chris@49
|
162 typename SpMat<eT>::const_iterator&
|
Chris@49
|
163 SpMat<eT>::const_iterator::operator--()
|
Chris@49
|
164 {
|
Chris@49
|
165 //iterator_base::M.print("M");
|
Chris@49
|
166
|
Chris@49
|
167 // printf("decrement from %d, %d, %d\n", iterator_base::internal_pos, iterator_base::internal_col, iterator_base::row());
|
Chris@49
|
168
|
Chris@49
|
169 --iterator_base::internal_pos;
|
Chris@49
|
170
|
Chris@49
|
171 // printf("now pos %d\n", iterator_base::internal_pos);
|
Chris@49
|
172
|
Chris@49
|
173 // First, see if we moved back a column.
|
Chris@49
|
174 while (iterator_base::internal_pos < iterator_base::M.col_ptrs[iterator_base::internal_col])
|
Chris@49
|
175 {
|
Chris@49
|
176 // printf("colptr %d (col %d)\n", iterator_base::M.col_ptrs[iterator_base::internal_col], iterator_base::internal_col);
|
Chris@49
|
177
|
Chris@49
|
178 --iterator_base::internal_col;
|
Chris@49
|
179 }
|
Chris@49
|
180
|
Chris@49
|
181
|
Chris@49
|
182 return *this;
|
Chris@49
|
183 }
|
Chris@49
|
184
|
Chris@49
|
185
|
Chris@49
|
186
|
Chris@49
|
187 template<typename eT>
|
Chris@49
|
188 inline
|
Chris@49
|
189 arma_hot
|
Chris@49
|
190 typename SpMat<eT>::const_iterator
|
Chris@49
|
191 SpMat<eT>::const_iterator::operator--(int)
|
Chris@49
|
192 {
|
Chris@49
|
193 typename SpMat<eT>::const_iterator tmp(*this);
|
Chris@49
|
194
|
Chris@49
|
195 --(*this);
|
Chris@49
|
196
|
Chris@49
|
197 return tmp;
|
Chris@49
|
198 }
|
Chris@49
|
199
|
Chris@49
|
200
|
Chris@49
|
201
|
Chris@49
|
202 template<typename eT>
|
Chris@49
|
203 inline
|
Chris@49
|
204 arma_hot
|
Chris@49
|
205 bool
|
Chris@49
|
206 SpMat<eT>::const_iterator::operator==(const const_iterator& rhs) const
|
Chris@49
|
207 {
|
Chris@49
|
208 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
209 }
|
Chris@49
|
210
|
Chris@49
|
211
|
Chris@49
|
212
|
Chris@49
|
213 template<typename eT>
|
Chris@49
|
214 inline
|
Chris@49
|
215 arma_hot
|
Chris@49
|
216 bool
|
Chris@49
|
217 SpMat<eT>::const_iterator::operator!=(const const_iterator& rhs) const
|
Chris@49
|
218 {
|
Chris@49
|
219 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
220 }
|
Chris@49
|
221
|
Chris@49
|
222
|
Chris@49
|
223
|
Chris@49
|
224 template<typename eT>
|
Chris@49
|
225 inline
|
Chris@49
|
226 arma_hot
|
Chris@49
|
227 bool
|
Chris@49
|
228 SpMat<eT>::const_iterator::operator==(const typename SpSubview<eT>::const_iterator& rhs) const
|
Chris@49
|
229 {
|
Chris@49
|
230 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
231 }
|
Chris@49
|
232
|
Chris@49
|
233
|
Chris@49
|
234
|
Chris@49
|
235 template<typename eT>
|
Chris@49
|
236 inline
|
Chris@49
|
237 arma_hot
|
Chris@49
|
238 bool
|
Chris@49
|
239 SpMat<eT>::const_iterator::operator!=(const typename SpSubview<eT>::const_iterator& rhs) const
|
Chris@49
|
240 {
|
Chris@49
|
241 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
242 }
|
Chris@49
|
243
|
Chris@49
|
244
|
Chris@49
|
245
|
Chris@49
|
246 template<typename eT>
|
Chris@49
|
247 inline
|
Chris@49
|
248 arma_hot
|
Chris@49
|
249 bool
|
Chris@49
|
250 SpMat<eT>::const_iterator::operator==(const const_row_iterator& rhs) const
|
Chris@49
|
251 {
|
Chris@49
|
252 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
253 }
|
Chris@49
|
254
|
Chris@49
|
255
|
Chris@49
|
256
|
Chris@49
|
257 template<typename eT>
|
Chris@49
|
258 inline
|
Chris@49
|
259 arma_hot
|
Chris@49
|
260 bool
|
Chris@49
|
261 SpMat<eT>::const_iterator::operator!=(const const_row_iterator& rhs) const
|
Chris@49
|
262 {
|
Chris@49
|
263 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
264 }
|
Chris@49
|
265
|
Chris@49
|
266
|
Chris@49
|
267
|
Chris@49
|
268 template<typename eT>
|
Chris@49
|
269 inline
|
Chris@49
|
270 arma_hot
|
Chris@49
|
271 bool
|
Chris@49
|
272 SpMat<eT>::const_iterator::operator==(const typename SpSubview<eT>::const_row_iterator& rhs) const
|
Chris@49
|
273 {
|
Chris@49
|
274 return (rhs.row() == (*this).row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
275 }
|
Chris@49
|
276
|
Chris@49
|
277
|
Chris@49
|
278
|
Chris@49
|
279 template<typename eT>
|
Chris@49
|
280 inline
|
Chris@49
|
281 arma_hot
|
Chris@49
|
282 bool
|
Chris@49
|
283 SpMat<eT>::const_iterator::operator!=(const typename SpSubview<eT>::const_row_iterator& rhs) const
|
Chris@49
|
284 {
|
Chris@49
|
285 return (rhs.row() != (*this).row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
286 }
|
Chris@49
|
287
|
Chris@49
|
288
|
Chris@49
|
289
|
Chris@49
|
290 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
291 // SpMat::iterator implementation //
|
Chris@49
|
292 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
293
|
Chris@49
|
294 template<typename eT>
|
Chris@49
|
295 inline
|
Chris@49
|
296 arma_hot
|
Chris@49
|
297 SpValProxy<SpMat<eT> >
|
Chris@49
|
298 SpMat<eT>::iterator::operator*()
|
Chris@49
|
299 {
|
Chris@49
|
300 return SpValProxy<SpMat<eT> >(
|
Chris@49
|
301 iterator_base::M.row_indices[iterator_base::internal_pos],
|
Chris@49
|
302 iterator_base::internal_col,
|
Chris@49
|
303 access::rw(iterator_base::M),
|
Chris@49
|
304 &access::rw(iterator_base::M.values[iterator_base::internal_pos]));
|
Chris@49
|
305 }
|
Chris@49
|
306
|
Chris@49
|
307
|
Chris@49
|
308
|
Chris@49
|
309 template<typename eT>
|
Chris@49
|
310 inline
|
Chris@49
|
311 arma_hot
|
Chris@49
|
312 typename SpMat<eT>::iterator&
|
Chris@49
|
313 SpMat<eT>::iterator::operator++()
|
Chris@49
|
314 {
|
Chris@49
|
315 const_iterator::operator++();
|
Chris@49
|
316 return *this;
|
Chris@49
|
317 }
|
Chris@49
|
318
|
Chris@49
|
319
|
Chris@49
|
320
|
Chris@49
|
321 template<typename eT>
|
Chris@49
|
322 inline
|
Chris@49
|
323 arma_hot
|
Chris@49
|
324 typename SpMat<eT>::iterator
|
Chris@49
|
325 SpMat<eT>::iterator::operator++(int)
|
Chris@49
|
326 {
|
Chris@49
|
327 typename SpMat<eT>::iterator tmp(*this);
|
Chris@49
|
328
|
Chris@49
|
329 const_iterator::operator++();
|
Chris@49
|
330
|
Chris@49
|
331 return tmp;
|
Chris@49
|
332 }
|
Chris@49
|
333
|
Chris@49
|
334
|
Chris@49
|
335
|
Chris@49
|
336 template<typename eT>
|
Chris@49
|
337 inline
|
Chris@49
|
338 arma_hot
|
Chris@49
|
339 typename SpMat<eT>::iterator&
|
Chris@49
|
340 SpMat<eT>::iterator::operator--()
|
Chris@49
|
341 {
|
Chris@49
|
342 const_iterator::operator--();
|
Chris@49
|
343 return *this;
|
Chris@49
|
344 }
|
Chris@49
|
345
|
Chris@49
|
346
|
Chris@49
|
347
|
Chris@49
|
348 template<typename eT>
|
Chris@49
|
349 inline
|
Chris@49
|
350 arma_hot
|
Chris@49
|
351 typename SpMat<eT>::iterator
|
Chris@49
|
352 SpMat<eT>::iterator::operator--(int)
|
Chris@49
|
353 {
|
Chris@49
|
354 typename SpMat<eT>::iterator tmp(*this);
|
Chris@49
|
355
|
Chris@49
|
356 const_iterator::operator--();
|
Chris@49
|
357
|
Chris@49
|
358 return tmp;
|
Chris@49
|
359 }
|
Chris@49
|
360
|
Chris@49
|
361
|
Chris@49
|
362
|
Chris@49
|
363 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
364 // SpMat::const_row_iterator implementation //
|
Chris@49
|
365 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
366
|
Chris@49
|
367 /**
|
Chris@49
|
368 * Initialize the const_row_iterator.
|
Chris@49
|
369 */
|
Chris@49
|
370 template<typename eT>
|
Chris@49
|
371 inline
|
Chris@49
|
372 SpMat<eT>::const_row_iterator::const_row_iterator(const SpMat<eT>& in_M, uword initial_pos)
|
Chris@49
|
373 : iterator_base(in_M, 0, initial_pos)
|
Chris@49
|
374 , internal_row(0)
|
Chris@49
|
375 , actual_pos(0)
|
Chris@49
|
376 {
|
Chris@49
|
377 // Corner case for empty matrix.
|
Chris@49
|
378 if(in_M.n_nonzero == 0)
|
Chris@49
|
379 {
|
Chris@49
|
380 iterator_base::internal_col = 0;
|
Chris@49
|
381 internal_row = in_M.n_rows;
|
Chris@49
|
382 return;
|
Chris@49
|
383 }
|
Chris@49
|
384
|
Chris@49
|
385 // We don't count zeroes in our position count, so we have to find the nonzero
|
Chris@49
|
386 // value corresponding to the given initial position. We assume initial_pos
|
Chris@49
|
387 // is valid.
|
Chris@49
|
388
|
Chris@49
|
389 // This is irritating because we don't know where the elements are in each
|
Chris@49
|
390 // row. What we will do is loop across all columns looking for elements in
|
Chris@49
|
391 // row 0 (and add to our sum), then in row 1, and so forth, until we get to
|
Chris@49
|
392 // the desired position.
|
Chris@49
|
393 uword cur_pos = -1;
|
Chris@49
|
394 uword cur_row = 0;
|
Chris@49
|
395 uword cur_col = 0;
|
Chris@49
|
396
|
Chris@49
|
397 while(true) // This loop is terminated from the inside.
|
Chris@49
|
398 {
|
Chris@49
|
399 // Is there anything in the column we are looking at?
|
Chris@49
|
400 for (uword ind = 0; ((iterator_base::M.col_ptrs[cur_col] + ind < iterator_base::M.col_ptrs[cur_col + 1]) && (iterator_base::M.row_indices[iterator_base::M.col_ptrs[cur_col] + ind] <= cur_row)); ind++)
|
Chris@49
|
401 {
|
Chris@49
|
402 // There is something in this column. Is it in the row we are looking at?
|
Chris@49
|
403 const uword row_index = iterator_base::M.row_indices[iterator_base::M.col_ptrs[cur_col] + ind];
|
Chris@49
|
404 if (row_index == cur_row)
|
Chris@49
|
405 {
|
Chris@49
|
406 // Yes, it is what we are looking for. Increment our current position.
|
Chris@49
|
407 if (++cur_pos == iterator_base::internal_pos)
|
Chris@49
|
408 {
|
Chris@49
|
409 actual_pos = iterator_base::M.col_ptrs[cur_col] + ind;
|
Chris@49
|
410 internal_row = cur_row;
|
Chris@49
|
411 iterator_base::internal_col = cur_col;
|
Chris@49
|
412
|
Chris@49
|
413 return;
|
Chris@49
|
414 }
|
Chris@49
|
415
|
Chris@49
|
416 // We are done with this column. Break to the column incrementing code (directly below).
|
Chris@49
|
417 break;
|
Chris@49
|
418 }
|
Chris@49
|
419 else if(row_index > cur_row)
|
Chris@49
|
420 {
|
Chris@49
|
421 break; // Can't be in this column.
|
Chris@49
|
422 }
|
Chris@49
|
423 }
|
Chris@49
|
424
|
Chris@49
|
425 cur_col++; // Done with the column. Move on.
|
Chris@49
|
426 if (cur_col == iterator_base::M.n_cols)
|
Chris@49
|
427 {
|
Chris@49
|
428 // We are out of columns. Loop back to the beginning and look on the
|
Chris@49
|
429 // next row.
|
Chris@49
|
430 cur_col = 0;
|
Chris@49
|
431 cur_row++;
|
Chris@49
|
432 }
|
Chris@49
|
433 }
|
Chris@49
|
434 }
|
Chris@49
|
435
|
Chris@49
|
436
|
Chris@49
|
437
|
Chris@49
|
438 template<typename eT>
|
Chris@49
|
439 inline
|
Chris@49
|
440 SpMat<eT>::const_row_iterator::const_row_iterator(const SpMat<eT>& in_M, uword in_row, uword in_col)
|
Chris@49
|
441 : iterator_base(in_M, in_col, 0)
|
Chris@49
|
442 , internal_row(0)
|
Chris@49
|
443 , actual_pos(0)
|
Chris@49
|
444 {
|
Chris@49
|
445 // This is slow. It needs to be rewritten.
|
Chris@49
|
446 // So we have a destination we want to be just after, but don't know what position that is. Make another iterator to find out...
|
Chris@49
|
447 const_row_iterator it(in_M, 0);
|
Chris@49
|
448 while((it.row() < in_row) || ((it.row() == in_row) && (it.col() < in_col)))
|
Chris@49
|
449 {
|
Chris@49
|
450 it++;
|
Chris@49
|
451 }
|
Chris@49
|
452
|
Chris@49
|
453 // Now that it is at the right place, take its position.
|
Chris@49
|
454 iterator_base::internal_col = it.internal_col;
|
Chris@49
|
455 iterator_base::internal_pos = it.internal_pos;
|
Chris@49
|
456 internal_row = it.internal_row;
|
Chris@49
|
457 actual_pos = it.actual_pos;
|
Chris@49
|
458 }
|
Chris@49
|
459
|
Chris@49
|
460
|
Chris@49
|
461
|
Chris@49
|
462 /**
|
Chris@49
|
463 * Initialize the const_row_iterator from another const_row_iterator.
|
Chris@49
|
464 */
|
Chris@49
|
465 template<typename eT>
|
Chris@49
|
466 inline
|
Chris@49
|
467 SpMat<eT>::const_row_iterator::const_row_iterator(const typename SpMat<eT>::const_row_iterator& other)
|
Chris@49
|
468 : iterator_base(other.M, other.internal_col, other.internal_pos)
|
Chris@49
|
469 , internal_row(other.internal_row)
|
Chris@49
|
470 , actual_pos(other.actual_pos)
|
Chris@49
|
471 {
|
Chris@49
|
472 // Nothing to do.
|
Chris@49
|
473 }
|
Chris@49
|
474
|
Chris@49
|
475
|
Chris@49
|
476
|
Chris@49
|
477 /**
|
Chris@49
|
478 * Increment the row_iterator.
|
Chris@49
|
479 */
|
Chris@49
|
480 template<typename eT>
|
Chris@49
|
481 inline
|
Chris@49
|
482 arma_hot
|
Chris@49
|
483 typename SpMat<eT>::const_row_iterator&
|
Chris@49
|
484 SpMat<eT>::const_row_iterator::operator++()
|
Chris@49
|
485 {
|
Chris@49
|
486 // We just need to find the next nonzero element.
|
Chris@49
|
487 iterator_base::internal_pos++;
|
Chris@49
|
488
|
Chris@49
|
489 if(iterator_base::internal_pos == iterator_base::M.n_nonzero)
|
Chris@49
|
490 {
|
Chris@49
|
491 internal_row = iterator_base::M.n_rows;
|
Chris@49
|
492 iterator_base::internal_col = 0;
|
Chris@49
|
493 actual_pos = iterator_base::M.n_nonzero;
|
Chris@49
|
494
|
Chris@49
|
495 return *this;
|
Chris@49
|
496 }
|
Chris@49
|
497
|
Chris@49
|
498 // Otherwise, we need to search.
|
Chris@49
|
499 uword cur_col = iterator_base::internal_col;
|
Chris@49
|
500 uword cur_row = internal_row;
|
Chris@49
|
501
|
Chris@49
|
502 while (true) // This loop is terminated from the inside.
|
Chris@49
|
503 {
|
Chris@49
|
504 // Increment the current column and see if we are now on a new row.
|
Chris@49
|
505 if (++cur_col == iterator_base::M.n_cols)
|
Chris@49
|
506 {
|
Chris@49
|
507 cur_col = 0;
|
Chris@49
|
508 cur_row++;
|
Chris@49
|
509 }
|
Chris@49
|
510
|
Chris@49
|
511 // Is there anything in this new column?
|
Chris@49
|
512 for (uword ind = 0; ((iterator_base::M.col_ptrs[cur_col] + ind < iterator_base::M.col_ptrs[cur_col + 1]) && (iterator_base::M.row_indices[iterator_base::M.col_ptrs[cur_col] + ind] <= cur_row)); ind++)
|
Chris@49
|
513 {
|
Chris@49
|
514 if (iterator_base::M.row_indices[iterator_base::M.col_ptrs[cur_col] + ind] == cur_row)
|
Chris@49
|
515 {
|
Chris@49
|
516 // We have successfully incremented.
|
Chris@49
|
517 internal_row = cur_row;
|
Chris@49
|
518 iterator_base::internal_col = cur_col;
|
Chris@49
|
519 actual_pos = iterator_base::M.col_ptrs[cur_col] + ind;
|
Chris@49
|
520
|
Chris@49
|
521 return *this; // Now we are done.
|
Chris@49
|
522 }
|
Chris@49
|
523 }
|
Chris@49
|
524 }
|
Chris@49
|
525 }
|
Chris@49
|
526
|
Chris@49
|
527
|
Chris@49
|
528
|
Chris@49
|
529 /**
|
Chris@49
|
530 * Increment the row_iterator (but do not return anything.
|
Chris@49
|
531 */
|
Chris@49
|
532 template<typename eT>
|
Chris@49
|
533 inline
|
Chris@49
|
534 arma_hot
|
Chris@49
|
535 typename SpMat<eT>::const_row_iterator
|
Chris@49
|
536 SpMat<eT>::const_row_iterator::operator++(int)
|
Chris@49
|
537 {
|
Chris@49
|
538 typename SpMat<eT>::const_row_iterator tmp(*this);
|
Chris@49
|
539
|
Chris@49
|
540 ++(*this);
|
Chris@49
|
541
|
Chris@49
|
542 return tmp;
|
Chris@49
|
543 }
|
Chris@49
|
544
|
Chris@49
|
545
|
Chris@49
|
546
|
Chris@49
|
547 /**
|
Chris@49
|
548 * Decrement the row_iterator.
|
Chris@49
|
549 */
|
Chris@49
|
550 template<typename eT>
|
Chris@49
|
551 inline
|
Chris@49
|
552 arma_hot
|
Chris@49
|
553 typename SpMat<eT>::const_row_iterator&
|
Chris@49
|
554 SpMat<eT>::const_row_iterator::operator--()
|
Chris@49
|
555 {
|
Chris@49
|
556 iterator_base::internal_pos--;
|
Chris@49
|
557
|
Chris@49
|
558 // We have to search backwards.
|
Chris@49
|
559 uword cur_col = iterator_base::internal_col;
|
Chris@49
|
560 uword cur_row = internal_row;
|
Chris@49
|
561
|
Chris@49
|
562 while (true) // This loop is terminated from the inside.
|
Chris@49
|
563 {
|
Chris@49
|
564 // Decrement the current column and see if we are now on a new row. This is a uword so a negativity check won't work.
|
Chris@49
|
565 if (--cur_col > iterator_base::M.n_cols /* this means it underflew */)
|
Chris@49
|
566 {
|
Chris@49
|
567 cur_col = iterator_base::M.n_cols - 1;
|
Chris@49
|
568 cur_row--;
|
Chris@49
|
569 }
|
Chris@49
|
570
|
Chris@49
|
571 // Is there anything in this new column?
|
Chris@49
|
572 for (uword ind = 0; ((iterator_base::M.col_ptrs[cur_col] + ind < iterator_base::M.col_ptrs[cur_col + 1]) && (iterator_base::M.row_indices[iterator_base::M.col_ptrs[cur_col] + ind] <= cur_row)); ind++)
|
Chris@49
|
573 {
|
Chris@49
|
574 if (iterator_base::M.row_indices[iterator_base::M.col_ptrs[cur_col] + ind] == cur_row)
|
Chris@49
|
575 {
|
Chris@49
|
576 // We have successfully decremented.
|
Chris@49
|
577 iterator_base::internal_col = cur_col;
|
Chris@49
|
578 internal_row = cur_row;
|
Chris@49
|
579 actual_pos = iterator_base::M.col_ptrs[cur_col] + ind;
|
Chris@49
|
580
|
Chris@49
|
581 return *this; // Now we are done.
|
Chris@49
|
582 }
|
Chris@49
|
583 }
|
Chris@49
|
584 }
|
Chris@49
|
585 }
|
Chris@49
|
586
|
Chris@49
|
587
|
Chris@49
|
588
|
Chris@49
|
589 /**
|
Chris@49
|
590 * Decrement the row_iterator.
|
Chris@49
|
591 */
|
Chris@49
|
592 template<typename eT>
|
Chris@49
|
593 inline
|
Chris@49
|
594 arma_hot
|
Chris@49
|
595 typename SpMat<eT>::const_row_iterator
|
Chris@49
|
596 SpMat<eT>::const_row_iterator::operator--(int)
|
Chris@49
|
597 {
|
Chris@49
|
598 typename SpMat<eT>::const_row_iterator tmp(*this);
|
Chris@49
|
599
|
Chris@49
|
600 --(*this);
|
Chris@49
|
601
|
Chris@49
|
602 return tmp;
|
Chris@49
|
603 }
|
Chris@49
|
604
|
Chris@49
|
605
|
Chris@49
|
606
|
Chris@49
|
607 template<typename eT>
|
Chris@49
|
608 inline
|
Chris@49
|
609 arma_hot
|
Chris@49
|
610 bool
|
Chris@49
|
611 SpMat<eT>::const_row_iterator::operator==(const const_iterator& rhs) const
|
Chris@49
|
612 {
|
Chris@49
|
613 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
614 }
|
Chris@49
|
615
|
Chris@49
|
616
|
Chris@49
|
617
|
Chris@49
|
618 template<typename eT>
|
Chris@49
|
619 inline
|
Chris@49
|
620 arma_hot
|
Chris@49
|
621 bool
|
Chris@49
|
622 SpMat<eT>::const_row_iterator::operator!=(const const_iterator& rhs) const
|
Chris@49
|
623 {
|
Chris@49
|
624 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
625 }
|
Chris@49
|
626
|
Chris@49
|
627
|
Chris@49
|
628
|
Chris@49
|
629 template<typename eT>
|
Chris@49
|
630 inline
|
Chris@49
|
631 arma_hot
|
Chris@49
|
632 bool
|
Chris@49
|
633 SpMat<eT>::const_row_iterator::operator==(const typename SpSubview<eT>::const_iterator& rhs) const
|
Chris@49
|
634 {
|
Chris@49
|
635 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
636 }
|
Chris@49
|
637
|
Chris@49
|
638
|
Chris@49
|
639
|
Chris@49
|
640 template<typename eT>
|
Chris@49
|
641 inline
|
Chris@49
|
642 arma_hot
|
Chris@49
|
643 bool
|
Chris@49
|
644 SpMat<eT>::const_row_iterator::operator!=(const typename SpSubview<eT>::const_iterator& rhs) const
|
Chris@49
|
645 {
|
Chris@49
|
646 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
647 }
|
Chris@49
|
648
|
Chris@49
|
649
|
Chris@49
|
650
|
Chris@49
|
651 template<typename eT>
|
Chris@49
|
652 inline
|
Chris@49
|
653 arma_hot
|
Chris@49
|
654 bool
|
Chris@49
|
655 SpMat<eT>::const_row_iterator::operator==(const const_row_iterator& rhs) const
|
Chris@49
|
656 {
|
Chris@49
|
657 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
658 }
|
Chris@49
|
659
|
Chris@49
|
660
|
Chris@49
|
661
|
Chris@49
|
662 template<typename eT>
|
Chris@49
|
663 inline
|
Chris@49
|
664 arma_hot
|
Chris@49
|
665 bool
|
Chris@49
|
666 SpMat<eT>::const_row_iterator::operator!=(const const_row_iterator& rhs) const
|
Chris@49
|
667 {
|
Chris@49
|
668 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
669 }
|
Chris@49
|
670
|
Chris@49
|
671
|
Chris@49
|
672
|
Chris@49
|
673 template<typename eT>
|
Chris@49
|
674 inline
|
Chris@49
|
675 arma_hot
|
Chris@49
|
676 bool
|
Chris@49
|
677 SpMat<eT>::const_row_iterator::operator==(const typename SpSubview<eT>::const_row_iterator& rhs) const
|
Chris@49
|
678 {
|
Chris@49
|
679 return (rhs.row() == row()) && (rhs.col() == iterator_base::internal_col);
|
Chris@49
|
680 }
|
Chris@49
|
681
|
Chris@49
|
682
|
Chris@49
|
683
|
Chris@49
|
684 template<typename eT>
|
Chris@49
|
685 inline
|
Chris@49
|
686 arma_hot
|
Chris@49
|
687 bool
|
Chris@49
|
688 SpMat<eT>::const_row_iterator::operator!=(const typename SpSubview<eT>::const_row_iterator& rhs) const
|
Chris@49
|
689 {
|
Chris@49
|
690 return (rhs.row() != row()) || (rhs.col() != iterator_base::internal_col);
|
Chris@49
|
691 }
|
Chris@49
|
692
|
Chris@49
|
693
|
Chris@49
|
694
|
Chris@49
|
695 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
696 // SpMat::row_iterator implementation //
|
Chris@49
|
697 ///////////////////////////////////////////////////////////////////////////////
|
Chris@49
|
698
|
Chris@49
|
699 template<typename eT>
|
Chris@49
|
700 inline
|
Chris@49
|
701 arma_hot
|
Chris@49
|
702 SpValProxy<SpMat<eT> >
|
Chris@49
|
703 SpMat<eT>::row_iterator::operator*()
|
Chris@49
|
704 {
|
Chris@49
|
705 return SpValProxy<SpMat<eT> >(
|
Chris@49
|
706 const_row_iterator::internal_row,
|
Chris@49
|
707 iterator_base::internal_col,
|
Chris@49
|
708 access::rw(iterator_base::M),
|
Chris@49
|
709 &access::rw(iterator_base::M.values[const_row_iterator::actual_pos]));
|
Chris@49
|
710 }
|
Chris@49
|
711
|
Chris@49
|
712
|
Chris@49
|
713
|
Chris@49
|
714 template<typename eT>
|
Chris@49
|
715 inline
|
Chris@49
|
716 arma_hot
|
Chris@49
|
717 typename SpMat<eT>::row_iterator&
|
Chris@49
|
718 SpMat<eT>::row_iterator::operator++()
|
Chris@49
|
719 {
|
Chris@49
|
720 const_row_iterator::operator++();
|
Chris@49
|
721 return *this;
|
Chris@49
|
722 }
|
Chris@49
|
723
|
Chris@49
|
724
|
Chris@49
|
725
|
Chris@49
|
726 template<typename eT>
|
Chris@49
|
727 inline
|
Chris@49
|
728 arma_hot
|
Chris@49
|
729 typename SpMat<eT>::row_iterator
|
Chris@49
|
730 SpMat<eT>::row_iterator::operator++(int)
|
Chris@49
|
731 {
|
Chris@49
|
732 typename SpMat<eT>::row_iterator tmp(*this);
|
Chris@49
|
733
|
Chris@49
|
734 const_row_iterator::operator++();
|
Chris@49
|
735
|
Chris@49
|
736 return tmp;
|
Chris@49
|
737 }
|
Chris@49
|
738
|
Chris@49
|
739
|
Chris@49
|
740
|
Chris@49
|
741 template<typename eT>
|
Chris@49
|
742 inline
|
Chris@49
|
743 arma_hot
|
Chris@49
|
744 typename SpMat<eT>::row_iterator&
|
Chris@49
|
745 SpMat<eT>::row_iterator::operator--()
|
Chris@49
|
746 {
|
Chris@49
|
747 const_row_iterator::operator--();
|
Chris@49
|
748 return *this;
|
Chris@49
|
749 }
|
Chris@49
|
750
|
Chris@49
|
751
|
Chris@49
|
752
|
Chris@49
|
753 template<typename eT>
|
Chris@49
|
754 inline
|
Chris@49
|
755 arma_hot
|
Chris@49
|
756 typename SpMat<eT>::row_iterator
|
Chris@49
|
757 SpMat<eT>::row_iterator::operator--(int)
|
Chris@49
|
758 {
|
Chris@49
|
759 typename SpMat<eT>::row_iterator tmp(*this);
|
Chris@49
|
760
|
Chris@49
|
761 const_row_iterator::operator--();
|
Chris@49
|
762
|
Chris@49
|
763 return tmp;
|
Chris@49
|
764 }
|
Chris@49
|
765
|
Chris@49
|
766 //! @}
|