File indexing completed on 2025-01-18 09:43:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef _BOOST_UBLAS_VECTOR_OF_VECTOR_
0014 #define _BOOST_UBLAS_VECTOR_OF_VECTOR_
0015
0016 #include <boost/type_traits.hpp>
0017
0018 #include <boost/numeric/ublas/storage_sparse.hpp>
0019 #include <boost/numeric/ublas/matrix_sparse.hpp>
0020
0021
0022
0023 namespace boost { namespace numeric { namespace ublas {
0024
0025
0026
0027 template<class T, class L, class A>
0028 class generalized_vector_of_vector:
0029 public matrix_container<generalized_vector_of_vector<T, L, A> > {
0030
0031 typedef T &true_reference;
0032 typedef T *pointer;
0033 typedef const T *const_pointer;
0034 typedef L layout_type;
0035 typedef generalized_vector_of_vector<T, L, A> self_type;
0036 public:
0037 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0038 using matrix_container<self_type>::operator ();
0039 #endif
0040 typedef typename A::size_type size_type;
0041 typedef typename A::difference_type difference_type;
0042 typedef T value_type;
0043 typedef const T &const_reference;
0044 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
0045 typedef T &reference;
0046 #else
0047 typedef sparse_matrix_element<self_type> reference;
0048 #endif
0049 typedef A array_type;
0050 typedef const matrix_reference<const self_type> const_closure_type;
0051 typedef matrix_reference<self_type> closure_type;
0052 typedef typename A::value_type vector_data_value_type;
0053 typedef vector_data_value_type vector_temporary_type;
0054 typedef self_type matrix_temporary_type;
0055 typedef sparse_tag storage_category;
0056 typedef typename L::orientation_category orientation_category;
0057
0058
0059 BOOST_UBLAS_INLINE
0060 generalized_vector_of_vector ():
0061 matrix_container<self_type> (),
0062 size1_ (0), size2_ (0), data_ (1) {
0063 const size_type sizeM = layout_type::size_M (size1_, size2_);
0064
0065 data_.insert_element (sizeM, vector_data_value_type ());
0066 storage_invariants ();
0067 }
0068 BOOST_UBLAS_INLINE
0069 generalized_vector_of_vector (size_type size1, size_type size2, size_type ):
0070 matrix_container<self_type> (),
0071 size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) {
0072 const size_type sizeM = layout_type::size_M (size1_, size2_);
0073 const size_type sizem = layout_type::size_m (size1_, size2_);
0074 for (size_type i = 0; i < sizeM; ++ i)
0075 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0076 data_.insert_element (sizeM, vector_data_value_type ());
0077 storage_invariants ();
0078 }
0079 BOOST_UBLAS_INLINE
0080 generalized_vector_of_vector (const generalized_vector_of_vector &m):
0081 matrix_container<self_type> (),
0082 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {
0083 storage_invariants ();
0084 }
0085 template<class AE>
0086 BOOST_UBLAS_INLINE
0087 generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type ):
0088 matrix_container<self_type> (),
0089 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
0090 const size_type sizeM = layout_type::size_M (size1_, size2_);
0091 const size_type sizem = layout_type::size_m (size1_, size2_);
0092 for (size_type i = 0; i < sizeM; ++ i)
0093 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0094 data_.insert_element (sizeM, vector_data_value_type ());
0095 storage_invariants ();
0096 matrix_assign<scalar_assign> (*this, ae);
0097 }
0098
0099
0100 BOOST_UBLAS_INLINE
0101 size_type size1 () const {
0102 return size1_;
0103 }
0104 BOOST_UBLAS_INLINE
0105 size_type size2 () const {
0106 return size2_;
0107 }
0108 BOOST_UBLAS_INLINE
0109 size_type nnz_capacity () const {
0110 size_type non_zeros = 0;
0111 for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
0112 non_zeros += (*itv).nnz_capacity ();
0113 return non_zeros;
0114 }
0115 BOOST_UBLAS_INLINE
0116 size_type nnz () const {
0117 size_type non_zeros = 0;
0118 for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
0119 non_zeros += (*itv).nnz ();
0120 return non_zeros;
0121 }
0122
0123
0124 BOOST_UBLAS_INLINE
0125 const array_type &data () const {
0126 return data_;
0127 }
0128 BOOST_UBLAS_INLINE
0129 array_type &data () {
0130 return data_;
0131 }
0132
0133
0134 BOOST_UBLAS_INLINE
0135 void resize (size_type size1, size_type size2, bool preserve = true) {
0136 const size_type oldM = layout_type::size_M (size1_, size2_);
0137 size1_ = size1;
0138 size2_ = size2;
0139 const size_type sizeM = layout_type::size_M (size1_, size2_);
0140 const size_type sizem = layout_type::size_m (size1_, size2_);
0141 data ().resize (sizeM + 1, preserve);
0142 if (preserve) {
0143 for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i)
0144 ref (data () [i]).resize (sizem, preserve);
0145 for (size_type i = oldM+1; i < sizeM; ++ i)
0146 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0147 if (sizeM > oldM) {
0148 data_.insert_element (sizeM, vector_data_value_type ());
0149 } else {
0150 ref (data () [sizeM]).resize (0, false);
0151 }
0152 } else {
0153 for (size_type i = 0; i < sizeM; ++ i)
0154 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0155 data_.insert_element (sizeM, vector_data_value_type ());
0156 }
0157 storage_invariants ();
0158 }
0159
0160
0161 BOOST_UBLAS_INLINE
0162 pointer find_element (size_type i, size_type j) {
0163 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
0164 }
0165 BOOST_UBLAS_INLINE
0166 const_pointer find_element (size_type i, size_type j) const {
0167 const size_type elementM = layout_type::index_M (i, j);
0168 const size_type elementm = layout_type::index_m (i, j);
0169
0170 if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
0171 return & (data () [elementM] [elementm]);
0172 }
0173 else {
0174 const typename array_type::value_type *pv = data ().find_element (elementM);
0175 if (!pv)
0176 return 0;
0177 return pv->find_element (elementm);
0178 }
0179 }
0180
0181
0182 BOOST_UBLAS_INLINE
0183 const_reference operator () (size_type i, size_type j) const {
0184 const_pointer p = find_element (i, j);
0185
0186 if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
0187 BOOST_UBLAS_CHECK (p, internal_logic () );
0188 return *p;
0189 }
0190 else {
0191 if (p)
0192 return *p;
0193 else
0194 return zero_;
0195 }
0196 }
0197 BOOST_UBLAS_INLINE
0198 reference operator () (size_type i, size_type j) {
0199 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
0200 return at_element (i, j);
0201 #else
0202 return reference (*this, i, j);
0203 #endif
0204 }
0205
0206
0207 BOOST_UBLAS_INLINE
0208 generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) {
0209 if (this != &m) {
0210 size1_ = m.size1_;
0211 size2_ = m.size2_;
0212 data () = m.data ();
0213 }
0214 storage_invariants ();
0215 return *this;
0216 }
0217 BOOST_UBLAS_INLINE
0218 generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) {
0219 swap (m);
0220 return *this;
0221 }
0222 template<class AE>
0223 BOOST_UBLAS_INLINE
0224 generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) {
0225 self_type temporary (ae);
0226 return assign_temporary (temporary);
0227 }
0228 template<class AE>
0229 BOOST_UBLAS_INLINE
0230 generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) {
0231 matrix_assign<scalar_assign> (*this, ae);
0232 return *this;
0233 }
0234 template<class AE>
0235 BOOST_UBLAS_INLINE
0236 generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) {
0237 self_type temporary (*this + ae);
0238 return assign_temporary (temporary);
0239 }
0240 template<class AE>
0241 BOOST_UBLAS_INLINE
0242 generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
0243 matrix_assign<scalar_plus_assign> (*this, ae);
0244 return *this;
0245 }
0246 template<class AE>
0247 BOOST_UBLAS_INLINE
0248 generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
0249 self_type temporary (*this - ae);
0250 return assign_temporary (temporary);
0251 }
0252 template<class AE>
0253 BOOST_UBLAS_INLINE
0254 generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
0255 matrix_assign<scalar_minus_assign> (*this, ae);
0256 return *this;
0257 }
0258 template<class AT>
0259 BOOST_UBLAS_INLINE
0260 generalized_vector_of_vector& operator *= (const AT &at) {
0261 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
0262 return *this;
0263 }
0264 template<class AT>
0265 BOOST_UBLAS_INLINE
0266 generalized_vector_of_vector& operator /= (const AT &at) {
0267 matrix_assign_scalar<scalar_divides_assign> (*this, at);
0268 return *this;
0269 }
0270
0271
0272 BOOST_UBLAS_INLINE
0273 void swap (generalized_vector_of_vector &m) {
0274 if (this != &m) {
0275 std::swap (size1_, m.size1_);
0276 std::swap (size2_, m.size2_);
0277 data ().swap (m.data ());
0278 }
0279 storage_invariants ();
0280 }
0281 BOOST_UBLAS_INLINE
0282 friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) {
0283 m1.swap (m2);
0284 }
0285
0286
0287 void sort () {
0288 vectoriterator_type itv (data ().begin ());
0289 vectoriterator_type itv_end (data ().end ());
0290 while (itv != itv_end) {
0291 (*itv).sort ();
0292 ++ itv;
0293 }
0294 }
0295
0296
0297 BOOST_UBLAS_INLINE
0298 true_reference insert_element (size_type i, size_type j, const_reference t) {
0299 const size_type elementM = layout_type::index_M (i, j);
0300 const size_type elementm = layout_type::index_m (i, j);
0301 vector_data_value_type& vd (ref (data () [elementM]));
0302 storage_invariants ();
0303 return vd.insert_element (elementm, t);
0304 }
0305 BOOST_UBLAS_INLINE
0306 void append_element (size_type i, size_type j, const_reference t) {
0307 const size_type elementM = layout_type::index_M (i, j);
0308 const size_type elementm = layout_type::index_m (i, j);
0309 vector_data_value_type& vd (ref (data () [elementM]));
0310 storage_invariants ();
0311 return vd.append_element (elementm, t);
0312 }
0313 BOOST_UBLAS_INLINE
0314 void erase_element (size_type i, size_type j) {
0315 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0316 if (itv == data ().end ())
0317 return;
0318 (*itv).erase_element (layout_type::index_m (i, j));
0319 storage_invariants ();
0320 }
0321 BOOST_UBLAS_INLINE
0322 void clear () {
0323 const size_type sizeM = layout_type::size_M (size1_, size2_);
0324
0325 for (size_type i = 0; i < sizeM; ++ i)
0326 ref (data () [i]).clear ();
0327 storage_invariants ();
0328 }
0329
0330
0331 private:
0332
0333 typedef typename A::const_iterator const_vectoriterator_type;
0334 typedef typename A::iterator vectoriterator_type;
0335 typedef typename A::value_type::const_iterator const_subiterator_type;
0336 typedef typename A::value_type::iterator subiterator_type;
0337
0338 BOOST_UBLAS_INLINE
0339 true_reference at_element (size_type i, size_type j) {
0340 return ref (ref (data () [layout_type::index_M (i, j)]) [layout_type::index_m (i, j)]);
0341 }
0342
0343 public:
0344 class const_iterator1;
0345 class iterator1;
0346 class const_iterator2;
0347 class iterator2;
0348 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
0349 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
0350 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
0351 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
0352
0353
0354
0355 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
0356 for (;;) {
0357 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0358 const_vectoriterator_type itv_end (data ().end ());
0359 if (itv == itv_end)
0360 return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0361
0362 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0363 const_subiterator_type it_end ((*itv).end ());
0364 if (rank == 0)
0365 return const_iterator1 (*this, rank, i, j, itv, it);
0366 if (it != it_end && it.index () == layout_type::index_m (i, j))
0367 return const_iterator1 (*this, rank, i, j, itv, it);
0368 if (direction > 0) {
0369 if (layout_type::fast_i ()) {
0370 if (it == it_end)
0371 return const_iterator1 (*this, rank, i, j, itv, it);
0372 i = it.index ();
0373 } else {
0374 if (i >= size1_)
0375 return const_iterator1 (*this, rank, i, j, itv, it);
0376 ++ i;
0377 }
0378 } else {
0379 if (layout_type::fast_i ()) {
0380 if (it == (*itv).begin ())
0381 return const_iterator1 (*this, rank, i, j, itv, it);
0382 --it;
0383 i = it.index ();
0384 } else {
0385 if (i == 0)
0386 return const_iterator1 (*this, rank, i, j, itv, it);
0387 -- i;
0388 }
0389 }
0390 }
0391 }
0392
0393 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
0394 for (;;) {
0395 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0396 vectoriterator_type itv_end (data ().end ());
0397 if (itv == itv_end)
0398 return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0399
0400 subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0401 subiterator_type it_end ((*itv).end ());
0402 if (rank == 0)
0403 return iterator1 (*this, rank, i, j, itv, it);
0404 if (it != it_end && it.index () == layout_type::index_m (i, j))
0405 return iterator1 (*this, rank, i, j, itv, it);
0406 if (direction > 0) {
0407 if (layout_type::fast_i ()) {
0408 if (it == it_end)
0409 return iterator1 (*this, rank, i, j, itv, it);
0410 i = it.index ();
0411 } else {
0412 if (i >= size1_)
0413 return iterator1 (*this, rank, i, j, itv, it);
0414 ++ i;
0415 }
0416 } else {
0417 if (layout_type::fast_i ()) {
0418 if (it == (*itv).begin ())
0419 return iterator1 (*this, rank, i, j, itv, it);
0420 --it;
0421 i = it.index ();
0422 } else {
0423 if (i == 0)
0424 return iterator1 (*this, rank, i, j, itv, it);
0425 -- i;
0426 }
0427 }
0428 }
0429 }
0430
0431 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
0432 for (;;) {
0433 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0434 const_vectoriterator_type itv_end (data ().end ());
0435 if (itv == itv_end)
0436 return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0437
0438 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0439 const_subiterator_type it_end ((*itv).end ());
0440 if (rank == 0)
0441 return const_iterator2 (*this, rank, i, j, itv, it);
0442 if (it != it_end && it.index () == layout_type::index_m (i, j))
0443 return const_iterator2 (*this, rank, i, j, itv, it);
0444 if (direction > 0) {
0445 if (layout_type::fast_j ()) {
0446 if (it == it_end)
0447 return const_iterator2 (*this, rank, i, j, itv, it);
0448 j = it.index ();
0449 } else {
0450 if (j >= size2_)
0451 return const_iterator2 (*this, rank, i, j, itv, it);
0452 ++ j;
0453 }
0454 } else {
0455 if (layout_type::fast_j ()) {
0456 if (it == (*itv).begin ())
0457 return const_iterator2 (*this, rank, i, j, itv, it);
0458 --it;
0459 j = it.index ();
0460 } else {
0461 if (j == 0)
0462 return const_iterator2 (*this, rank, i, j, itv, it);
0463 -- j;
0464 }
0465 }
0466 }
0467 }
0468
0469 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
0470 for (;;) {
0471 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0472 vectoriterator_type itv_end (data ().end ());
0473 if (itv == itv_end)
0474 return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0475
0476 subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0477 subiterator_type it_end ((*itv).end ());
0478 if (rank == 0)
0479 return iterator2 (*this, rank, i, j, itv, it);
0480 if (it != it_end && it.index () == layout_type::index_m (i, j))
0481 return iterator2 (*this, rank, i, j, itv, it);
0482 if (direction > 0) {
0483 if (layout_type::fast_j ()) {
0484 if (it == it_end)
0485 return iterator2 (*this, rank, i, j, itv, it);
0486 j = it.index ();
0487 } else {
0488 if (j >= size2_)
0489 return iterator2 (*this, rank, i, j, itv, it);
0490 ++ j;
0491 }
0492 } else {
0493 if (layout_type::fast_j ()) {
0494 if (it == (*itv).begin ())
0495 return iterator2 (*this, rank, i, j, itv, it);
0496 --it;
0497 j = it.index ();
0498 } else {
0499 if (j == 0)
0500 return iterator2 (*this, rank, i, j, itv, it);
0501 -- j;
0502 }
0503 }
0504 }
0505 }
0506
0507
0508 class const_iterator1:
0509 public container_const_reference<generalized_vector_of_vector>,
0510 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
0511 const_iterator1, value_type> {
0512 public:
0513 typedef typename generalized_vector_of_vector::difference_type difference_type;
0514 typedef typename generalized_vector_of_vector::value_type value_type;
0515 typedef typename generalized_vector_of_vector::const_reference reference;
0516 typedef const typename generalized_vector_of_vector::pointer pointer;
0517
0518 typedef const_iterator2 dual_iterator_type;
0519 typedef const_reverse_iterator2 dual_reverse_iterator_type;
0520
0521
0522 BOOST_UBLAS_INLINE
0523 const_iterator1 ():
0524 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
0525 BOOST_UBLAS_INLINE
0526 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
0527 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
0528 BOOST_UBLAS_INLINE
0529 const_iterator1 (const iterator1 &it):
0530 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
0531
0532
0533 BOOST_UBLAS_INLINE
0534 const_iterator1 &operator ++ () {
0535 if (rank_ == 1 && layout_type::fast_i ())
0536 ++ it_;
0537 else {
0538 const self_type &m = (*this) ();
0539 i_ = index1 () + 1;
0540 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
0541 *this = m.find1 (rank_, i_, j_, 1);
0542 else if (rank_ == 1) {
0543 it_ = (*itv_).begin ();
0544 if (it_ == (*itv_).end () || index2 () != j_)
0545 *this = m.find1 (rank_, i_, j_, 1);
0546 }
0547 }
0548 return *this;
0549 }
0550 BOOST_UBLAS_INLINE
0551 const_iterator1 &operator -- () {
0552 if (rank_ == 1 && layout_type::fast_i ())
0553 -- it_;
0554 else {
0555 const self_type &m = (*this) ();
0556 i_ = index1 () - 1;
0557 if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
0558 *this = m.find1 (rank_, i_, j_, -1);
0559 else if (rank_ == 1) {
0560 it_ = (*itv_).begin ();
0561 if (it_ == (*itv_).end () || index2 () != j_)
0562 *this = m.find1 (rank_, i_, j_, -1);
0563 }
0564 }
0565 return *this;
0566 }
0567
0568
0569 BOOST_UBLAS_INLINE
0570 const_reference operator * () const {
0571 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
0572 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
0573 if (rank_ == 1) {
0574 return *it_;
0575 } else {
0576 return (*this) () (i_, j_);
0577 }
0578 }
0579
0580 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0581 BOOST_UBLAS_INLINE
0582 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0583 typename self_type::
0584 #endif
0585 const_iterator2 begin () const {
0586 const self_type &m = (*this) ();
0587 return m.find2 (1, index1 (), 0);
0588 }
0589 BOOST_UBLAS_INLINE
0590 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0591 typename self_type::
0592 #endif
0593 const_iterator2 cbegin () const {
0594 return begin ();
0595 }
0596 BOOST_UBLAS_INLINE
0597 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0598 typename self_type::
0599 #endif
0600 const_iterator2 end () const {
0601 const self_type &m = (*this) ();
0602 return m.find2 (1, index1 (), m.size2 ());
0603 }
0604 BOOST_UBLAS_INLINE
0605 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0606 typename self_type::
0607 #endif
0608 const_iterator2 cend () const {
0609 return end ();
0610 }
0611
0612 BOOST_UBLAS_INLINE
0613 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0614 typename self_type::
0615 #endif
0616 const_reverse_iterator2 rbegin () const {
0617 return const_reverse_iterator2 (end ());
0618 }
0619 BOOST_UBLAS_INLINE
0620 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0621 typename self_type::
0622 #endif
0623 const_reverse_iterator2 crbegin () const {
0624 return rbegin ();
0625 }
0626 BOOST_UBLAS_INLINE
0627 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0628 typename self_type::
0629 #endif
0630 const_reverse_iterator2 rend () const {
0631 return const_reverse_iterator2 (begin ());
0632 }
0633 BOOST_UBLAS_INLINE
0634 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0635 typename self_type::
0636 #endif
0637 const_reverse_iterator2 crend () const {
0638 return rend ();
0639 }
0640 #endif
0641
0642
0643 BOOST_UBLAS_INLINE
0644 size_type index1 () const {
0645 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0646 if (rank_ == 1) {
0647 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
0648 return layout_type::index_M (itv_.index (), it_.index ());
0649 } else {
0650 return i_;
0651 }
0652 }
0653 BOOST_UBLAS_INLINE
0654 size_type index2 () const {
0655 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0656 if (rank_ == 1) {
0657 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
0658 return layout_type::index_m (itv_.index (), it_.index ());
0659 } else {
0660 return j_;
0661 }
0662 }
0663
0664
0665 BOOST_UBLAS_INLINE
0666 const_iterator1 &operator = (const const_iterator1 &it) {
0667 container_const_reference<self_type>::assign (&it ());
0668 rank_ = it.rank_;
0669 i_ = it.i_;
0670 j_ = it.j_;
0671 itv_ = it.itv_;
0672 it_ = it.it_;
0673 return *this;
0674 }
0675
0676
0677 BOOST_UBLAS_INLINE
0678 bool operator == (const const_iterator1 &it) const {
0679 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0680
0681 if (rank_ == 1 || it.rank_ == 1) {
0682 return it_ == it.it_;
0683 } else {
0684 return i_ == it.i_ && j_ == it.j_;
0685 }
0686 }
0687
0688 private:
0689 int rank_;
0690 size_type i_;
0691 size_type j_;
0692 const_vectoriterator_type itv_;
0693 const_subiterator_type it_;
0694 };
0695
0696 BOOST_UBLAS_INLINE
0697 const_iterator1 begin1 () const {
0698 return find1 (0, 0, 0);
0699 }
0700 BOOST_UBLAS_INLINE
0701 const_iterator1 cbegin1 () const {
0702 return begin1 ();
0703 }
0704 BOOST_UBLAS_INLINE
0705 const_iterator1 end1 () const {
0706 return find1 (0, size1_, 0);
0707 }
0708 BOOST_UBLAS_INLINE
0709 const_iterator1 cend1 () const {
0710 return end1 ();
0711 }
0712
0713 class iterator1:
0714 public container_reference<generalized_vector_of_vector>,
0715 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
0716 iterator1, value_type> {
0717 public:
0718 typedef typename generalized_vector_of_vector::difference_type difference_type;
0719 typedef typename generalized_vector_of_vector::value_type value_type;
0720 typedef typename generalized_vector_of_vector::true_reference reference;
0721 typedef typename generalized_vector_of_vector::pointer pointer;
0722
0723 typedef iterator2 dual_iterator_type;
0724 typedef reverse_iterator2 dual_reverse_iterator_type;
0725
0726
0727 BOOST_UBLAS_INLINE
0728 iterator1 ():
0729 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
0730 BOOST_UBLAS_INLINE
0731 iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
0732 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
0733
0734
0735 BOOST_UBLAS_INLINE
0736 iterator1 &operator ++ () {
0737 if (rank_ == 1 && layout_type::fast_i ())
0738 ++ it_;
0739 else {
0740 self_type &m = (*this) ();
0741 i_ = index1 () + 1;
0742 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
0743 *this = m.find1 (rank_, i_, j_, 1);
0744 else if (rank_ == 1) {
0745 it_ = (*itv_).begin ();
0746 if (it_ == (*itv_).end () || index2 () != j_)
0747 *this = m.find1 (rank_, i_, j_, 1);
0748 }
0749 }
0750 return *this;
0751 }
0752 BOOST_UBLAS_INLINE
0753 iterator1 &operator -- () {
0754 if (rank_ == 1 && layout_type::fast_i ())
0755 -- it_;
0756 else {
0757 self_type &m = (*this) ();
0758 i_ = index1 () - 1;
0759 if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
0760 *this = m.find1 (rank_, i_, j_, -1);
0761 else if (rank_ == 1) {
0762 it_ = (*itv_).begin ();
0763 if (it_ == (*itv_).end () || index2 () != j_)
0764 *this = m.find1 (rank_, i_, j_, -1);
0765 }
0766 }
0767 return *this;
0768 }
0769
0770
0771 BOOST_UBLAS_INLINE
0772 true_reference operator * () const {
0773 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
0774 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
0775 if (rank_ == 1) {
0776 return *it_;
0777 } else {
0778 return (*this) ().at_element (i_, j_);
0779 }
0780 }
0781
0782 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0783 BOOST_UBLAS_INLINE
0784 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0785 typename self_type::
0786 #endif
0787 iterator2 begin () const {
0788 self_type &m = (*this) ();
0789 return m.find2 (1, index1 (), 0);
0790 }
0791 BOOST_UBLAS_INLINE
0792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0793 typename self_type::
0794 #endif
0795 iterator2 end () const {
0796 self_type &m = (*this) ();
0797 return m.find2 (1, index1 (), m.size2 ());
0798 }
0799 BOOST_UBLAS_INLINE
0800 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0801 typename self_type::
0802 #endif
0803 reverse_iterator2 rbegin () const {
0804 return reverse_iterator2 (end ());
0805 }
0806 BOOST_UBLAS_INLINE
0807 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0808 typename self_type::
0809 #endif
0810 reverse_iterator2 rend () const {
0811 return reverse_iterator2 (begin ());
0812 }
0813 #endif
0814
0815
0816 BOOST_UBLAS_INLINE
0817 size_type index1 () const {
0818 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0819 if (rank_ == 1) {
0820 BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
0821 return layout_type::index_M (itv_.index (), it_.index ());
0822 } else {
0823 return i_;
0824 }
0825 }
0826 BOOST_UBLAS_INLINE
0827 size_type index2 () const {
0828 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0829 if (rank_ == 1) {
0830 BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
0831 return layout_type::index_m (itv_.index (), it_.index ());
0832 } else {
0833 return j_;
0834 }
0835 }
0836
0837
0838 BOOST_UBLAS_INLINE
0839 iterator1 &operator = (const iterator1 &it) {
0840 container_reference<self_type>::assign (&it ());
0841 rank_ = it.rank_;
0842 i_ = it.i_;
0843 j_ = it.j_;
0844 itv_ = it.itv_;
0845 it_ = it.it_;
0846 return *this;
0847 }
0848
0849
0850 BOOST_UBLAS_INLINE
0851 bool operator == (const iterator1 &it) const {
0852 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0853
0854 if (rank_ == 1 || it.rank_ == 1) {
0855 return it_ == it.it_;
0856 } else {
0857 return i_ == it.i_ && j_ == it.j_;
0858 }
0859 }
0860
0861 private:
0862 int rank_;
0863 size_type i_;
0864 size_type j_;
0865 vectoriterator_type itv_;
0866 subiterator_type it_;
0867
0868 friend class const_iterator1;
0869 };
0870
0871 BOOST_UBLAS_INLINE
0872 iterator1 begin1 () {
0873 return find1 (0, 0, 0);
0874 }
0875 BOOST_UBLAS_INLINE
0876 iterator1 end1 () {
0877 return find1 (0, size1_, 0);
0878 }
0879
0880 class const_iterator2:
0881 public container_const_reference<generalized_vector_of_vector>,
0882 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
0883 const_iterator2, value_type> {
0884 public:
0885 typedef typename generalized_vector_of_vector::difference_type difference_type;
0886 typedef typename generalized_vector_of_vector::value_type value_type;
0887 typedef typename generalized_vector_of_vector::const_reference reference;
0888 typedef const typename generalized_vector_of_vector::pointer pointer;
0889
0890 typedef const_iterator1 dual_iterator_type;
0891 typedef const_reverse_iterator1 dual_reverse_iterator_type;
0892
0893
0894 BOOST_UBLAS_INLINE
0895 const_iterator2 ():
0896 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
0897 BOOST_UBLAS_INLINE
0898 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
0899 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
0900 BOOST_UBLAS_INLINE
0901 const_iterator2 (const iterator2 &it):
0902 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
0903
0904
0905 BOOST_UBLAS_INLINE
0906 const_iterator2 &operator ++ () {
0907 if (rank_ == 1 && layout_type::fast_j ())
0908 ++ it_;
0909 else {
0910 const self_type &m = (*this) ();
0911 j_ = index2 () + 1;
0912 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
0913 *this = m.find2 (rank_, i_, j_, 1);
0914 else if (rank_ == 1) {
0915 it_ = (*itv_).begin ();
0916 if (it_ == (*itv_).end () || index1 () != i_)
0917 *this = m.find2 (rank_, i_, j_, 1);
0918 }
0919 }
0920 return *this;
0921 }
0922 BOOST_UBLAS_INLINE
0923 const_iterator2 &operator -- () {
0924 if (rank_ == 1 && layout_type::fast_j ())
0925 -- it_;
0926 else {
0927 const self_type &m = (*this) ();
0928 j_ = index2 () - 1;
0929 if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
0930 *this = m.find2 (rank_, i_, j_, -1);
0931 else if (rank_ == 1) {
0932 it_ = (*itv_).begin ();
0933 if (it_ == (*itv_).end () || index1 () != i_)
0934 *this = m.find2 (rank_, i_, j_, -1);
0935 }
0936 }
0937 return *this;
0938 }
0939
0940
0941 BOOST_UBLAS_INLINE
0942 const_reference operator * () const {
0943 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
0944 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
0945 if (rank_ == 1) {
0946 return *it_;
0947 } else {
0948 return (*this) () (i_, j_);
0949 }
0950 }
0951
0952 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0953 BOOST_UBLAS_INLINE
0954 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0955 typename self_type::
0956 #endif
0957 const_iterator1 begin () const {
0958 const self_type &m = (*this) ();
0959 return m.find1 (1, 0, index2 ());
0960 }
0961 BOOST_UBLAS_INLINE
0962 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0963 typename self_type::
0964 #endif
0965 const_iterator1 cbegin () const {
0966 return begin ();
0967 }
0968 BOOST_UBLAS_INLINE
0969 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0970 typename self_type::
0971 #endif
0972 const_iterator1 end () const {
0973 const self_type &m = (*this) ();
0974 return m.find1 (1, m.size1 (), index2 ());
0975 }
0976 BOOST_UBLAS_INLINE
0977 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0978 typename self_type::
0979 #endif
0980 const_iterator1 cend () const {
0981 return end ();
0982 }
0983 BOOST_UBLAS_INLINE
0984 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0985 typename self_type::
0986 #endif
0987 const_reverse_iterator1 rbegin () const {
0988 return const_reverse_iterator1 (end ());
0989 }
0990 BOOST_UBLAS_INLINE
0991 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0992 typename self_type::
0993 #endif
0994 const_reverse_iterator1 crbegin () const {
0995 return rbegin ();
0996 }
0997 BOOST_UBLAS_INLINE
0998 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0999 typename self_type::
1000 #endif
1001 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
1008 const_reverse_iterator1 crend () const {
1009 return rend ();
1010 }
1011 #endif
1012
1013
1014 BOOST_UBLAS_INLINE
1015 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
1025 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
1036 BOOST_UBLAS_INLINE
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
1048 BOOST_UBLAS_INLINE
1049 bool operator == (const const_iterator2 &it) const {
1050 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1051
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
1068 const_iterator2 begin2 () const {
1069 return find2 (0, 0, 0);
1070 }
1071 BOOST_UBLAS_INLINE
1072 const_iterator2 cbegin2 () const {
1073 return begin2 ();
1074 }
1075 BOOST_UBLAS_INLINE
1076 const_iterator2 end2 () const {
1077 return find2 (0, 0, size2_);
1078 }
1079 BOOST_UBLAS_INLINE
1080 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
1098 BOOST_UBLAS_INLINE
1099 iterator2 ():
1100 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
1101 BOOST_UBLAS_INLINE
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
1106 BOOST_UBLAS_INLINE
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
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
1142 BOOST_UBLAS_INLINE
1143 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
1158 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
1166 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
1174 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
1181 reverse_iterator1 rend () const {
1182 return reverse_iterator1 (begin ());
1183 }
1184 #endif
1185
1186
1187 BOOST_UBLAS_INLINE
1188 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
1198 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
1209 BOOST_UBLAS_INLINE
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
1221 BOOST_UBLAS_INLINE
1222 bool operator == (const iterator2 &it) const {
1223 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1224
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
1243 iterator2 begin2 () {
1244 return find2 (0, 0, 0);
1245 }
1246 BOOST_UBLAS_INLINE
1247 iterator2 end2 () {
1248 return find2 (0, 0, size2_);
1249 }
1250
1251
1252
1253 BOOST_UBLAS_INLINE
1254 const_reverse_iterator1 rbegin1 () const {
1255 return const_reverse_iterator1 (end1 ());
1256 }
1257 BOOST_UBLAS_INLINE
1258 const_reverse_iterator1 crbegin1 () const {
1259 return rbegin1 ();
1260 }
1261 BOOST_UBLAS_INLINE
1262 const_reverse_iterator1 rend1 () const {
1263 return const_reverse_iterator1 (begin1 ());
1264 }
1265 BOOST_UBLAS_INLINE
1266 const_reverse_iterator1 crend1 () const {
1267 return rend1 ();
1268 }
1269
1270 BOOST_UBLAS_INLINE
1271 reverse_iterator1 rbegin1 () {
1272 return reverse_iterator1 (end1 ());
1273 }
1274 BOOST_UBLAS_INLINE
1275 reverse_iterator1 rend1 () {
1276 return reverse_iterator1 (begin1 ());
1277 }
1278
1279 BOOST_UBLAS_INLINE
1280 const_reverse_iterator2 rbegin2 () const {
1281 return const_reverse_iterator2 (end2 ());
1282 }
1283 BOOST_UBLAS_INLINE
1284 const_reverse_iterator2 crbegin2 () const {
1285 return rbegin2 ();
1286 }
1287 BOOST_UBLAS_INLINE
1288 const_reverse_iterator2 rend2 () const {
1289 return const_reverse_iterator2 (begin2 ());
1290 }
1291 BOOST_UBLAS_INLINE
1292 const_reverse_iterator2 crend2 () const {
1293 return rend2 ();
1294 }
1295
1296 BOOST_UBLAS_INLINE
1297 reverse_iterator2 rbegin2 () {
1298 return reverse_iterator2 (end2 ());
1299 }
1300 BOOST_UBLAS_INLINE
1301 reverse_iterator2 rend2 () {
1302 return reverse_iterator2 (begin2 ());
1303 }
1304
1305
1306 template<class Archive>
1307 void serialize(Archive & ar, const unsigned int ){
1308
1309
1310
1311 serialization::collection_size_type s1 (size1_);
1312 serialization::collection_size_type s2 (size2_);
1313
1314
1315 ar & serialization::make_nvp("size1",s1)
1316 & serialization::make_nvp("size2",s2);
1317
1318
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:
1330 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();
1344
1345 }}}
1346
1347 #endif