...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
00001 // 00002 // Copyright (c) 2003 00003 // Gunter Winkler, Joerg Walter 00004 // 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 // 00009 // The authors gratefully acknowledge the support of 00010 // GeNeSys mbH & Co. KG in producing this work. 00011 // 00012 00013 #ifndef _BOOST_UBLAS_VECTOR_OF_VECTOR_ 00014 #define _BOOST_UBLAS_VECTOR_OF_VECTOR_ 00015 00016 #include <boost/type_traits.hpp> 00017 00018 #include <boost/numeric/ublas/storage_sparse.hpp> 00019 #include <boost/numeric/ublas/matrix_sparse.hpp> 00020 00021 // Iterators based on ideas of Jeremy Siek 00022 00023 namespace boost { namespace numeric { namespace ublas { 00024 00025 // uBLAS sparse vector based sparse matrix class 00026 // FIXME outer vector can be sparse type but it is completely filled 00027 template<class T, class L, class A> 00028 class generalized_vector_of_vector: 00029 public matrix_container<generalized_vector_of_vector<T, L, A> > { 00030 00031 typedef T &true_reference; 00032 typedef T *pointer; 00033 typedef const T *const_pointer; 00034 typedef L layout_type; 00035 typedef generalized_vector_of_vector<T, L, A> self_type; 00036 public: 00037 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00038 using matrix_container<self_type>::operator (); 00039 #endif 00040 typedef typename A::size_type size_type; 00041 typedef typename A::difference_type difference_type; 00042 typedef T value_type; 00043 typedef const T &const_reference; 00044 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE 00045 typedef T &reference; 00046 #else 00047 typedef sparse_matrix_element<self_type> reference; 00048 #endif 00049 typedef A array_type; 00050 typedef const matrix_reference<const self_type> const_closure_type; 00051 typedef matrix_reference<self_type> closure_type; 00052 typedef typename A::value_type vector_data_value_type; 00053 typedef vector_data_value_type vector_temporary_type; 00054 typedef self_type matrix_temporary_type; 00055 typedef sparse_tag storage_category; 00056 typedef typename L::orientation_category orientation_category; 00057 00058 // Construction and destruction 00059 BOOST_UBLAS_INLINE 00060 generalized_vector_of_vector (): 00061 matrix_container<self_type> (), 00062 size1_ (0), size2_ (0), data_ (1) { 00063 const size_type sizeM = layout_type::size_M (size1_, size2_); 00064 // create size1+1 empty vector elements 00065 data_.insert_element (sizeM, vector_data_value_type ()); 00066 storage_invariants (); 00067 } 00068 BOOST_UBLAS_INLINE 00069 generalized_vector_of_vector (size_type size1, size_type size2, size_type non_zeros = 0): 00070 matrix_container<self_type> (), 00071 size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) { 00072 const size_type sizeM = layout_type::size_M (size1_, size2_); 00073 const size_type sizem = layout_type::size_m (size1_, size2_); 00074 for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements 00075 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 00076 data_.insert_element (sizeM, vector_data_value_type ()); 00077 storage_invariants (); 00078 } 00079 BOOST_UBLAS_INLINE 00080 generalized_vector_of_vector (const generalized_vector_of_vector &m): 00081 matrix_container<self_type> (), 00082 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) { 00083 storage_invariants (); 00084 } 00085 template<class AE> 00086 BOOST_UBLAS_INLINE 00087 generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0): 00088 matrix_container<self_type> (), 00089 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) { 00090 const size_type sizeM = layout_type::size_M (size1_, size2_); 00091 const size_type sizem = layout_type::size_m (size1_, size2_); 00092 for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements 00093 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 00094 data_.insert_element (sizeM, vector_data_value_type ()); 00095 storage_invariants (); 00096 matrix_assign<scalar_assign> (*this, ae); 00097 } 00098 00099 // Accessors 00100 BOOST_UBLAS_INLINE 00101 size_type size1 () const { 00102 return size1_; 00103 } 00104 BOOST_UBLAS_INLINE 00105 size_type size2 () const { 00106 return size2_; 00107 } 00108 BOOST_UBLAS_INLINE 00109 size_type nnz_capacity () const { 00110 size_type non_zeros = 0; 00111 for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv) 00112 non_zeros += (*itv).nnz_capacity (); 00113 return non_zeros; 00114 } 00115 BOOST_UBLAS_INLINE 00116 size_type nnz () const { 00117 size_type non_zeros = 0; 00118 for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv) 00119 non_zeros += (*itv).nnz (); 00120 return non_zeros; 00121 } 00122 00123 // Storage accessors 00124 BOOST_UBLAS_INLINE 00125 const array_type &data () const { 00126 return data_; 00127 } 00128 BOOST_UBLAS_INLINE 00129 array_type &data () { 00130 return data_; 00131 } 00132 00133 // Resizing 00134 BOOST_UBLAS_INLINE 00135 void resize (size_type size1, size_type size2, bool preserve = true) { 00136 const size_type oldM = layout_type::size_M (size1_, size2_); 00137 size1_ = size1; 00138 size2_ = size2; 00139 const size_type sizeM = layout_type::size_M (size1_, size2_); 00140 const size_type sizem = layout_type::size_m (size1_, size2_); 00141 data ().resize (sizeM + 1, preserve); 00142 if (preserve) { 00143 for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i) 00144 ref (data () [i]).resize (sizem, preserve); 00145 for (size_type i = oldM+1; i < sizeM; ++ i) // create new vector elements 00146 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 00147 if (sizeM > oldM) { 00148 data_.insert_element (sizeM, vector_data_value_type ()); 00149 } else { 00150 ref (data () [sizeM]).resize (0, false); 00151 } 00152 } else { 00153 for (size_type i = 0; i < sizeM; ++ i) 00154 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false); 00155 data_.insert_element (sizeM, vector_data_value_type ()); 00156 } 00157 storage_invariants (); 00158 } 00159 00160 // Element support 00161 BOOST_UBLAS_INLINE 00162 pointer find_element (size_type i, size_type j) { 00163 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j)); 00164 } 00165 BOOST_UBLAS_INLINE 00166 const_pointer find_element (size_type i, size_type j) const { 00167 const size_type elementM = layout_type::index_M (i, j); 00168 const size_type elementm = layout_type::index_m (i, j); 00169 // optimise: check the storage_type and index directly if element always exists 00170 if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) { 00171 return & (data () [elementM] [elementm]); 00172 } 00173 else { 00174 const typename array_type::value_type *pv = data ().find_element (elementM); 00175 if (!pv) 00176 return 0; 00177 return pv->find_element (elementm); 00178 } 00179 } 00180 00181 // Element access 00182 BOOST_UBLAS_INLINE 00183 const_reference operator () (size_type i, size_type j) const { 00184 const_pointer p = find_element (i, j); 00185 // optimise: check the storage_type and index directly if element always exists 00186 if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) { 00187 BOOST_UBLAS_CHECK (p, internal_logic () ); 00188 return *p; 00189 } 00190 else { 00191 if (p) 00192 return *p; 00193 else 00194 return zero_; 00195 } 00196 } 00197 BOOST_UBLAS_INLINE 00198 reference operator () (size_type i, size_type j) { 00199 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE 00200 return at_element (i, j); 00201 #else 00202 return reference (*this, i, j); 00203 #endif 00204 } 00205 00206 // Assignment 00207 BOOST_UBLAS_INLINE 00208 generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) { 00209 if (this != &m) { 00210 size1_ = m.size1_; 00211 size2_ = m.size2_; 00212 data () = m.data (); 00213 } 00214 storage_invariants (); 00215 return *this; 00216 } 00217 BOOST_UBLAS_INLINE 00218 generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) { 00219 swap (m); 00220 return *this; 00221 } 00222 template<class AE> 00223 BOOST_UBLAS_INLINE 00224 generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) { 00225 self_type temporary (ae); 00226 return assign_temporary (temporary); 00227 } 00228 template<class AE> 00229 BOOST_UBLAS_INLINE 00230 generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) { 00231 matrix_assign<scalar_assign> (*this, ae); 00232 return *this; 00233 } 00234 template<class AE> 00235 BOOST_UBLAS_INLINE 00236 generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) { 00237 self_type temporary (*this + ae); 00238 return assign_temporary (temporary); 00239 } 00240 template<class AE> 00241 BOOST_UBLAS_INLINE 00242 generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) { 00243 matrix_assign<scalar_plus_assign> (*this, ae); 00244 return *this; 00245 } 00246 template<class AE> 00247 BOOST_UBLAS_INLINE 00248 generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) { 00249 self_type temporary (*this - ae); 00250 return assign_temporary (temporary); 00251 } 00252 template<class AE> 00253 BOOST_UBLAS_INLINE 00254 generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) { 00255 matrix_assign<scalar_minus_assign> (*this, ae); 00256 return *this; 00257 } 00258 template<class AT> 00259 BOOST_UBLAS_INLINE 00260 generalized_vector_of_vector& operator *= (const AT &at) { 00261 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 00262 return *this; 00263 } 00264 template<class AT> 00265 BOOST_UBLAS_INLINE 00266 generalized_vector_of_vector& operator /= (const AT &at) { 00267 matrix_assign_scalar<scalar_divides_assign> (*this, at); 00268 return *this; 00269 } 00270 00271 // Swapping 00272 BOOST_UBLAS_INLINE 00273 void swap (generalized_vector_of_vector &m) { 00274 if (this != &m) { 00275 std::swap (size1_, m.size1_); 00276 std::swap (size2_, m.size2_); 00277 data ().swap (m.data ()); 00278 } 00279 storage_invariants (); 00280 } 00281 BOOST_UBLAS_INLINE 00282 friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) { 00283 m1.swap (m2); 00284 } 00285 00286 // Sorting 00287 void sort () { 00288 vectoriterator_type itv (data ().begin ()); 00289 vectoriterator_type itv_end (data ().end ()); 00290 while (itv != itv_end) { 00291 (*itv).sort (); 00292 ++ itv; 00293 } 00294 } 00295 00296 // Element insertion and erasure 00297 BOOST_UBLAS_INLINE 00298 true_reference insert_element (size_type i, size_type j, const_reference t) { 00299 const size_type elementM = layout_type::index_M (i, j); 00300 const size_type elementm = layout_type::index_m (i, j); 00301 vector_data_value_type& vd (ref (data () [elementM])); 00302 storage_invariants (); 00303 return vd.insert_element (elementm, t); 00304 } 00305 BOOST_UBLAS_INLINE 00306 void append_element (size_type i, size_type j, const_reference t) { 00307 const size_type elementM = layout_type::index_M (i, j); 00308 const size_type elementm = layout_type::index_m (i, j); 00309 vector_data_value_type& vd (ref (data () [elementM])); 00310 storage_invariants (); 00311 return vd.append_element (elementm, t); 00312 } 00313 BOOST_UBLAS_INLINE 00314 void erase_element (size_type i, size_type j) { 00315 vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 00316 if (itv == data ().end ()) 00317 return; 00318 (*itv).erase_element (layout_type::index_m (i, j)); 00319 storage_invariants (); 00320 } 00321 BOOST_UBLAS_INLINE 00322 void clear () { 00323 const size_type sizeM = layout_type::size_M (size1_, size2_); 00324 // FIXME should clear data () if this is done via value_type/*zero*/() then it is not size preserving 00325 for (size_type i = 0; i < sizeM; ++ i) 00326 ref (data () [i]).clear (); 00327 storage_invariants (); 00328 } 00329 00330 // Iterator types 00331 private: 00332 // Use vector iterator 00333 typedef typename A::const_iterator const_vectoriterator_type; 00334 typedef typename A::iterator vectoriterator_type; 00335 typedef typename A::value_type::const_iterator const_subiterator_type; 00336 typedef typename A::value_type::iterator subiterator_type; 00337 00338 BOOST_UBLAS_INLINE 00339 true_reference at_element (size_type i, size_type j) { 00340 return ref (ref (data () [layout_type::index_M (i, j)]) [layout_type::index_m (i, j)]); 00341 } 00342 00343 public: 00344 class const_iterator1; 00345 class iterator1; 00346 class const_iterator2; 00347 class iterator2; 00348 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 00349 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 00350 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 00351 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 00352 00353 // Element lookup 00354 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. 00355 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { 00356 for (;;) { 00357 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 00358 const_vectoriterator_type itv_end (data ().end ()); 00359 if (itv == itv_end) 00360 return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 00361 00362 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 00363 const_subiterator_type it_end ((*itv).end ()); 00364 if (rank == 0) 00365 return const_iterator1 (*this, rank, i, j, itv, it); 00366 if (it != it_end && it.index () == layout_type::index_m (i, j)) 00367 return const_iterator1 (*this, rank, i, j, itv, it); 00368 if (direction > 0) { 00369 if (layout_type::fast_i ()) { 00370 if (it == it_end) 00371 return const_iterator1 (*this, rank, i, j, itv, it); 00372 i = it.index (); 00373 } else { 00374 if (i >= size1_) 00375 return const_iterator1 (*this, rank, i, j, itv, it); 00376 ++ i; 00377 } 00378 } else /* if (direction < 0) */ { 00379 if (layout_type::fast_i ()) { 00380 if (it == (*itv).begin ()) 00381 return const_iterator1 (*this, rank, i, j, itv, it); 00382 --it; 00383 i = it.index (); 00384 } else { 00385 if (i == 0) 00386 return const_iterator1 (*this, rank, i, j, itv, it); 00387 -- i; 00388 } 00389 } 00390 } 00391 } 00392 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. 00393 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { 00394 for (;;) { 00395 vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 00396 vectoriterator_type itv_end (data ().end ()); 00397 if (itv == itv_end) 00398 return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 00399 00400 subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 00401 subiterator_type it_end ((*itv).end ()); 00402 if (rank == 0) 00403 return iterator1 (*this, rank, i, j, itv, it); 00404 if (it != it_end && it.index () == layout_type::index_m (i, j)) 00405 return iterator1 (*this, rank, i, j, itv, it); 00406 if (direction > 0) { 00407 if (layout_type::fast_i ()) { 00408 if (it == it_end) 00409 return iterator1 (*this, rank, i, j, itv, it); 00410 i = it.index (); 00411 } else { 00412 if (i >= size1_) 00413 return iterator1 (*this, rank, i, j, itv, it); 00414 ++ i; 00415 } 00416 } else /* if (direction < 0) */ { 00417 if (layout_type::fast_i ()) { 00418 if (it == (*itv).begin ()) 00419 return iterator1 (*this, rank, i, j, itv, it); 00420 --it; 00421 i = it.index (); 00422 } else { 00423 if (i == 0) 00424 return iterator1 (*this, rank, i, j, itv, it); 00425 -- i; 00426 } 00427 } 00428 } 00429 } 00430 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. 00431 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { 00432 for (;;) { 00433 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 00434 const_vectoriterator_type itv_end (data ().end ()); 00435 if (itv == itv_end) 00436 return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 00437 00438 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 00439 const_subiterator_type it_end ((*itv).end ()); 00440 if (rank == 0) 00441 return const_iterator2 (*this, rank, i, j, itv, it); 00442 if (it != it_end && it.index () == layout_type::index_m (i, j)) 00443 return const_iterator2 (*this, rank, i, j, itv, it); 00444 if (direction > 0) { 00445 if (layout_type::fast_j ()) { 00446 if (it == it_end) 00447 return const_iterator2 (*this, rank, i, j, itv, it); 00448 j = it.index (); 00449 } else { 00450 if (j >= size2_) 00451 return const_iterator2 (*this, rank, i, j, itv, it); 00452 ++ j; 00453 } 00454 } else /* if (direction < 0) */ { 00455 if (layout_type::fast_j ()) { 00456 if (it == (*itv).begin ()) 00457 return const_iterator2 (*this, rank, i, j, itv, it); 00458 --it; 00459 j = it.index (); 00460 } else { 00461 if (j == 0) 00462 return const_iterator2 (*this, rank, i, j, itv, it); 00463 -- j; 00464 } 00465 } 00466 } 00467 } 00468 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. 00469 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { 00470 for (;;) { 00471 vectoriterator_type itv (data ().find (layout_type::index_M (i, j))); 00472 vectoriterator_type itv_end (data ().end ()); 00473 if (itv == itv_end) 00474 return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ()); 00475 00476 subiterator_type it ((*itv).find (layout_type::index_m (i, j))); 00477 subiterator_type it_end ((*itv).end ()); 00478 if (rank == 0) 00479 return iterator2 (*this, rank, i, j, itv, it); 00480 if (it != it_end && it.index () == layout_type::index_m (i, j)) 00481 return iterator2 (*this, rank, i, j, itv, it); 00482 if (direction > 0) { 00483 if (layout_type::fast_j ()) { 00484 if (it == it_end) 00485 return iterator2 (*this, rank, i, j, itv, it); 00486 j = it.index (); 00487 } else { 00488 if (j >= size2_) 00489 return iterator2 (*this, rank, i, j, itv, it); 00490 ++ j; 00491 } 00492 } else /* if (direction < 0) */ { 00493 if (layout_type::fast_j ()) { 00494 if (it == (*itv).begin ()) 00495 return iterator2 (*this, rank, i, j, itv, it); 00496 --it; 00497 j = it.index (); 00498 } else { 00499 if (j == 0) 00500 return iterator2 (*this, rank, i, j, itv, it); 00501 -- j; 00502 } 00503 } 00504 } 00505 } 00506 00507 00508 class const_iterator1: 00509 public container_const_reference<generalized_vector_of_vector>, 00510 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 00511 const_iterator1, value_type> { 00512 public: 00513 typedef typename generalized_vector_of_vector::difference_type difference_type; 00514 typedef typename generalized_vector_of_vector::value_type value_type; 00515 typedef typename generalized_vector_of_vector::const_reference reference; 00516 typedef const typename generalized_vector_of_vector::pointer pointer; 00517 00518 typedef const_iterator2 dual_iterator_type; 00519 typedef const_reverse_iterator2 dual_reverse_iterator_type; 00520 00521 // Construction and destruction 00522 BOOST_UBLAS_INLINE 00523 const_iterator1 (): 00524 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 00525 BOOST_UBLAS_INLINE 00526 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it): 00527 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 00528 BOOST_UBLAS_INLINE 00529 const_iterator1 (const iterator1 &it): 00530 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} 00531 00532 // Arithmetic 00533 BOOST_UBLAS_INLINE 00534 const_iterator1 &operator ++ () { 00535 if (rank_ == 1 && layout_type::fast_i ()) 00536 ++ it_; 00537 else { 00538 const self_type &m = (*this) (); 00539 i_ = index1 () + 1; 00540 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) 00541 *this = m.find1 (rank_, i_, j_, 1); 00542 else if (rank_ == 1) { 00543 it_ = (*itv_).begin (); 00544 if (it_ == (*itv_).end () || index2 () != j_) 00545 *this = m.find1 (rank_, i_, j_, 1); 00546 } 00547 } 00548 return *this; 00549 } 00550 BOOST_UBLAS_INLINE 00551 const_iterator1 &operator -- () { 00552 if (rank_ == 1 && layout_type::fast_i ()) 00553 -- it_; 00554 else { 00555 const self_type &m = (*this) (); 00556 i_ = index1 () - 1; 00557 if (rank_ == 1 && -- itv_ == m.end1 ().itv_) 00558 *this = m.find1 (rank_, i_, j_, -1); 00559 else if (rank_ == 1) { 00560 it_ = (*itv_).begin (); 00561 if (it_ == (*itv_).end () || index2 () != j_) 00562 *this = m.find1 (rank_, i_, j_, -1); 00563 } 00564 } 00565 return *this; 00566 } 00567 00568 // Dereference 00569 BOOST_UBLAS_INLINE 00570 const_reference operator * () const { 00571 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 00572 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 00573 if (rank_ == 1) { 00574 return *it_; 00575 } else { 00576 return (*this) () (i_, j_); 00577 } 00578 } 00579 00580 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00581 BOOST_UBLAS_INLINE 00582 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00583 typename self_type:: 00584 #endif 00585 const_iterator2 begin () const { 00586 const self_type &m = (*this) (); 00587 return m.find2 (1, index1 (), 0); 00588 } 00589 BOOST_UBLAS_INLINE 00590 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00591 typename self_type:: 00592 #endif 00593 const_iterator2 end () const { 00594 const self_type &m = (*this) (); 00595 return m.find2 (1, index1 (), m.size2 ()); 00596 } 00597 BOOST_UBLAS_INLINE 00598 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00599 typename self_type:: 00600 #endif 00601 const_reverse_iterator2 rbegin () const { 00602 return const_reverse_iterator2 (end ()); 00603 } 00604 BOOST_UBLAS_INLINE 00605 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00606 typename self_type:: 00607 #endif 00608 const_reverse_iterator2 rend () const { 00609 return const_reverse_iterator2 (begin ()); 00610 } 00611 #endif 00612 00613 // Indices 00614 BOOST_UBLAS_INLINE 00615 size_type index1 () const { 00616 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 00617 if (rank_ == 1) { 00618 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 00619 return layout_type::index_M (itv_.index (), it_.index ()); 00620 } else { 00621 return i_; 00622 } 00623 } 00624 BOOST_UBLAS_INLINE 00625 size_type index2 () const { 00626 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 00627 if (rank_ == 1) { 00628 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 00629 return layout_type::index_m (itv_.index (), it_.index ()); 00630 } else { 00631 return j_; 00632 } 00633 } 00634 00635 // Assignment 00636 BOOST_UBLAS_INLINE 00637 const_iterator1 &operator = (const const_iterator1 &it) { 00638 container_const_reference<self_type>::assign (&it ()); 00639 rank_ = it.rank_; 00640 i_ = it.i_; 00641 j_ = it.j_; 00642 itv_ = it.itv_; 00643 it_ = it.it_; 00644 return *this; 00645 } 00646 00647 // Comparison 00648 BOOST_UBLAS_INLINE 00649 bool operator == (const const_iterator1 &it) const { 00650 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00651 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 00652 if (rank_ == 1 || it.rank_ == 1) { 00653 return it_ == it.it_; 00654 } else { 00655 return i_ == it.i_ && j_ == it.j_; 00656 } 00657 } 00658 00659 private: 00660 int rank_; 00661 size_type i_; 00662 size_type j_; 00663 const_vectoriterator_type itv_; 00664 const_subiterator_type it_; 00665 }; 00666 00667 BOOST_UBLAS_INLINE 00668 const_iterator1 begin1 () const { 00669 return find1 (0, 0, 0); 00670 } 00671 BOOST_UBLAS_INLINE 00672 const_iterator1 end1 () const { 00673 return find1 (0, size1_, 0); 00674 } 00675 00676 class iterator1: 00677 public container_reference<generalized_vector_of_vector>, 00678 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 00679 iterator1, value_type> { 00680 public: 00681 typedef typename generalized_vector_of_vector::difference_type difference_type; 00682 typedef typename generalized_vector_of_vector::value_type value_type; 00683 typedef typename generalized_vector_of_vector::true_reference reference; 00684 typedef typename generalized_vector_of_vector::pointer pointer; 00685 00686 typedef iterator2 dual_iterator_type; 00687 typedef reverse_iterator2 dual_reverse_iterator_type; 00688 00689 // Construction and destruction 00690 BOOST_UBLAS_INLINE 00691 iterator1 (): 00692 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 00693 BOOST_UBLAS_INLINE 00694 iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it): 00695 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 00696 00697 // Arithmetic 00698 BOOST_UBLAS_INLINE 00699 iterator1 &operator ++ () { 00700 if (rank_ == 1 && layout_type::fast_i ()) 00701 ++ it_; 00702 else { 00703 self_type &m = (*this) (); 00704 i_ = index1 () + 1; 00705 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) 00706 *this = m.find1 (rank_, i_, j_, 1); 00707 else if (rank_ == 1) { 00708 it_ = (*itv_).begin (); 00709 if (it_ == (*itv_).end () || index2 () != j_) 00710 *this = m.find1 (rank_, i_, j_, 1); 00711 } 00712 } 00713 return *this; 00714 } 00715 BOOST_UBLAS_INLINE 00716 iterator1 &operator -- () { 00717 if (rank_ == 1 && layout_type::fast_i ()) 00718 -- it_; 00719 else { 00720 self_type &m = (*this) (); 00721 i_ = index1 () - 1; 00722 if (rank_ == 1 && -- itv_ == m.end1 ().itv_) 00723 *this = m.find1 (rank_, i_, j_, -1); 00724 else if (rank_ == 1) { 00725 it_ = (*itv_).begin (); 00726 if (it_ == (*itv_).end () || index2 () != j_) 00727 *this = m.find1 (rank_, i_, j_, -1); 00728 } 00729 } 00730 return *this; 00731 } 00732 00733 // Dereference 00734 BOOST_UBLAS_INLINE 00735 true_reference operator * () const { 00736 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 00737 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 00738 if (rank_ == 1) { 00739 return *it_; 00740 } else { 00741 return (*this) ().at_element (i_, j_); 00742 } 00743 } 00744 00745 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00746 BOOST_UBLAS_INLINE 00747 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00748 typename self_type:: 00749 #endif 00750 iterator2 begin () const { 00751 self_type &m = (*this) (); 00752 return m.find2 (1, index1 (), 0); 00753 } 00754 BOOST_UBLAS_INLINE 00755 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00756 typename self_type:: 00757 #endif 00758 iterator2 end () const { 00759 self_type &m = (*this) (); 00760 return m.find2 (1, index1 (), m.size2 ()); 00761 } 00762 BOOST_UBLAS_INLINE 00763 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00764 typename self_type:: 00765 #endif 00766 reverse_iterator2 rbegin () const { 00767 return reverse_iterator2 (end ()); 00768 } 00769 BOOST_UBLAS_INLINE 00770 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00771 typename self_type:: 00772 #endif 00773 reverse_iterator2 rend () const { 00774 return reverse_iterator2 (begin ()); 00775 } 00776 #endif 00777 00778 // Indices 00779 BOOST_UBLAS_INLINE 00780 size_type index1 () const { 00781 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 00782 if (rank_ == 1) { 00783 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 00784 return layout_type::index_M (itv_.index (), it_.index ()); 00785 } else { 00786 return i_; 00787 } 00788 } 00789 BOOST_UBLAS_INLINE 00790 size_type index2 () const { 00791 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); 00792 if (rank_ == 1) { 00793 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 00794 return layout_type::index_m (itv_.index (), it_.index ()); 00795 } else { 00796 return j_; 00797 } 00798 } 00799 00800 // Assignment 00801 BOOST_UBLAS_INLINE 00802 iterator1 &operator = (const iterator1 &it) { 00803 container_reference<self_type>::assign (&it ()); 00804 rank_ = it.rank_; 00805 i_ = it.i_; 00806 j_ = it.j_; 00807 itv_ = it.itv_; 00808 it_ = it.it_; 00809 return *this; 00810 } 00811 00812 // Comparison 00813 BOOST_UBLAS_INLINE 00814 bool operator == (const iterator1 &it) const { 00815 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00816 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 00817 if (rank_ == 1 || it.rank_ == 1) { 00818 return it_ == it.it_; 00819 } else { 00820 return i_ == it.i_ && j_ == it.j_; 00821 } 00822 } 00823 00824 private: 00825 int rank_; 00826 size_type i_; 00827 size_type j_; 00828 vectoriterator_type itv_; 00829 subiterator_type it_; 00830 00831 friend class const_iterator1; 00832 }; 00833 00834 BOOST_UBLAS_INLINE 00835 iterator1 begin1 () { 00836 return find1 (0, 0, 0); 00837 } 00838 BOOST_UBLAS_INLINE 00839 iterator1 end1 () { 00840 return find1 (0, size1_, 0); 00841 } 00842 00843 class const_iterator2: 00844 public container_const_reference<generalized_vector_of_vector>, 00845 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 00846 const_iterator2, value_type> { 00847 public: 00848 typedef typename generalized_vector_of_vector::difference_type difference_type; 00849 typedef typename generalized_vector_of_vector::value_type value_type; 00850 typedef typename generalized_vector_of_vector::const_reference reference; 00851 typedef const typename generalized_vector_of_vector::pointer pointer; 00852 00853 typedef const_iterator1 dual_iterator_type; 00854 typedef const_reverse_iterator1 dual_reverse_iterator_type; 00855 00856 // Construction and destruction 00857 BOOST_UBLAS_INLINE 00858 const_iterator2 (): 00859 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 00860 BOOST_UBLAS_INLINE 00861 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it): 00862 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 00863 BOOST_UBLAS_INLINE 00864 const_iterator2 (const iterator2 &it): 00865 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} 00866 00867 // Arithmetic 00868 BOOST_UBLAS_INLINE 00869 const_iterator2 &operator ++ () { 00870 if (rank_ == 1 && layout_type::fast_j ()) 00871 ++ it_; 00872 else { 00873 const self_type &m = (*this) (); 00874 j_ = index2 () + 1; 00875 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) 00876 *this = m.find2 (rank_, i_, j_, 1); 00877 else if (rank_ == 1) { 00878 it_ = (*itv_).begin (); 00879 if (it_ == (*itv_).end () || index1 () != i_) 00880 *this = m.find2 (rank_, i_, j_, 1); 00881 } 00882 } 00883 return *this; 00884 } 00885 BOOST_UBLAS_INLINE 00886 const_iterator2 &operator -- () { 00887 if (rank_ == 1 && layout_type::fast_j ()) 00888 -- it_; 00889 else { 00890 const self_type &m = (*this) (); 00891 j_ = index2 () - 1; 00892 if (rank_ == 1 && -- itv_ == m.end2 ().itv_) 00893 *this = m.find2 (rank_, i_, j_, -1); 00894 else if (rank_ == 1) { 00895 it_ = (*itv_).begin (); 00896 if (it_ == (*itv_).end () || index1 () != i_) 00897 *this = m.find2 (rank_, i_, j_, -1); 00898 } 00899 } 00900 return *this; 00901 } 00902 00903 // Dereference 00904 BOOST_UBLAS_INLINE 00905 const_reference operator * () const { 00906 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 00907 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 00908 if (rank_ == 1) { 00909 return *it_; 00910 } else { 00911 return (*this) () (i_, j_); 00912 } 00913 } 00914 00915 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00916 BOOST_UBLAS_INLINE 00917 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00918 typename self_type:: 00919 #endif 00920 const_iterator1 begin () const { 00921 const self_type &m = (*this) (); 00922 return m.find1 (1, 0, index2 ()); 00923 } 00924 BOOST_UBLAS_INLINE 00925 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00926 typename self_type:: 00927 #endif 00928 const_iterator1 end () const { 00929 const self_type &m = (*this) (); 00930 return m.find1 (1, m.size1 (), index2 ()); 00931 } 00932 BOOST_UBLAS_INLINE 00933 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00934 typename self_type:: 00935 #endif 00936 const_reverse_iterator1 rbegin () const { 00937 return const_reverse_iterator1 (end ()); 00938 } 00939 BOOST_UBLAS_INLINE 00940 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00941 typename self_type:: 00942 #endif 00943 const_reverse_iterator1 rend () const { 00944 return const_reverse_iterator1 (begin ()); 00945 } 00946 #endif 00947 00948 // Indices 00949 BOOST_UBLAS_INLINE 00950 size_type index1 () const { 00951 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 00952 if (rank_ == 1) { 00953 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 00954 return layout_type::index_M (itv_.index (), it_.index ()); 00955 } else { 00956 return i_; 00957 } 00958 } 00959 BOOST_UBLAS_INLINE 00960 size_type index2 () const { 00961 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 00962 if (rank_ == 1) { 00963 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 00964 return layout_type::index_m (itv_.index (), it_.index ()); 00965 } else { 00966 return j_; 00967 } 00968 } 00969 00970 // Assignment 00971 BOOST_UBLAS_INLINE 00972 const_iterator2 &operator = (const const_iterator2 &it) { 00973 container_const_reference<self_type>::assign (&it ()); 00974 rank_ = it.rank_; 00975 i_ = it.i_; 00976 j_ = it.j_; 00977 itv_ = it.itv_; 00978 it_ = it.it_; 00979 return *this; 00980 } 00981 00982 // Comparison 00983 BOOST_UBLAS_INLINE 00984 bool operator == (const const_iterator2 &it) const { 00985 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00986 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 00987 if (rank_ == 1 || it.rank_ == 1) { 00988 return it_ == it.it_; 00989 } else { 00990 return i_ == it.i_ && j_ == it.j_; 00991 } 00992 } 00993 00994 private: 00995 int rank_; 00996 size_type i_; 00997 size_type j_; 00998 const_vectoriterator_type itv_; 00999 const_subiterator_type it_; 01000 }; 01001 01002 BOOST_UBLAS_INLINE 01003 const_iterator2 begin2 () const { 01004 return find2 (0, 0, 0); 01005 } 01006 BOOST_UBLAS_INLINE 01007 const_iterator2 end2 () const { 01008 return find2 (0, 0, size2_); 01009 } 01010 01011 class iterator2: 01012 public container_reference<generalized_vector_of_vector>, 01013 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 01014 iterator2, value_type> { 01015 public: 01016 typedef typename generalized_vector_of_vector::difference_type difference_type; 01017 typedef typename generalized_vector_of_vector::value_type value_type; 01018 typedef typename generalized_vector_of_vector::true_reference reference; 01019 typedef typename generalized_vector_of_vector::pointer pointer; 01020 01021 typedef iterator1 dual_iterator_type; 01022 typedef reverse_iterator1 dual_reverse_iterator_type; 01023 01024 // Construction and destruction 01025 BOOST_UBLAS_INLINE 01026 iterator2 (): 01027 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} 01028 BOOST_UBLAS_INLINE 01029 iterator2 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it): 01030 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} 01031 01032 // Arithmetic 01033 BOOST_UBLAS_INLINE 01034 iterator2 &operator ++ () { 01035 if (rank_ == 1 && layout_type::fast_j ()) 01036 ++ it_; 01037 else { 01038 self_type &m = (*this) (); 01039 j_ = index2 () + 1; 01040 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) 01041 *this = m.find2 (rank_, i_, j_, 1); 01042 else if (rank_ == 1) { 01043 it_ = (*itv_).begin (); 01044 if (it_ == (*itv_).end () || index1 () != i_) 01045 *this = m.find2 (rank_, i_, j_, 1); 01046 } 01047 } 01048 return *this; 01049 } 01050 BOOST_UBLAS_INLINE 01051 iterator2 &operator -- () { 01052 if (rank_ == 1 && layout_type::fast_j ()) 01053 -- it_; 01054 else { 01055 self_type &m = (*this) (); 01056 j_ = index2 () - 1; 01057 if (rank_ == 1 && -- itv_ == m.end2 ().itv_) 01058 *this = m.find2 (rank_, i_, j_, -1); 01059 else if (rank_ == 1) { 01060 it_ = (*itv_).begin (); 01061 if (it_ == (*itv_).end () || index1 () != i_) 01062 *this = m.find2 (rank_, i_, j_, -1); 01063 } 01064 } 01065 return *this; 01066 } 01067 01068 // Dereference 01069 BOOST_UBLAS_INLINE 01070 true_reference operator * () const { 01071 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 01072 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 01073 if (rank_ == 1) { 01074 return *it_; 01075 } else { 01076 return (*this) ().at_element (i_, j_); 01077 } 01078 } 01079 01080 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 01081 BOOST_UBLAS_INLINE 01082 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01083 typename self_type:: 01084 #endif 01085 iterator1 begin () const { 01086 self_type &m = (*this) (); 01087 return m.find1 (1, 0, index2 ()); 01088 } 01089 BOOST_UBLAS_INLINE 01090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01091 typename self_type:: 01092 #endif 01093 iterator1 end () const { 01094 self_type &m = (*this) (); 01095 return m.find1 (1, m.size1 (), index2 ()); 01096 } 01097 BOOST_UBLAS_INLINE 01098 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01099 typename self_type:: 01100 #endif 01101 reverse_iterator1 rbegin () const { 01102 return reverse_iterator1 (end ()); 01103 } 01104 BOOST_UBLAS_INLINE 01105 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01106 typename self_type:: 01107 #endif 01108 reverse_iterator1 rend () const { 01109 return reverse_iterator1 (begin ()); 01110 } 01111 #endif 01112 01113 // Indices 01114 BOOST_UBLAS_INLINE 01115 size_type index1 () const { 01116 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 01117 if (rank_ == 1) { 01118 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ()); 01119 return layout_type::index_M (itv_.index (), it_.index ()); 01120 } else { 01121 return i_; 01122 } 01123 } 01124 BOOST_UBLAS_INLINE 01125 size_type index2 () const { 01126 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); 01127 if (rank_ == 1) { 01128 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ()); 01129 return layout_type::index_m (itv_.index (), it_.index ()); 01130 } else { 01131 return j_; 01132 } 01133 } 01134 01135 // Assignment 01136 BOOST_UBLAS_INLINE 01137 iterator2 &operator = (const iterator2 &it) { 01138 container_reference<self_type>::assign (&it ()); 01139 rank_ = it.rank_; 01140 i_ = it.i_; 01141 j_ = it.j_; 01142 itv_ = it.itv_; 01143 it_ = it.it_; 01144 return *this; 01145 } 01146 01147 // Comparison 01148 BOOST_UBLAS_INLINE 01149 bool operator == (const iterator2 &it) const { 01150 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01151 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); 01152 if (rank_ == 1 || it.rank_ == 1) { 01153 return it_ == it.it_; 01154 } else { 01155 return i_ == it.i_ && j_ == it.j_; 01156 } 01157 } 01158 01159 private: 01160 int rank_; 01161 size_type i_; 01162 size_type j_; 01163 vectoriterator_type itv_; 01164 subiterator_type it_; 01165 01166 friend class const_iterator2; 01167 }; 01168 01169 BOOST_UBLAS_INLINE 01170 iterator2 begin2 () { 01171 return find2 (0, 0, 0); 01172 } 01173 BOOST_UBLAS_INLINE 01174 iterator2 end2 () { 01175 return find2 (0, 0, size2_); 01176 } 01177 01178 // Reverse iterators 01179 01180 BOOST_UBLAS_INLINE 01181 const_reverse_iterator1 rbegin1 () const { 01182 return const_reverse_iterator1 (end1 ()); 01183 } 01184 BOOST_UBLAS_INLINE 01185 const_reverse_iterator1 rend1 () const { 01186 return const_reverse_iterator1 (begin1 ()); 01187 } 01188 01189 BOOST_UBLAS_INLINE 01190 reverse_iterator1 rbegin1 () { 01191 return reverse_iterator1 (end1 ()); 01192 } 01193 BOOST_UBLAS_INLINE 01194 reverse_iterator1 rend1 () { 01195 return reverse_iterator1 (begin1 ()); 01196 } 01197 01198 BOOST_UBLAS_INLINE 01199 const_reverse_iterator2 rbegin2 () const { 01200 return const_reverse_iterator2 (end2 ()); 01201 } 01202 BOOST_UBLAS_INLINE 01203 const_reverse_iterator2 rend2 () const { 01204 return const_reverse_iterator2 (begin2 ()); 01205 } 01206 01207 BOOST_UBLAS_INLINE 01208 reverse_iterator2 rbegin2 () { 01209 return reverse_iterator2 (end2 ()); 01210 } 01211 BOOST_UBLAS_INLINE 01212 reverse_iterator2 rend2 () { 01213 return reverse_iterator2 (begin2 ()); 01214 } 01215 01216 // Serialization 01217 template<class Archive> 01218 void serialize(Archive & ar, const unsigned int /* file_version */){ 01219 01220 // we need to copy to a collection_size_type to get a portable 01221 // and efficient serialization 01222 serialization::collection_size_type s1 (size1_); 01223 serialization::collection_size_type s2 (size2_); 01224 01225 // serialize the sizes 01226 ar & serialization::make_nvp("size1",s1) 01227 & serialization::make_nvp("size2",s2); 01228 01229 // copy the values back if loading 01230 if (Archive::is_loading::value) { 01231 size1_ = s1; 01232 size2_ = s2; 01233 } 01234 01235 ar & serialization::make_nvp("data", data_); 01236 01237 storage_invariants(); 01238 } 01239 01240 private: 01241 void storage_invariants () const 01242 { 01243 BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == data_.size (), internal_logic ()); 01244 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); 01245 01246 } 01247 size_type size1_; 01248 size_type size2_; 01249 array_type data_; 01250 static const value_type zero_; 01251 }; 01252 01253 template<class T, class L, class A> 01254 const typename generalized_vector_of_vector<T, L, A>::value_type generalized_vector_of_vector<T, L, A>::zero_ = value_type/*zero*/(); 01255 01256 }}} 01257 01258 #endif