comparison armadillo-3.900.4/include/armadillo_bits/SpMat_iterators_meat.hpp @ 49:1ec0e2823891

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