1 // 2 // Copyright (c) 2003 3 // Gunter Winkler, Joerg Walter 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // The authors gratefully acknowledge the support of 10 // GeNeSys mbH & Co. KG in producing this work. 11 // 12 13 #ifndef _BOOST_UBLAS_VECTOR_OF_VECTOR_ 14 #define _BOOST_UBLAS_VECTOR_OF_VECTOR_ 15 16 #include <boost/type_traits.hpp> 17 18 #include <boost/numeric/ublas/storage_sparse.hpp> 19 #include <boost/numeric/ublas/matrix_sparse.hpp> 20 21 // Iterators based on ideas of Jeremy Siek 22 23 namespace boost { namespace numeric { namespace ublas { 24 25 // uBLAS sparse vector based sparse matrix class 26 // FIXME outer vector can be sparse type but it is completely filled 27 template<class T, class L, class A> 28 class generalized_vector_of_vector: 29 public matrix_container<generalized_vector_of_vector<T, L, A> > { 30 31 typedef T &true_reference; 32 typedef T *pointer; 33 typedef const T *const_pointer; 34 typedef L layout_type; 35 typedef generalized_vector_of_vector<T, L, A> self_type; 36 public: 37 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 38 using matrix_container<self_type>::operator (); 39 #endif 40 typedef typename A::size_type size_type; 41 typedef typename A::difference_type difference_type; 42 typedef T value_type; 43 typedef const T &const_reference; 44 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE 45 typedef T &reference; 46 #else 47 typedef sparse_matrix_element<self_type> reference; 48 #endif 49 typedef A array_type; 50 typedef const matrix_reference<const self_type> const_closure_type; 51 typedef matrix_reference<self_type> closure_type; 52 typedef typename A::value_type vector_data_value_type; 53 typedef vector_data_value_type vector_temporary_type; 54 typedef self_type matrix_temporary_type; 55 typedef sparse_tag storage_category; 56 typedef typename L::orientation_category orientation_category; 57 58 // Construction and destruction 59 BOOST_UBLAS_INLINE generalized_vector_of_vector()60 generalized_vector_of_vector (): 61 matrix_container<self_type> (), 62 size1_ (0), size2_ (0), data_ (1) { 63 const size_type sizeM = layout_type::size_M (size1_, size2_); 64 // create size1+1 empty vector elements 65 data_.insert_element (sizeM, vector_data_value_type ()); 66 storage_invariants (); 67 } 68 BOOST_UBLAS_INLINE generalized_vector_of_vector(size_type size1,size_type size2,size_type)69 generalized_vector_of_vector (size_type size1, size_type size2, size_type /*non_zeros = 0*/): 70 matrix_container<self_type> (), 71 size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) { 72 const size_type sizeM = layout_type::size_M (size1_, size2_); 73 const size_type sizem = layout_type::size_m (size1_, size2_); 74 for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements 75 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 76 data_.insert_element (sizeM, vector_data_value_type ()); 77 storage_invariants (); 78 } 79 BOOST_UBLAS_INLINE generalized_vector_of_vector(const generalized_vector_of_vector & m)80 generalized_vector_of_vector (const generalized_vector_of_vector &m): 81 matrix_container<self_type> (), 82 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) { 83 storage_invariants (); 84 } 85 template<class AE> 86 BOOST_UBLAS_INLINE generalized_vector_of_vector(const matrix_expression<AE> & ae,size_type)87 generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type /*non_zeros = 0*/): 88 matrix_container<self_type> (), 89 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) { 90 const size_type sizeM = layout_type::size_M (size1_, size2_); 91 const size_type sizem = layout_type::size_m (size1_, size2_); 92 for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements 93 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 94 data_.insert_element (sizeM, vector_data_value_type ()); 95 storage_invariants (); 96 matrix_assign<scalar_assign> (*this, ae); 97 } 98 99 // Accessors 100 BOOST_UBLAS_INLINE size1() const101 size_type size1 () const { 102 return size1_; 103 } 104 BOOST_UBLAS_INLINE size2() const105 size_type size2 () const { 106 return size2_; 107 } 108 BOOST_UBLAS_INLINE nnz_capacity() const109 size_type nnz_capacity () const { 110 size_type non_zeros = 0; 111 for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv) 112 non_zeros += (*itv).nnz_capacity (); 113 return non_zeros; 114 } 115 BOOST_UBLAS_INLINE nnz() const116 size_type nnz () const { 117 size_type non_zeros = 0; 118 for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv) 119 non_zeros += (*itv).nnz (); 120 return non_zeros; 121 } 122 123 // Storage accessors 124 BOOST_UBLAS_INLINE data() const125 const array_type &data () const { 126 return data_; 127 } 128 BOOST_UBLAS_INLINE data()129 array_type &data () { 130 return data_; 131 } 132 133 // Resizing 134 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool preserve=true)135 void resize (size_type size1, size_type size2, bool preserve = true) { 136 const size_type oldM = layout_type::size_M (size1_, size2_); 137 size1_ = size1; 138 size2_ = size2; 139 const size_type sizeM = layout_type::size_M (size1_, size2_); 140 const size_type sizem = layout_type::size_m (size1_, size2_); 141 data ().resize (sizeM + 1, preserve); 142 if (preserve) { 143 for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i) 144 ref (data () [i]).resize (sizem, preserve); 145 for (size_type i = oldM+1; i < sizeM; ++ i) // create new vector elements 146 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 147 if (sizeM > oldM) { 148 data_.insert_element (sizeM, vector_data_value_type ()); 149 } else { 150 ref (data () [sizeM]).resize (0, false); 151 } 152 } else { 153 for (size_type i = 0; i < sizeM; ++ i) 154 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 155 data_.insert_element (sizeM, vector_data_value_type ()); 156 } 157 storage_invariants (); 158 } 159 160 // Element support 161 BOOST_UBLAS_INLINE find_element(size_type i,size_type j)162 pointer find_element (size_type i, size_type j) { 163 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j)); 164 } 165 BOOST_UBLAS_INLINE find_element(size_type i,size_type j) const166 const_pointer find_element (size_type i, size_type j) const { 167 const size_type elementM = layout_type::index_M (i, j); 168 const size_type elementm = layout_type::index_m (i, j); 169 // optimise: check the storage_type and index directly if element always exists 170 if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) { 171 return & (data () [elementM] [elementm]); 172 } 173 else { 174 const typename array_type::value_type *pv = data ().find_element (elementM); 175 if (!pv) 176 return 0; 177 return pv->find_element (elementm); 178 } 179 } 180 181 // Element access 182 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const183 const_reference operator () (size_type i, size_type j) const { 184 const_pointer p = find_element (i, j); 185 // optimise: check the storage_type and index directly if element always exists 186 if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) { 187 BOOST_UBLAS_CHECK (p, internal_logic () ); 188 return *p; 189 } 190 else { 191 if (p) 192 return *p; 193 else 194 return zero_; 195 } 196 } 197 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)198 reference operator () (size_type i, size_type j) { 199 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE 200 return at_element (i, j); 201 #else 202 return reference (*this, i, j); 203 #endif 204 } 205 206 // Assignment 207 BOOST_UBLAS_INLINE operator =(const generalized_vector_of_vector & m)208 generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) { 209 if (this != &m) { 210 size1_ = m.size1_; 211 size2_ = m.size2_; 212 data () = m.data (); 213 } 214 storage_invariants (); 215 return *this; 216 } 217 BOOST_UBLAS_INLINE assign_temporary(generalized_vector_of_vector & m)218 generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) { 219 swap (m); 220 return *this; 221 } 222 template<class AE> 223 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)224 generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) { 225 self_type temporary (ae); 226 return assign_temporary (temporary); 227 } 228 template<class AE> 229 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)230 generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) { 231 matrix_assign<scalar_assign> (*this, ae); 232 return *this; 233 } 234 template<class AE> 235 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)236 generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) { 237 self_type temporary (*this + ae); 238 return assign_temporary (temporary); 239 } 240 template<class AE> 241 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)242 generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) { 243 matrix_assign<scalar_plus_assign> (*this, ae); 244 return *this; 245 } 246 template<class AE> 247 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)248 generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) { 249 self_type temporary (*this - ae); 250 return assign_temporary (temporary); 251 } 252 template<class AE> 253 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)254 generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) { 255 matrix_assign<scalar_minus_assign> (*this, ae); 256 return *this; 257 } 258 template<class AT> 259 BOOST_UBLAS_INLINE operator *=(const AT & at)260 generalized_vector_of_vector& operator *= (const AT &at) { 261 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 262 return *this; 263 } 264 template<class AT> 265 BOOST_UBLAS_INLINE operator /=(const AT & at)266 generalized_vector_of_vector& operator /= (const AT &at) { 267 matrix_assign_scalar<scalar_divides_assign> (*this, at); 268 return *this; 269 } 270 271 // Swapping 272 BOOST_UBLAS_INLINE swap(generalized_vector_of_vector & m)273 void swap (generalized_vector_of_vector &m) { 274 if (this != &m) { 275 std::swap (size1_, m.size1_); 276 std::swap (size2_, m.size2_); 277 data ().swap (m.data ()); 278 } 279 storage_invariants (); 280 } 281 BOOST_UBLAS_INLINE swap(generalized_vector_of_vector & m1,generalized_vector_of_vector & m2)282 friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) { 283 m1.swap (m2); 284 } 285 286 // Sorting sort()287 void sort () { 288 vectoriterator_type itv (data ().begin ()); 289 vectoriterator_type itv_end (data ().end ()); 290 while (itv != itv_end) { 291 (*itv).sort (); 292 ++ itv; 293 } 294 } 295 296 // Element insertion and erasure 297 BOOST_UBLAS_INLINE insert_element(size_type i,size_type j,const_reference t)298 true_reference insert_element (size_type i, size_type j, const_reference t) { 299 const size_type elementM = layout_type::index_M (i, j); 300 const size_type elementm = layout_type::index_m (i, j); 301 vector_data_value_type& vd (ref (data () [elementM])); 302 storage_invariants (); 303 return vd.insert_element (elementm, t); 304 } 305 BOOST_UBLAS_INLINE append_element(size_type i,size_type j,const_reference t)306 void append_element (size_type i, size_type j, const_reference t) { 307 const size_type elementM = layout_type::index_M (i, j); 308 const size_type elementm = layout_type::index_m (i, j); 309 vector_data_value_type& vd (ref (data () [elementM])); 310 storage_invariants (); 311 return vd.append_element (elementm, t); 312 } 313 BOOST_UBLAS_INLINE erase_element(size_type i,size_type j)314 void erase_element (size_type i, size_type j) { 315 vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 316 if (itv == data ().end ()) 317 return; 318 (*itv).erase_element (layout_type::index_m (i, j)); 319 storage_invariants (); 320 } 321 BOOST_UBLAS_INLINE clear()322 void clear () { 323 const size_type sizeM = layout_type::size_M (size1_, size2_); 324 // FIXME should clear data () if this is done via value_type/*zero*/() then it is not size preserving 325 for (size_type i = 0; i < sizeM; ++ i) 326 ref (data () [i]).clear (); 327 storage_invariants (); 328 } 329 330 // Iterator types 331 private: 332 // Use vector iterator 333 typedef typename A::const_iterator const_vectoriterator_type; 334 typedef typename A::iterator vectoriterator_type; 335 typedef typename A::value_type::const_iterator const_subiterator_type; 336 typedef typename A::value_type::iterator subiterator_type; 337 338 BOOST_UBLAS_INLINE at_element(size_type i,size_type j)339 true_reference at_element (size_type i, size_type j) { 340 return ref (ref (data () [layout_type::index_M (i, j)]) [layout_type::index_m (i, j)]); 341 } 342 343 public: 344 class const_iterator1; 345 class iterator1; 346 class const_iterator2; 347 class iterator2; 348 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 349 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 350 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 351 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 352 353 // Element lookup 354 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. find1(int rank,size_type i,size_type j,int direction=1) const355 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { 356 for (;;) { 357 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 358 const_vectoriterator_type itv_end (data ().end ()); 359 if (itv == itv_end) 360 return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 361 362 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 363 const_subiterator_type it_end ((*itv).end ()); 364 if (rank == 0) 365 return const_iterator1 (*this, rank, i, j, itv, it); 366 if (it != it_end && it.index () == layout_type::index_m (i, j)) 367 return const_iterator1 (*this, rank, i, j, itv, it); 368 if (direction > 0) { 369 if (layout_type::fast_i ()) { 370 if (it == it_end) 371 return const_iterator1 (*this, rank, i, j, itv, it); 372 i = it.index (); 373 } else { 374 if (i >= size1_) 375 return const_iterator1 (*this, rank, i, j, itv, it); 376 ++ i; 377 } 378 } else /* if (direction < 0) */ { 379 if (layout_type::fast_i ()) { 380 if (it == (*itv).begin ()) 381 return const_iterator1 (*this, rank, i, j, itv, it); 382 --it; 383 i = it.index (); 384 } else { 385 if (i == 0) 386 return const_iterator1 (*this, rank, i, j, itv, it); 387 -- i; 388 } 389 } 390 } 391 } 392 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. find1(int rank,size_type i,size_type j,int direction=1)393 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { 394 for (;;) { 395 vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 396 vectoriterator_type itv_end (data ().end ()); 397 if (itv == itv_end) 398 return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 399 400 subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 401 subiterator_type it_end ((*itv).end ()); 402 if (rank == 0) 403 return iterator1 (*this, rank, i, j, itv, it); 404 if (it != it_end && it.index () == layout_type::index_m (i, j)) 405 return iterator1 (*this, rank, i, j, itv, it); 406 if (direction > 0) { 407 if (layout_type::fast_i ()) { 408 if (it == it_end) 409 return iterator1 (*this, rank, i, j, itv, it); 410 i = it.index (); 411 } else { 412 if (i >= size1_) 413 return iterator1 (*this, rank, i, j, itv, it); 414 ++ i; 415 } 416 } else /* if (direction < 0) */ { 417 if (layout_type::fast_i ()) { 418 if (it == (*itv).begin ()) 419 return iterator1 (*this, rank, i, j, itv, it); 420 --it; 421 i = it.index (); 422 } else { 423 if (i == 0) 424 return iterator1 (*this, rank, i, j, itv, it); 425 -- i; 426 } 427 } 428 } 429 } 430 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. find2(int rank,size_type i,size_type j,int direction=1) const431 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { 432 for (;;) { 433 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 434 const_vectoriterator_type itv_end (data ().end ()); 435 if (itv == itv_end) 436 return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 437 438 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 439 const_subiterator_type it_end ((*itv).end ()); 440 if (rank == 0) 441 return const_iterator2 (*this, rank, i, j, itv, it); 442 if (it != it_end && it.index () == layout_type::index_m (i, j)) 443 return const_iterator2 (*this, rank, i, j, itv, it); 444 if (direction > 0) { 445 if (layout_type::fast_j ()) { 446 if (it == it_end) 447 return const_iterator2 (*this, rank, i, j, itv, it); 448 j = it.index (); 449 } else { 450 if (j >= size2_) 451 return const_iterator2 (*this, rank, i, j, itv, it); 452 ++ j; 453 } 454 } else /* if (direction < 0) */ { 455 if (layout_type::fast_j ()) { 456 if (it == (*itv).begin ()) 457 return const_iterator2 (*this, rank, i, j, itv, it); 458 --it; 459 j = it.index (); 460 } else { 461 if (j == 0) 462 return const_iterator2 (*this, rank, i, j, itv, it); 463 -- j; 464 } 465 } 466 } 467 } 468 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. find2(int rank,size_type i,size_type j,int direction=1)469 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { 470 for (;;) { 471 vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 472 vectoriterator_type itv_end (data ().end ()); 473 if (itv == itv_end) 474 return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 475 476 subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 477 subiterator_type it_end ((*itv).end ()); 478 if (rank == 0) 479 return iterator2 (*this, rank, i, j, itv, it); 480 if (it != it_end && it.index () == layout_type::index_m (i, j)) 481 return iterator2 (*this, rank, i, j, itv, it); 482 if (direction > 0) { 483 if (layout_type::fast_j ()) { 484 if (it == it_end) 485 return iterator2 (*this, rank, i, j, itv, it); 486 j = it.index (); 487 } else { 488 if (j >= size2_) 489 return iterator2 (*this, rank, i, j, itv, it); 490 ++ j; 491 } 492 } else /* if (direction < 0) */ { 493 if (layout_type::fast_j ()) { 494 if (it == (*itv).begin ()) 495 return iterator2 (*this, rank, i, j, itv, it); 496 --it; 497 j = it.index (); 498 } else { 499 if (j == 0) 500 return iterator2 (*this, rank, i, j, itv, it); 501 -- j; 502 } 503 } 504 } 505 } 506 507 508 class const_iterator1: 509 public container_const_reference<generalized_vector_of_vector>, 510 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 511 const_iterator1, value_type> { 512 public: 513 typedef typename generalized_vector_of_vector::difference_type difference_type; 514 typedef typename generalized_vector_of_vector::value_type value_type; 515 typedef typename generalized_vector_of_vector::const_reference reference; 516 typedef const typename generalized_vector_of_vector::pointer pointer; 517 518 typedef const_iterator2 dual_iterator_type; 519 typedef const_reverse_iterator2 dual_reverse_iterator_type; 520 521 // Construction and destruction 522 BOOST_UBLAS_INLINE const_iterator1()523 const_iterator1 (): 524 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 525 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,int rank,size_type i,size_type j,const const_vectoriterator_type & itv,const const_subiterator_type & it)526 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it): 527 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 528 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)529 const_iterator1 (const iterator1 &it): 530 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} 531 532 // Arithmetic 533 BOOST_UBLAS_INLINE operator ++()534 const_iterator1 &operator ++ () { 535 if (rank_ == 1 && layout_type::fast_i ()) 536 ++ it_; 537 else { 538 const self_type &m = (*this) (); 539 i_ = index1 () + 1; 540 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) 541 *this = m.find1 (rank_, i_, j_, 1); 542 else if (rank_ == 1) { 543 it_ = (*itv_).begin (); 544 if (it_ == (*itv_).end () || index2 () != j_) 545 *this = m.find1 (rank_, i_, j_, 1); 546 } 547 } 548 return *this; 549 } 550 BOOST_UBLAS_INLINE operator --()551 const_iterator1 &operator -- () { 552 if (rank_ == 1 && layout_type::fast_i ()) 553 -- it_; 554 else { 555 const self_type &m = (*this) (); 556 i_ = index1 () - 1; 557 if (rank_ == 1 && -- itv_ == m.end1 ().itv_) 558 *this = m.find1 (rank_, i_, j_, -1); 559 else if (rank_ == 1) { 560 it_ = (*itv_).begin (); 561 if (it_ == (*itv_).end () || index2 () != j_) 562 *this = m.find1 (rank_, i_, j_, -1); 563 } 564 } 565 return *this; 566 } 567 568 // Dereference 569 BOOST_UBLAS_INLINE operator *() const570 const_reference operator * () const { 571 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 572 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 573 if (rank_ == 1) { 574 return *it_; 575 } else { 576 return (*this) () (i_, j_); 577 } 578 } 579 580 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 581 BOOST_UBLAS_INLINE 582 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 583 typename self_type:: 584 #endif begin() const585 const_iterator2 begin () const { 586 const self_type &m = (*this) (); 587 return m.find2 (1, index1 (), 0); 588 } 589 BOOST_UBLAS_INLINE 590 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 591 typename self_type:: 592 #endif cbegin() const593 const_iterator2 cbegin () const { 594 return begin (); 595 } 596 BOOST_UBLAS_INLINE 597 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 598 typename self_type:: 599 #endif end() const600 const_iterator2 end () const { 601 const self_type &m = (*this) (); 602 return m.find2 (1, index1 (), m.size2 ()); 603 } 604 BOOST_UBLAS_INLINE 605 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 606 typename self_type:: 607 #endif cend() const608 const_iterator2 cend () const { 609 return end (); 610 } 611 612 BOOST_UBLAS_INLINE 613 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 614 typename self_type:: 615 #endif rbegin() const616 const_reverse_iterator2 rbegin () const { 617 return const_reverse_iterator2 (end ()); 618 } 619 BOOST_UBLAS_INLINE 620 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 621 typename self_type:: 622 #endif crbegin() const623 const_reverse_iterator2 crbegin () const { 624 return rbegin (); 625 } 626 BOOST_UBLAS_INLINE 627 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 628 typename self_type:: 629 #endif rend() const630 const_reverse_iterator2 rend () const { 631 return const_reverse_iterator2 (begin ()); 632 } 633 BOOST_UBLAS_INLINE 634 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 635 typename self_type:: 636 #endif crend() const637 const_reverse_iterator2 crend () const { 638 return rend (); 639 } 640 #endif 641 642 // Indices 643 BOOST_UBLAS_INLINE index1() const644 size_type index1 () const { 645 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 646 if (rank_ == 1) { 647 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 648 return layout_type::index_M (itv_.index (), it_.index ()); 649 } else { 650 return i_; 651 } 652 } 653 BOOST_UBLAS_INLINE index2() const654 size_type index2 () const { 655 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 656 if (rank_ == 1) { 657 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 658 return layout_type::index_m (itv_.index (), it_.index ()); 659 } else { 660 return j_; 661 } 662 } 663 664 // Assignment 665 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)666 const_iterator1 &operator = (const const_iterator1 &it) { 667 container_const_reference<self_type>::assign (&it ()); 668 rank_ = it.rank_; 669 i_ = it.i_; 670 j_ = it.j_; 671 itv_ = it.itv_; 672 it_ = it.it_; 673 return *this; 674 } 675 676 // Comparison 677 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const678 bool operator == (const const_iterator1 &it) const { 679 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 680 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 681 if (rank_ == 1 || it.rank_ == 1) { 682 return it_ == it.it_; 683 } else { 684 return i_ == it.i_ && j_ == it.j_; 685 } 686 } 687 688 private: 689 int rank_; 690 size_type i_; 691 size_type j_; 692 const_vectoriterator_type itv_; 693 const_subiterator_type it_; 694 }; 695 696 BOOST_UBLAS_INLINE begin1() const697 const_iterator1 begin1 () const { 698 return find1 (0, 0, 0); 699 } 700 BOOST_UBLAS_INLINE cbegin1() const701 const_iterator1 cbegin1 () const { 702 return begin1 (); 703 } 704 BOOST_UBLAS_INLINE end1() const705 const_iterator1 end1 () const { 706 return find1 (0, size1_, 0); 707 } 708 BOOST_UBLAS_INLINE cend1() const709 const_iterator1 cend1 () const { 710 return end1 (); 711 } 712 713 class iterator1: 714 public container_reference<generalized_vector_of_vector>, 715 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 716 iterator1, value_type> { 717 public: 718 typedef typename generalized_vector_of_vector::difference_type difference_type; 719 typedef typename generalized_vector_of_vector::value_type value_type; 720 typedef typename generalized_vector_of_vector::true_reference reference; 721 typedef typename generalized_vector_of_vector::pointer pointer; 722 723 typedef iterator2 dual_iterator_type; 724 typedef reverse_iterator2 dual_reverse_iterator_type; 725 726 // Construction and destruction 727 BOOST_UBLAS_INLINE iterator1()728 iterator1 (): 729 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 730 BOOST_UBLAS_INLINE iterator1(self_type & m,int rank,size_type i,size_type j,const vectoriterator_type & itv,const subiterator_type & it)731 iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it): 732 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 733 734 // Arithmetic 735 BOOST_UBLAS_INLINE operator ++()736 iterator1 &operator ++ () { 737 if (rank_ == 1 && layout_type::fast_i ()) 738 ++ it_; 739 else { 740 self_type &m = (*this) (); 741 i_ = index1 () + 1; 742 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) 743 *this = m.find1 (rank_, i_, j_, 1); 744 else if (rank_ == 1) { 745 it_ = (*itv_).begin (); 746 if (it_ == (*itv_).end () || index2 () != j_) 747 *this = m.find1 (rank_, i_, j_, 1); 748 } 749 } 750 return *this; 751 } 752 BOOST_UBLAS_INLINE operator --()753 iterator1 &operator -- () { 754 if (rank_ == 1 && layout_type::fast_i ()) 755 -- it_; 756 else { 757 self_type &m = (*this) (); 758 i_ = index1 () - 1; 759 if (rank_ == 1 && -- itv_ == m.end1 ().itv_) 760 *this = m.find1 (rank_, i_, j_, -1); 761 else if (rank_ == 1) { 762 it_ = (*itv_).begin (); 763 if (it_ == (*itv_).end () || index2 () != j_) 764 *this = m.find1 (rank_, i_, j_, -1); 765 } 766 } 767 return *this; 768 } 769 770 // Dereference 771 BOOST_UBLAS_INLINE operator *() const772 true_reference operator * () const { 773 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 774 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 775 if (rank_ == 1) { 776 return *it_; 777 } else { 778 return (*this) ().at_element (i_, j_); 779 } 780 } 781 782 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 783 BOOST_UBLAS_INLINE 784 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 785 typename self_type:: 786 #endif begin() const787 iterator2 begin () const { 788 self_type &m = (*this) (); 789 return m.find2 (1, index1 (), 0); 790 } 791 BOOST_UBLAS_INLINE 792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 793 typename self_type:: 794 #endif end() const795 iterator2 end () const { 796 self_type &m = (*this) (); 797 return m.find2 (1, index1 (), m.size2 ()); 798 } 799 BOOST_UBLAS_INLINE 800 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 801 typename self_type:: 802 #endif rbegin() const803 reverse_iterator2 rbegin () const { 804 return reverse_iterator2 (end ()); 805 } 806 BOOST_UBLAS_INLINE 807 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 808 typename self_type:: 809 #endif rend() const810 reverse_iterator2 rend () const { 811 return reverse_iterator2 (begin ()); 812 } 813 #endif 814 815 // Indices 816 BOOST_UBLAS_INLINE index1() const817 size_type index1 () const { 818 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 819 if (rank_ == 1) { 820 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 821 return layout_type::index_M (itv_.index (), it_.index ()); 822 } else { 823 return i_; 824 } 825 } 826 BOOST_UBLAS_INLINE index2() const827 size_type index2 () const { 828 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 829 if (rank_ == 1) { 830 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 831 return layout_type::index_m (itv_.index (), it_.index ()); 832 } else { 833 return j_; 834 } 835 } 836 837 // Assignment 838 BOOST_UBLAS_INLINE operator =(const iterator1 & it)839 iterator1 &operator = (const iterator1 &it) { 840 container_reference<self_type>::assign (&it ()); 841 rank_ = it.rank_; 842 i_ = it.i_; 843 j_ = it.j_; 844 itv_ = it.itv_; 845 it_ = it.it_; 846 return *this; 847 } 848 849 // Comparison 850 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const851 bool operator == (const iterator1 &it) const { 852 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 853 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 854 if (rank_ == 1 || it.rank_ == 1) { 855 return it_ == it.it_; 856 } else { 857 return i_ == it.i_ && j_ == it.j_; 858 } 859 } 860 861 private: 862 int rank_; 863 size_type i_; 864 size_type j_; 865 vectoriterator_type itv_; 866 subiterator_type it_; 867 868 friend class const_iterator1; 869 }; 870 871 BOOST_UBLAS_INLINE begin1()872 iterator1 begin1 () { 873 return find1 (0, 0, 0); 874 } 875 BOOST_UBLAS_INLINE end1()876 iterator1 end1 () { 877 return find1 (0, size1_, 0); 878 } 879 880 class const_iterator2: 881 public container_const_reference<generalized_vector_of_vector>, 882 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 883 const_iterator2, value_type> { 884 public: 885 typedef typename generalized_vector_of_vector::difference_type difference_type; 886 typedef typename generalized_vector_of_vector::value_type value_type; 887 typedef typename generalized_vector_of_vector::const_reference reference; 888 typedef const typename generalized_vector_of_vector::pointer pointer; 889 890 typedef const_iterator1 dual_iterator_type; 891 typedef const_reverse_iterator1 dual_reverse_iterator_type; 892 893 // Construction and destruction 894 BOOST_UBLAS_INLINE const_iterator2()895 const_iterator2 (): 896 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 897 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,int rank,size_type i,size_type j,const const_vectoriterator_type & itv,const const_subiterator_type & it)898 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it): 899 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 900 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)901 const_iterator2 (const iterator2 &it): 902 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} 903 904 // Arithmetic 905 BOOST_UBLAS_INLINE operator ++()906 const_iterator2 &operator ++ () { 907 if (rank_ == 1 && layout_type::fast_j ()) 908 ++ it_; 909 else { 910 const self_type &m = (*this) (); 911 j_ = index2 () + 1; 912 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) 913 *this = m.find2 (rank_, i_, j_, 1); 914 else if (rank_ == 1) { 915 it_ = (*itv_).begin (); 916 if (it_ == (*itv_).end () || index1 () != i_) 917 *this = m.find2 (rank_, i_, j_, 1); 918 } 919 } 920 return *this; 921 } 922 BOOST_UBLAS_INLINE operator --()923 const_iterator2 &operator -- () { 924 if (rank_ == 1 && layout_type::fast_j ()) 925 -- it_; 926 else { 927 const self_type &m = (*this) (); 928 j_ = index2 () - 1; 929 if (rank_ == 1 && -- itv_ == m.end2 ().itv_) 930 *this = m.find2 (rank_, i_, j_, -1); 931 else if (rank_ == 1) { 932 it_ = (*itv_).begin (); 933 if (it_ == (*itv_).end () || index1 () != i_) 934 *this = m.find2 (rank_, i_, j_, -1); 935 } 936 } 937 return *this; 938 } 939 940 // Dereference 941 BOOST_UBLAS_INLINE operator *() const942 const_reference operator * () const { 943 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 944 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 945 if (rank_ == 1) { 946 return *it_; 947 } else { 948 return (*this) () (i_, j_); 949 } 950 } 951 952 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 953 BOOST_UBLAS_INLINE 954 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 955 typename self_type:: 956 #endif begin() const957 const_iterator1 begin () const { 958 const self_type &m = (*this) (); 959 return m.find1 (1, 0, index2 ()); 960 } 961 BOOST_UBLAS_INLINE 962 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 963 typename self_type:: 964 #endif cbegin() const965 const_iterator1 cbegin () const { 966 return begin (); 967 } 968 BOOST_UBLAS_INLINE 969 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 970 typename self_type:: 971 #endif end() const972 const_iterator1 end () const { 973 const self_type &m = (*this) (); 974 return m.find1 (1, m.size1 (), index2 ()); 975 } 976 BOOST_UBLAS_INLINE 977 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 978 typename self_type:: 979 #endif cend() const980 const_iterator1 cend () const { 981 return end (); 982 } 983 BOOST_UBLAS_INLINE 984 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 985 typename self_type:: 986 #endif rbegin() const987 const_reverse_iterator1 rbegin () const { 988 return const_reverse_iterator1 (end ()); 989 } 990 BOOST_UBLAS_INLINE 991 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 992 typename self_type:: 993 #endif crbegin() const994 const_reverse_iterator1 crbegin () const { 995 return rbegin (); 996 } 997 BOOST_UBLAS_INLINE 998 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 999 typename self_type:: 1000 #endif rend() const1001 const_reverse_iterator1 rend () const { 1002 return const_reverse_iterator1 (begin ()); 1003 } 1004 BOOST_UBLAS_INLINE 1005 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1006 typename self_type:: 1007 #endif crend() const1008 const_reverse_iterator1 crend () const { 1009 return rend (); 1010 } 1011 #endif 1012 1013 // Indices 1014 BOOST_UBLAS_INLINE index1() const1015 size_type index1 () const { 1016 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 1017 if (rank_ == 1) { 1018 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 1019 return layout_type::index_M (itv_.index (), it_.index ()); 1020 } else { 1021 return i_; 1022 } 1023 } 1024 BOOST_UBLAS_INLINE index2() const1025 size_type index2 () const { 1026 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 1027 if (rank_ == 1) { 1028 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 1029 return layout_type::index_m (itv_.index (), it_.index ()); 1030 } else { 1031 return j_; 1032 } 1033 } 1034 1035 // Assignment 1036 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)1037 const_iterator2 &operator = (const const_iterator2 &it) { 1038 container_const_reference<self_type>::assign (&it ()); 1039 rank_ = it.rank_; 1040 i_ = it.i_; 1041 j_ = it.j_; 1042 itv_ = it.itv_; 1043 it_ = it.it_; 1044 return *this; 1045 } 1046 1047 // Comparison 1048 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const1049 bool operator == (const const_iterator2 &it) const { 1050 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1051 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 1052 if (rank_ == 1 || it.rank_ == 1) { 1053 return it_ == it.it_; 1054 } else { 1055 return i_ == it.i_ && j_ == it.j_; 1056 } 1057 } 1058 1059 private: 1060 int rank_; 1061 size_type i_; 1062 size_type j_; 1063 const_vectoriterator_type itv_; 1064 const_subiterator_type it_; 1065 }; 1066 1067 BOOST_UBLAS_INLINE begin2() const1068 const_iterator2 begin2 () const { 1069 return find2 (0, 0, 0); 1070 } 1071 BOOST_UBLAS_INLINE cbegin2() const1072 const_iterator2 cbegin2 () const { 1073 return begin2 (); 1074 } 1075 BOOST_UBLAS_INLINE end2() const1076 const_iterator2 end2 () const { 1077 return find2 (0, 0, size2_); 1078 } 1079 BOOST_UBLAS_INLINE cend2() const1080 const_iterator2 cend2 () const { 1081 return end2 (); 1082 } 1083 1084 class iterator2: 1085 public container_reference<generalized_vector_of_vector>, 1086 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 1087 iterator2, value_type> { 1088 public: 1089 typedef typename generalized_vector_of_vector::difference_type difference_type; 1090 typedef typename generalized_vector_of_vector::value_type value_type; 1091 typedef typename generalized_vector_of_vector::true_reference reference; 1092 typedef typename generalized_vector_of_vector::pointer pointer; 1093 1094 typedef iterator1 dual_iterator_type; 1095 typedef reverse_iterator1 dual_reverse_iterator_type; 1096 1097 // Construction and destruction 1098 BOOST_UBLAS_INLINE iterator2()1099 iterator2 (): 1100 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 1101 BOOST_UBLAS_INLINE iterator2(self_type & m,int rank,size_type i,size_type j,const vectoriterator_type & itv,const subiterator_type & it)1102 iterator2 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it): 1103 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 1104 1105 // Arithmetic 1106 BOOST_UBLAS_INLINE operator ++()1107 iterator2 &operator ++ () { 1108 if (rank_ == 1 && layout_type::fast_j ()) 1109 ++ it_; 1110 else { 1111 self_type &m = (*this) (); 1112 j_ = index2 () + 1; 1113 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) 1114 *this = m.find2 (rank_, i_, j_, 1); 1115 else if (rank_ == 1) { 1116 it_ = (*itv_).begin (); 1117 if (it_ == (*itv_).end () || index1 () != i_) 1118 *this = m.find2 (rank_, i_, j_, 1); 1119 } 1120 } 1121 return *this; 1122 } 1123 BOOST_UBLAS_INLINE operator --()1124 iterator2 &operator -- () { 1125 if (rank_ == 1 && layout_type::fast_j ()) 1126 -- it_; 1127 else { 1128 self_type &m = (*this) (); 1129 j_ = index2 () - 1; 1130 if (rank_ == 1 && -- itv_ == m.end2 ().itv_) 1131 *this = m.find2 (rank_, i_, j_, -1); 1132 else if (rank_ == 1) { 1133 it_ = (*itv_).begin (); 1134 if (it_ == (*itv_).end () || index1 () != i_) 1135 *this = m.find2 (rank_, i_, j_, -1); 1136 } 1137 } 1138 return *this; 1139 } 1140 1141 // Dereference 1142 BOOST_UBLAS_INLINE operator *() const1143 true_reference operator * () const { 1144 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1145 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1146 if (rank_ == 1) { 1147 return *it_; 1148 } else { 1149 return (*this) ().at_element (i_, j_); 1150 } 1151 } 1152 1153 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1154 BOOST_UBLAS_INLINE 1155 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1156 typename self_type:: 1157 #endif begin() const1158 iterator1 begin () const { 1159 self_type &m = (*this) (); 1160 return m.find1 (1, 0, index2 ()); 1161 } 1162 BOOST_UBLAS_INLINE 1163 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1164 typename self_type:: 1165 #endif end() const1166 iterator1 end () const { 1167 self_type &m = (*this) (); 1168 return m.find1 (1, m.size1 (), index2 ()); 1169 } 1170 BOOST_UBLAS_INLINE 1171 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1172 typename self_type:: 1173 #endif rbegin() const1174 reverse_iterator1 rbegin () const { 1175 return reverse_iterator1 (end ()); 1176 } 1177 BOOST_UBLAS_INLINE 1178 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1179 typename self_type:: 1180 #endif rend() const1181 reverse_iterator1 rend () const { 1182 return reverse_iterator1 (begin ()); 1183 } 1184 #endif 1185 1186 // Indices 1187 BOOST_UBLAS_INLINE index1() const1188 size_type index1 () const { 1189 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 1190 if (rank_ == 1) { 1191 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 1192 return layout_type::index_M (itv_.index (), it_.index ()); 1193 } else { 1194 return i_; 1195 } 1196 } 1197 BOOST_UBLAS_INLINE index2() const1198 size_type index2 () const { 1199 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 1200 if (rank_ == 1) { 1201 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 1202 return layout_type::index_m (itv_.index (), it_.index ()); 1203 } else { 1204 return j_; 1205 } 1206 } 1207 1208 // Assignment 1209 BOOST_UBLAS_INLINE operator =(const iterator2 & it)1210 iterator2 &operator = (const iterator2 &it) { 1211 container_reference<self_type>::assign (&it ()); 1212 rank_ = it.rank_; 1213 i_ = it.i_; 1214 j_ = it.j_; 1215 itv_ = it.itv_; 1216 it_ = it.it_; 1217 return *this; 1218 } 1219 1220 // Comparison 1221 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const1222 bool operator == (const iterator2 &it) const { 1223 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1224 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 1225 if (rank_ == 1 || it.rank_ == 1) { 1226 return it_ == it.it_; 1227 } else { 1228 return i_ == it.i_ && j_ == it.j_; 1229 } 1230 } 1231 1232 private: 1233 int rank_; 1234 size_type i_; 1235 size_type j_; 1236 vectoriterator_type itv_; 1237 subiterator_type it_; 1238 1239 friend class const_iterator2; 1240 }; 1241 1242 BOOST_UBLAS_INLINE begin2()1243 iterator2 begin2 () { 1244 return find2 (0, 0, 0); 1245 } 1246 BOOST_UBLAS_INLINE end2()1247 iterator2 end2 () { 1248 return find2 (0, 0, size2_); 1249 } 1250 1251 // Reverse iterators 1252 1253 BOOST_UBLAS_INLINE rbegin1() const1254 const_reverse_iterator1 rbegin1 () const { 1255 return const_reverse_iterator1 (end1 ()); 1256 } 1257 BOOST_UBLAS_INLINE crbegin1() const1258 const_reverse_iterator1 crbegin1 () const { 1259 return rbegin1 (); 1260 } 1261 BOOST_UBLAS_INLINE rend1() const1262 const_reverse_iterator1 rend1 () const { 1263 return const_reverse_iterator1 (begin1 ()); 1264 } 1265 BOOST_UBLAS_INLINE crend1() const1266 const_reverse_iterator1 crend1 () const { 1267 return rend1 (); 1268 } 1269 1270 BOOST_UBLAS_INLINE rbegin1()1271 reverse_iterator1 rbegin1 () { 1272 return reverse_iterator1 (end1 ()); 1273 } 1274 BOOST_UBLAS_INLINE rend1()1275 reverse_iterator1 rend1 () { 1276 return reverse_iterator1 (begin1 ()); 1277 } 1278 1279 BOOST_UBLAS_INLINE rbegin2() const1280 const_reverse_iterator2 rbegin2 () const { 1281 return const_reverse_iterator2 (end2 ()); 1282 } 1283 BOOST_UBLAS_INLINE crbegin2() const1284 const_reverse_iterator2 crbegin2 () const { 1285 return rbegin2 (); 1286 } 1287 BOOST_UBLAS_INLINE rend2() const1288 const_reverse_iterator2 rend2 () const { 1289 return const_reverse_iterator2 (begin2 ()); 1290 } 1291 BOOST_UBLAS_INLINE crend2() const1292 const_reverse_iterator2 crend2 () const { 1293 return rend2 (); 1294 } 1295 1296 BOOST_UBLAS_INLINE rbegin2()1297 reverse_iterator2 rbegin2 () { 1298 return reverse_iterator2 (end2 ()); 1299 } 1300 BOOST_UBLAS_INLINE rend2()1301 reverse_iterator2 rend2 () { 1302 return reverse_iterator2 (begin2 ()); 1303 } 1304 1305 // Serialization 1306 template<class Archive> serialize(Archive & ar,const unsigned int)1307 void serialize(Archive & ar, const unsigned int /* file_version */){ 1308 1309 // we need to copy to a collection_size_type to get a portable 1310 // and efficient serialization 1311 serialization::collection_size_type s1 (size1_); 1312 serialization::collection_size_type s2 (size2_); 1313 1314 // serialize the sizes 1315 ar & serialization::make_nvp("size1",s1) 1316 & serialization::make_nvp("size2",s2); 1317 1318 // copy the values back if loading 1319 if (Archive::is_loading::value) { 1320 size1_ = s1; 1321 size2_ = s2; 1322 } 1323 1324 ar & serialization::make_nvp("data", data_); 1325 1326 storage_invariants(); 1327 } 1328 1329 private: storage_invariants() const1330 void storage_invariants () const 1331 { 1332 BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == data_.size (), internal_logic ()); 1333 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); 1334 1335 } 1336 size_type size1_; 1337 size_type size2_; 1338 array_type data_; 1339 static const value_type zero_; 1340 }; 1341 1342 template<class T, class L, class A> 1343 const typename generalized_vector_of_vector<T, L, A>::value_type generalized_vector_of_vector<T, L, A>::zero_ = value_type/*zero*/(); 1344 1345 }}} 1346 1347 #endif 1348