00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00022
00023 namespace boost { namespace numeric { namespace ublas {
00024
00025
00026
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
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
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)
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)
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
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
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
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)
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
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
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
00182 BOOST_UBLAS_INLINE
00183 const_reference operator () (size_type i, size_type j) const {
00184 const_pointer p = find_element (i, j);
00185
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
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
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
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
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
00325 for (size_type i = 0; i < sizeM; ++ i)
00326 ref (data () [i]).clear ();
00327 storage_invariants ();
00328 }
00329
00330
00331 private:
00332
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
00354
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 {
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
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 {
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
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 {
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
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 {
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
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
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
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
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
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
00648 BOOST_UBLAS_INLINE
00649 bool operator == (const const_iterator1 &it) const {
00650 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00651
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
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
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
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
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
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
00813 BOOST_UBLAS_INLINE
00814 bool operator == (const iterator1 &it) const {
00815 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00816
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
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
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
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
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
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
00983 BOOST_UBLAS_INLINE
00984 bool operator == (const const_iterator2 &it) const {
00985 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00986
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
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
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
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
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
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
01148 BOOST_UBLAS_INLINE
01149 bool operator == (const iterator2 &it) const {
01150 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01151
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
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
01217 template<class Archive>
01218 void serialize(Archive & ar, const unsigned int ){
01219
01220
01221
01222 serialization::collection_size_type s1 (size1_);
01223 serialization::collection_size_type s2 (size2_);
01224
01225
01226 ar & serialization::make_nvp("size1",s1)
01227 & serialization::make_nvp("size2",s2);
01228
01229
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();
01255
01256 }}}
01257
01258 #endif