source: mmcs/armadillo_bits/SpSubview_iterators_meat.hpp @ 8daa049

matrices
Last change on this file since 8daa049 was 9dd61b1, checked in by rboet <rboet@…>, 9 years ago

Avance del proyecto 60%

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