annotate armadillo-3.900.4/include/armadillo_bits/SpSubview_iterators_meat.hpp @ 84:55a047986812 tip

Update library URI so as not to be document-local
author Chris Cannam
date Wed, 22 Apr 2020 14:21:57 +0100
parents 1ec0e2823891
children
rev   line source
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 //! @}